From f11e40a8119bac1ab28c1cbaf18078466d84d951 Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Fri, 16 Jun 2017 22:59:20 +0300 Subject: [PATCH 001/162] deriv(Hash) for single-variant enum should not hash discriminant Fixes #39137 --- src/libsyntax_ext/deriving/clone.rs | 2 +- src/libsyntax_ext/deriving/debug.rs | 2 +- src/libsyntax_ext/deriving/encodable.rs | 2 +- src/libsyntax_ext/deriving/generic/mod.rs | 9 +++++---- src/libsyntax_ext/deriving/hash.rs | 2 +- src/test/run-pass/deriving-hash.rs | 13 +++++++++++-- 6 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/libsyntax_ext/deriving/clone.rs b/src/libsyntax_ext/deriving/clone.rs index 1993d6ebe5b..35a2a2513f4 100644 --- a/src/libsyntax_ext/deriving/clone.rs +++ b/src/libsyntax_ext/deriving/clone.rs @@ -167,7 +167,7 @@ fn cs_clone(name: &str, all_fields = af; vdata = vdata_; } - EnumMatching(_, variant, ref af) => { + EnumMatching(.., variant, ref af) => { ctor_path = cx.path(trait_span, vec![substr.type_ident, variant.node.name]); all_fields = af; vdata = &variant.node.data; diff --git a/src/libsyntax_ext/deriving/debug.rs b/src/libsyntax_ext/deriving/debug.rs index ec4cb815960..38ed596098b 100644 --- a/src/libsyntax_ext/deriving/debug.rs +++ b/src/libsyntax_ext/deriving/debug.rs @@ -60,7 +60,7 @@ fn show_substructure(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P (substr.type_ident, vdata.is_struct()), - EnumMatching(_, v, _) => (v.node.name, v.node.data.is_struct()), + EnumMatching(_, _, v, _) => (v.node.name, v.node.data.is_struct()), EnumNonMatchingCollapsed(..) | StaticStruct(..) | StaticEnum(..) => cx.span_bug(span, "nonsensical .fields in `#[derive(Debug)]`"), diff --git a/src/libsyntax_ext/deriving/encodable.rs b/src/libsyntax_ext/deriving/encodable.rs index 9d155c22ad0..811135e5368 100644 --- a/src/libsyntax_ext/deriving/encodable.rs +++ b/src/libsyntax_ext/deriving/encodable.rs @@ -233,7 +233,7 @@ fn encodable_substructure(cx: &mut ExtCtxt, blk]) } - EnumMatching(idx, variant, ref fields) => { + EnumMatching(idx, _, variant, ref fields) => { // We're not generating an AST that the borrow checker is expecting, // so we need to generate a unique local variable to take the // mutable loan out on, otherwise we get conflicts which don't diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index be7883cad5f..1fe26a0ac4b 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -305,10 +305,10 @@ pub enum StaticFields { /// A summary of the possible sets of fields. pub enum SubstructureFields<'a> { Struct(&'a ast::VariantData, Vec>), - /// Matching variants of the enum: variant index, ast::Variant, + /// Matching variants of the enum: variant index, variant count, ast::Variant, /// fields: the field name is only non-`None` in the case of a struct /// variant. - EnumMatching(usize, &'a ast::Variant, Vec>), + EnumMatching(usize, usize, &'a ast::Variant, Vec>), /// Non-matching variants of the enum, but with all state hidden from /// the consequent code. The first component holds `Ident`s for all of @@ -1250,7 +1250,7 @@ impl<'a> MethodDef<'a> { // expressions for referencing every field of every // Self arg, assuming all are instances of VariantK. // Build up code associated with such a case. - let substructure = EnumMatching(index, variant, field_tuples); + let substructure = EnumMatching(index, variants.len(), variant, field_tuples); let arm_expr = self.call_substructure_method(cx, trait_, type_ident, @@ -1267,12 +1267,13 @@ impl<'a> MethodDef<'a> { // We need a default case that handles the fieldless variants. // The index and actual variant aren't meaningful in this case, // so just use whatever + let substructure = EnumMatching(0, variants.len(), v, Vec::new()); Some(self.call_substructure_method(cx, trait_, type_ident, &self_args[..], nonself_args, - &EnumMatching(0, v, Vec::new()))) + &substructure)) } _ if variants.len() > 1 && self_args.len() > 1 => { // Since we know that all the arguments will match if we reach diff --git a/src/libsyntax_ext/deriving/hash.rs b/src/libsyntax_ext/deriving/hash.rs index 97d7f2ce800..a341c21d0a1 100644 --- a/src/libsyntax_ext/deriving/hash.rs +++ b/src/libsyntax_ext/deriving/hash.rs @@ -81,7 +81,7 @@ fn hash_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) let mut stmts = Vec::new(); let fields = match *substr.fields { - Struct(_, ref fs) => fs, + Struct(_, ref fs) | EnumMatching(_, 1, .., ref fs) => fs, EnumMatching(.., ref fs) => { let variant_value = deriving::call_intrinsic(cx, trait_span, diff --git a/src/test/run-pass/deriving-hash.rs b/src/test/run-pass/deriving-hash.rs index 91bfc2f9201..18b2fbe015b 100644 --- a/src/test/run-pass/deriving-hash.rs +++ b/src/test/run-pass/deriving-hash.rs @@ -45,8 +45,8 @@ impl<'a> Hasher for FakeHasher<'a> { } } -fn fake_hash(v: &mut Vec, e: E) { - e.hash(&mut FakeHasher(v)); +fn fake_hash(v: &mut Vec, a: A) { + a.hash(&mut FakeHasher(v)); } fn main() { @@ -69,4 +69,13 @@ fn main() { fake_hash(&mut va, E::A); fake_hash(&mut vb, E::B); assert!(va != vb); + + // issue #39137: single variant enum hash should not hash discriminant + #[derive(Hash)] + enum SingleVariantEnum { + A(u8), + } + let mut v = vec![]; + fake_hash(&mut v, SingleVariantEnum::A(17)); + assert_eq!(vec![17], v); } From b4038977a39f7c5bfa76cccf586930ec57befbad Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 20 Jun 2017 15:25:51 -0700 Subject: [PATCH 002/162] Add `Iterator::for_each` This works like a `for` loop in functional style, applying a closure to every item in the `Iterator`. It doesn't allow `break`/`continue` like a `for` loop, nor any other control flow outside the closure, but it may be a more legible style for tying up the end of a long iterator chain. This was tried before in #14911, but nobody made the case for using it with longer iterators. There was also `Iterator::advance` at that time which was more capable than `for_each`, but that no longer exists. The `itertools` crate has `Itertools::foreach` with the same behavior, but thankfully the names won't collide. The `rayon` crate also has a `ParallelIterator::for_each` where simple `for` loops aren't possible. > I really wish we had `for_each` on seq iterators. Having to use a > dummy operation is annoying. - [@nikomatsakis][1] [1]: https://github.com/nikomatsakis/rayon/pull/367#issuecomment-308455185 --- .../src/library-features/iterator-for-each.md | 17 +++++++ src/libcore/iter/iterator.rs | 46 +++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 src/doc/unstable-book/src/library-features/iterator-for-each.md diff --git a/src/doc/unstable-book/src/library-features/iterator-for-each.md b/src/doc/unstable-book/src/library-features/iterator-for-each.md new file mode 100644 index 00000000000..72fdac5e40d --- /dev/null +++ b/src/doc/unstable-book/src/library-features/iterator-for-each.md @@ -0,0 +1,17 @@ +# `iterator_for_each` + +The tracking issue for this feature is: [#TBD] + +[#TBD]: https://github.com/rust-lang/rust/issues/TBD + +------------------------ + +To call a closure on each element of an iterator, you can use `for_each`: + +```rust +#![feature(iterator_for_each)] + +fn main() { + (0..10).for_each(|i| println!("{}", i)); +} +``` diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index 30d09e5453b..49c43d133e5 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -482,6 +482,52 @@ pub trait Iterator { Map{iter: self, f: f} } + /// Calls a closure on each element of an iterator. + /// + /// This is equivalent to using a [`for`] loop on the iterator, although + /// `break` and `continue` are not possible from a closure. It's generally + /// more idiomatic to use a `for` loop, but `for_each` may be more legible + /// when processing items at the end of longer iterator chains. + /// + /// [`for`]: ../../book/first-edition/loops.html#for + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(iterator_for_each)] + /// + /// let mut v = vec![]; + /// (0..5).for_each(|x| v.push(x * 100)); + /// + /// let mut v2 = vec![]; + /// for x in 0..5 { v2.push(x * 100); } + /// + /// assert_eq!(v, v2); + /// ``` + /// + /// For such a small example, the `for` loop is cleaner, but `for_each` + /// might be preferable to keep a functional style with longer iterators: + /// + /// ``` + /// #![feature(iterator_for_each)] + /// + /// (0..5).flat_map(|x| x * 100 .. x * 110) + /// .enumerate() + /// .filter(|&(i, x)| (i + x) % 3 == 0) + /// .for_each(|(i, x)| println!("{}:{}", i, x)); + /// ``` + #[inline] + #[unstable(feature = "iterator_for_each", issue = "0")] + fn for_each(self, mut f: F) where + Self: Sized, F: FnMut(Self::Item), + { + for item in self { + f(item); + } + } + /// Creates an iterator which uses a closure to determine if an element /// should be yielded. /// From 5a97036b6900ee208f90c52ceadcce606d497e93 Mon Sep 17 00:00:00 2001 From: Clar Charr Date: Sat, 20 May 2017 15:40:53 -0400 Subject: [PATCH 003/162] Convert Intos to Froms. --- src/liballoc/string.rs | 6 +++--- src/libstd/ffi/c_str.rs | 6 +++--- src/libstd/ffi/os_str.rs | 6 +++--- src/libstd/path.rs | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index 2cb81029f95..c1ef1c2f96c 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -2009,9 +2009,9 @@ impl From> for String { } #[stable(feature = "box_from_str", since = "1.18.0")] -impl Into> for String { - fn into(self) -> Box { - self.into_boxed_str() +impl From for Box { + fn from(s: String) -> Box { + s.into_boxed_str() } } diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 1a91417ca0e..1586e0a4ddb 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -586,10 +586,10 @@ impl From> for CString { } #[stable(feature = "box_from_c_string", since = "1.18.0")] -impl Into> for CString { +impl From for Box { #[inline] - fn into(self) -> Box { - self.into_boxed_c_str() + fn from(s: CString) -> Box { + s.into_boxed_c_str() } } diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index f54d79c201f..3815f986681 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -543,9 +543,9 @@ impl From> for OsString { } #[stable(feature = "box_from_os_string", since = "1.18.0")] -impl Into> for OsString { - fn into(self) -> Box { - self.into_boxed_os_str() +impl From for Box { + fn from(s: OsString) -> Box { + s.into_boxed_os_str() } } diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 42a54ed6d75..e9bf7b33b8e 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -1349,9 +1349,9 @@ impl From> for PathBuf { } #[stable(feature = "box_from_path_buf", since = "1.18.0")] -impl Into> for PathBuf { - fn into(self) -> Box { - self.into_boxed_path() +impl From for Box { + fn from(p: PathBuf) -> Box { + p.into_boxed_path() } } From 0d885efe16899c2dbad2918345c9ede7b83caa7f Mon Sep 17 00:00:00 2001 From: Oliver Middleton Date: Tue, 13 Jun 2017 00:08:37 +0100 Subject: [PATCH 004/162] Update version numbers for From impls --- src/liballoc/string.rs | 2 +- src/libstd/ffi/c_str.rs | 2 +- src/libstd/ffi/os_str.rs | 2 +- src/libstd/path.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index c1ef1c2f96c..02ecb65fa38 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -2008,7 +2008,7 @@ impl From> for String { } } -#[stable(feature = "box_from_str", since = "1.18.0")] +#[stable(feature = "box_from_str", since = "1.20.0")] impl From for Box { fn from(s: String) -> Box { s.into_boxed_str() diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 1586e0a4ddb..5f0b11a616e 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -585,7 +585,7 @@ impl From> for CString { } } -#[stable(feature = "box_from_c_string", since = "1.18.0")] +#[stable(feature = "box_from_c_string", since = "1.20.0")] impl From for Box { #[inline] fn from(s: CString) -> Box { diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index 3815f986681..3232a51546e 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -542,7 +542,7 @@ impl From> for OsString { } } -#[stable(feature = "box_from_os_string", since = "1.18.0")] +#[stable(feature = "box_from_os_string", since = "1.20.0")] impl From for Box { fn from(s: OsString) -> Box { s.into_boxed_os_str() diff --git a/src/libstd/path.rs b/src/libstd/path.rs index e9bf7b33b8e..7a8c8935394 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -1348,7 +1348,7 @@ impl From> for PathBuf { } } -#[stable(feature = "box_from_path_buf", since = "1.18.0")] +#[stable(feature = "box_from_path_buf", since = "1.20.0")] impl From for Box { fn from(p: PathBuf) -> Box { p.into_boxed_path() From 3ac976861d68c9e00bb844c0feadbe1ce882d5e6 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Wed, 21 Jun 2017 14:50:43 +0300 Subject: [PATCH 005/162] avoid translating roots with predicates that do not hold Fixes #37725. --- src/librustc/traits/mod.rs | 7 +++++-- src/librustc_trans/collector.rs | 14 +++++--------- src/librustc_trans/trans_item.rs | 18 +++++++++++++++++- src/test/run-pass/issue-37725.rs | 14 ++++++++++++++ 4 files changed, 41 insertions(+), 12 deletions(-) create mode 100644 src/test/run-pass/issue-37725.rs diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index e9196cd1243..d5d92cfcc3e 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -597,7 +597,7 @@ pub fn normalize_and_test_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, debug!("normalize_and_test_predicates(predicates={:?})", predicates); - tcx.infer_ctxt().enter(|infcx| { + let result = tcx.infer_ctxt().enter(|infcx| { let param_env = ty::ParamEnv::empty(Reveal::All); let mut selcx = SelectionContext::new(&infcx); let mut fulfill_cx = FulfillmentContext::new(); @@ -613,7 +613,10 @@ pub fn normalize_and_test_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } fulfill_cx.select_all_or_error(&infcx).is_ok() - }) + }); + debug!("normalize_and_test_predicates(predicates={:?}) = {:?}", + predicates, result); + result } /// Given a trait `trait_ref`, iterates the vtable entries diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index d723cf32571..3536dcf16e5 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -195,7 +195,7 @@ use rustc::hir::map as hir_map; use rustc::hir::def_id::DefId; use rustc::middle::lang_items::{ExchangeMallocFnLangItem}; use rustc::traits; -use rustc::ty::subst::{Substs, Subst}; +use rustc::ty::subst::Substs; use rustc::ty::{self, TypeFoldable, TyCtxt}; use rustc::ty::adjustment::CustomCoerceUnsized; use rustc::mir::{self, Location}; @@ -304,6 +304,7 @@ fn collect_roots<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, scx.tcx().hir.krate().visit_all_item_likes(&mut visitor); } + roots.retain(|root| root.is_instantiable(scx.tcx())); roots } @@ -937,14 +938,9 @@ fn create_trans_items_for_default_impls<'a, 'tcx>(scx: &SharedCrateContext<'a, ' let instance = monomorphize::resolve(scx, method.def_id, callee_substs); - let predicates = tcx.predicates_of(instance.def_id()).predicates - .subst(tcx, instance.substs); - if !traits::normalize_and_test_predicates(tcx, predicates) { - continue; - } - - if should_trans_locally(tcx, &instance) { - output.push(create_fn_trans_item(instance)); + let trans_item = create_fn_trans_item(instance); + if trans_item.is_instantiable(tcx) && should_trans_locally(tcx, &instance) { + output.push(trans_item); } } } diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs index 0dc2bc85e30..6e8b2e0a2a6 100644 --- a/src/librustc_trans/trans_item.rs +++ b/src/librustc_trans/trans_item.rs @@ -25,8 +25,9 @@ use llvm; use monomorphize::Instance; use rustc::hir; use rustc::hir::def_id::DefId; +use rustc::traits; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; -use rustc::ty::subst::Substs; +use rustc::ty::subst::{Subst, Substs}; use syntax::ast::{self, NodeId}; use syntax::attr; use syntax_pos::Span; @@ -250,6 +251,21 @@ impl<'a, 'tcx> TransItem<'tcx> { } } + /// Returns whether this instance is instantiable - whether it has no unsatisfied + /// predicates. + pub fn is_instantiable(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> bool { + debug!("is_instantiable({:?})", self); + let (def_id, substs) = match *self { + TransItem::Fn(ref instance) => (instance.def_id(), instance.substs), + TransItem::Static(node_id) => (tcx.hir.local_def_id(node_id), Substs::empty()), + // global asm never has predicates + TransItem::GlobalAsm(..) => return true + }; + + let predicates = tcx.predicates_of(def_id).predicates.subst(tcx, substs); + traits::normalize_and_test_predicates(tcx, predicates) + } + pub fn to_string(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> String { let hir_map = &tcx.hir; diff --git a/src/test/run-pass/issue-37725.rs b/src/test/run-pass/issue-37725.rs new file mode 100644 index 00000000000..5ed1295c85c --- /dev/null +++ b/src/test/run-pass/issue-37725.rs @@ -0,0 +1,14 @@ +// Copyright 2016 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. + +pub fn foo<'a>(s: &'a mut ()) where &'a mut (): Clone { + s.clone(); +} +fn main() {} From 7769c9a7ec8aec50260956a6383c38f4e8dbdf35 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Wed, 21 Jun 2017 20:28:09 +0300 Subject: [PATCH 006/162] coerce fields to the expected field type Fully fixes #31260. This needs a crater run. --- src/librustc_typeck/check/mod.rs | 29 +++++++++----------- src/test/run-pass/issue-31260.rs | 5 +++- src/test/ui/mismatched_types/abridged.rs | 10 ++++--- src/test/ui/mismatched_types/abridged.stderr | 24 ++++------------ 4 files changed, 29 insertions(+), 39 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index f7e23d28987..9d93388edc7 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3159,11 +3159,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let adt_ty_hint = self.expected_inputs_for_expected_output(span, expected, adt_ty, &[adt_ty]) - .get(0).cloned().unwrap_or(adt_ty); + .get(0).cloned().unwrap_or(adt_ty); + // re-link the regions that EIfEO can erase. + self.demand_eqtype(span, adt_ty_hint, adt_ty); - let (substs, hint_substs, adt_kind, kind_name) = match (&adt_ty.sty, &adt_ty_hint.sty) { - (&ty::TyAdt(adt, substs), &ty::TyAdt(_, hint_substs)) => { - (substs, hint_substs, adt.adt_kind(), adt.variant_descr()) + let (substs, adt_kind, kind_name) = match &adt_ty.sty{ + &ty::TyAdt(adt, substs) => { + (substs, adt.adt_kind(), adt.variant_descr()) } _ => span_bug!(span, "non-ADT passed to check_expr_struct_fields") }; @@ -3179,14 +3181,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Typecheck each field. for field in ast_fields { - let final_field_type; - let field_type_hint; - let ident = tcx.adjust(field.name.node, variant.did, self.body_id).0; - if let Some(v_field) = remaining_fields.remove(&ident) { - final_field_type = self.field_ty(field.span, v_field, substs); - field_type_hint = self.field_ty(field.span, v_field, hint_substs); - + let field_type = if let Some(v_field) = remaining_fields.remove(&ident) { seen_fields.insert(field.name.node, field.span); // we don't look at stability attributes on @@ -3195,10 +3191,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if adt_kind != ty::AdtKind::Enum { tcx.check_stability(v_field.did, expr_id, field.span); } + + self.field_ty(field.span, v_field, substs) } else { error_happened = true; - final_field_type = tcx.types.err; - field_type_hint = tcx.types.err; if let Some(_) = variant.find_field_named(field.name.node) { let mut err = struct_span_err!(self.tcx.sess, field.name.span, @@ -3216,12 +3212,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } else { self.report_unknown_field(adt_ty, variant, field, ast_fields, kind_name); } - } + + tcx.types.err + }; // Make sure to give a type to the field even if there's // an error, so we can continue typechecking - let ty = self.check_expr_with_hint(&field.expr, field_type_hint); - self.demand_coerce(&field.expr, ty, final_field_type); + self.check_expr_coercable_to_type(&field.expr, field_type); } // Make sure the programmer specified correct number of fields. diff --git a/src/test/run-pass/issue-31260.rs b/src/test/run-pass/issue-31260.rs index e771fc7464d..d21ffb96bef 100644 --- a/src/test/run-pass/issue-31260.rs +++ b/src/test/run-pass/issue-31260.rs @@ -12,9 +12,12 @@ pub struct Struct { pub field: K, } -// Partial fix for #31260, doesn't work without {...}. static STRUCT: Struct<&'static [u8]> = Struct { field: {&[1]} }; +static STRUCT2: Struct<&'static [u8]> = Struct { + field: &[1] +}; + fn main() {} diff --git a/src/test/ui/mismatched_types/abridged.rs b/src/test/ui/mismatched_types/abridged.rs index c448ad955fa..03f889224be 100644 --- a/src/test/ui/mismatched_types/abridged.rs +++ b/src/test/ui/mismatched_types/abridged.rs @@ -39,23 +39,25 @@ fn c() -> Result { } fn d() -> X, String> { - X { + let x = X { x: X { x: "".to_string(), y: 2, }, y: 3, - } + }; + x } fn e() -> X, String> { - X { + let x = X { x: X { x: "".to_string(), y: 2, }, y: "".to_string(), - } + }; + x } fn main() {} diff --git a/src/test/ui/mismatched_types/abridged.stderr b/src/test/ui/mismatched_types/abridged.stderr index 78b5dcda1d9..8513da1e1d2 100644 --- a/src/test/ui/mismatched_types/abridged.stderr +++ b/src/test/ui/mismatched_types/abridged.stderr @@ -35,31 +35,19 @@ error[E0308]: mismatched types found type `Foo` error[E0308]: mismatched types - --> $DIR/abridged.rs:42:5 + --> $DIR/abridged.rs:49:5 | -42 | / X { -43 | | x: X { -44 | | x: "".to_string(), -45 | | y: 2, -46 | | }, -47 | | y: 3, -48 | | } - | |_____^ expected struct `std::string::String`, found integral variable +49 | x + | ^ expected struct `std::string::String`, found integral variable | = note: expected type `X, std::string::String>` found type `X, {integer}>` error[E0308]: mismatched types - --> $DIR/abridged.rs:52:5 + --> $DIR/abridged.rs:60:5 | -52 | / X { -53 | | x: X { -54 | | x: "".to_string(), -55 | | y: 2, -56 | | }, -57 | | y: "".to_string(), -58 | | } - | |_____^ expected struct `std::string::String`, found integral variable +60 | x + | ^ expected struct `std::string::String`, found integral variable | = note: expected type `X, _>` found type `X, _>` From 4a8ddac99e1edfb219e11c3ea2d6c43ccecb29ab Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 21 Jun 2017 13:22:27 -0700 Subject: [PATCH 007/162] Use `fold` to implement `Iterator::for_each` The benefit of using internal iteration is shown in new benchmarks: test iter::bench_for_each_chain_fold ... bench: 635,110 ns/iter (+/- 5,135) test iter::bench_for_each_chain_loop ... bench: 2,249,983 ns/iter (+/- 42,001) test iter::bench_for_each_chain_ref_fold ... bench: 2,248,061 ns/iter (+/- 51,940) --- src/libcore/benches/iter.rs | 47 ++++++++++++++++++++++++++++++++++++ src/libcore/iter/iterator.rs | 8 +++--- 2 files changed, 51 insertions(+), 4 deletions(-) diff --git a/src/libcore/benches/iter.rs b/src/libcore/benches/iter.rs index 93d38a5bc83..5b06229c21f 100644 --- a/src/libcore/benches/iter.rs +++ b/src/libcore/benches/iter.rs @@ -99,3 +99,50 @@ fn bench_zip_add(b: &mut Bencher) { add_zip(&source, &mut dst) }); } + +/// `Iterator::for_each` implemented as a plain loop. +fn for_each_loop(iter: I, mut f: F) where + I: Iterator, F: FnMut(I::Item) +{ + for item in iter { + f(item); + } +} + +/// `Iterator::for_each` implemented with `fold` for internal iteration. +/// (except when `by_ref()` effectively disables that optimization.) +fn for_each_fold(iter: I, mut f: F) where + I: Iterator, F: FnMut(I::Item) +{ + iter.fold((), move |(), item| f(item)); +} + +#[bench] +fn bench_for_each_chain_loop(b: &mut Bencher) { + b.iter(|| { + let mut acc = 0; + let iter = (0i64..1000000).chain(0..1000000).map(black_box); + for_each_loop(iter, |x| acc += x); + acc + }); +} + +#[bench] +fn bench_for_each_chain_fold(b: &mut Bencher) { + b.iter(|| { + let mut acc = 0; + let iter = (0i64..1000000).chain(0..1000000).map(black_box); + for_each_fold(iter, |x| acc += x); + acc + }); +} + +#[bench] +fn bench_for_each_chain_ref_fold(b: &mut Bencher) { + b.iter(|| { + let mut acc = 0; + let mut iter = (0i64..1000000).chain(0..1000000).map(black_box); + for_each_fold(iter.by_ref(), |x| acc += x); + acc + }); +} diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index 49c43d133e5..d38864f3edd 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -487,7 +487,9 @@ pub trait Iterator { /// This is equivalent to using a [`for`] loop on the iterator, although /// `break` and `continue` are not possible from a closure. It's generally /// more idiomatic to use a `for` loop, but `for_each` may be more legible - /// when processing items at the end of longer iterator chains. + /// when processing items at the end of longer iterator chains. In some + /// cases `for_each` may also be faster than a loop, because it will use + /// internal iteration on adaptors like `Chain`. /// /// [`for`]: ../../book/first-edition/loops.html#for /// @@ -523,9 +525,7 @@ pub trait Iterator { fn for_each(self, mut f: F) where Self: Sized, F: FnMut(Self::Item), { - for item in self { - f(item); - } + self.fold((), move |(), item| f(item)); } /// Creates an iterator which uses a closure to determine if an element From 47fa016193a729091aef9c531df9385548ad46ab Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Tue, 20 Jun 2017 23:48:15 -0700 Subject: [PATCH 008/162] Reuse the mem::swap optimizations to speed up slice::rotate Exposes the swapping logic from PR 40454 as `pub unsafe fn ptr::swap_nonoverlapping` under feature swap_nonoverlapping This is most helpful for compound types where LLVM didn't vectorize the loop. Highlight: bench slice::rotate_medium_by727_strings gets 38% faster. --- src/libcore/mem.rs | 54 +----------------------- src/libcore/ptr.rs | 84 +++++++++++++++++++++++++++++++++++++ src/libcore/slice/rotate.rs | 9 +--- 3 files changed, 86 insertions(+), 61 deletions(-) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 509b396f211..62dff93d85c 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -499,59 +499,7 @@ pub unsafe fn uninitialized() -> T { #[stable(feature = "rust1", since = "1.0.0")] pub fn swap(x: &mut T, y: &mut T) { unsafe { - // The approach here is to utilize simd to swap x & y efficiently. Testing reveals - // that swapping either 32 bytes or 64 bytes at a time is most efficient for intel - // Haswell E processors. LLVM is more able to optimize if we give a struct a - // #[repr(simd)], even if we don't actually use this struct directly. - // - // FIXME repr(simd) broken on emscripten and redox - #[cfg_attr(not(any(target_os = "emscripten", target_os = "redox")), repr(simd))] - struct Block(u64, u64, u64, u64); - struct UnalignedBlock(u64, u64, u64, u64); - - let block_size = size_of::(); - - // Get raw pointers to the bytes of x & y for easier manipulation - let x = x as *mut T as *mut u8; - let y = y as *mut T as *mut u8; - - // Loop through x & y, copying them `Block` at a time - // The optimizer should unroll the loop fully for most types - // N.B. We can't use a for loop as the `range` impl calls `mem::swap` recursively - let len = size_of::(); - let mut i = 0; - while i + block_size <= len { - // Create some uninitialized memory as scratch space - // Declaring `t` here avoids aligning the stack when this loop is unused - let mut t: Block = uninitialized(); - let t = &mut t as *mut _ as *mut u8; - let x = x.offset(i as isize); - let y = y.offset(i as isize); - - // Swap a block of bytes of x & y, using t as a temporary buffer - // This should be optimized into efficient SIMD operations where available - ptr::copy_nonoverlapping(x, t, block_size); - ptr::copy_nonoverlapping(y, x, block_size); - ptr::copy_nonoverlapping(t, y, block_size); - i += block_size; - } - - - if i < len { - // Swap any remaining bytes, using aligned types to copy - // where appropriate (this information is lost by conversion - // to *mut u8, so restore it manually here) - let mut t: UnalignedBlock = uninitialized(); - let rem = len - i; - - let t = &mut t as *mut _ as *mut u8; - let x = x.offset(i as isize); - let y = y.offset(i as isize); - - ptr::copy_nonoverlapping(x, t, rem); - ptr::copy_nonoverlapping(y, x, rem); - ptr::copy_nonoverlapping(t, y, rem); - } + ptr::swap_nonoverlapping(x, y, 1); } } diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index f89f86e18a1..bd311743beb 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -117,6 +117,90 @@ pub unsafe fn swap(x: *mut T, y: *mut T) { mem::forget(tmp); } +/// Swaps a sequence of values at two mutable locations of the same type. +/// +/// # Safety +/// +/// The two arguments must each point to the beginning of `count` locations +/// of valid memory, and the two memory ranges must not overlap. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// #![feature(swap_nonoverlapping)] +/// +/// use std::ptr; +/// +/// let mut x = [1, 2, 3, 4]; +/// let mut y = [7, 8, 9]; +/// +/// unsafe { +/// ptr::swap_nonoverlapping(x.as_mut_ptr(), y.as_mut_ptr(), 2); +/// } +/// +/// assert_eq!(x, [7, 8, 3, 4]); +/// assert_eq!(y, [1, 2, 9]); +/// ``` +#[inline] +#[unstable(feature = "swap_nonoverlapping", issue = "42818")] +pub unsafe fn swap_nonoverlapping(x: *mut T, y: *mut T, count: usize) { + let x = x as *mut u8; + let y = y as *mut u8; + let len = mem::size_of::() * count; + swap_nonoverlapping_bytes(x, y, len) +} + +#[inline] +unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) { + // The approach here is to utilize simd to swap x & y efficiently. Testing reveals + // that swapping either 32 bytes or 64 bytes at a time is most efficient for intel + // Haswell E processors. LLVM is more able to optimize if we give a struct a + // #[repr(simd)], even if we don't actually use this struct directly. + // + // FIXME repr(simd) broken on emscripten and redox + #[cfg_attr(not(any(target_os = "emscripten", target_os = "redox")), repr(simd))] + struct Block(u64, u64, u64, u64); + struct UnalignedBlock(u64, u64, u64, u64); + + let block_size = mem::size_of::(); + + // Loop through x & y, copying them `Block` at a time + // The optimizer should unroll the loop fully for most types + // N.B. We can't use a for loop as the `range` impl calls `mem::swap` recursively + let mut i = 0; + while i + block_size <= len { + // Create some uninitialized memory as scratch space + // Declaring `t` here avoids aligning the stack when this loop is unused + let mut t: Block = mem::uninitialized(); + let t = &mut t as *mut _ as *mut u8; + let x = x.offset(i as isize); + let y = y.offset(i as isize); + + // Swap a block of bytes of x & y, using t as a temporary buffer + // This should be optimized into efficient SIMD operations where available + copy_nonoverlapping(x, t, block_size); + copy_nonoverlapping(y, x, block_size); + copy_nonoverlapping(t, y, block_size); + i += block_size; + } + + if i < len { + // Swap any remaining bytes + let mut t: UnalignedBlock = mem::uninitialized(); + let rem = len - i; + + let t = &mut t as *mut _ as *mut u8; + let x = x.offset(i as isize); + let y = y.offset(i as isize); + + copy_nonoverlapping(x, t, rem); + copy_nonoverlapping(y, x, rem); + copy_nonoverlapping(t, y, rem); + } +} + /// Replaces the value at `dest` with `src`, returning the old /// value, without dropping either. /// diff --git a/src/libcore/slice/rotate.rs b/src/libcore/slice/rotate.rs index 3b9ae5652c5..e4a4e33c172 100644 --- a/src/libcore/slice/rotate.rs +++ b/src/libcore/slice/rotate.rs @@ -76,7 +76,7 @@ pub unsafe fn ptr_rotate(mut left: usize, mid: *mut T, mut right: usize) { break; } - ptr_swap_n( + ptr::swap_nonoverlapping( mid.offset(-(left as isize)), mid.offset((right-delta) as isize), delta); @@ -103,10 +103,3 @@ pub unsafe fn ptr_rotate(mut left: usize, mid: *mut T, mut right: usize) { ptr::copy_nonoverlapping(buf, mid.offset(-(left as isize)), right); } } - -unsafe fn ptr_swap_n(a: *mut T, b: *mut T, n: usize) { - for i in 0..n { - // These are nonoverlapping, so use mem::swap instead of ptr::swap - mem::swap(&mut *a.offset(i as isize), &mut *b.offset(i as isize)); - } -} From b9a44fc489a55ebdcc04b09067e2ab9164f30810 Mon Sep 17 00:00:00 2001 From: Ryan Thomas Date: Thu, 22 Jun 2017 19:50:56 +0100 Subject: [PATCH 009/162] Update docs for fmt::write. I reworded it slightly to make it more clear that the function only take two arguments - the output and the Arguments struct that can be generated from the format_args! macro. r? @steveklabnik --- src/libcore/fmt/mod.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 8c3d3ce7d88..bcc6d53c81d 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -897,14 +897,11 @@ pub trait UpperExp { fn fmt(&self, f: &mut Formatter) -> Result; } -/// The `write` function takes an output stream, a precompiled format string, -/// and a list of arguments. The arguments will be formatted according to the -/// specified format string into the output stream provided. +/// The `write` function takes an output stream, and an `Arguments` struct +/// that can be precompiled with the `format_args!` macro. /// -/// # Arguments -/// -/// * output - the buffer to write output to -/// * args - the precompiled arguments generated by `format_args!` +/// The arguments will be formatted according to the specified format string +/// into the output stream provided. /// /// # Examples /// From c5d078fd8cf554aa1ee6e6b3a0d670ca9afa4054 Mon Sep 17 00:00:00 2001 From: Ryan Thomas Date: Thu, 22 Jun 2017 20:02:57 +0100 Subject: [PATCH 010/162] Update docs for std::fmt::format #29355. This rewords and removes the `Arguments` section from the docs for fmt::format. r? @steveklabnik --- src/liballoc/fmt.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/liballoc/fmt.rs b/src/liballoc/fmt.rs index 62a88164621..3afce884b11 100644 --- a/src/liballoc/fmt.rs +++ b/src/liballoc/fmt.rs @@ -498,12 +498,10 @@ pub use core::fmt::{DebugList, DebugMap, DebugSet, DebugStruct, DebugTuple}; use string; -/// The format function takes a precompiled format string and a list of -/// arguments, to return the resulting formatted string. +/// The `format` function takes an `Arguments` struct and returns the resulting +/// formatted string. /// -/// # Arguments -/// -/// * args - a structure of arguments generated via the `format_args!` macro. +/// The `Arguments` instance can be created with the `format_args!` macro. /// /// # Examples /// From 3b9fe77bfcd4c800fab8afcdcc82d31facdc515b Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Sun, 4 Jun 2017 21:44:57 +0300 Subject: [PATCH 011/162] Fix NaN handling in is_sign_negative/positive See #42425 --- src/libcore/num/f32.rs | 19 +++++++++++++------ src/libcore/num/f64.rs | 17 +++++++++++------ src/libstd/f32.rs | 24 ++++++++---------------- src/libstd/f64.rs | 26 ++++++++------------------ 4 files changed, 40 insertions(+), 46 deletions(-) diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index 91ca213e96e..aca37221f09 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -205,18 +205,25 @@ impl Float for f32 { } } - /// Returns `true` if `self` is positive, including `+0.0` and - /// `Float::infinity()`. + /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with + /// positive sign bit and positive infinity. #[inline] fn is_sign_positive(self) -> bool { - self > 0.0 || (1.0 / self) == INFINITY + !self.is_sign_negative() } - /// Returns `true` if `self` is negative, including `-0.0` and - /// `Float::neg_infinity()`. + /// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with + /// negative sign bit and negative infinity. #[inline] fn is_sign_negative(self) -> bool { - self < 0.0 || (1.0 / self) == NEG_INFINITY + // IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus + // applies to zeros and NaNs as well. + #[repr(C)] + union F32Bytes { + f: f32, + b: u32 + } + unsafe { F32Bytes { f: self }.b & 0x8000_0000 != 0 } } /// Returns the reciprocal (multiplicative inverse) of the number. diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index 7d6d6cef049..ebe5daa67a7 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -205,18 +205,23 @@ impl Float for f64 { } } - /// Returns `true` if `self` is positive, including `+0.0` and - /// `Float::infinity()`. + /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with + /// positive sign bit and positive infinity. #[inline] fn is_sign_positive(self) -> bool { - self > 0.0 || (1.0 / self) == INFINITY + !self.is_sign_negative() } - /// Returns `true` if `self` is negative, including `-0.0` and - /// `Float::neg_infinity()`. + /// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with + /// negative sign bit and negative infinity. #[inline] fn is_sign_negative(self) -> bool { - self < 0.0 || (1.0 / self) == NEG_INFINITY + #[repr(C)] + union F64Bytes { + f: f64, + b: u64 + } + unsafe { F64Bytes { f: self }.b & 0x8000_0000_0000_0000 != 0 } } /// Returns the reciprocal (multiplicative inverse) of the number. diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs index 4abad7e24f8..2f5a7c72411 100644 --- a/src/libstd/f32.rs +++ b/src/libstd/f32.rs @@ -365,39 +365,29 @@ impl f32 { #[inline] pub fn signum(self) -> f32 { num::Float::signum(self) } - /// Returns `true` if `self`'s sign bit is positive, including - /// `+0.0` and `INFINITY`. + /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with + /// positive sign bit and positive infinity. /// /// ``` - /// use std::f32; - /// - /// let nan = f32::NAN; /// let f = 7.0_f32; /// let g = -7.0_f32; /// /// assert!(f.is_sign_positive()); /// assert!(!g.is_sign_positive()); - /// // Requires both tests to determine if is `NaN` - /// assert!(!nan.is_sign_positive() && !nan.is_sign_negative()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn is_sign_positive(self) -> bool { num::Float::is_sign_positive(self) } - /// Returns `true` if `self`'s sign is negative, including `-0.0` - /// and `NEG_INFINITY`. + /// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with + /// negative sign bit and negative infinity. /// /// ``` - /// use std::f32; - /// - /// let nan = f32::NAN; /// let f = 7.0f32; /// let g = -7.0f32; /// /// assert!(!f.is_sign_negative()); /// assert!(g.is_sign_negative()); - /// // Requires both tests to determine if is `NaN`. - /// assert!(!nan.is_sign_positive() && !nan.is_sign_negative()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -1186,7 +1176,7 @@ mod tests { assert!(!nan.is_infinite()); assert!(!nan.is_finite()); assert!(!nan.is_normal()); - assert!(!nan.is_sign_positive()); + assert!(nan.is_sign_positive()); assert!(!nan.is_sign_negative()); assert_eq!(Fp::Nan, nan.classify()); } @@ -1430,7 +1420,8 @@ mod tests { assert!(!(-1f32).is_sign_positive()); assert!(!NEG_INFINITY.is_sign_positive()); assert!(!(1f32/NEG_INFINITY).is_sign_positive()); - assert!(!NAN.is_sign_positive()); + assert!(NAN.is_sign_positive()); + assert!(!(-NAN).is_sign_positive()); } #[test] @@ -1443,6 +1434,7 @@ mod tests { assert!(NEG_INFINITY.is_sign_negative()); assert!((1f32/NEG_INFINITY).is_sign_negative()); assert!(!NAN.is_sign_negative()); + assert!((-NAN).is_sign_negative()); } #[test] diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs index 82e3903eec7..3513546fb64 100644 --- a/src/libstd/f64.rs +++ b/src/libstd/f64.rs @@ -303,21 +303,15 @@ impl f64 { #[inline] pub fn signum(self) -> f64 { num::Float::signum(self) } - /// Returns `true` if `self`'s sign bit is positive, including - /// `+0.0` and `INFINITY`. + /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with + /// positive sign bit and positive infinity. /// /// ``` - /// use std::f64; - /// - /// let nan: f64 = f64::NAN; - /// /// let f = 7.0_f64; /// let g = -7.0_f64; /// /// assert!(f.is_sign_positive()); /// assert!(!g.is_sign_positive()); - /// // Requires both tests to determine if is `NaN` - /// assert!(!nan.is_sign_positive() && !nan.is_sign_negative()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -328,21 +322,15 @@ impl f64 { #[inline] pub fn is_positive(self) -> bool { num::Float::is_sign_positive(self) } - /// Returns `true` if `self`'s sign is negative, including `-0.0` - /// and `NEG_INFINITY`. + /// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with + /// negative sign bit and negative infinity. /// /// ``` - /// use std::f64; - /// - /// let nan = f64::NAN; - /// /// let f = 7.0_f64; /// let g = -7.0_f64; /// /// assert!(!f.is_sign_negative()); /// assert!(g.is_sign_negative()); - /// // Requires both tests to determine if is `NaN`. - /// assert!(!nan.is_sign_positive() && !nan.is_sign_negative()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -1103,7 +1091,7 @@ mod tests { assert!(!nan.is_infinite()); assert!(!nan.is_finite()); assert!(!nan.is_normal()); - assert!(!nan.is_sign_positive()); + assert!(nan.is_sign_positive()); assert!(!nan.is_sign_negative()); assert_eq!(Fp::Nan, nan.classify()); } @@ -1346,7 +1334,8 @@ mod tests { assert!(!(-1f64).is_sign_positive()); assert!(!NEG_INFINITY.is_sign_positive()); assert!(!(1f64/NEG_INFINITY).is_sign_positive()); - assert!(!NAN.is_sign_positive()); + assert!(NAN.is_sign_positive()); + assert!(!(-NAN).is_sign_positive()); } #[test] @@ -1359,6 +1348,7 @@ mod tests { assert!(NEG_INFINITY.is_sign_negative()); assert!((1f64/NEG_INFINITY).is_sign_negative()); assert!(!NAN.is_sign_negative()); + assert!((-NAN).is_sign_negative()); } #[test] From 87f6d6249c6841bcf4997146afb6390b79b71d98 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Thu, 22 Jun 2017 19:14:26 -0700 Subject: [PATCH 012/162] Fix Redox build, broken in ecbb896b9eb2acadefde57be493e4298c1aa04a3 --- src/libstd/sys/redox/net/tcp.rs | 1 - src/libstd/sys/redox/pipe.rs | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/libstd/sys/redox/net/tcp.rs b/src/libstd/sys/redox/net/tcp.rs index ac3fd2ad6b9..17673f0bd60 100644 --- a/src/libstd/sys/redox/net/tcp.rs +++ b/src/libstd/sys/redox/net/tcp.rs @@ -17,7 +17,6 @@ use sys::fs::{File, OpenOptions}; use sys::syscall::TimeSpec; use sys_common::{AsInner, FromInner, IntoInner}; use time::Duration; -use vec::Vec; use super::{path_to_peer_addr, path_to_local_addr}; diff --git a/src/libstd/sys/redox/pipe.rs b/src/libstd/sys/redox/pipe.rs index 05863adf108..28645facd93 100644 --- a/src/libstd/sys/redox/pipe.rs +++ b/src/libstd/sys/redox/pipe.rs @@ -49,8 +49,8 @@ pub fn read2(p1: AnonPipe, //FIXME: Use event based I/O multiplexing //unimplemented!() - p1.read_to_end(v1)?; - p2.read_to_end(v2)?; + p1.0.read_to_end(v1)?; + p2.0.read_to_end(v2)?; Ok(()) From ebe71fdd53b47b2f1e684454e71e42062dbdf6a4 Mon Sep 17 00:00:00 2001 From: Andre Bogus Date: Fri, 23 Jun 2017 18:23:23 +0200 Subject: [PATCH 013/162] change binding name of for loop lowering to appease clippy With the latest change to for loop lowering, a `_next` binding was introduced. Unfortunately, this disturbs clippy's `used_underscore_binding` lint. This commit just renames the binding to `__next` so clippy will be happy. It should have no other effect. --- src/librustc/hir/lowering.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 62bedcdfcbe..873d39ec9e9 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -2170,12 +2170,12 @@ impl<'a> LoweringContext<'a> { // let result = match ::std::iter::IntoIterator::into_iter() { // mut iter => { // [opt_ident]: loop { - // let mut _next; + // let mut __next; // match ::std::iter::Iterator::next(&mut iter) { - // ::std::option::Option::Some(val) => _next = val, + // ::std::option::Option::Some(val) => __next = val, // ::std::option::Option::None => break // }; - // let = _next; + // let = __next; // StmtExpr(); // } // } @@ -2188,7 +2188,7 @@ impl<'a> LoweringContext<'a> { let iter = self.str_to_ident("iter"); - let next_ident = self.str_to_ident("_next"); + let next_ident = self.str_to_ident("__next"); let next_pat = self.pat_ident_binding_mode(e.span, next_ident, hir::BindByValue(hir::MutMutable)); @@ -2237,13 +2237,13 @@ impl<'a> LoweringContext<'a> { let next_expr = P(self.expr_ident(e.span, next_ident, next_pat.id)); - // `let mut _next` + // `let mut __next` let next_let = self.stmt_let_pat(e.span, None, next_pat, hir::LocalSource::ForLoopDesugar); - // `let = _next` + // `let = __next` let pat = self.lower_pat(pat); let pat_let = self.stmt_let_pat(e.span, Some(next_expr), From 8e11189cbb129b5df33e27d21c077da6cfc5926f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 23 Jun 2017 17:43:35 -0700 Subject: [PATCH 014/162] Move tests to `ui` --- .../block-must-not-have-result-do.rs | 0 .../block-must-not-have-result-do.stderr | 11 +++++ .../block-must-not-have-result-res.rs | 0 .../block-must-not-have-result-res.stderr | 11 +++++ .../block-must-not-have-result-while.rs | 0 .../block-must-not-have-result-while.stderr | 11 +++++ .../consider-removing-last-semi.rs | 0 .../consider-removing-last-semi.stderr | 38 +++++++++++++++++ .../expected-return-on-unit.stderr | 4 ++ .../block-result}/issue-11714.rs | 0 src/test/ui/block-result/issue-11714.stderr | 21 ++++++++++ .../block-result}/issue-13428.rs | 0 src/test/ui/block-result/issue-13428.stderr | 41 +++++++++++++++++++ .../block-result}/issue-13624.rs | 0 src/test/ui/block-result/issue-13624.stderr | 20 +++++++++ .../block-result}/issue-20862.rs | 0 src/test/ui/block-result/issue-20862.stderr | 17 ++++++++ .../block-result}/issue-22645.rs | 0 src/test/ui/block-result/issue-22645.stderr | 21 ++++++++++ .../block-result}/issue-3563.rs | 0 src/test/ui/block-result/issue-3563.stderr | 17 ++++++++ .../block-result}/issue-5500.rs | 0 src/test/ui/block-result/issue-5500.stderr | 11 +++++ .../block-result/unexpected-return-on-unit.rs | 24 +++++++++++ .../unexpected-return-on-unit.stderr | 11 +++++ .../for-loop-has-unit-body.rs | 0 .../for-loop-has-unit-body.stderr | 11 +++++ 27 files changed, 269 insertions(+) rename src/test/{compile-fail => ui/block-result}/block-must-not-have-result-do.rs (100%) create mode 100644 src/test/ui/block-result/block-must-not-have-result-do.stderr rename src/test/{compile-fail => ui/block-result}/block-must-not-have-result-res.rs (100%) create mode 100644 src/test/ui/block-result/block-must-not-have-result-res.stderr rename src/test/{compile-fail => ui/block-result}/block-must-not-have-result-while.rs (100%) create mode 100644 src/test/ui/block-result/block-must-not-have-result-while.stderr rename src/test/{compile-fail => ui/block-result}/consider-removing-last-semi.rs (100%) create mode 100644 src/test/ui/block-result/consider-removing-last-semi.stderr create mode 100644 src/test/ui/block-result/expected-return-on-unit.stderr rename src/test/{compile-fail => ui/block-result}/issue-11714.rs (100%) create mode 100644 src/test/ui/block-result/issue-11714.stderr rename src/test/{compile-fail => ui/block-result}/issue-13428.rs (100%) create mode 100644 src/test/ui/block-result/issue-13428.stderr rename src/test/{compile-fail => ui/block-result}/issue-13624.rs (100%) create mode 100644 src/test/ui/block-result/issue-13624.stderr rename src/test/{compile-fail => ui/block-result}/issue-20862.rs (100%) create mode 100644 src/test/ui/block-result/issue-20862.stderr rename src/test/{compile-fail => ui/block-result}/issue-22645.rs (100%) create mode 100644 src/test/ui/block-result/issue-22645.stderr rename src/test/{compile-fail => ui/block-result}/issue-3563.rs (100%) create mode 100644 src/test/ui/block-result/issue-3563.stderr rename src/test/{compile-fail => ui/block-result}/issue-5500.rs (100%) create mode 100644 src/test/ui/block-result/issue-5500.stderr create mode 100644 src/test/ui/block-result/unexpected-return-on-unit.rs create mode 100644 src/test/ui/block-result/unexpected-return-on-unit.stderr rename src/test/{compile-fail => ui/mismatched_types}/for-loop-has-unit-body.rs (100%) create mode 100644 src/test/ui/mismatched_types/for-loop-has-unit-body.stderr diff --git a/src/test/compile-fail/block-must-not-have-result-do.rs b/src/test/ui/block-result/block-must-not-have-result-do.rs similarity index 100% rename from src/test/compile-fail/block-must-not-have-result-do.rs rename to src/test/ui/block-result/block-must-not-have-result-do.rs diff --git a/src/test/ui/block-result/block-must-not-have-result-do.stderr b/src/test/ui/block-result/block-must-not-have-result-do.stderr new file mode 100644 index 00000000000..a770ebeab35 --- /dev/null +++ b/src/test/ui/block-result/block-must-not-have-result-do.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/block-must-not-have-result-do.rs:13:9 + | +13 | true //~ ERROR mismatched types + | ^^^^ expected (), found bool + | + = note: expected type `()` + found type `bool` + +error: aborting due to previous error(s) + diff --git a/src/test/compile-fail/block-must-not-have-result-res.rs b/src/test/ui/block-result/block-must-not-have-result-res.rs similarity index 100% rename from src/test/compile-fail/block-must-not-have-result-res.rs rename to src/test/ui/block-result/block-must-not-have-result-res.rs diff --git a/src/test/ui/block-result/block-must-not-have-result-res.stderr b/src/test/ui/block-result/block-must-not-have-result-res.stderr new file mode 100644 index 00000000000..b1146864566 --- /dev/null +++ b/src/test/ui/block-result/block-must-not-have-result-res.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/block-must-not-have-result-res.rs:15:9 + | +15 | true //~ ERROR mismatched types + | ^^^^ expected (), found bool + | + = note: expected type `()` + found type `bool` + +error: aborting due to previous error(s) + diff --git a/src/test/compile-fail/block-must-not-have-result-while.rs b/src/test/ui/block-result/block-must-not-have-result-while.rs similarity index 100% rename from src/test/compile-fail/block-must-not-have-result-while.rs rename to src/test/ui/block-result/block-must-not-have-result-while.rs diff --git a/src/test/ui/block-result/block-must-not-have-result-while.stderr b/src/test/ui/block-result/block-must-not-have-result-while.stderr new file mode 100644 index 00000000000..31ec7cdd3c5 --- /dev/null +++ b/src/test/ui/block-result/block-must-not-have-result-while.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/block-must-not-have-result-while.rs:13:9 + | +13 | true //~ ERROR mismatched types + | ^^^^ expected (), found bool + | + = note: expected type `()` + found type `bool` + +error: aborting due to previous error(s) + diff --git a/src/test/compile-fail/consider-removing-last-semi.rs b/src/test/ui/block-result/consider-removing-last-semi.rs similarity index 100% rename from src/test/compile-fail/consider-removing-last-semi.rs rename to src/test/ui/block-result/consider-removing-last-semi.rs diff --git a/src/test/ui/block-result/consider-removing-last-semi.stderr b/src/test/ui/block-result/consider-removing-last-semi.stderr new file mode 100644 index 00000000000..944c9d6c427 --- /dev/null +++ b/src/test/ui/block-result/consider-removing-last-semi.stderr @@ -0,0 +1,38 @@ +error[E0308]: mismatched types + --> $DIR/consider-removing-last-semi.rs:11:18 + | +11 | fn f() -> String { //~ ERROR mismatched types + | __________________^ +12 | | 0u8; +13 | | "bla".to_string(); //~ HELP consider removing this semicolon +14 | | } + | |_^ expected struct `std::string::String`, found () + | + = note: expected type `std::string::String` + found type `()` +help: consider removing this semicolon: + --> $DIR/consider-removing-last-semi.rs:13:22 + | +13 | "bla".to_string(); //~ HELP consider removing this semicolon + | ^ + +error[E0308]: mismatched types + --> $DIR/consider-removing-last-semi.rs:16:18 + | +16 | fn g() -> String { //~ ERROR mismatched types + | __________________^ +17 | | "this won't work".to_string(); +18 | | "removeme".to_string(); //~ HELP consider removing this semicolon +19 | | } + | |_^ expected struct `std::string::String`, found () + | + = note: expected type `std::string::String` + found type `()` +help: consider removing this semicolon: + --> $DIR/consider-removing-last-semi.rs:18:27 + | +18 | "removeme".to_string(); //~ HELP consider removing this semicolon + | ^ + +error: aborting due to previous error(s) + diff --git a/src/test/ui/block-result/expected-return-on-unit.stderr b/src/test/ui/block-result/expected-return-on-unit.stderr new file mode 100644 index 00000000000..8a0d7a335d6 --- /dev/null +++ b/src/test/ui/block-result/expected-return-on-unit.stderr @@ -0,0 +1,4 @@ +error[E0601]: main function not found + +error: aborting due to previous error(s) + diff --git a/src/test/compile-fail/issue-11714.rs b/src/test/ui/block-result/issue-11714.rs similarity index 100% rename from src/test/compile-fail/issue-11714.rs rename to src/test/ui/block-result/issue-11714.rs diff --git a/src/test/ui/block-result/issue-11714.stderr b/src/test/ui/block-result/issue-11714.stderr new file mode 100644 index 00000000000..cba9c3f51d7 --- /dev/null +++ b/src/test/ui/block-result/issue-11714.stderr @@ -0,0 +1,21 @@ +error[E0308]: mismatched types + --> $DIR/issue-11714.rs:11:18 + | +11 | fn blah() -> i32 { //~ ERROR mismatched types + | __________________^ +12 | | 1 +13 | | +14 | | ; //~ HELP consider removing this semicolon: +15 | | } + | |_^ expected i32, found () + | + = note: expected type `i32` + found type `()` +help: consider removing this semicolon: + --> $DIR/issue-11714.rs:14:5 + | +14 | ; //~ HELP consider removing this semicolon: + | ^ + +error: aborting due to previous error(s) + diff --git a/src/test/compile-fail/issue-13428.rs b/src/test/ui/block-result/issue-13428.rs similarity index 100% rename from src/test/compile-fail/issue-13428.rs rename to src/test/ui/block-result/issue-13428.rs diff --git a/src/test/ui/block-result/issue-13428.stderr b/src/test/ui/block-result/issue-13428.stderr new file mode 100644 index 00000000000..d0ed8935cd7 --- /dev/null +++ b/src/test/ui/block-result/issue-13428.stderr @@ -0,0 +1,41 @@ +error[E0308]: mismatched types + --> $DIR/issue-13428.rs:13:20 + | +13 | fn foo() -> String { //~ ERROR mismatched types + | ____________________^ +14 | | format!("Hello {}", +15 | | "world") +16 | | // Put the trailing semicolon on its own line to test that the +17 | | // note message gets the offending semicolon exactly +18 | | ; //~ HELP consider removing this semicolon +19 | | } + | |_^ expected struct `std::string::String`, found () + | + = note: expected type `std::string::String` + found type `()` +help: consider removing this semicolon: + --> $DIR/issue-13428.rs:18:5 + | +18 | ; //~ HELP consider removing this semicolon + | ^ + +error[E0308]: mismatched types + --> $DIR/issue-13428.rs:21:20 + | +21 | fn bar() -> String { //~ ERROR mismatched types + | ____________________^ +22 | | "foobar".to_string() +23 | | ; //~ HELP consider removing this semicolon +24 | | } + | |_^ expected struct `std::string::String`, found () + | + = note: expected type `std::string::String` + found type `()` +help: consider removing this semicolon: + --> $DIR/issue-13428.rs:23:5 + | +23 | ; //~ HELP consider removing this semicolon + | ^ + +error: aborting due to previous error(s) + diff --git a/src/test/compile-fail/issue-13624.rs b/src/test/ui/block-result/issue-13624.rs similarity index 100% rename from src/test/compile-fail/issue-13624.rs rename to src/test/ui/block-result/issue-13624.rs diff --git a/src/test/ui/block-result/issue-13624.stderr b/src/test/ui/block-result/issue-13624.stderr new file mode 100644 index 00000000000..72ff859d7e9 --- /dev/null +++ b/src/test/ui/block-result/issue-13624.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/issue-13624.rs:17:5 + | +17 | Enum::EnumStructVariant { x: 1, y: 2, z: 3 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found enum `a::Enum` + | + = note: expected type `()` + found type `a::Enum` + +error[E0308]: mismatched types + --> $DIR/issue-13624.rs:32:9 + | +32 | a::Enum::EnumStructVariant { x, y, z } => { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found enum `a::Enum` + | + = note: expected type `()` + found type `a::Enum` + +error: aborting due to previous error(s) + diff --git a/src/test/compile-fail/issue-20862.rs b/src/test/ui/block-result/issue-20862.rs similarity index 100% rename from src/test/compile-fail/issue-20862.rs rename to src/test/ui/block-result/issue-20862.rs diff --git a/src/test/ui/block-result/issue-20862.stderr b/src/test/ui/block-result/issue-20862.stderr new file mode 100644 index 00000000000..757fe1666c3 --- /dev/null +++ b/src/test/ui/block-result/issue-20862.stderr @@ -0,0 +1,17 @@ +error[E0308]: mismatched types + --> $DIR/issue-20862.rs:12:5 + | +12 | |y| x + y + | ^^^^^^^^^ expected (), found closure + | + = note: expected type `()` + found type `[closure@$DIR/issue-20862.rs:12:5: 12:14 x:_]` + +error[E0618]: expected function, found `()` + --> $DIR/issue-20862.rs:17:13 + | +17 | let x = foo(5)(2); + | ^^^^^^^^^ + +error: aborting due to previous error(s) + diff --git a/src/test/compile-fail/issue-22645.rs b/src/test/ui/block-result/issue-22645.rs similarity index 100% rename from src/test/compile-fail/issue-22645.rs rename to src/test/ui/block-result/issue-22645.rs diff --git a/src/test/ui/block-result/issue-22645.stderr b/src/test/ui/block-result/issue-22645.stderr new file mode 100644 index 00000000000..3921a301c92 --- /dev/null +++ b/src/test/ui/block-result/issue-22645.stderr @@ -0,0 +1,21 @@ +error[E0277]: the trait bound `{integer}: Scalar` is not satisfied + --> $DIR/issue-22645.rs:25:5 + | +25 | b + 3 //~ ERROR E0277 + | ^ the trait `Scalar` is not implemented for `{integer}` + | + = help: the following implementations were found: + + = note: required because of the requirements on the impl of `std::ops::Add<{integer}>` for `Bob` + +error[E0308]: mismatched types + --> $DIR/issue-22645.rs:25:3 + | +25 | b + 3 //~ ERROR E0277 + | ^^^^^ expected (), found struct `Bob` + | + = note: expected type `()` + found type `Bob` + +error: aborting due to previous error(s) + diff --git a/src/test/compile-fail/issue-3563.rs b/src/test/ui/block-result/issue-3563.rs similarity index 100% rename from src/test/compile-fail/issue-3563.rs rename to src/test/ui/block-result/issue-3563.rs diff --git a/src/test/ui/block-result/issue-3563.stderr b/src/test/ui/block-result/issue-3563.stderr new file mode 100644 index 00000000000..9b403bcd93d --- /dev/null +++ b/src/test/ui/block-result/issue-3563.stderr @@ -0,0 +1,17 @@ +error[E0599]: no method named `b` found for type `&Self` in the current scope + --> $DIR/issue-3563.rs:13:17 + | +13 | || self.b() + | ^ + +error[E0308]: mismatched types + --> $DIR/issue-3563.rs:13:9 + | +13 | || self.b() + | ^^^^^^^^^^^ expected (), found closure + | + = note: expected type `()` + found type `[closure@$DIR/issue-3563.rs:13:9: 13:20 self:_]` + +error: aborting due to previous error(s) + diff --git a/src/test/compile-fail/issue-5500.rs b/src/test/ui/block-result/issue-5500.rs similarity index 100% rename from src/test/compile-fail/issue-5500.rs rename to src/test/ui/block-result/issue-5500.rs diff --git a/src/test/ui/block-result/issue-5500.stderr b/src/test/ui/block-result/issue-5500.stderr new file mode 100644 index 00000000000..bffe2a82ca8 --- /dev/null +++ b/src/test/ui/block-result/issue-5500.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/issue-5500.rs:12:5 + | +12 | &panic!() + | ^^^^^^^^^ expected (), found reference + | + = note: expected type `()` + found type `&_` + +error: aborting due to previous error(s) + diff --git a/src/test/ui/block-result/unexpected-return-on-unit.rs b/src/test/ui/block-result/unexpected-return-on-unit.rs new file mode 100644 index 00000000000..291b7a16f14 --- /dev/null +++ b/src/test/ui/block-result/unexpected-return-on-unit.rs @@ -0,0 +1,24 @@ +// Copyright 2017 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. + +// Test that we do some basic error correcton in the tokeniser (and don't spew +// too many bogus errors). + +fn foo() -> usize { + 3 +} + +fn bar() { + foo() +} + +fn main() { + bar() +} diff --git a/src/test/ui/block-result/unexpected-return-on-unit.stderr b/src/test/ui/block-result/unexpected-return-on-unit.stderr new file mode 100644 index 00000000000..ad10312d064 --- /dev/null +++ b/src/test/ui/block-result/unexpected-return-on-unit.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/unexpected-return-on-unit.rs:19:5 + | +19 | foo() + | ^^^^^ expected (), found usize + | + = note: expected type `()` + found type `usize` + +error: aborting due to previous error(s) + diff --git a/src/test/compile-fail/for-loop-has-unit-body.rs b/src/test/ui/mismatched_types/for-loop-has-unit-body.rs similarity index 100% rename from src/test/compile-fail/for-loop-has-unit-body.rs rename to src/test/ui/mismatched_types/for-loop-has-unit-body.rs diff --git a/src/test/ui/mismatched_types/for-loop-has-unit-body.stderr b/src/test/ui/mismatched_types/for-loop-has-unit-body.stderr new file mode 100644 index 00000000000..6787fe91bf3 --- /dev/null +++ b/src/test/ui/mismatched_types/for-loop-has-unit-body.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/for-loop-has-unit-body.rs:13:9 + | +13 | x //~ ERROR mismatched types + | ^ expected (), found integral variable + | + = note: expected type `()` + found type `{integer}` + +error: aborting due to previous error(s) + From 426331b9e44a955b0e43da9b1542b7cf15fac31e Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Fri, 23 Jun 2017 18:29:30 -0700 Subject: [PATCH 015/162] remove unused parameters from LintStore.find_lint Long ago, in the before-time, the find_lint method was created with the unused_variables ("unused_variable" in the singular, as it was called at the time) attribute in anticipation of using the session and span in the handling of renamed lints (31b7d64fd), and indeed, the session and span came to be used in this method, while the unused_variables attribute remained (1ad1e2e29). In modern times, the session and span are again no longer used (ca81d3dd); it seems we can safely prune them from the method signature, for justice, and mercy. --- src/librustc/lint/context.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index a9e0ef51102..a550db34d6f 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -291,16 +291,13 @@ impl LintStore { self.by_name.insert(name.into(), Removed(reason.into())); } - #[allow(unused_variables)] - fn find_lint(&self, lint_name: &str, sess: &Session, span: Option) - -> Result - { + fn find_lint(&self, lint_name: &str) -> Result { match self.by_name.get(lint_name) { Some(&Id(lint_id)) => Ok(lint_id), Some(&Renamed(_, lint_id)) => { Ok(lint_id) }, - Some(&Removed(ref reason)) => { + Some(&Removed(_)) => { Err(FindLintError::Removed) }, None => Err(FindLintError::NotFound) @@ -313,7 +310,7 @@ impl LintStore { &lint_name[..], level); let lint_flag_val = Symbol::intern(&lint_name); - match self.find_lint(&lint_name[..], sess, None) { + match self.find_lint(&lint_name[..]) { Ok(lint_id) => self.levels.set(lint_id, (level, CommandLine(lint_flag_val))), Err(FindLintError::Removed) => { } Err(_) => { @@ -731,7 +728,7 @@ pub trait LintContext<'tcx>: Sized { continue; } Ok((lint_name, level, span)) => { - match self.lints().find_lint(&lint_name.as_str(), &self.sess(), Some(span)) { + match self.lints().find_lint(&lint_name.as_str()) { Ok(lint_id) => vec![(lint_id, level, span)], Err(FindLintError::NotFound) => { match self.lints().lint_groups.get(&*lint_name.as_str()) { @@ -1420,7 +1417,7 @@ impl Decodable for LintId { fn decode(d: &mut D) -> Result { let s = d.read_str()?; ty::tls::with(|tcx| { - match tcx.sess.lint_store.borrow().find_lint(&s, tcx.sess, None) { + match tcx.sess.lint_store.borrow().find_lint(&s) { Ok(id) => Ok(id), Err(_) => panic!("invalid lint-id `{}`", s), } From 890a76f479e32d7509b85aadd48301634508de39 Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Fri, 23 Jun 2017 19:22:06 -0700 Subject: [PATCH 016/162] only set "overruled by outer forbid" once for lint groups, by group name Previously, conflicting forbid/allow attributes for a lint group would result in a separate "allow(L) overruled by outer forbid(L)" error for every lint L in the group. This was needlessly and annoyingly verbose; we prefer to just have one error pointing out the conflicting attributes. Resolves #42873. --- src/librustc/lint/context.rs | 26 ++++++++++++++++--------- src/test/ui/lint/outer-forbid.rs | 22 +++++++++++++++++++++ src/test/ui/lint/outer-forbid.stderr | 29 ++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 9 deletions(-) create mode 100644 src/test/ui/lint/outer-forbid.rs create mode 100644 src/test/ui/lint/outer-forbid.stderr diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index a550db34d6f..466d163854f 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -721,7 +721,7 @@ pub trait LintContext<'tcx>: Sized { let mut pushed = 0; for result in gather_attrs(attrs) { - let v = match result { + let (is_group, lint_level_spans) = match result { Err(span) => { span_err!(self.sess(), span, E0452, "malformed lint attribute"); @@ -729,13 +729,14 @@ pub trait LintContext<'tcx>: Sized { } Ok((lint_name, level, span)) => { match self.lints().find_lint(&lint_name.as_str()) { - Ok(lint_id) => vec![(lint_id, level, span)], + Ok(lint_id) => (false, vec![(lint_id, level, span)]), Err(FindLintError::NotFound) => { match self.lints().lint_groups.get(&*lint_name.as_str()) { - Some(&(ref v, _)) => v.iter() + Some(&(ref v, _)) => (true, + v.iter() .map(|lint_id: &LintId| (*lint_id, level, span)) - .collect(), + .collect()), None => { // The lint or lint group doesn't exist. // This is an error, but it was handled @@ -751,14 +752,18 @@ pub trait LintContext<'tcx>: Sized { let lint_attr_name = result.expect("lint attribute should be well-formed").0; - for (lint_id, level, span) in v { + for (lint_id, level, span) in lint_level_spans { let (now, now_source) = self.lint_sess().get_source(lint_id); if now == Forbid && level != Forbid { - let lint_name = lint_id.to_string(); + let forbidden_lint_name = match now_source { + LintSource::Default => lint_id.to_string(), + LintSource::Node(name, _) => name.to_string(), + LintSource::CommandLine(name) => name.to_string(), + }; let mut diag_builder = struct_span_err!(self.sess(), span, E0453, "{}({}) overruled by outer forbid({})", - level.as_str(), lint_name, - lint_name); + level.as_str(), lint_attr_name, + forbidden_lint_name); diag_builder.span_label(span, "overruled by previous forbid"); match now_source { LintSource::Default => &mut diag_builder, @@ -769,7 +774,10 @@ pub trait LintContext<'tcx>: Sized { LintSource::CommandLine(_) => { diag_builder.note("`forbid` lint level was set on command line") } - }.emit() + }.emit(); + if is_group { // don't set a separate error for every lint in the group + break; + } } else if now != level { let cx = self.lint_sess_mut(); cx.stack.push((lint_id, (now, now_source))); diff --git a/src/test/ui/lint/outer-forbid.rs b/src/test/ui/lint/outer-forbid.rs new file mode 100644 index 00000000000..d71da58829a --- /dev/null +++ b/src/test/ui/lint/outer-forbid.rs @@ -0,0 +1,22 @@ +// Copyright 2017 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. + +// Forbidding a group (here, `unused`) overrules subsequent allowance of both +// the group, and an individual lint in the group (here, `unused_variables`); +// and, forbidding an individual lint (here, `non_snake_case`) overrules +// subsequent allowance of a lint group containing it (here, `bad_style`). See +// Issue #42873. + +#![forbid(unused, non_snake_case)] + +#[allow(unused, unused_variables, bad_style)] +fn main() { + println!("hello forbidden world") +} diff --git a/src/test/ui/lint/outer-forbid.stderr b/src/test/ui/lint/outer-forbid.stderr new file mode 100644 index 00000000000..831b3f65634 --- /dev/null +++ b/src/test/ui/lint/outer-forbid.stderr @@ -0,0 +1,29 @@ +error[E0453]: allow(unused) overruled by outer forbid(unused) + --> $DIR/outer-forbid.rs:19:9 + | +17 | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +18 | +19 | #[allow(unused, unused_variables, bad_style)] + | ^^^^^^ overruled by previous forbid + +error[E0453]: allow(unused_variables) overruled by outer forbid(unused) + --> $DIR/outer-forbid.rs:19:17 + | +17 | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +18 | +19 | #[allow(unused, unused_variables, bad_style)] + | ^^^^^^^^^^^^^^^^ overruled by previous forbid + +error[E0453]: allow(bad_style) overruled by outer forbid(non_snake_case) + --> $DIR/outer-forbid.rs:19:35 + | +17 | #![forbid(unused, non_snake_case)] + | -------------- `forbid` level set here +18 | +19 | #[allow(unused, unused_variables, bad_style)] + | ^^^^^^^^^ overruled by previous forbid + +error: aborting due to previous error(s) + From c023856b38c847731720fa8e26f3e1b9062bc946 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 24 Jun 2017 00:57:39 -0700 Subject: [PATCH 017/162] Detect missing `;` on methods with return type `()` - Point out the origin of a type requirement when it is the return type of a method - Point out possibly missing semicolon when the return type is () and the implicit return makes sense as a statement - Suggest changing the return type of methods with default return type - Don't suggest changing the return type on fn main() - Don't suggest changing the return type on impl fn --- src/librustc/hir/map/mod.rs | 44 ++++- src/librustc/traits/error_reporting.rs | 4 +- src/librustc/traits/mod.rs | 51 +++--- src/librustc/traits/structural_impls.rs | 44 ++--- src/librustc_typeck/check/coercion.rs | 18 ++ src/librustc_typeck/check/demand.rs | 17 +- src/librustc_typeck/check/mod.rs | 156 +++++++++++++++++- src/test/ui/block-result/issue-13624.stderr | 2 + src/test/ui/block-result/issue-20862.stderr | 5 + src/test/ui/block-result/issue-22645.stderr | 3 + src/test/ui/block-result/issue-3563.stderr | 5 + src/test/ui/block-result/issue-5500.stderr | 2 + .../unexpected-return-on-unit.stderr | 6 + src/test/ui/impl-trait/equality.stderr | 3 + src/test/ui/mismatched_types/abridged.stderr | 12 ++ .../ui/mismatched_types/issue-19109.stderr | 5 + .../ui/resolve/token-error-correct-3.stderr | 7 +- 17 files changed, 320 insertions(+), 64 deletions(-) diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index a1875cd46a0..ddcc2c08850 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -594,8 +594,12 @@ impl<'hir> Map<'hir> { /// last good node id we found. Note that reaching the crate root (id == 0), /// is not an error, since items in the crate module have the crate root as /// parent. - fn walk_parent_nodes(&self, start_id: NodeId, found: F) -> Result - where F: Fn(&Node<'hir>) -> bool + fn walk_parent_nodes(&self, + start_id: NodeId, + found: F, + bail_early: F2) + -> Result + where F: Fn(&Node<'hir>) -> bool, F2: Fn(&Node<'hir>) -> bool { let mut id = start_id; loop { @@ -616,6 +620,8 @@ impl<'hir> Map<'hir> { Some(ref node) => { if found(node) { return Ok(parent_node); + } else if bail_early(node) { + return Err(parent_node); } } None => { @@ -626,6 +632,34 @@ impl<'hir> Map<'hir> { } } + pub fn get_return_block(&self, id: NodeId) -> Option { + let match_fn = |node: &Node| { + match *node { + NodeItem(_) | + NodeForeignItem(_) | + NodeTraitItem(_) | + NodeImplItem(_) => true, + _ => false, + } + }; + let match_non_returning_block = |node: &Node| { + match *node { + NodeExpr(ref expr) => { + match expr.node { + ExprWhile(..) | ExprLoop(..) => true, + _ => false, + } + } + _ => false, + } + }; + + match self.walk_parent_nodes(id, match_fn, match_non_returning_block) { + Ok(id) => Some(id), + Err(_) => None, + } + } + /// Retrieve the NodeId for `id`'s parent item, or `id` itself if no /// parent item is in this map. The "parent item" is the closest parent node /// in the AST which is recorded by the map and is an item, either an item @@ -637,7 +671,7 @@ impl<'hir> Map<'hir> { NodeTraitItem(_) | NodeImplItem(_) => true, _ => false, - }) { + }, |_| false) { Ok(id) => id, Err(id) => id, } @@ -649,7 +683,7 @@ impl<'hir> Map<'hir> { let id = match self.walk_parent_nodes(id, |node| match *node { NodeItem(&Item { node: Item_::ItemMod(_), .. }) => true, _ => false, - }) { + }, |_| false) { Ok(id) => id, Err(id) => id, }; @@ -668,7 +702,7 @@ impl<'hir> Map<'hir> { NodeImplItem(_) | NodeBlock(_) => true, _ => false, - }) { + }, |_| false) { Ok(id) => Some(id), Err(_) => None, } diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 247fb079fe7..2f260b0b9ee 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -1088,7 +1088,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ObligationCauseCode::VariableType(_) => { err.note("all local variables must have a statically known size"); } - ObligationCauseCode::ReturnType => { + ObligationCauseCode::SizedReturnType => { err.note("the return type of a function must have a \ statically known size"); } @@ -1133,6 +1133,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { but not on the corresponding trait method", predicate)); } + ObligationCauseCode::ReturnType(_) | + ObligationCauseCode::BlockTailExpression(_) => (), } } diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index e9196cd1243..a98be90e3a0 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -118,27 +118,32 @@ pub enum ObligationCauseCode<'tcx> { /// Obligation incurred due to an object cast. ObjectCastObligation(/* Object type */ Ty<'tcx>), - /// Various cases where expressions must be sized/copy/etc: - AssignmentLhsSized, // L = X implies that L is Sized - StructInitializerSized, // S { ... } must be Sized - VariableType(ast::NodeId), // Type of each variable must be Sized - ReturnType, // Return type must be Sized - RepeatVec, // [T,..n] --> T must be Copy + // Various cases where expressions must be sized/copy/etc: + /// L = X implies that L is Sized + AssignmentLhsSized, + /// S { ... } must be Sized + StructInitializerSized, + /// Type of each variable must be Sized + VariableType(ast::NodeId), + /// Return type must be Sized + SizedReturnType, + /// [T,..n] --> T must be Copy + RepeatVec, - // Types of fields (other than the last) in a struct must be sized. + /// Types of fields (other than the last) in a struct must be sized. FieldSized, - // Constant expressions must be sized. + /// Constant expressions must be sized. ConstSized, - // static items must have `Sync` type + /// static items must have `Sync` type SharedStatic, BuiltinDerivedObligation(DerivedObligationCause<'tcx>), ImplDerivedObligation(DerivedObligationCause<'tcx>), - // error derived when matching traits/impls; see ObligationCause for more details + /// error derived when matching traits/impls; see ObligationCause for more details CompareImplMethodObligation { item_name: ast::Name, impl_item_def_id: DefId, @@ -146,37 +151,43 @@ pub enum ObligationCauseCode<'tcx> { lint_id: Option, }, - // Checking that this expression can be assigned where it needs to be + /// Checking that this expression can be assigned where it needs to be // FIXME(eddyb) #11161 is the original Expr required? ExprAssignable, - // Computing common supertype in the arms of a match expression + /// Computing common supertype in the arms of a match expression MatchExpressionArm { arm_span: Span, source: hir::MatchSource }, - // Computing common supertype in an if expression + /// Computing common supertype in an if expression IfExpression, - // Computing common supertype of an if expression with no else counter-part + /// Computing common supertype of an if expression with no else counter-part IfExpressionWithNoElse, - // `where a == b` + /// `where a == b` EquatePredicate, - // `main` has wrong type + /// `main` has wrong type MainFunctionType, - // `start` has wrong type + /// `start` has wrong type StartFunctionType, - // intrinsic has wrong type + /// intrinsic has wrong type IntrinsicType, - // method receiver + /// method receiver MethodReceiver, - // `return` with no expression + /// `return` with no expression ReturnNoExpression, + + /// `return` with an expression + ReturnType(ast::NodeId), + + /// Block implicit return + BlockTailExpression(ast::NodeId), } #[derive(Clone, Debug, PartialEq, Eq)] diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index 4abb0cb549d..0d6df78c2ac 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -191,7 +191,8 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> { super::AssignmentLhsSized => Some(super::AssignmentLhsSized), super::StructInitializerSized => Some(super::StructInitializerSized), super::VariableType(id) => Some(super::VariableType(id)), - super::ReturnType => Some(super::ReturnType), + super::ReturnType(id) => Some(super::ReturnType(id)), + super::SizedReturnType => Some(super::SizedReturnType), super::RepeatVec => Some(super::RepeatVec), super::FieldSized => Some(super::FieldSized), super::ConstSized => Some(super::ConstSized), @@ -213,34 +214,19 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> { lint_id: lint_id, }) } - super::ExprAssignable => { - Some(super::ExprAssignable) - } + super::ExprAssignable => Some(super::ExprAssignable), super::MatchExpressionArm { arm_span, source } => { Some(super::MatchExpressionArm { arm_span: arm_span, source: source }) } - super::IfExpression => { - Some(super::IfExpression) - } - super::IfExpressionWithNoElse => { - Some(super::IfExpressionWithNoElse) - } - super::EquatePredicate => { - Some(super::EquatePredicate) - } - super::MainFunctionType => { - Some(super::MainFunctionType) - } - super::StartFunctionType => { - Some(super::StartFunctionType) - } - super::IntrinsicType => { - Some(super::IntrinsicType) - } - super::MethodReceiver => { - Some(super::MethodReceiver) - } + super::IfExpression => Some(super::IfExpression), + super::IfExpressionWithNoElse => Some(super::IfExpressionWithNoElse), + super::EquatePredicate => Some(super::EquatePredicate), + super::MainFunctionType => Some(super::MainFunctionType), + super::StartFunctionType => Some(super::StartFunctionType), + super::IntrinsicType => Some(super::IntrinsicType), + super::MethodReceiver => Some(super::MethodReceiver), + super::BlockTailExpression(id) => Some(super::BlockTailExpression(id)), } } } @@ -492,12 +478,14 @@ impl<'tcx> TypeFoldable<'tcx> for traits::ObligationCauseCode<'tcx> { super::AssignmentLhsSized | super::StructInitializerSized | super::VariableType(_) | - super::ReturnType | + super::ReturnType(_) | + super::SizedReturnType | super::ReturnNoExpression | super::RepeatVec | super::FieldSized | super::ConstSized | super::SharedStatic | + super::BlockTailExpression(_) | super::CompareImplMethodObligation { .. } => self.clone(), super::ProjectionWf(proj) => super::ProjectionWf(proj.fold_with(folder)), @@ -537,12 +525,14 @@ impl<'tcx> TypeFoldable<'tcx> for traits::ObligationCauseCode<'tcx> { super::AssignmentLhsSized | super::StructInitializerSized | super::VariableType(_) | - super::ReturnType | + super::ReturnType(_) | + super::SizedReturnType | super::ReturnNoExpression | super::RepeatVec | super::FieldSized | super::ConstSized | super::SharedStatic | + super::BlockTailExpression(_) | super::CompareImplMethodObligation { .. } => false, super::ProjectionWf(proj) => proj.visit_with(visitor), diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index 30ac7b4bfb9..660f6c5a093 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -1162,6 +1162,24 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E> "`return;` in a function whose return type is not `()`"); db.span_label(cause.span, "return type is not ()"); } + ObligationCauseCode::BlockTailExpression(blk_id) => { + db = fcx.report_mismatched_types(cause, expected, found, err); + + let expr = expression.unwrap_or_else(|| { + span_bug!(cause.span, + "supposed to be part of a block tail expression, but the \ + expression is empty"); + }); + fcx.suggest_mismatched_types_on_tail(&mut db, expr, + expected, found, + cause.span, blk_id); + } + ObligationCauseCode::ReturnType(ret_id) => { + db = fcx.report_mismatched_types(cause, expected, found, err); + if let Some((fn_decl, _)) = fcx.get_fn_decl(ret_id) { + fcx.point_to_type_requirement(&mut db, &fn_decl, expected); + } + } _ => { db = fcx.report_mismatched_types(cause, expected, found, err); } diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 1b6f96cf651..1edb141c2af 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -73,15 +73,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } + pub fn demand_coerce(&self, expr: &hir::Expr, checked_ty: Ty<'tcx>, expected: Ty<'tcx>) { + if let Some(mut err) = self.demand_coerce_diag(expr, checked_ty, expected) { + err.emit(); + } + } + // Checks that the type of `expr` can be coerced to `expected`. // // NB: This code relies on `self.diverges` to be accurate. In // particular, assignments to `!` will be permitted if the // diverges flag is currently "always". - pub fn demand_coerce(&self, - expr: &hir::Expr, - checked_ty: Ty<'tcx>, - expected: Ty<'tcx>) { + pub fn demand_coerce_diag(&self, + expr: &hir::Expr, + checked_ty: Ty<'tcx>, + expected: Ty<'tcx>) -> Option> { let expected = self.resolve_type_vars_with_obligations(expected); if let Err(e) = self.try_coerce(expr, checked_ty, self.diverges.get(), expected) { @@ -105,8 +111,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.get_best_match(&suggestions).join("\n"))); } } - err.emit(); + return Some(err); } + None } fn format_method_suggestion(&self, method: &AssociatedItem) -> String { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 2bf24d5b350..684e5a66fc5 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -124,6 +124,7 @@ use syntax_pos::{self, BytePos, Span}; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::hir::itemlikevisit::ItemLikeVisitor; +use rustc::hir::map::Node; use rustc::hir::{self, PatKind}; use rustc::middle::lang_items; use rustc_back::slice; @@ -985,7 +986,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, *fcx.ps.borrow_mut() = UnsafetyState::function(fn_sig.unsafety, fn_id); let ret_ty = fn_sig.output(); - fcx.require_type_is_sized(ret_ty, decl.output.span(), traits::ReturnType); + fcx.require_type_is_sized(ret_ty, decl.output.span(), traits::SizedReturnType); let ret_ty = fcx.instantiate_anon_types(&ret_ty); fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(ret_ty))); fn_sig = fcx.tcx.mk_fn_sig( @@ -1908,7 +1909,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Require that the predicate holds for the concrete type. let cause = traits::ObligationCause::new(span, self.body_id, - traits::ReturnType); + traits::SizedReturnType); self.register_predicate(traits::Obligation::new(cause, self.param_env, predicate)); @@ -2848,10 +2849,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { "check_return_expr called outside fn body")); let ret_ty = ret_coercion.borrow().expected_ty(); - let return_expr_ty = self.check_expr_with_hint(return_expr, ret_ty); + let return_expr_ty = self.check_expr_with_hint(return_expr, ret_ty.clone()); ret_coercion.borrow_mut() .coerce(self, - &self.misc(return_expr.span), + &self.cause(return_expr.span, + ObligationCauseCode::ReturnType(return_expr.id)), return_expr, return_expr_ty, self.diverges.get()); @@ -4170,8 +4172,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let mut coerce = ctxt.coerce.as_mut().unwrap(); if let Some(tail_expr_ty) = tail_expr_ty { let tail_expr = tail_expr.unwrap(); + let cause = self.cause(tail_expr.span, + ObligationCauseCode::BlockTailExpression(blk.id)); coerce.coerce(self, - &self.misc(tail_expr.span), + &cause, tail_expr, tail_expr_ty, self.diverges.get()); @@ -4210,6 +4214,148 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ty } + /// Given a `NodeId`, return the `FnDecl` of the method it is enclosed by and wether it is + /// `fn main` if it is a method, `None` otherwise. + pub fn get_fn_decl(&self, blk_id: ast::NodeId) -> Option<(hir::FnDecl, bool)> { + // Get enclosing Fn, if it is a function or a trait method, unless there's a `loop` or + // `while` before reaching it, as block tail returns are not available in them. + if let Some(fn_id) = self.tcx.hir.get_return_block(blk_id) { + let parent = self.tcx.hir.get(fn_id); + + if let Node::NodeItem(&hir::Item { + name, node: hir::ItemFn(ref decl, ..), .. + }) = parent { + decl.clone().and_then(|decl| { + // This is less than ideal, it will not present the return type span on any + // method called `main`, regardless of wether it is actually the entry point. + Some((decl, name == Symbol::intern("main"))) + }) + } else if let Node::NodeTraitItem(&hir::TraitItem { + node: hir::TraitItemKind::Method(hir::MethodSig { + ref decl, .. + }, ..), .. + }) = parent { + decl.clone().and_then(|decl| { + Some((decl, false)) + }) + } else { + None + } + } else { + None + } + } + + /// On implicit return expressions with mismatched types, provide the following suggestions: + /// + /// - Point out the method's return type as the reason for the expected type + /// - Possible missing semicolon + /// - Possible missing return type if the return type is the default, and not `fn main()` + pub fn suggest_mismatched_types_on_tail(&self, + err: &mut DiagnosticBuilder<'tcx>, + expression: &'gcx hir::Expr, + expected: Ty<'tcx>, + found: Ty<'tcx>, + cause_span: Span, + blk_id: ast::NodeId) { + self.suggest_missing_semicolon(err, expression, expected, cause_span); + + if let Some((fn_decl, is_main)) = self.get_fn_decl(blk_id) { + self.point_to_type_requirement(err, &fn_decl, expected); + // `fn main()` must return `()`, do not suggest changing return type + if !is_main { + self.suggest_missing_return_type(err, &fn_decl, found); + } + } + } + + pub fn point_to_type_requirement(&self, + err: &mut DiagnosticBuilder<'tcx>, + fn_decl: &hir::FnDecl, + ty: Ty<'tcx>) { + let msg = if let &hir::FnDecl { + output: hir::FunctionRetTy::DefaultReturn(_), .. + } = fn_decl { + "default " + } else { + "" + }; + let ty = self.resolve_type_vars_if_possible(&ty); + if ty.to_string().len() < 10 { + err.span_label(fn_decl.output.span(), + format!("expected `{}` because of this {}return type", ty, msg)); + } else { + err.span_label(fn_decl.output.span(), + format!("expected because of this {}return type", msg)); + } + } + + /// A common error is to forget to add a semicolon at the end of a block: + /// + /// ``` + /// fn foo() { + /// bar_that_returns_u32() + /// } + /// ``` + /// + /// This routine checks if the return expression in a block would make sense on its own as a + /// statement and the return type has been left as defaultor has been specified as `()`. If so, + /// it suggests adding a semicolon. + fn suggest_missing_semicolon(&self, + err: &mut DiagnosticBuilder<'tcx>, + expression: &'gcx hir::Expr, + expected: Ty<'tcx>, + cause_span: Span) { + if expected.is_nil() { + // `BlockTailExpression` only relevant if the tail expr would be + // useful on its own. + match expression.node { + hir::ExprCall(..) | + hir::ExprMethodCall(..) | + hir::ExprIf(..) | + hir::ExprWhile(..) | + hir::ExprLoop(..) | + hir::ExprMatch(..) | + hir::ExprBlock(..) => { + let sp = cause_span.next_point(); + err.span_suggestion(sp, + "did you mean to add a semicolon here?", + ";".to_string()); + } + _ => (), + } + } + } + + + /// A possible error is to forget to add a return type that is needed: + /// + /// ``` + /// fn foo() { + /// bar_that_returns_u32() + /// } + /// ``` + /// + /// This routine checks if the return type is left as default, the method is not part of an + /// `impl` block and that it isn't the `main` method. If so, it suggests setting the return + /// type. + fn suggest_missing_return_type(&self, + err: &mut DiagnosticBuilder<'tcx>, + fn_decl: &hir::FnDecl, + ty: Ty<'tcx>) { + + // Only recommend changing the return type for methods that + // haven't set a return type at all (and aren't `fn main()` or an impl). + if let &hir::FnDecl { + output: hir::FunctionRetTy::DefaultReturn(span), .. + } = fn_decl { + err.span_suggestion(span, + "possibly return type missing here?", + format!("-> {} ", ty)); + } + } + + /// A common error is to add an extra semicolon: /// /// ``` diff --git a/src/test/ui/block-result/issue-13624.stderr b/src/test/ui/block-result/issue-13624.stderr index 72ff859d7e9..69c6e647cfc 100644 --- a/src/test/ui/block-result/issue-13624.stderr +++ b/src/test/ui/block-result/issue-13624.stderr @@ -1,6 +1,8 @@ error[E0308]: mismatched types --> $DIR/issue-13624.rs:17:5 | +16 | pub fn get_enum_struct_variant() -> () { + | -- expected `()` because of this return type 17 | Enum::EnumStructVariant { x: 1, y: 2, z: 3 } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found enum `a::Enum` | diff --git a/src/test/ui/block-result/issue-20862.stderr b/src/test/ui/block-result/issue-20862.stderr index 757fe1666c3..0d88a44d6b9 100644 --- a/src/test/ui/block-result/issue-20862.stderr +++ b/src/test/ui/block-result/issue-20862.stderr @@ -1,6 +1,11 @@ error[E0308]: mismatched types --> $DIR/issue-20862.rs:12:5 | +11 | fn foo(x: i32) { + | - + | | + | help: possibly return type missing here? `-> [closure@$DIR/issue-20862.rs:12:5: 12:14 x:_] ` + | expected `()` because of this default return type 12 | |y| x + y | ^^^^^^^^^ expected (), found closure | diff --git a/src/test/ui/block-result/issue-22645.stderr b/src/test/ui/block-result/issue-22645.stderr index 3921a301c92..93da3c6a489 100644 --- a/src/test/ui/block-result/issue-22645.stderr +++ b/src/test/ui/block-result/issue-22645.stderr @@ -11,6 +11,9 @@ error[E0277]: the trait bound `{integer}: Scalar` is not satisfied error[E0308]: mismatched types --> $DIR/issue-22645.rs:25:3 | +23 | fn main() { + | - expected `()` because of this default return type +24 | let b = Bob + 3.5; 25 | b + 3 //~ ERROR E0277 | ^^^^^ expected (), found struct `Bob` | diff --git a/src/test/ui/block-result/issue-3563.stderr b/src/test/ui/block-result/issue-3563.stderr index 9b403bcd93d..e9ace85c1d9 100644 --- a/src/test/ui/block-result/issue-3563.stderr +++ b/src/test/ui/block-result/issue-3563.stderr @@ -7,6 +7,11 @@ error[E0599]: no method named `b` found for type `&Self` in the current scope error[E0308]: mismatched types --> $DIR/issue-3563.rs:13:9 | +12 | fn a(&self) { + | - + | | + | help: possibly return type missing here? `-> [closure@$DIR/issue-3563.rs:13:9: 13:20 self:_] ` + | expected `()` because of this default return type 13 | || self.b() | ^^^^^^^^^^^ expected (), found closure | diff --git a/src/test/ui/block-result/issue-5500.stderr b/src/test/ui/block-result/issue-5500.stderr index bffe2a82ca8..6fda2aa00ff 100644 --- a/src/test/ui/block-result/issue-5500.stderr +++ b/src/test/ui/block-result/issue-5500.stderr @@ -1,6 +1,8 @@ error[E0308]: mismatched types --> $DIR/issue-5500.rs:12:5 | +11 | fn main() { + | - expected `()` because of this default return type 12 | &panic!() | ^^^^^^^^^ expected (), found reference | diff --git a/src/test/ui/block-result/unexpected-return-on-unit.stderr b/src/test/ui/block-result/unexpected-return-on-unit.stderr index ad10312d064..e5481ffd316 100644 --- a/src/test/ui/block-result/unexpected-return-on-unit.stderr +++ b/src/test/ui/block-result/unexpected-return-on-unit.stderr @@ -1,11 +1,17 @@ error[E0308]: mismatched types --> $DIR/unexpected-return-on-unit.rs:19:5 | +18 | fn bar() { + | - expected `()` because of this default return type 19 | foo() | ^^^^^ expected (), found usize | = note: expected type `()` found type `usize` +help: did you mean to add a semicolon here? + | foo(); +help: possibly return type missing here? + | fn bar() -> usize { error: aborting due to previous error(s) diff --git a/src/test/ui/impl-trait/equality.stderr b/src/test/ui/impl-trait/equality.stderr index 2206234b777..ca37596f1b9 100644 --- a/src/test/ui/impl-trait/equality.stderr +++ b/src/test/ui/impl-trait/equality.stderr @@ -1,6 +1,9 @@ error[E0308]: mismatched types --> $DIR/equality.rs:25:5 | +21 | fn two(x: bool) -> impl Foo { + | -------- expected `i32` because of this return type +... 25 | 0_u32 | ^^^^^ expected i32, found u32 | diff --git a/src/test/ui/mismatched_types/abridged.stderr b/src/test/ui/mismatched_types/abridged.stderr index 78b5dcda1d9..6282541ba0e 100644 --- a/src/test/ui/mismatched_types/abridged.stderr +++ b/src/test/ui/mismatched_types/abridged.stderr @@ -1,6 +1,8 @@ error[E0308]: mismatched types --> $DIR/abridged.rs:26:5 | +25 | fn a() -> Foo { + | --- expected `Foo` because of this return type 26 | Some(Foo { bar: 1 }) | ^^^^^^^^^^^^^^^^^^^^ expected struct `Foo`, found enum `std::option::Option` | @@ -10,6 +12,8 @@ error[E0308]: mismatched types error[E0308]: mismatched types --> $DIR/abridged.rs:30:5 | +29 | fn a2() -> Foo { + | --- expected `Foo` because of this return type 30 | Ok(Foo { bar: 1}) | ^^^^^^^^^^^^^^^^^ expected struct `Foo`, found enum `std::result::Result` | @@ -19,6 +23,8 @@ error[E0308]: mismatched types error[E0308]: mismatched types --> $DIR/abridged.rs:34:5 | +33 | fn b() -> Option { + | ----------- expected because of this return type 34 | Foo { bar: 1 } | ^^^^^^^^^^^^^^ expected enum `std::option::Option`, found struct `Foo` | @@ -28,6 +34,8 @@ error[E0308]: mismatched types error[E0308]: mismatched types --> $DIR/abridged.rs:38:5 | +37 | fn c() -> Result { + | ---------------- expected because of this return type 38 | Foo { bar: 1 } | ^^^^^^^^^^^^^^ expected enum `std::result::Result`, found struct `Foo` | @@ -37,6 +45,8 @@ error[E0308]: mismatched types error[E0308]: mismatched types --> $DIR/abridged.rs:42:5 | +41 | fn d() -> X, String> { + | ---------------------------- expected because of this return type 42 | / X { 43 | | x: X { 44 | | x: "".to_string(), @@ -52,6 +62,8 @@ error[E0308]: mismatched types error[E0308]: mismatched types --> $DIR/abridged.rs:52:5 | +51 | fn e() -> X, String> { + | ---------------------------- expected because of this return type 52 | / X { 53 | | x: X { 54 | | x: "".to_string(), diff --git a/src/test/ui/mismatched_types/issue-19109.stderr b/src/test/ui/mismatched_types/issue-19109.stderr index cbce4f810c5..5efa3fa6a1d 100644 --- a/src/test/ui/mismatched_types/issue-19109.stderr +++ b/src/test/ui/mismatched_types/issue-19109.stderr @@ -1,6 +1,11 @@ error[E0308]: mismatched types --> $DIR/issue-19109.rs:14:5 | +13 | fn function(t: &mut Trait) { + | - + | | + | help: possibly return type missing here? `-> *mut Trait ` + | expected `()` because of this default return type 14 | t as *mut Trait | ^^^^^^^^^^^^^^^ expected (), found *-ptr | diff --git a/src/test/ui/resolve/token-error-correct-3.stderr b/src/test/ui/resolve/token-error-correct-3.stderr index d234c8538fe..2a50428dbb9 100644 --- a/src/test/ui/resolve/token-error-correct-3.stderr +++ b/src/test/ui/resolve/token-error-correct-3.stderr @@ -34,8 +34,13 @@ error[E0425]: cannot find function `is_directory` in this scope error[E0308]: mismatched types --> $DIR/token-error-correct-3.rs:25:13 | +20 | -> io::Result { + | ---------------- expected `()` because of this return type +... 25 | fs::create_dir_all(path.as_ref()).map(|()| true) //~ ERROR: mismatched types - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found enum `std::result::Result` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- help: did you mean to add a semicolon here? `;` + | | + | expected (), found enum `std::result::Result` | = note: expected type `()` found type `std::result::Result` From 60dd83ea85853f6a31f8998eb80ce47446fdb785 Mon Sep 17 00:00:00 2001 From: Paul Woolcock Date: Wed, 24 May 2017 13:58:37 -0400 Subject: [PATCH 018/162] add `allow_fail` test attribute This change allows the user to add an `#[allow_fail]` attribute to tests that will cause the test to compile & run, but if the test fails it will not cause the entire test run to fail. The test output will show the failure, but in yellow instead of red, and also indicate that it was an allowed failure. --- src/librustdoc/html/markdown.rs | 41 +++++++++++++---------- src/librustdoc/test.rs | 3 +- src/libsyntax/feature_gate.rs | 1 + src/libsyntax/test.rs | 14 ++++++-- src/libtest/lib.rs | 23 +++++++++++-- src/test/run-pass/test-allow-fail-attr.rs | 23 +++++++++++++ src/tools/compiletest/src/main.rs | 1 + 7 files changed, 81 insertions(+), 25 deletions(-) create mode 100644 src/test/run-pass/test-allow-fail-attr.rs diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index bea13397eca..5a56c33b806 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -769,7 +769,7 @@ pub fn old_find_testable_code(doc: &str, tests: &mut ::test::Collector, position block_info.should_panic, block_info.no_run, block_info.ignore, block_info.test_harness, block_info.compile_fail, block_info.error_codes, - line, filename); + line, filename, block_info.allow_fail); } else { tests.add_old_test(text, filename); } @@ -859,7 +859,7 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Sp block_info.should_panic, block_info.no_run, block_info.ignore, block_info.test_harness, block_info.compile_fail, block_info.error_codes, - line, filename); + line, filename, block_info.allow_fail); prev_offset = offset; } Event::Start(Tag::Header(level)) => { @@ -889,6 +889,7 @@ struct LangString { test_harness: bool, compile_fail: bool, error_codes: Vec, + allow_fail: bool, } impl LangString { @@ -902,6 +903,7 @@ impl LangString { test_harness: false, compile_fail: false, error_codes: Vec::new(), + allow_fail: false, } } @@ -930,6 +932,7 @@ impl LangString { } "no_run" => { data.no_run = true; seen_rust_tags = !seen_other_tags; } "ignore" => { data.ignore = true; seen_rust_tags = !seen_other_tags; } + "allow_fail" => { data.allow_fail = true; seen_rust_tags = !seen_other_tags; } "rust" => { data.rust = true; seen_rust_tags = true; } "test_harness" => { data.test_harness = true; @@ -1118,7 +1121,7 @@ mod tests { fn test_lang_string_parse() { fn t(s: &str, should_panic: bool, no_run: bool, ignore: bool, rust: bool, test_harness: bool, - compile_fail: bool, error_codes: Vec) { + compile_fail: bool, allow_fail: bool, error_codes: Vec) { assert_eq!(LangString::parse(s), LangString { should_panic: should_panic, no_run: no_run, @@ -1128,25 +1131,27 @@ mod tests { compile_fail: compile_fail, error_codes: error_codes, original: s.to_owned(), + allow_fail: allow_fail, }) } // marker | should_panic| no_run| ignore| rust | test_harness| compile_fail - // | error_codes - t("", false, false, false, true, false, false, Vec::new()); - t("rust", false, false, false, true, false, false, Vec::new()); - t("sh", false, false, false, false, false, false, Vec::new()); - t("ignore", false, false, true, true, false, false, Vec::new()); - t("should_panic", true, false, false, true, false, false, Vec::new()); - t("no_run", false, true, false, true, false, false, Vec::new()); - t("test_harness", false, false, false, true, true, false, Vec::new()); - t("compile_fail", false, true, false, true, false, true, Vec::new()); - t("{.no_run .example}", false, true, false, true, false, false, Vec::new()); - t("{.sh .should_panic}", true, false, false, false, false, false, Vec::new()); - t("{.example .rust}", false, false, false, true, false, false, Vec::new()); - t("{.test_harness .rust}", false, false, false, true, true, false, Vec::new()); - t("text, no_run", false, true, false, false, false, false, Vec::new()); - t("text,no_run", false, true, false, false, false, false, Vec::new()); + // | allow_fail | error_codes + t("", false, false, false, true, false, false, false, Vec::new()); + t("rust", false, false, false, true, false, false, false, Vec::new()); + t("sh", false, false, false, false, false, false, false, Vec::new()); + t("ignore", false, false, true, true, false, false, false, Vec::new()); + t("should_panic", true, false, false, true, false, false, false, Vec::new()); + t("no_run", false, true, false, true, false, false, false, Vec::new()); + t("test_harness", false, false, false, true, true, false, false, Vec::new()); + t("compile_fail", false, true, false, true, false, true, false, Vec::new()); + t("allow_fail", false, false, false, true, false, false, true, Vec::new()); + t("{.no_run .example}", false, true, false, true, false, false, false, Vec::new()); + t("{.sh .should_panic}", true, false, false, false, false, false, false, Vec::new()); + t("{.example .rust}", false, false, false, true, false, false, false, Vec::new()); + t("{.test_harness .rust}", false, false, false, true, true, false, false, Vec::new()); + t("text, no_run", false, true, false, false, false, false, false, Vec::new()); + t("text,no_run", false, true, false, false, false, false, false, Vec::new()); } #[test] diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index cfe2fad0fa4..4766778eed1 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -467,7 +467,7 @@ impl Collector { pub fn add_test(&mut self, test: String, should_panic: bool, no_run: bool, should_ignore: bool, as_test_harness: bool, compile_fail: bool, error_codes: Vec, - line: usize, filename: String) { + line: usize, filename: String, allow_fail: bool) { let name = self.generate_name(line, &filename); // to be removed when hoedown is removed if self.render_type == RenderType::Pulldown { @@ -499,6 +499,7 @@ impl Collector { ignore: should_ignore, // compiler failures are test failures should_panic: testing::ShouldPanic::No, + allow_fail: allow_fail, }, testfn: testing::DynTestFn(box move |()| { let panic = io::set_panic(None); diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index d7d3a70f3c7..07db5b83331 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -534,6 +534,7 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG ("derive", Normal, Ungated), ("should_panic", Normal, Ungated), ("ignore", Normal, Ungated), + ("allow_fail", Normal, Ungated), ("no_implicit_prelude", Normal, Ungated), ("reexport_test_harness_main", Normal, Ungated), ("link_args", Normal, Ungated), diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index a0d1785c6ff..86f5f42eac7 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -52,7 +52,8 @@ struct Test { path: Vec , bench: bool, ignore: bool, - should_panic: ShouldPanic + should_panic: ShouldPanic, + allow_fail: bool, } struct TestCtxt<'a> { @@ -133,7 +134,8 @@ impl<'a> fold::Folder for TestHarnessGenerator<'a> { path: self.cx.path.clone(), bench: is_bench_fn(&self.cx, &i), ignore: is_ignored(&i), - should_panic: should_panic(&i, &self.cx) + should_panic: should_panic(&i, &self.cx), + allow_fail: is_allowed_fail(&i), }; self.cx.testfns.push(test); self.tests.push(i.ident); @@ -383,6 +385,10 @@ fn is_ignored(i: &ast::Item) -> bool { i.attrs.iter().any(|attr| attr.check_name("ignore")) } +fn is_allowed_fail(i: &ast::Item) -> bool { + i.attrs.iter().any(|attr| attr.check_name("allow_fail")) +} + fn should_panic(i: &ast::Item, cx: &TestCtxt) -> ShouldPanic { match i.attrs.iter().find(|attr| attr.check_name("should_panic")) { Some(attr) => { @@ -668,6 +674,7 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> P { } } }; + let allow_fail_expr = ecx.expr_bool(span, test.allow_fail); // self::test::TestDesc { ... } let desc_expr = ecx.expr_struct( @@ -675,7 +682,8 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> P { test_path("TestDesc"), vec![field("name", name_expr), field("ignore", ignore_expr), - field("should_panic", fail_expr)]); + field("should_panic", fail_expr), + field("allow_fail", allow_fail_expr)]); let mut visible_path = match cx.toplevel_reexport { diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 2094fd8898d..c68039f21ec 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -212,6 +212,7 @@ pub struct TestDesc { pub name: TestName, pub ignore: bool, pub should_panic: ShouldPanic, + pub allow_fail: bool, } #[derive(Clone)] @@ -523,6 +524,7 @@ pub enum TestResult { TrFailed, TrFailedMsg(String), TrIgnored, + TrAllowedFail, TrMetrics(MetricMap), TrBench(BenchSamples), } @@ -543,6 +545,7 @@ struct ConsoleTestState { passed: usize, failed: usize, ignored: usize, + allowed_fail: usize, filtered_out: usize, measured: usize, metrics: MetricMap, @@ -572,6 +575,7 @@ impl ConsoleTestState { passed: 0, failed: 0, ignored: 0, + allowed_fail: 0, filtered_out: 0, measured: 0, metrics: MetricMap::new(), @@ -594,6 +598,10 @@ impl ConsoleTestState { self.write_short_result("ignored", "i", term::color::YELLOW) } + pub fn write_allowed_fail(&mut self) -> io::Result<()> { + self.write_short_result("FAILED (allowed)", "a", term::color::YELLOW) + } + pub fn write_metric(&mut self) -> io::Result<()> { self.write_pretty("metric", term::color::CYAN) } @@ -669,6 +677,7 @@ impl ConsoleTestState { TrOk => self.write_ok(), TrFailed | TrFailedMsg(_) => self.write_failed(), TrIgnored => self.write_ignored(), + TrAllowedFail => self.write_allowed_fail(), TrMetrics(ref mm) => { self.write_metric()?; self.write_plain(&format!(": {}\n", mm.fmt_metrics())) @@ -702,6 +711,7 @@ impl ConsoleTestState { TrFailed => "failed".to_owned(), TrFailedMsg(ref msg) => format!("failed: {}", msg), TrIgnored => "ignored".to_owned(), + TrAllowedFail => "failed (allowed)".to_owned(), TrMetrics(ref mm) => mm.fmt_metrics(), TrBench(ref bs) => fmt_bench_samples(bs), }, @@ -761,7 +771,7 @@ impl ConsoleTestState { } pub fn write_run_finish(&mut self) -> io::Result { - assert!(self.passed + self.failed + self.ignored + self.measured == self.total); + assert!(self.passed + self.failed + self.ignored + self.measured + self.allowed_fail == self.total); if self.options.display_output { self.write_outputs()?; @@ -778,9 +788,10 @@ impl ConsoleTestState { } else { self.write_pretty("FAILED", term::color::RED)?; } - let s = format!(". {} passed; {} failed; {} ignored; {} measured; {} filtered out\n\n", + let s = format!(". {} passed; {} failed; {} allowed to fail; {} ignored; {} measured; {} filtered out\n\n", self.passed, self.failed, + self.allowed_fail, self.ignored, self.measured, self.filtered_out); @@ -891,6 +902,7 @@ pub fn run_tests_console(opts: &TestOpts, tests: Vec) -> io::Resu st.not_failures.push((test, stdout)); } TrIgnored => st.ignored += 1, + TrAllowedFail => st.allowed_fail += 1, TrMetrics(mm) => { let tname = test.name; let MetricMap(mm) = mm; @@ -1471,8 +1483,13 @@ fn calc_result(desc: &TestDesc, task_result: Result<(), Box>) -> Tes .unwrap_or(false) { TrOk } else { - TrFailedMsg(format!("Panic did not include expected string '{}'", msg)) + if desc.allow_fail { + TrAllowedFail + } else { + TrFailedMsg(format!("Panic did not include expected string '{}'", msg)) + } }, + _ if desc.allow_fail => TrAllowedFail, _ => TrFailed, } } diff --git a/src/test/run-pass/test-allow-fail-attr.rs b/src/test/run-pass/test-allow-fail-attr.rs new file mode 100644 index 00000000000..7d750d51dcd --- /dev/null +++ b/src/test/run-pass/test-allow-fail-attr.rs @@ -0,0 +1,23 @@ +// Copyright 2016 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: --test + +#[test] +#[allow_fail] +fn test1() { + panic!(); +} + +#[test] +#[allow_fail] +fn test2() { + assert!(true); +} diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index c88ffba357a..b4663b0ee6c 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -476,6 +476,7 @@ pub fn make_test(config: &Config, testpaths: &TestPaths) -> test::TestDescAndFn name: make_test_name(config, testpaths), ignore: ignore, should_panic: should_panic, + allow_fail: false, }, testfn: make_test_closure(config, testpaths), } From 76d605255bdb53ff879488d375299127c2490a00 Mon Sep 17 00:00:00 2001 From: Paul Woolcock Date: Thu, 25 May 2017 11:36:18 -0400 Subject: [PATCH 019/162] Shorten some lines so this can pass the tidy checks --- src/librustdoc/html/markdown.rs | 34 ++++++++++++++++++--------------- src/libtest/lib.rs | 18 +++++++++-------- 2 files changed, 29 insertions(+), 23 deletions(-) diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 5a56c33b806..03da451fd9a 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -1135,23 +1135,27 @@ mod tests { }) } + fn v() -> Vec { + Vec::new() + } + // marker | should_panic| no_run| ignore| rust | test_harness| compile_fail // | allow_fail | error_codes - t("", false, false, false, true, false, false, false, Vec::new()); - t("rust", false, false, false, true, false, false, false, Vec::new()); - t("sh", false, false, false, false, false, false, false, Vec::new()); - t("ignore", false, false, true, true, false, false, false, Vec::new()); - t("should_panic", true, false, false, true, false, false, false, Vec::new()); - t("no_run", false, true, false, true, false, false, false, Vec::new()); - t("test_harness", false, false, false, true, true, false, false, Vec::new()); - t("compile_fail", false, true, false, true, false, true, false, Vec::new()); - t("allow_fail", false, false, false, true, false, false, true, Vec::new()); - t("{.no_run .example}", false, true, false, true, false, false, false, Vec::new()); - t("{.sh .should_panic}", true, false, false, false, false, false, false, Vec::new()); - t("{.example .rust}", false, false, false, true, false, false, false, Vec::new()); - t("{.test_harness .rust}", false, false, false, true, true, false, false, Vec::new()); - t("text, no_run", false, true, false, false, false, false, false, Vec::new()); - t("text,no_run", false, true, false, false, false, false, false, Vec::new()); + t("", false, false, false, true, false, false, false, v()); + t("rust", false, false, false, true, false, false, false, v()); + t("sh", false, false, false, false, false, false, false, v()); + t("ignore", false, false, true, true, false, false, false, v()); + t("should_panic", true, false, false, true, false, false, false, v()); + t("no_run", false, true, false, true, false, false, false, v()); + t("test_harness", false, false, false, true, true, false, false, v()); + t("compile_fail", false, true, false, true, false, true, false, v()); + t("allow_fail", false, false, false, true, false, false, true, v()); + t("{.no_run .example}", false, true, false, true, false, false, false, v()); + t("{.sh .should_panic}", true, false, false, false, false, false, false, v()); + t("{.example .rust}", false, false, false, true, false, false, false, v()); + t("{.test_harness .rust}", false, false, false, true, true, false, false, v()); + t("text, no_run", false, true, false, false, false, false, false, v()); + t("text,no_run", false, true, false, false, false, false, false, v()); } #[test] diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index c68039f21ec..7a09883a72e 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -771,7 +771,8 @@ impl ConsoleTestState { } pub fn write_run_finish(&mut self) -> io::Result { - assert!(self.passed + self.failed + self.ignored + self.measured + self.allowed_fail == self.total); + assert!(self.passed + self.failed + self.ignored + self.measured + + self.allowed_fail == self.total); if self.options.display_output { self.write_outputs()?; @@ -788,13 +789,14 @@ impl ConsoleTestState { } else { self.write_pretty("FAILED", term::color::RED)?; } - let s = format!(". {} passed; {} failed; {} allowed to fail; {} ignored; {} measured; {} filtered out\n\n", - self.passed, - self.failed, - self.allowed_fail, - self.ignored, - self.measured, - self.filtered_out); + let s = format!( + ". {} passed; {} failed ({} allowed); {} ignored; {} measured; {} filtered out\n\n", + self.passed, + self.failed, + self.allowed_fail, + self.ignored, + self.measured, + self.filtered_out); self.write_plain(&s)?; return Ok(success); } From 7ad95378128bb267885ea17001af32388d451523 Mon Sep 17 00:00:00 2001 From: Paul Woolcock Date: Thu, 25 May 2017 16:17:29 -0400 Subject: [PATCH 020/162] fix some tests i missed --- src/libtest/lib.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 7a09883a72e..0567be4e604 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -959,12 +959,14 @@ fn should_sort_failures_before_printing_them() { name: StaticTestName("a"), ignore: false, should_panic: ShouldPanic::No, + allow_fail: false, }; let test_b = TestDesc { name: StaticTestName("b"), ignore: false, should_panic: ShouldPanic::No, + allow_fail: false, }; let mut st = ConsoleTestState { @@ -976,6 +978,7 @@ fn should_sort_failures_before_printing_them() { passed: 0, failed: 0, ignored: 0, + allowed_fail: 0, filtered_out: 0, measured: 0, max_name_len: 10, @@ -1725,6 +1728,7 @@ mod tests { name: StaticTestName("whatever"), ignore: true, should_panic: ShouldPanic::No, + allow_fail: false, }, testfn: DynTestFn(Box::new(move |()| f())), }; @@ -1742,6 +1746,7 @@ mod tests { name: StaticTestName("whatever"), ignore: true, should_panic: ShouldPanic::No, + allow_fail: false, }, testfn: DynTestFn(Box::new(move |()| f())), }; @@ -1761,6 +1766,7 @@ mod tests { name: StaticTestName("whatever"), ignore: false, should_panic: ShouldPanic::Yes, + allow_fail: false, }, testfn: DynTestFn(Box::new(move |()| f())), }; @@ -1780,6 +1786,7 @@ mod tests { name: StaticTestName("whatever"), ignore: false, should_panic: ShouldPanic::YesWithMessage("error message"), + allow_fail: false, }, testfn: DynTestFn(Box::new(move |()| f())), }; @@ -1801,6 +1808,7 @@ mod tests { name: StaticTestName("whatever"), ignore: false, should_panic: ShouldPanic::YesWithMessage(expected), + allow_fail: false, }, testfn: DynTestFn(Box::new(move |()| f())), }; @@ -1818,6 +1826,7 @@ mod tests { name: StaticTestName("whatever"), ignore: false, should_panic: ShouldPanic::Yes, + allow_fail: false, }, testfn: DynTestFn(Box::new(move |()| f())), }; @@ -1851,6 +1860,7 @@ mod tests { name: StaticTestName("1"), ignore: true, should_panic: ShouldPanic::No, + allow_fail: false, }, testfn: DynTestFn(Box::new(move |()| {})), }, @@ -1859,6 +1869,7 @@ mod tests { name: StaticTestName("2"), ignore: false, should_panic: ShouldPanic::No, + allow_fail: false, }, testfn: DynTestFn(Box::new(move |()| {})), }]; @@ -1882,6 +1893,7 @@ mod tests { name: StaticTestName(name), ignore: false, should_panic: ShouldPanic::No, + allow_fail: false, }, testfn: DynTestFn(Box::new(move |()| {})) }) @@ -1963,6 +1975,7 @@ mod tests { name: DynTestName((*name).clone()), ignore: false, should_panic: ShouldPanic::No, + allow_fail: false, }, testfn: DynTestFn(Box::new(move |()| testfn())), }; From 12205f1450f390f10602a19a4e40b6d8f26857e4 Mon Sep 17 00:00:00 2001 From: Stjepan Glavina Date: Sat, 24 Jun 2017 16:51:16 +0200 Subject: [PATCH 021/162] Improve sort tests and benchmarks --- src/liballoc/benches/lib.rs | 1 + src/liballoc/benches/slice.rs | 54 ++++--- src/liballoc/slice.rs | 4 +- src/liballoc/tests/slice.rs | 44 ++++-- src/test/run-pass/vector-sort-panic-safe.rs | 163 ++++++++++++-------- 5 files changed, 175 insertions(+), 91 deletions(-) diff --git a/src/liballoc/benches/lib.rs b/src/liballoc/benches/lib.rs index 958020d0b0e..5f274eec87d 100644 --- a/src/liballoc/benches/lib.rs +++ b/src/liballoc/benches/lib.rs @@ -17,6 +17,7 @@ #![feature(sort_unstable)] #![feature(test)] +extern crate rand; extern crate test; mod btree; diff --git a/src/liballoc/benches/slice.rs b/src/liballoc/benches/slice.rs index aa5a438b35e..d99270e7f31 100644 --- a/src/liballoc/benches/slice.rs +++ b/src/liballoc/benches/slice.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::{mem, ptr}; -use std::__rand::{Rng, thread_rng}; +use std::__rand::{thread_rng}; +use std::mem; +use std::ptr; +use rand::{Rng, SeedableRng, XorShiftRng}; use test::{Bencher, black_box}; #[bench] @@ -191,17 +193,17 @@ fn gen_descending(len: usize) -> Vec { } fn gen_random(len: usize) -> Vec { - let mut rng = thread_rng(); + let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]); rng.gen_iter::().take(len).collect() } fn gen_random_bytes(len: usize) -> Vec { - let mut rng = thread_rng(); + let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]); rng.gen_iter::().take(len).collect() } fn gen_mostly_ascending(len: usize) -> Vec { - let mut rng = thread_rng(); + let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]); let mut v = gen_ascending(len); for _ in (0usize..).take_while(|x| x * x <= len) { let x = rng.gen::() % len; @@ -212,7 +214,7 @@ fn gen_mostly_ascending(len: usize) -> Vec { } fn gen_mostly_descending(len: usize) -> Vec { - let mut rng = thread_rng(); + let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]); let mut v = gen_descending(len); for _ in (0usize..).take_while(|x| x * x <= len) { let x = rng.gen::() % len; @@ -223,7 +225,7 @@ fn gen_mostly_descending(len: usize) -> Vec { } fn gen_strings(len: usize) -> Vec { - let mut rng = thread_rng(); + let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]); let mut v = vec![]; for _ in 0..len { let n = rng.gen::() % 20 + 1; @@ -233,7 +235,7 @@ fn gen_strings(len: usize) -> Vec { } fn gen_big_random(len: usize) -> Vec<[u64; 16]> { - let mut rng = thread_rng(); + let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]); rng.gen_iter().map(|x| [x; 16]).take(len).collect() } @@ -241,18 +243,32 @@ macro_rules! sort { ($f:ident, $name:ident, $gen:expr, $len:expr) => { #[bench] fn $name(b: &mut Bencher) { - b.iter(|| $gen($len).$f()); + let v = $gen($len); + b.iter(|| v.clone().$f()); b.bytes = $len * mem::size_of_val(&$gen(1)[0]) as u64; } } } +macro_rules! sort_strings { + ($f:ident, $name:ident, $gen:expr, $len:expr) => { + #[bench] + fn $name(b: &mut Bencher) { + let v = $gen($len); + let v = v.iter().map(|s| &**s).collect::>(); + b.iter(|| v.clone().$f()); + b.bytes = $len * mem::size_of::<&str>() as u64; + } + } +} + macro_rules! sort_expensive { ($f:ident, $name:ident, $gen:expr, $len:expr) => { #[bench] fn $name(b: &mut Bencher) { + let v = $gen($len); b.iter(|| { - let mut v = $gen($len); + let mut v = v.clone(); let mut count = 0; v.$f(|a: &u64, b: &u64| { count += 1; @@ -263,7 +279,7 @@ macro_rules! sort_expensive { }); black_box(count); }); - b.bytes = $len as u64 * mem::size_of::() as u64; + b.bytes = $len * mem::size_of_val(&$gen(1)[0]) as u64; } } } @@ -271,30 +287,30 @@ macro_rules! sort_expensive { sort!(sort, sort_small_ascending, gen_ascending, 10); sort!(sort, sort_small_descending, gen_descending, 10); sort!(sort, sort_small_random, gen_random, 10); -sort!(sort, sort_small_big_random, gen_big_random, 10); +sort!(sort, sort_small_big, gen_big_random, 10); sort!(sort, sort_medium_random, gen_random, 100); sort!(sort, sort_large_ascending, gen_ascending, 10000); sort!(sort, sort_large_descending, gen_descending, 10000); sort!(sort, sort_large_mostly_ascending, gen_mostly_ascending, 10000); sort!(sort, sort_large_mostly_descending, gen_mostly_descending, 10000); sort!(sort, sort_large_random, gen_random, 10000); -sort!(sort, sort_large_big_random, gen_big_random, 10000); -sort!(sort, sort_large_strings, gen_strings, 10000); -sort_expensive!(sort_by, sort_large_random_expensive, gen_random, 10000); +sort!(sort, sort_large_big, gen_big_random, 10000); +sort_strings!(sort, sort_large_strings, gen_strings, 10000); +sort_expensive!(sort_by, sort_large_expensive, gen_random, 10000); sort!(sort_unstable, sort_unstable_small_ascending, gen_ascending, 10); sort!(sort_unstable, sort_unstable_small_descending, gen_descending, 10); sort!(sort_unstable, sort_unstable_small_random, gen_random, 10); -sort!(sort_unstable, sort_unstable_small_big_random, gen_big_random, 10); +sort!(sort_unstable, sort_unstable_small_big, gen_big_random, 10); sort!(sort_unstable, sort_unstable_medium_random, gen_random, 100); sort!(sort_unstable, sort_unstable_large_ascending, gen_ascending, 10000); sort!(sort_unstable, sort_unstable_large_descending, gen_descending, 10000); sort!(sort_unstable, sort_unstable_large_mostly_ascending, gen_mostly_ascending, 10000); sort!(sort_unstable, sort_unstable_large_mostly_descending, gen_mostly_descending, 10000); sort!(sort_unstable, sort_unstable_large_random, gen_random, 10000); -sort!(sort_unstable, sort_unstable_large_big_random, gen_big_random, 10000); -sort!(sort_unstable, sort_unstable_large_strings, gen_strings, 10000); -sort_expensive!(sort_unstable_by, sort_unstable_large_random_expensive, gen_random, 10000); +sort!(sort_unstable, sort_unstable_large_big, gen_big_random, 10000); +sort_strings!(sort_unstable, sort_unstable_large_strings, gen_strings, 10000); +sort_expensive!(sort_unstable_by, sort_unstable_large_expensive, gen_random, 10000); macro_rules! reverse { ($name:ident, $ty:ty, $f:expr) => { diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index 88876999d76..fe8893904eb 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -1794,7 +1794,7 @@ unsafe fn merge(v: &mut [T], mid: usize, buf: *mut T, is_less: &mut F) impl Drop for MergeHole { fn drop(&mut self) { - // `T` is not a zero-sized type, so it's okay to divide by it's size. + // `T` is not a zero-sized type, so it's okay to divide by its size. let len = (self.end as usize - self.start as usize) / mem::size_of::(); unsafe { ptr::copy_nonoverlapping(self.start, self.dest, len); } } @@ -1908,7 +1908,7 @@ fn merge_sort(v: &mut [T], mut is_less: F) // if `Some(r)` is returned, that means `runs[r]` and `runs[r + 1]` must be merged next. If the // algorithm should continue building a new run instead, `None` is returned. // - // TimSort is infamous for it's buggy implementations, as described here: + // TimSort is infamous for its buggy implementations, as described here: // http://envisage-project.eu/timsort-specification-and-verification/ // // The gist of the story is: we must enforce the invariants on the top four runs on the stack. diff --git a/src/liballoc/tests/slice.rs b/src/liballoc/tests/slice.rs index 7fa65a2144e..c53bf15f1bf 100644 --- a/src/liballoc/tests/slice.rs +++ b/src/liballoc/tests/slice.rs @@ -396,18 +396,44 @@ fn test_sort() { let mut rng = thread_rng(); for len in (2..25).chain(500..510) { - for _ in 0..100 { - let mut v: Vec<_> = rng.gen_iter::().take(len).collect(); - let mut v1 = v.clone(); + for &modulus in &[5, 10, 100, 1000] { + for _ in 0..10 { + let orig: Vec<_> = rng.gen_iter::() + .map(|x| x % modulus) + .take(len) + .collect(); - v.sort(); - assert!(v.windows(2).all(|w| w[0] <= w[1])); + // Sort in default order. + let mut v = orig.clone(); + v.sort(); + assert!(v.windows(2).all(|w| w[0] <= w[1])); - v1.sort_by(|a, b| a.cmp(b)); - assert!(v1.windows(2).all(|w| w[0] <= w[1])); + // Sort in ascending order. + let mut v = orig.clone(); + v.sort_by(|a, b| a.cmp(b)); + assert!(v.windows(2).all(|w| w[0] <= w[1])); - v1.sort_by(|a, b| b.cmp(a)); - assert!(v1.windows(2).all(|w| w[0] >= w[1])); + // Sort in descending order. + let mut v = orig.clone(); + v.sort_by(|a, b| b.cmp(a)); + assert!(v.windows(2).all(|w| w[0] >= w[1])); + + // Sort with many pre-sorted runs. + let mut v = orig.clone(); + v.sort(); + v.reverse(); + for _ in 0..5 { + let a = rng.gen::() % len; + let b = rng.gen::() % len; + if a < b { + v[a..b].reverse(); + } else { + v.swap(a, b); + } + } + v.sort(); + assert!(v.windows(2).all(|w| w[0] <= w[1])); + } } } diff --git a/src/test/run-pass/vector-sort-panic-safe.rs b/src/test/run-pass/vector-sort-panic-safe.rs index 8ad6ca0abb0..3458199bdaf 100644 --- a/src/test/run-pass/vector-sort-panic-safe.rs +++ b/src/test/run-pass/vector-sort-panic-safe.rs @@ -10,14 +10,17 @@ // ignore-emscripten no threads support -#![feature(rand)] #![feature(const_fn)] +#![feature(rand)] +#![feature(sort_unstable)] use std::__rand::{thread_rng, Rng}; -use std::panic; -use std::sync::atomic::{AtomicUsize, Ordering}; -use std::thread; use std::cell::Cell; +use std::cmp::Ordering; +use std::panic; +use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize}; +use std::sync::atomic::Ordering::Relaxed; +use std::thread; const MAX_LEN: usize = 80; @@ -45,54 +48,85 @@ static DROP_COUNTS: [AtomicUsize; MAX_LEN] = [ AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), ]; -#[derive(Clone, PartialEq, PartialOrd, Eq, Ord)] +static VERSIONS: AtomicUsize = ATOMIC_USIZE_INIT; + +#[derive(Clone, Eq)] struct DropCounter { x: u32, id: usize, + version: Cell, +} + +impl PartialEq for DropCounter { + fn eq(&self, other: &Self) -> bool { + self.partial_cmp(other) == Some(Ordering::Equal) + } +} + +impl PartialOrd for DropCounter { + fn partial_cmp(&self, other: &Self) -> Option { + self.version.set(self.version.get() + 1); + other.version.set(other.version.get() + 1); + VERSIONS.fetch_add(2, Relaxed); + self.x.partial_cmp(&other.x) + } +} + +impl Ord for DropCounter { + fn cmp(&self, other: &Self) -> Ordering { + self.partial_cmp(other).unwrap() + } } impl Drop for DropCounter { fn drop(&mut self) { - DROP_COUNTS[self.id].fetch_add(1, Ordering::Relaxed); + DROP_COUNTS[self.id].fetch_add(1, Relaxed); + VERSIONS.fetch_sub(self.version.get(), Relaxed); } } -fn test(input: &[DropCounter]) { - let len = input.len(); +macro_rules! test { + ($input:ident, $func:ident) => { + let len = $input.len(); - // Work out the total number of comparisons required to sort - // this array... - let mut count = 0usize; - input.to_owned().sort_by(|a, b| { count += 1; a.cmp(b) }); + // Work out the total number of comparisons required to sort + // this array... + let mut count = 0usize; + $input.to_owned().$func(|a, b| { count += 1; a.cmp(b) }); - // ... and then panic on each and every single one. - for panic_countdown in 0..count { - // Refresh the counters. - for i in 0..len { - DROP_COUNTS[i].store(0, Ordering::Relaxed); - } + // ... and then panic on each and every single one. + for panic_countdown in 0..count { + // Refresh the counters. + VERSIONS.store(0, Relaxed); + for i in 0..len { + DROP_COUNTS[i].store(0, Relaxed); + } - let v = input.to_owned(); - let _ = thread::spawn(move || { - let mut v = v; - let mut panic_countdown = panic_countdown; - v.sort_by(|a, b| { - if panic_countdown == 0 { - SILENCE_PANIC.with(|s| s.set(true)); - panic!(); - } - panic_countdown -= 1; - a.cmp(b) - }) - }).join(); + let v = $input.to_owned(); + let _ = thread::spawn(move || { + let mut v = v; + let mut panic_countdown = panic_countdown; + v.$func(|a, b| { + if panic_countdown == 0 { + SILENCE_PANIC.with(|s| s.set(true)); + panic!(); + } + panic_countdown -= 1; + a.cmp(b) + }) + }).join(); - // Check that the number of things dropped is exactly - // what we expect (i.e. the contents of `v`). - for (i, c) in DROP_COUNTS.iter().enumerate().take(len) { - let count = c.load(Ordering::Relaxed); - assert!(count == 1, - "found drop count == {} for i == {}, len == {}", - count, i, len); + // Check that the number of things dropped is exactly + // what we expect (i.e. the contents of `v`). + for (i, c) in DROP_COUNTS.iter().enumerate().take(len) { + let count = c.load(Relaxed); + assert!(count == 1, + "found drop count == {} for i == {}, len == {}", + count, i, len); + } + + // Check that the most recent versions of values were dropped. + assert_eq!(VERSIONS.load(Relaxed), 0); } } } @@ -106,33 +140,40 @@ fn main() { prev(info); } })); + for len in (1..20).chain(70..MAX_LEN) { - // Test on a random array. - let mut rng = thread_rng(); - let input = (0..len).map(|id| { - DropCounter { - x: rng.next_u32(), - id: id, - } - }).collect::>(); - test(&input); + for &modulus in &[5, 20, 50] { + for &has_runs in &[false, true] { + let mut rng = thread_rng(); + let mut input = (0..len) + .map(|id| { + DropCounter { + x: rng.next_u32() % modulus, + id: id, + version: Cell::new(0), + } + }) + .collect::>(); - // Test on a sorted array with two elements randomly swapped, creating several natural - // runs of random lengths. Such arrays have very high chances of hitting all code paths in - // the merge procedure. - for _ in 0..5 { - let mut input = (0..len).map(|i| - DropCounter { - x: i as u32, - id: i, + if has_runs { + for c in &mut input { + c.x = c.id as u32; + } + + for _ in 0..5 { + let a = rng.gen::() % len; + let b = rng.gen::() % len; + if a < b { + input[a..b].reverse(); + } else { + input.swap(a, b); + } + } } - ).collect::>(); - let a = rng.gen::() % len; - let b = rng.gen::() % len; - input.swap(a, b); - - test(&input); + test!(input, sort_by); + test!(input, sort_unstable_by); + } } } } From 45af6ee4fcaf4a0f0dcd72ac8a38681700590b98 Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Sat, 24 Jun 2017 18:23:39 +0300 Subject: [PATCH 022/162] Move global vars changing tests into run-pass Should fix race #42795 --- src/libstd/env.rs | 82 +-------------------------------- src/test/run-pass/env.rs | 98 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+), 81 deletions(-) create mode 100644 src/test/run-pass/env.rs diff --git a/src/libstd/env.rs b/src/libstd/env.rs index 1dfae0ce83f..f81adad3ebe 100644 --- a/src/libstd/env.rs +++ b/src/libstd/env.rs @@ -949,63 +949,9 @@ mod arch { mod tests { use super::*; - use iter::repeat; - use rand::{self, Rng}; - use ffi::{OsString, OsStr}; + use ffi::OsStr; use path::{Path, PathBuf}; - fn make_rand_name() -> OsString { - let mut rng = rand::thread_rng(); - let n = format!("TEST{}", rng.gen_ascii_chars().take(10) - .collect::()); - let n = OsString::from(n); - assert!(var_os(&n).is_none()); - n - } - - fn eq(a: Option, b: Option<&str>) { - assert_eq!(a.as_ref().map(|s| &**s), b.map(OsStr::new).map(|s| &*s)); - } - - #[test] - fn test_set_var() { - let n = make_rand_name(); - set_var(&n, "VALUE"); - eq(var_os(&n), Some("VALUE")); - } - - #[test] - fn test_remove_var() { - let n = make_rand_name(); - set_var(&n, "VALUE"); - remove_var(&n); - eq(var_os(&n), None); - } - - #[test] - fn test_set_var_overwrite() { - let n = make_rand_name(); - set_var(&n, "1"); - set_var(&n, "2"); - eq(var_os(&n), Some("2")); - set_var(&n, ""); - eq(var_os(&n), Some("")); - } - - #[test] - #[cfg_attr(target_os = "emscripten", ignore)] - fn test_var_big() { - let mut s = "".to_string(); - let mut i = 0; - while i < 100 { - s.push_str("aaaaaaaaaa"); - i += 1; - } - let n = make_rand_name(); - set_var(&n, &s); - eq(var_os(&n), Some(&s)); - } - #[test] #[cfg_attr(target_os = "emscripten", ignore)] fn test_self_exe_path() { @@ -1017,32 +963,6 @@ mod tests { assert!(path.is_absolute()); } - #[test] - #[cfg_attr(target_os = "emscripten", ignore)] - fn test_env_set_get_huge() { - let n = make_rand_name(); - let s = repeat("x").take(10000).collect::(); - set_var(&n, &s); - eq(var_os(&n), Some(&s)); - remove_var(&n); - eq(var_os(&n), None); - } - - #[test] - fn test_env_set_var() { - let n = make_rand_name(); - - let mut e = vars_os(); - set_var(&n, "VALUE"); - assert!(!e.any(|(k, v)| { - &*k == &*n && &*v == "VALUE" - })); - - assert!(vars_os().any(|(k, v)| { - &*k == &*n && &*v == "VALUE" - })); - } - #[test] fn test() { assert!((!Path::new("test-path").is_absolute())); diff --git a/src/test/run-pass/env.rs b/src/test/run-pass/env.rs new file mode 100644 index 00000000000..e602fb2d7d2 --- /dev/null +++ b/src/test/run-pass/env.rs @@ -0,0 +1,98 @@ +// Copyright 2017 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: --test + +#![feature(rand, std_panic)] + +use std::env::*; +use std::__rand as rand; +use std::__rand::Rng; +use std::iter::repeat; +use std::ffi::{OsString, OsStr}; + + +fn make_rand_name() -> OsString { + let mut rng = rand::thread_rng(); + let n = format!("TEST{}", rng.gen_ascii_chars().take(10) + .collect::()); + let n = OsString::from(n); + assert!(var_os(&n).is_none()); + n +} + +fn eq(a: Option, b: Option<&str>) { + assert_eq!(a.as_ref().map(|s| &**s), b.map(OsStr::new).map(|s| &*s)); +} + +#[test] +fn test_set_var() { + let n = make_rand_name(); + set_var(&n, "VALUE"); + eq(var_os(&n), Some("VALUE")); +} + +#[test] +fn test_remove_var() { + let n = make_rand_name(); + set_var(&n, "VALUE"); + remove_var(&n); + eq(var_os(&n), None); +} + +#[test] +fn test_set_var_overwrite() { + let n = make_rand_name(); + set_var(&n, "1"); + set_var(&n, "2"); + eq(var_os(&n), Some("2")); + set_var(&n, ""); + eq(var_os(&n), Some("")); +} + +#[test] +#[cfg_attr(target_os = "emscripten", ignore)] +fn test_var_big() { + let mut s = "".to_string(); + let mut i = 0; + while i < 100 { + s.push_str("aaaaaaaaaa"); + i += 1; + } + let n = make_rand_name(); + set_var(&n, &s); + eq(var_os(&n), Some(&s)); +} + +#[test] +#[cfg_attr(target_os = "emscripten", ignore)] +fn test_env_set_get_huge() { + let n = make_rand_name(); + let s = repeat("x").take(10000).collect::(); + set_var(&n, &s); + eq(var_os(&n), Some(&s)); + remove_var(&n); + eq(var_os(&n), None); +} + +#[test] +fn test_env_set_var() { + let n = make_rand_name(); + + let mut e = vars_os(); + set_var(&n, "VALUE"); + assert!(!e.any(|(k, v)| { + &*k == &*n && &*v == "VALUE" + })); + + assert!(vars_os().any(|(k, v)| { + &*k == &*n && &*v == "VALUE" + })); +} From 8e5a3023c9ef299be6a617bca55ad16d12ce1036 Mon Sep 17 00:00:00 2001 From: Paul Woolcock Date: Fri, 23 Jun 2017 09:43:28 -0400 Subject: [PATCH 023/162] Add a feature gate for the `#[allow_fail]` attribute --- src/libsyntax/feature_gate.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 07db5b83331..74bf19b841e 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -354,6 +354,9 @@ declare_features! ( // rustc internal (active, abi_thiscall, "1.19.0", None), + + // Allows a test to fail without failing the whole suite + (active, allow_fail, "1.19.0", Some(42219)), ); declare_features! ( @@ -534,7 +537,6 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG ("derive", Normal, Ungated), ("should_panic", Normal, Ungated), ("ignore", Normal, Ungated), - ("allow_fail", Normal, Ungated), ("no_implicit_prelude", Normal, Ungated), ("reexport_test_harness_main", Normal, Ungated), ("link_args", Normal, Ungated), @@ -813,6 +815,11 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG "used internally by rustc", cfg_fn!(rustc_attrs))), + ("allow_fail", Normal, Gated(Stability::Unstable, + "allow_fail", + "allow_fail attribute is currently unstable", + cfg_fn!(allow_fail))), + // Crate level attributes ("crate_name", CrateLevel, Ungated), ("crate_type", CrateLevel, Ungated), From ecde91a69d8414113b71bf2f5c79e607861dba23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 24 Jun 2017 01:09:57 -0700 Subject: [PATCH 024/162] Suggest removal of semicolon (instead of being help) --- src/librustc_errors/emitter.rs | 7 ++++++- src/librustc_typeck/check/mod.rs | 2 +- .../block-result/consider-removing-last-semi.stderr | 12 ++---------- src/test/ui/block-result/issue-11714.stderr | 6 +----- src/test/ui/block-result/issue-13428.stderr | 12 ++---------- .../ui/coercion-missing-tail-expected-type.stderr | 12 ++---------- 6 files changed, 14 insertions(+), 37 deletions(-) diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 2d25d12d3a9..4b71aa6b85f 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -47,7 +47,12 @@ impl Emitter for EmitterWriter { // don't display multiline suggestions as labels sugg.substitution_parts[0].substitutions[0].find('\n').is_none() { let substitution = &sugg.substitution_parts[0].substitutions[0]; - let msg = format!("help: {} `{}`", sugg.msg, substitution); + let msg = if substitution.len() == 0 { + // This substitution is only removal, don't show it + format!("help: {}", sugg.msg) + } else { + format!("help: {} `{}`", sugg.msg, substitution) + }; primary_span.push_span_label(sugg.substitution_spans().next().unwrap(), msg); } else { // if there are multiple suggestions, print them all in full diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 684e5a66fc5..0467f24948e 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4391,7 +4391,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { hi: original_span.hi, ctxt: original_span.ctxt, }; - err.span_help(span_semi, "consider removing this semicolon:"); + err.span_suggestion(span_semi, "consider removing this semicolon", "".to_string()); } // Instantiates the given path, which must refer to an item with the given diff --git a/src/test/ui/block-result/consider-removing-last-semi.stderr b/src/test/ui/block-result/consider-removing-last-semi.stderr index 944c9d6c427..282583d32a6 100644 --- a/src/test/ui/block-result/consider-removing-last-semi.stderr +++ b/src/test/ui/block-result/consider-removing-last-semi.stderr @@ -5,16 +5,12 @@ error[E0308]: mismatched types | __________________^ 12 | | 0u8; 13 | | "bla".to_string(); //~ HELP consider removing this semicolon + | | - help: consider removing this semicolon 14 | | } | |_^ expected struct `std::string::String`, found () | = note: expected type `std::string::String` found type `()` -help: consider removing this semicolon: - --> $DIR/consider-removing-last-semi.rs:13:22 - | -13 | "bla".to_string(); //~ HELP consider removing this semicolon - | ^ error[E0308]: mismatched types --> $DIR/consider-removing-last-semi.rs:16:18 @@ -23,16 +19,12 @@ error[E0308]: mismatched types | __________________^ 17 | | "this won't work".to_string(); 18 | | "removeme".to_string(); //~ HELP consider removing this semicolon + | | - help: consider removing this semicolon 19 | | } | |_^ expected struct `std::string::String`, found () | = note: expected type `std::string::String` found type `()` -help: consider removing this semicolon: - --> $DIR/consider-removing-last-semi.rs:18:27 - | -18 | "removeme".to_string(); //~ HELP consider removing this semicolon - | ^ error: aborting due to previous error(s) diff --git a/src/test/ui/block-result/issue-11714.stderr b/src/test/ui/block-result/issue-11714.stderr index cba9c3f51d7..ed61ec6ca29 100644 --- a/src/test/ui/block-result/issue-11714.stderr +++ b/src/test/ui/block-result/issue-11714.stderr @@ -6,16 +6,12 @@ error[E0308]: mismatched types 12 | | 1 13 | | 14 | | ; //~ HELP consider removing this semicolon: + | | - help: consider removing this semicolon 15 | | } | |_^ expected i32, found () | = note: expected type `i32` found type `()` -help: consider removing this semicolon: - --> $DIR/issue-11714.rs:14:5 - | -14 | ; //~ HELP consider removing this semicolon: - | ^ error: aborting due to previous error(s) diff --git a/src/test/ui/block-result/issue-13428.stderr b/src/test/ui/block-result/issue-13428.stderr index d0ed8935cd7..5e8d92f64e2 100644 --- a/src/test/ui/block-result/issue-13428.stderr +++ b/src/test/ui/block-result/issue-13428.stderr @@ -8,16 +8,12 @@ error[E0308]: mismatched types 16 | | // Put the trailing semicolon on its own line to test that the 17 | | // note message gets the offending semicolon exactly 18 | | ; //~ HELP consider removing this semicolon + | | - help: consider removing this semicolon 19 | | } | |_^ expected struct `std::string::String`, found () | = note: expected type `std::string::String` found type `()` -help: consider removing this semicolon: - --> $DIR/issue-13428.rs:18:5 - | -18 | ; //~ HELP consider removing this semicolon - | ^ error[E0308]: mismatched types --> $DIR/issue-13428.rs:21:20 @@ -26,16 +22,12 @@ error[E0308]: mismatched types | ____________________^ 22 | | "foobar".to_string() 23 | | ; //~ HELP consider removing this semicolon + | | - help: consider removing this semicolon 24 | | } | |_^ expected struct `std::string::String`, found () | = note: expected type `std::string::String` found type `()` -help: consider removing this semicolon: - --> $DIR/issue-13428.rs:23:5 - | -23 | ; //~ HELP consider removing this semicolon - | ^ error: aborting due to previous error(s) diff --git a/src/test/ui/coercion-missing-tail-expected-type.stderr b/src/test/ui/coercion-missing-tail-expected-type.stderr index e96bc425e0b..49e8b9febc2 100644 --- a/src/test/ui/coercion-missing-tail-expected-type.stderr +++ b/src/test/ui/coercion-missing-tail-expected-type.stderr @@ -4,16 +4,12 @@ error[E0308]: mismatched types 13 | fn plus_one(x: i32) -> i32 { | ____________________________^ 14 | | x + 1; + | | - help: consider removing this semicolon 15 | | } | |_^ expected i32, found () | = note: expected type `i32` found type `()` -help: consider removing this semicolon: - --> $DIR/coercion-missing-tail-expected-type.rs:14:10 - | -14 | x + 1; - | ^ error[E0308]: mismatched types --> $DIR/coercion-missing-tail-expected-type.rs:17:29 @@ -21,16 +17,12 @@ error[E0308]: mismatched types 17 | fn foo() -> Result { | _____________________________^ 18 | | Ok(1); + | | - help: consider removing this semicolon 19 | | } | |_^ expected enum `std::result::Result`, found () | = note: expected type `std::result::Result` found type `()` -help: consider removing this semicolon: - --> $DIR/coercion-missing-tail-expected-type.rs:18:10 - | -18 | Ok(1); - | ^ error: aborting due to previous error(s) From 927625912a76e97a204643215617e50423124194 Mon Sep 17 00:00:00 2001 From: Oliver Middleton Date: Sat, 24 Jun 2017 18:16:39 +0100 Subject: [PATCH 025/162] rustdoc: Don't ICE on `use *;` --- src/librustdoc/html/format.rs | 6 +++++- src/test/rustdoc/issue-42875.rs | 23 +++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 src/test/rustdoc/issue-42875.rs diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 635691dd345..766e76137ca 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -1019,7 +1019,11 @@ impl fmt::Display for clean::Import { } } clean::Import::Glob(ref src) => { - write!(f, "use {}::*;", *src) + if src.path.segments.is_empty() { + write!(f, "use *;") + } else { + write!(f, "use {}::*;", *src) + } } } } diff --git a/src/test/rustdoc/issue-42875.rs b/src/test/rustdoc/issue-42875.rs new file mode 100644 index 00000000000..ebf7056755e --- /dev/null +++ b/src/test/rustdoc/issue-42875.rs @@ -0,0 +1,23 @@ +// Copyright 2017 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: --no-defaults + +#![crate_name = "foo"] + +// @has foo/a/index.html '//code' 'use *;' +mod a { + use *; +} + +// @has foo/b/index.html '//code' 'pub use *;' +pub mod b { + pub use *; +} From 27d4b314c5b663a8382a33bd69cb8b27134fb3f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 24 Jun 2017 12:16:20 -0700 Subject: [PATCH 026/162] Do not specify return type in suggestion for some `Ty`s Don't specify a suggested return type for `TyAnon`, `TyFnDef`, `TyFnPtr`, `TyDynamic`, `TyClosure` and `TyProjection`. --- src/librustc/ty/mod.rs | 12 ++++++++++++ src/librustc_typeck/check/mod.rs | 10 +++++++--- src/test/ui/block-result/issue-20862.stderr | 2 +- src/test/ui/block-result/issue-3563.stderr | 2 +- 4 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 13e46a265c6..65dd11bbc62 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -481,6 +481,18 @@ impl<'tcx> TyS<'tcx> { _ => false, } } + + pub fn is_suggestable(&self) -> bool { + match self.sty { + TypeVariants::TyAnon(..) | + TypeVariants::TyFnDef(..) | + TypeVariants::TyFnPtr(..) | + TypeVariants::TyDynamic(..) | + TypeVariants::TyClosure(..) | + TypeVariants::TyProjection(..) => false, + _ => true, + } + } } impl<'a, 'gcx, 'tcx> HashStable> for ty::TyS<'tcx> { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 0467f24948e..50e2e390d02 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4349,9 +4349,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let &hir::FnDecl { output: hir::FunctionRetTy::DefaultReturn(span), .. } = fn_decl { - err.span_suggestion(span, - "possibly return type missing here?", - format!("-> {} ", ty)); + if ty.is_suggestable() { + err.span_suggestion(span, + "possibly return type missing here?", + format!("-> {} ", ty)); + } else { + err.span_label(span, "possibly return type missing here?"); + } } } diff --git a/src/test/ui/block-result/issue-20862.stderr b/src/test/ui/block-result/issue-20862.stderr index 0d88a44d6b9..57cee8f7aca 100644 --- a/src/test/ui/block-result/issue-20862.stderr +++ b/src/test/ui/block-result/issue-20862.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types 11 | fn foo(x: i32) { | - | | - | help: possibly return type missing here? `-> [closure@$DIR/issue-20862.rs:12:5: 12:14 x:_] ` + | possibly return type missing here? | expected `()` because of this default return type 12 | |y| x + y | ^^^^^^^^^ expected (), found closure diff --git a/src/test/ui/block-result/issue-3563.stderr b/src/test/ui/block-result/issue-3563.stderr index e9ace85c1d9..d995dee3827 100644 --- a/src/test/ui/block-result/issue-3563.stderr +++ b/src/test/ui/block-result/issue-3563.stderr @@ -10,7 +10,7 @@ error[E0308]: mismatched types 12 | fn a(&self) { | - | | - | help: possibly return type missing here? `-> [closure@$DIR/issue-3563.rs:13:9: 13:20 self:_] ` + | possibly return type missing here? | expected `()` because of this default return type 13 | || self.b() | ^^^^^^^^^^^ expected (), found closure From d5977df1c1a934f9892e26a17b38065412ba31d1 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 7 Jun 2017 20:58:09 +0200 Subject: [PATCH 027/162] Add E0604 --- src/librustc_typeck/check/cast.rs | 8 ++------ src/librustc_typeck/diagnostics.rs | 17 +++++++++++++++++ src/test/compile-fail/E0604.rs | 13 +++++++++++++ .../ui/mismatched_types/cast-rfc0401.stderr | 2 +- 4 files changed, 33 insertions(+), 7 deletions(-) create mode 100644 src/test/compile-fail/E0604.rs diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 91aeade65aa..cff61df52cd 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -205,12 +205,8 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { .emit(); } CastError::CastToChar => { - fcx.type_error_message(self.span, - |actual| { - format!("only `u8` can be cast as `char`, not `{}`", - actual) - }, - self.expr_ty); + struct_span_err!(fcx.tcx.sess, self.span, E0604, + "only `u8` can be cast as `char`, not `{}`", self.expr_ty).emit(); } CastError::NonScalar => { fcx.type_error_message(self.span, diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index bc5ba4c323d..e750a897844 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -4208,6 +4208,23 @@ println!("{}", v[2]); ``` "##, +E0604: r##" +A cast to `char` was attempted on another type than `u8`. + +Erroneous code example: + +```compile_fail,E0604 +0u32 as char; // error: only `u8` can be cast as `char`, not `u32` +``` + +As the error message indicates, only `u8` can be casted into `char`. Example: + +``` +let c = 86u8 as char; // ok! +assert!(c, 'V'); +``` +"##, + E0609: r##" Attempted to access a non-existent field in a struct. diff --git a/src/test/compile-fail/E0604.rs b/src/test/compile-fail/E0604.rs new file mode 100644 index 00000000000..c5bf3a77b6c --- /dev/null +++ b/src/test/compile-fail/E0604.rs @@ -0,0 +1,13 @@ +// Copyright 2017 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() { + 1u32 as char; //~ ERROR E0604 +} diff --git a/src/test/ui/mismatched_types/cast-rfc0401.stderr b/src/test/ui/mismatched_types/cast-rfc0401.stderr index 58cd130dcc2..82672d5d873 100644 --- a/src/test/ui/mismatched_types/cast-rfc0401.stderr +++ b/src/test/ui/mismatched_types/cast-rfc0401.stderr @@ -92,7 +92,7 @@ error[E0054]: cannot cast as `bool` | = help: compare with zero instead -error: only `u8` can be cast as `char`, not `u32` +error[E0604]: only `u8` can be cast as `char`, not `u32` --> $DIR/cast-rfc0401.rs:51:13 | 51 | let _ = 0x61u32 as char; From 0e4b8ffccdfaa48e7ec61d8f8dc06f15f31c800f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 7 Jun 2017 22:24:15 +0200 Subject: [PATCH 028/162] Add E0605 --- src/librustc_typeck/check/cast.rs | 14 +++++----- src/librustc_typeck/diagnostics.rs | 26 +++++++++++++++++++ src/test/compile-fail/E0605.rs | 19 ++++++++++++++ .../ui/mismatched_types/cast-rfc0401.stderr | 20 ++++++++++---- .../ui/mismatched_types/issue-26480.stderr | 4 ++- 5 files changed, 70 insertions(+), 13 deletions(-) create mode 100644 src/test/compile-fail/E0605.rs diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index cff61df52cd..69174dacaaa 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -209,13 +209,13 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { "only `u8` can be cast as `char`, not `{}`", self.expr_ty).emit(); } CastError::NonScalar => { - fcx.type_error_message(self.span, - |actual| { - format!("non-scalar cast: `{}` as `{}`", - actual, - fcx.ty_to_string(self.cast_ty)) - }, - self.expr_ty); + struct_span_err!(fcx.tcx.sess, self.span, E0605, + "non-scalar cast: `{}` as `{}`", + self.expr_ty, + fcx.ty_to_string(self.cast_ty)) + .note("an `as` expression can only be used to convert between \ + primitive types. Consider using the `From` trait") + .emit(); } CastError::IllegalCast => { fcx.type_error_message(self.span, diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index e750a897844..a787aadc678 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -4225,6 +4225,32 @@ assert!(c, 'V'); ``` "##, +E0605: r##" +An invalid cast was attempted. + +Erroneous code examples: + +```compile_fail,E0605 +let x = 0u8; +x as Vec; // error: non-scalar cast: `u8` as `std::vec::Vec` + +// Another example + +let v = 0 as *const u8; // So here, `v` is a `*const u8`. +v as &u8; // error: non-scalar cast: `*const u8` as `&u8` +``` + +Only primitive types cast be casted into each others. Examples: + +``` +let x = 0u8; +x as u32; // ok! + +let v = 0 as *const u8; +v as *const i8; // ok! +``` +"##, + E0609: r##" Attempted to access a non-existent field in a struct. diff --git a/src/test/compile-fail/E0605.rs b/src/test/compile-fail/E0605.rs new file mode 100644 index 00000000000..add3fd8fd8a --- /dev/null +++ b/src/test/compile-fail/E0605.rs @@ -0,0 +1,19 @@ +// Copyright 2017 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 x = 0u8; + x as Vec; //~ ERROR E0605 + //~| NOTE an `as` expression can only be used to convert between primitive types + + let v = 0 as *const u8; + v as &u8; //~ ERROR E0605 + //~| NOTE an `as` expression can only be used to convert between primitive types +} diff --git a/src/test/ui/mismatched_types/cast-rfc0401.stderr b/src/test/ui/mismatched_types/cast-rfc0401.stderr index 82672d5d873..c79d242dc5e 100644 --- a/src/test/ui/mismatched_types/cast-rfc0401.stderr +++ b/src/test/ui/mismatched_types/cast-rfc0401.stderr @@ -20,35 +20,45 @@ error[E0609]: no field `f` on type `fn() {main}` 75 | let _ = main.f as *const u32; | ^ -error: non-scalar cast: `*const u8` as `&u8` +error[E0605]: non-scalar cast: `*const u8` as `&u8` --> $DIR/cast-rfc0401.rs:39:13 | 39 | let _ = v as &u8; | ^^^^^^^^ + | + = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait -error: non-scalar cast: `*const u8` as `E` +error[E0605]: non-scalar cast: `*const u8` as `E` --> $DIR/cast-rfc0401.rs:40:13 | 40 | let _ = v as E; | ^^^^^^ + | + = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait -error: non-scalar cast: `*const u8` as `fn()` +error[E0605]: non-scalar cast: `*const u8` as `fn()` --> $DIR/cast-rfc0401.rs:41:13 | 41 | let _ = v as fn(); | ^^^^^^^^^ + | + = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait -error: non-scalar cast: `*const u8` as `(u32,)` +error[E0605]: non-scalar cast: `*const u8` as `(u32,)` --> $DIR/cast-rfc0401.rs:42:13 | 42 | let _ = v as (u32,); | ^^^^^^^^^^^ + | + = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait -error: non-scalar cast: `std::option::Option<&*const u8>` as `*const u8` +error[E0605]: non-scalar cast: `std::option::Option<&*const u8>` as `*const u8` --> $DIR/cast-rfc0401.rs:43:13 | 43 | let _ = Some(&v) as *const u8; | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait error: casting `*const u8` as `f32` is invalid --> $DIR/cast-rfc0401.rs:45:13 diff --git a/src/test/ui/mismatched_types/issue-26480.stderr b/src/test/ui/mismatched_types/issue-26480.stderr index dc3764a376c..06b88069002 100644 --- a/src/test/ui/mismatched_types/issue-26480.stderr +++ b/src/test/ui/mismatched_types/issue-26480.stderr @@ -7,7 +7,7 @@ error[E0308]: mismatched types 37 | write!(hello); | -------------- in this macro invocation -error: non-scalar cast: `{integer}` as `()` +error[E0605]: non-scalar cast: `{integer}` as `()` --> $DIR/issue-26480.rs:32:19 | 32 | ($x:expr) => ($x as ()) @@ -15,6 +15,8 @@ error: non-scalar cast: `{integer}` as `()` ... 38 | cast!(2); | --------- in this macro invocation + | + = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait error: aborting due to previous error(s) From 30effc14e4ae23a682495ceadf7f56039b02e747 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 7 Jun 2017 23:54:51 +0200 Subject: [PATCH 029/162] Add E0606 --- src/librustc_typeck/check/cast.rs | 71 ++++++++----------- src/librustc_typeck/diagnostics.rs | 19 +++++ src/test/compile-fail/E0606.rs | 13 ++++ .../ui/mismatched_types/cast-rfc0401.stderr | 44 ++++++------ 4 files changed, 83 insertions(+), 64 deletions(-) create mode 100644 src/test/compile-fail/E0606.rs diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 69174dacaaa..5c255364311 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -40,9 +40,11 @@ use super::{Diverges, FnCtxt}; -use lint; +use errors::DiagnosticBuilder; use hir::def_id::DefId; +use lint; use rustc::hir; +use rustc::session::Session; use rustc::traits; use rustc::ty::{self, Ty, TypeFoldable}; use rustc::ty::cast::{CastKind, CastTy}; @@ -112,6 +114,18 @@ enum CastError { NonScalar, } +fn make_invalid_casting_error<'a, 'gcx, 'tcx>(sess: &'a Session, + span: Span, + expr_ty: Ty<'tcx>, + cast_ty: Ty<'tcx>, + fcx: &FnCtxt<'a, 'gcx, 'tcx>) + -> DiagnosticBuilder<'a> { + struct_span_err!(sess, span, E0606, + "casting `{}` as `{}` is invalid", + fcx.ty_to_string(expr_ty), + fcx.ty_to_string(cast_ty)) +} + impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { pub fn new(fcx: &FnCtxt<'a, 'gcx, 'tcx>, expr: &'tcx hir::Expr, @@ -146,14 +160,9 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { match e { CastError::NeedDeref => { let error_span = self.span; + let mut err = make_invalid_casting_error(fcx.tcx.sess, self.span, self.expr_ty, + self.cast_ty, fcx); let cast_ty = fcx.ty_to_string(self.cast_ty); - let mut err = fcx.type_error_struct(error_span, - |actual| { - format!("casting `{}` as `{}` is invalid", - actual, - cast_ty) - }, - self.expr_ty); err.span_label(error_span, format!("cannot cast `{}` as `{}`", fcx.ty_to_string(self.expr_ty), @@ -166,13 +175,8 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { } CastError::NeedViaThinPtr | CastError::NeedViaPtr => { - let mut err = fcx.type_error_struct(self.span, - |actual| { - format!("casting `{}` as `{}` is invalid", - actual, - fcx.ty_to_string(self.cast_ty)) - }, - self.expr_ty); + let mut err = make_invalid_casting_error(fcx.tcx.sess, self.span, self.expr_ty, + self.cast_ty, fcx); if self.cast_ty.is_uint() { err.help(&format!("cast through {} first", match e { @@ -184,13 +188,7 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { err.emit(); } CastError::NeedViaInt => { - fcx.type_error_struct(self.span, - |actual| { - format!("casting `{}` as `{}` is invalid", - actual, - fcx.ty_to_string(self.cast_ty)) - }, - self.expr_ty) + make_invalid_casting_error(fcx.tcx.sess, self.span, self.expr_ty, self.cast_ty, fcx) .help(&format!("cast through {} first", match e { CastError::NeedViaInt => "an integer", @@ -198,6 +196,15 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { })) .emit(); } + CastError::IllegalCast => { + make_invalid_casting_error(fcx.tcx.sess, self.span, self.expr_ty, self.cast_ty, fcx) + .emit(); + } + CastError::DifferingKinds => { + make_invalid_casting_error(fcx.tcx.sess, self.span, self.expr_ty, self.cast_ty, fcx) + .note("vtable kinds may not match") + .emit(); + } CastError::CastToBool => { struct_span_err!(fcx.tcx.sess, self.span, E0054, "cannot cast as `bool`") .span_label(self.span, "unsupported cast") @@ -217,15 +224,6 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { primitive types. Consider using the `From` trait") .emit(); } - CastError::IllegalCast => { - fcx.type_error_message(self.span, - |actual| { - format!("casting `{}` as `{}` is invalid", - actual, - fcx.ty_to_string(self.cast_ty)) - }, - self.expr_ty); - } CastError::SizedUnsizedCast => { fcx.type_error_message(self.span, |actual| { @@ -236,17 +234,6 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { }, self.expr_ty) } - CastError::DifferingKinds => { - fcx.type_error_struct(self.span, - |actual| { - format!("casting `{}` as `{}` is invalid", - actual, - fcx.ty_to_string(self.cast_ty)) - }, - self.expr_ty) - .note("vtable kinds may not match") - .emit(); - } } } diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index a787aadc678..d3138af978a 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -4251,6 +4251,25 @@ v as *const i8; // ok! ``` "##, +E0606: r##" +An incompatible cast was attempted. + +Erroneous code example: + +```compile_fail,E0606 +let x = &0u8; // Here, `x` is a `&u8`. +let y: u32 = x as u32; // error: casting `&u8` as `u32` is invalid +``` + +When casting, keep in mind that only primitive types cast be casted into each +others. Example: + +``` +let x = &0u8; +let y: u32 = *x as u32; // We dereference it first and then cast it. +``` +"##, + E0609: r##" Attempted to access a non-existent field in a struct. diff --git a/src/test/compile-fail/E0606.rs b/src/test/compile-fail/E0606.rs new file mode 100644 index 00000000000..55071736bfe --- /dev/null +++ b/src/test/compile-fail/E0606.rs @@ -0,0 +1,13 @@ +// Copyright 2017 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() { + &0u8 as u8; //~ ERROR E0606 +} diff --git a/src/test/ui/mismatched_types/cast-rfc0401.stderr b/src/test/ui/mismatched_types/cast-rfc0401.stderr index c79d242dc5e..b4c3106253e 100644 --- a/src/test/ui/mismatched_types/cast-rfc0401.stderr +++ b/src/test/ui/mismatched_types/cast-rfc0401.stderr @@ -1,4 +1,4 @@ -error: casting `*const U` as `*const V` is invalid +error[E0606]: casting `*const U` as `*const V` is invalid --> $DIR/cast-rfc0401.rs:13:5 | 13 | u as *const V @@ -6,7 +6,7 @@ error: casting `*const U` as `*const V` is invalid | = note: vtable kinds may not match -error: casting `*const U` as `*const str` is invalid +error[E0606]: casting `*const U` as `*const str` is invalid --> $DIR/cast-rfc0401.rs:18:5 | 18 | u as *const str @@ -60,19 +60,19 @@ error[E0605]: non-scalar cast: `std::option::Option<&*const u8>` as `*const u8` | = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait -error: casting `*const u8` as `f32` is invalid +error[E0606]: casting `*const u8` as `f32` is invalid --> $DIR/cast-rfc0401.rs:45:13 | 45 | let _ = v as f32; | ^^^^^^^^ -error: casting `fn() {main}` as `f64` is invalid +error[E0606]: casting `fn() {main}` as `f64` is invalid --> $DIR/cast-rfc0401.rs:46:13 | 46 | let _ = main as f64; | ^^^^^^^^^^^ -error: casting `&*const u8` as `usize` is invalid +error[E0606]: casting `&*const u8` as `usize` is invalid --> $DIR/cast-rfc0401.rs:47:13 | 47 | let _ = &v as usize; @@ -80,7 +80,7 @@ error: casting `&*const u8` as `usize` is invalid | = help: cast through a raw pointer first -error: casting `f32` as `*const u8` is invalid +error[E0606]: casting `f32` as `*const u8` is invalid --> $DIR/cast-rfc0401.rs:48:13 | 48 | let _ = f as *const u8; @@ -108,7 +108,7 @@ error[E0604]: only `u8` can be cast as `char`, not `u32` 51 | let _ = 0x61u32 as char; | ^^^^^^^^^^^^^^^ -error: casting `bool` as `f32` is invalid +error[E0606]: casting `bool` as `f32` is invalid --> $DIR/cast-rfc0401.rs:53:13 | 53 | let _ = false as f32; @@ -116,7 +116,7 @@ error: casting `bool` as `f32` is invalid | = help: cast through an integer first -error: casting `E` as `f32` is invalid +error[E0606]: casting `E` as `f32` is invalid --> $DIR/cast-rfc0401.rs:54:13 | 54 | let _ = E::A as f32; @@ -124,7 +124,7 @@ error: casting `E` as `f32` is invalid | = help: cast through an integer first -error: casting `char` as `f32` is invalid +error[E0606]: casting `char` as `f32` is invalid --> $DIR/cast-rfc0401.rs:55:13 | 55 | let _ = 'a' as f32; @@ -132,25 +132,25 @@ error: casting `char` as `f32` is invalid | = help: cast through an integer first -error: casting `bool` as `*const u8` is invalid +error[E0606]: casting `bool` as `*const u8` is invalid --> $DIR/cast-rfc0401.rs:57:13 | 57 | let _ = false as *const u8; | ^^^^^^^^^^^^^^^^^^ -error: casting `E` as `*const u8` is invalid +error[E0606]: casting `E` as `*const u8` is invalid --> $DIR/cast-rfc0401.rs:58:13 | 58 | let _ = E::A as *const u8; | ^^^^^^^^^^^^^^^^^ -error: casting `char` as `*const u8` is invalid +error[E0606]: casting `char` as `*const u8` is invalid --> $DIR/cast-rfc0401.rs:59:13 | 59 | let _ = 'a' as *const u8; | ^^^^^^^^^^^^^^^^ -error: casting `usize` as `*const [u8]` is invalid +error[E0606]: casting `usize` as `*const [u8]` is invalid --> $DIR/cast-rfc0401.rs:61:13 | 61 | let _ = 42usize as *const [u8]; @@ -162,37 +162,37 @@ error: cannot cast thin pointer `*const u8` to fat pointer `*const [u8]` 62 | let _ = v as *const [u8]; | ^^^^^^^^^^^^^^^^ -error: casting `&Foo` as `*const str` is invalid +error[E0606]: casting `&Foo` as `*const str` is invalid --> $DIR/cast-rfc0401.rs:64:13 | 64 | let _ = foo as *const str; | ^^^^^^^^^^^^^^^^^ -error: casting `&Foo` as `*mut str` is invalid +error[E0606]: casting `&Foo` as `*mut str` is invalid --> $DIR/cast-rfc0401.rs:65:13 | 65 | let _ = foo as *mut str; | ^^^^^^^^^^^^^^^ -error: casting `fn() {main}` as `*mut str` is invalid +error[E0606]: casting `fn() {main}` as `*mut str` is invalid --> $DIR/cast-rfc0401.rs:66:13 | 66 | let _ = main as *mut str; | ^^^^^^^^^^^^^^^^ -error: casting `&f32` as `*mut f32` is invalid +error[E0606]: casting `&f32` as `*mut f32` is invalid --> $DIR/cast-rfc0401.rs:67:13 | 67 | let _ = &f as *mut f32; | ^^^^^^^^^^^^^^ -error: casting `&f32` as `*const f64` is invalid +error[E0606]: casting `&f32` as `*const f64` is invalid --> $DIR/cast-rfc0401.rs:68:13 | 68 | let _ = &f as *const f64; | ^^^^^^^^^^^^^^^^ -error: casting `*const [i8]` as `usize` is invalid +error[E0606]: casting `*const [i8]` as `usize` is invalid --> $DIR/cast-rfc0401.rs:69:13 | 69 | let _ = fat_sv as usize; @@ -200,7 +200,7 @@ error: casting `*const [i8]` as `usize` is invalid | = help: cast through a thin pointer first -error: casting `*const Foo` as `*const [u16]` is invalid +error[E0606]: casting `*const Foo` as `*const [u16]` is invalid --> $DIR/cast-rfc0401.rs:78:13 | 78 | let _ = cf as *const [u16]; @@ -208,7 +208,7 @@ error: casting `*const Foo` as `*const [u16]` is invalid | = note: vtable kinds may not match -error: casting `*const Foo` as `*const Bar` is invalid +error[E0606]: casting `*const Foo` as `*const Bar` is invalid --> $DIR/cast-rfc0401.rs:79:13 | 79 | let _ = cf as *const Bar; @@ -234,7 +234,7 @@ error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied = help: the trait `std::marker::Sized` is not implemented for `str` = note: required for the cast to the object type `Foo` -error: casting `&{float}` as `f32` is invalid +error[E0606]: casting `&{float}` as `f32` is invalid --> $DIR/cast-rfc0401.rs:81:30 | 81 | vec![0.0].iter().map(|s| s as f32).collect::>(); From 7b8c6a2d30f7e6acee89a735ad8fd86c1e1c2370 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 8 Jun 2017 00:13:28 +0200 Subject: [PATCH 030/162] Add E0607 --- src/librustc_typeck/check/cast.rs | 12 ++++------ src/librustc_typeck/diagnostics.rs | 23 +++++++++++++++++++ src/test/compile-fail/E0607.rs | 14 +++++++++++ .../ui/mismatched_types/cast-rfc0401.stderr | 2 +- 4 files changed, 42 insertions(+), 9 deletions(-) create mode 100644 src/test/compile-fail/E0607.rs diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 5c255364311..52962e1e478 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -225,14 +225,10 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { .emit(); } CastError::SizedUnsizedCast => { - fcx.type_error_message(self.span, - |actual| { - format!("cannot cast thin pointer `{}` to fat pointer \ - `{}`", - actual, - fcx.ty_to_string(self.cast_ty)) - }, - self.expr_ty) + struct_span_err!(fcx.tcx.sess, self.span, E0607, + "cannot cast thin pointer `{}` to fat pointer `{}`", + self.expr_ty, + fcx.ty_to_string(self.cast_ty)).emit(); } } } diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index d3138af978a..ae13e236743 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -4270,6 +4270,29 @@ let y: u32 = *x as u32; // We dereference it first and then cast it. ``` "##, +E0607: r##" +A cast between a thin and a fat pointer was attempted. + +Erroneous code example: + +```compile_fail,E0607 +let v = 0 as *const u8; +v as *const [u8]; +``` + +First: what are thin and fat pointers? + +Thin pointers are "simple" pointers that simply reference a memory address. + +Fat pointers are pointers referencing Dynamically Sized Types (also called DST). +They don't have a statically known size, therefore they can only exist behind +some kind of pointers that contain additional information. Slices and trait +objects are DSTs. + +So in order to fix this error, don't try to cast directly between thin and fat +pointers. +"##, + E0609: r##" Attempted to access a non-existent field in a struct. diff --git a/src/test/compile-fail/E0607.rs b/src/test/compile-fail/E0607.rs new file mode 100644 index 00000000000..fa761f2c178 --- /dev/null +++ b/src/test/compile-fail/E0607.rs @@ -0,0 +1,14 @@ +// Copyright 2017 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 v = 0 as *const u8; + v as *const [u8]; //~ ERROR E0607 +} diff --git a/src/test/ui/mismatched_types/cast-rfc0401.stderr b/src/test/ui/mismatched_types/cast-rfc0401.stderr index b4c3106253e..50e18150579 100644 --- a/src/test/ui/mismatched_types/cast-rfc0401.stderr +++ b/src/test/ui/mismatched_types/cast-rfc0401.stderr @@ -156,7 +156,7 @@ error[E0606]: casting `usize` as `*const [u8]` is invalid 61 | let _ = 42usize as *const [u8]; | ^^^^^^^^^^^^^^^^^^^^^^ -error: cannot cast thin pointer `*const u8` to fat pointer `*const [u8]` +error[E0607]: cannot cast thin pointer `*const u8` to fat pointer `*const [u8]` --> $DIR/cast-rfc0401.rs:62:13 | 62 | let _ = v as *const [u8]; From deb1eb6134a8ac22c55dc3e9713d667ff352ecf5 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 9 Jun 2017 22:04:29 +0200 Subject: [PATCH 031/162] wording improvement --- src/librustc_typeck/check/cast.rs | 2 +- src/librustc_typeck/diagnostics.rs | 27 ++++++++++--------- src/test/compile-fail/cast-from-nil.rs | 2 +- src/test/compile-fail/cast-to-bare-fn.rs | 4 +-- src/test/compile-fail/cast-to-nil.rs | 2 +- src/test/compile-fail/closure-no-fn-3.rs | 2 +- src/test/compile-fail/coerce-to-bang-cast.rs | 2 +- src/test/compile-fail/fat-ptr-cast.rs | 2 +- src/test/compile-fail/issue-10991.rs | 2 +- src/test/compile-fail/issue-22289.rs | 2 +- src/test/compile-fail/issue-22312.rs | 2 +- src/test/compile-fail/issue-2995.rs | 2 +- src/test/compile-fail/nonscalar-cast.rs | 4 +-- .../tag-variant-cast-non-nullary.rs | 4 +-- .../compile-fail/uninhabited-enum-cast.rs | 2 +- .../ui/mismatched_types/cast-rfc0401.stderr | 10 +++---- .../ui/mismatched_types/issue-26480.stderr | 2 +- 17 files changed, 35 insertions(+), 38 deletions(-) diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 52962e1e478..aec9d6f16d2 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -217,7 +217,7 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { } CastError::NonScalar => { struct_span_err!(fcx.tcx.sess, self.span, E0605, - "non-scalar cast: `{}` as `{}`", + "non-primitive cast: `{}` as `{}`", self.expr_ty, fcx.ty_to_string(self.cast_ty)) .note("an `as` expression can only be used to convert between \ diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index ae13e236743..f9b44f0395f 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -4209,7 +4209,7 @@ println!("{}", v[2]); "##, E0604: r##" -A cast to `char` was attempted on another type than `u8`. +A cast to `char` was attempted on a type other than `u8`. Erroneous code example: @@ -4217,11 +4217,11 @@ Erroneous code example: 0u32 as char; // error: only `u8` can be cast as `char`, not `u32` ``` -As the error message indicates, only `u8` can be casted into `char`. Example: +As the error message indicates, only `u8` can be cast into `char`. Example: ``` let c = 86u8 as char; // ok! -assert!(c, 'V'); +assert_eq!(c, 'V'); ``` "##, @@ -4232,15 +4232,15 @@ Erroneous code examples: ```compile_fail,E0605 let x = 0u8; -x as Vec; // error: non-scalar cast: `u8` as `std::vec::Vec` +x as Vec; // error: non-primitive cast: `u8` as `std::vec::Vec` // Another example let v = 0 as *const u8; // So here, `v` is a `*const u8`. -v as &u8; // error: non-scalar cast: `*const u8` as `&u8` +v as &u8; // error: non-primitive cast: `*const u8` as `&u8` ``` -Only primitive types cast be casted into each others. Examples: +Only primitive types can be cast into each other. Examples: ``` let x = 0u8; @@ -4261,8 +4261,8 @@ let x = &0u8; // Here, `x` is a `&u8`. let y: u32 = x as u32; // error: casting `&u8` as `u32` is invalid ``` -When casting, keep in mind that only primitive types cast be casted into each -others. Example: +When casting, keep in mind that only primitive types can be cast into each +other. Example: ``` let x = &0u8; @@ -4282,15 +4282,16 @@ v as *const [u8]; First: what are thin and fat pointers? -Thin pointers are "simple" pointers that simply reference a memory address. +Thin pointers are "simple" pointers: they are purely a reference to a memory +address. Fat pointers are pointers referencing Dynamically Sized Types (also called DST). -They don't have a statically known size, therefore they can only exist behind +DST don't have a statically known size, therefore they can only exist behind some kind of pointers that contain additional information. Slices and trait -objects are DSTs. +objects are DSTs. In the case of slices, the additional information the fat +pointer holds is their size. -So in order to fix this error, don't try to cast directly between thin and fat -pointers. +To fix this error, don't try to cast directly between thin and fat pointers. "##, E0609: r##" diff --git a/src/test/compile-fail/cast-from-nil.rs b/src/test/compile-fail/cast-from-nil.rs index 4c6dcaccc9a..ab22d352480 100644 --- a/src/test/compile-fail/cast-from-nil.rs +++ b/src/test/compile-fail/cast-from-nil.rs @@ -8,5 +8,5 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern: non-scalar cast: `()` as `u32` +// error-pattern: non-primitive cast: `()` as `u32` fn main() { let u = (assert!(true) as u32); } diff --git a/src/test/compile-fail/cast-to-bare-fn.rs b/src/test/compile-fail/cast-to-bare-fn.rs index 7cc5c727bc7..d5a998c6e4b 100644 --- a/src/test/compile-fail/cast-to-bare-fn.rs +++ b/src/test/compile-fail/cast-to-bare-fn.rs @@ -13,8 +13,8 @@ fn foo(_x: isize) { } fn main() { let v: u64 = 5; let x = foo as extern "C" fn() -> isize; - //~^ ERROR non-scalar cast + //~^ ERROR non-primitive cast let y = v as extern "Rust" fn(isize) -> (isize, isize); - //~^ ERROR non-scalar cast + //~^ ERROR non-primitive cast y(x()); } diff --git a/src/test/compile-fail/cast-to-nil.rs b/src/test/compile-fail/cast-to-nil.rs index e5fd5bb33eb..27d9e8a42b1 100644 --- a/src/test/compile-fail/cast-to-nil.rs +++ b/src/test/compile-fail/cast-to-nil.rs @@ -8,5 +8,5 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern: non-scalar cast: `u32` as `()` +// error-pattern: non-primitive cast: `u32` as `()` fn main() { let u = 0u32 as (); } diff --git a/src/test/compile-fail/closure-no-fn-3.rs b/src/test/compile-fail/closure-no-fn-3.rs index 85dbc899208..6584c16c9de 100644 --- a/src/test/compile-fail/closure-no-fn-3.rs +++ b/src/test/compile-fail/closure-no-fn-3.rs @@ -14,5 +14,5 @@ fn main() { let b = 0u8; let baz: fn() -> u8 = (|| { b }) as fn() -> u8; - //~^ ERROR non-scalar cast + //~^ ERROR non-primitive cast } diff --git a/src/test/compile-fail/coerce-to-bang-cast.rs b/src/test/compile-fail/coerce-to-bang-cast.rs index 57d2192e635..0479f5cce65 100644 --- a/src/test/compile-fail/coerce-to-bang-cast.rs +++ b/src/test/compile-fail/coerce-to-bang-cast.rs @@ -17,7 +17,7 @@ fn cast_a() { } fn cast_b() { - let y = 22 as !; //~ ERROR non-scalar cast + let y = 22 as !; //~ ERROR non-primitive cast } fn main() { } diff --git a/src/test/compile-fail/fat-ptr-cast.rs b/src/test/compile-fail/fat-ptr-cast.rs index c62987a5b90..bc2dc1cc5d4 100644 --- a/src/test/compile-fail/fat-ptr-cast.rs +++ b/src/test/compile-fail/fat-ptr-cast.rs @@ -22,7 +22,7 @@ fn main() { a as isize; //~ ERROR casting a as i16; //~ ERROR casting `&[i32]` as `i16` is invalid a as u32; //~ ERROR casting `&[i32]` as `u32` is invalid - b as usize; //~ ERROR non-scalar cast + b as usize; //~ ERROR non-primitive cast p as usize; //~^ ERROR casting //~^^ HELP cast through a thin pointer diff --git a/src/test/compile-fail/issue-10991.rs b/src/test/compile-fail/issue-10991.rs index 25060b94dcf..2d00f339f33 100644 --- a/src/test/compile-fail/issue-10991.rs +++ b/src/test/compile-fail/issue-10991.rs @@ -10,5 +10,5 @@ fn main() { let nil = (); - let _t = nil as usize; //~ ERROR: non-scalar cast: `()` as `usize` + let _t = nil as usize; //~ ERROR: non-primitive cast: `()` as `usize` } diff --git a/src/test/compile-fail/issue-22289.rs b/src/test/compile-fail/issue-22289.rs index bcbc414d353..c23fc4f3344 100644 --- a/src/test/compile-fail/issue-22289.rs +++ b/src/test/compile-fail/issue-22289.rs @@ -9,5 +9,5 @@ // except according to those terms. fn main() { - 0 as &std::any::Any; //~ ERROR non-scalar cast + 0 as &std::any::Any; //~ ERROR non-primitive cast } diff --git a/src/test/compile-fail/issue-22312.rs b/src/test/compile-fail/issue-22312.rs index 4d6e6eded21..2128c420630 100644 --- a/src/test/compile-fail/issue-22312.rs +++ b/src/test/compile-fail/issue-22312.rs @@ -19,7 +19,7 @@ pub trait Array2D: Index { } let i = y * self.columns() + x; let indexer = &(*self as &Index>::Output>); - //~^ERROR non-scalar cast + //~^ERROR non-primitive cast Some(indexer.index(i)) } } diff --git a/src/test/compile-fail/issue-2995.rs b/src/test/compile-fail/issue-2995.rs index 8fbf97411cc..d735e184d5c 100644 --- a/src/test/compile-fail/issue-2995.rs +++ b/src/test/compile-fail/issue-2995.rs @@ -9,7 +9,7 @@ // except according to those terms. fn bad (p: *const isize) { - let _q: &isize = p as &isize; //~ ERROR non-scalar cast + let _q: &isize = p as &isize; //~ ERROR non-primitive cast } fn main() { } diff --git a/src/test/compile-fail/nonscalar-cast.rs b/src/test/compile-fail/nonscalar-cast.rs index d6f274da967..0abbc05eef0 100644 --- a/src/test/compile-fail/nonscalar-cast.rs +++ b/src/test/compile-fail/nonscalar-cast.rs @@ -8,13 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern:non-scalar cast - #[derive(Debug)] struct foo { x: isize } fn main() { - println!("{}", foo{ x: 1 } as isize); + println!("{}", foo{ x: 1 } as isize); //~ non-primitive cast: `foo` as `isize` [E0605] } diff --git a/src/test/compile-fail/tag-variant-cast-non-nullary.rs b/src/test/compile-fail/tag-variant-cast-non-nullary.rs index b0106329126..220537633ea 100644 --- a/src/test/compile-fail/tag-variant-cast-non-nullary.rs +++ b/src/test/compile-fail/tag-variant-cast-non-nullary.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//error-pattern: non-scalar cast - enum non_nullary { nullary, other(isize), @@ -17,5 +15,5 @@ enum non_nullary { fn main() { let v = non_nullary::nullary; - let val = v as isize; + let val = v as isize; //~ ERROR non-primitive cast: `non_nullary` as `isize` [E0605] } diff --git a/src/test/compile-fail/uninhabited-enum-cast.rs b/src/test/compile-fail/uninhabited-enum-cast.rs index b4df5fb1e2a..2a5d25e6b98 100644 --- a/src/test/compile-fail/uninhabited-enum-cast.rs +++ b/src/test/compile-fail/uninhabited-enum-cast.rs @@ -11,7 +11,7 @@ enum E {} fn f(e: E) { - println!("{}", (e as isize).to_string()); //~ ERROR non-scalar cast + println!("{}", (e as isize).to_string()); //~ ERROR non-primitive cast } fn main() {} diff --git a/src/test/ui/mismatched_types/cast-rfc0401.stderr b/src/test/ui/mismatched_types/cast-rfc0401.stderr index 50e18150579..879acbcf9d9 100644 --- a/src/test/ui/mismatched_types/cast-rfc0401.stderr +++ b/src/test/ui/mismatched_types/cast-rfc0401.stderr @@ -20,7 +20,7 @@ error[E0609]: no field `f` on type `fn() {main}` 75 | let _ = main.f as *const u32; | ^ -error[E0605]: non-scalar cast: `*const u8` as `&u8` +error[E0605]: non-primitive cast: `*const u8` as `&u8` --> $DIR/cast-rfc0401.rs:39:13 | 39 | let _ = v as &u8; @@ -28,7 +28,7 @@ error[E0605]: non-scalar cast: `*const u8` as `&u8` | = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait -error[E0605]: non-scalar cast: `*const u8` as `E` +error[E0605]: non-primitive cast: `*const u8` as `E` --> $DIR/cast-rfc0401.rs:40:13 | 40 | let _ = v as E; @@ -36,7 +36,7 @@ error[E0605]: non-scalar cast: `*const u8` as `E` | = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait -error[E0605]: non-scalar cast: `*const u8` as `fn()` +error[E0605]: non-primitive cast: `*const u8` as `fn()` --> $DIR/cast-rfc0401.rs:41:13 | 41 | let _ = v as fn(); @@ -44,7 +44,7 @@ error[E0605]: non-scalar cast: `*const u8` as `fn()` | = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait -error[E0605]: non-scalar cast: `*const u8` as `(u32,)` +error[E0605]: non-primitive cast: `*const u8` as `(u32,)` --> $DIR/cast-rfc0401.rs:42:13 | 42 | let _ = v as (u32,); @@ -52,7 +52,7 @@ error[E0605]: non-scalar cast: `*const u8` as `(u32,)` | = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait -error[E0605]: non-scalar cast: `std::option::Option<&*const u8>` as `*const u8` +error[E0605]: non-primitive cast: `std::option::Option<&*const u8>` as `*const u8` --> $DIR/cast-rfc0401.rs:43:13 | 43 | let _ = Some(&v) as *const u8; diff --git a/src/test/ui/mismatched_types/issue-26480.stderr b/src/test/ui/mismatched_types/issue-26480.stderr index 06b88069002..9da9042e78e 100644 --- a/src/test/ui/mismatched_types/issue-26480.stderr +++ b/src/test/ui/mismatched_types/issue-26480.stderr @@ -7,7 +7,7 @@ error[E0308]: mismatched types 37 | write!(hello); | -------------- in this macro invocation -error[E0605]: non-scalar cast: `{integer}` as `()` +error[E0605]: non-primitive cast: `{integer}` as `()` --> $DIR/issue-26480.rs:32:19 | 32 | ($x:expr) => ($x as ()) From 9137153e4725649443ac02f742424aa5737d15b6 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 12 Jun 2017 18:58:11 +0200 Subject: [PATCH 032/162] Use new macro instead --- src/librustc_typeck/check/cast.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index aec9d6f16d2..ea08f1f624e 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -120,10 +120,10 @@ fn make_invalid_casting_error<'a, 'gcx, 'tcx>(sess: &'a Session, cast_ty: Ty<'tcx>, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> DiagnosticBuilder<'a> { - struct_span_err!(sess, span, E0606, - "casting `{}` as `{}` is invalid", - fcx.ty_to_string(expr_ty), - fcx.ty_to_string(cast_ty)) + type_error_struct!(sess, span, expr_ty, E0606, + "casting `{}` as `{}` is invalid", + fcx.ty_to_string(expr_ty), + fcx.ty_to_string(cast_ty)) } impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { @@ -212,11 +212,11 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { .emit(); } CastError::CastToChar => { - struct_span_err!(fcx.tcx.sess, self.span, E0604, + type_error_struct!(fcx.tcx.sess, self.span, self.expr_ty, E0604, "only `u8` can be cast as `char`, not `{}`", self.expr_ty).emit(); } CastError::NonScalar => { - struct_span_err!(fcx.tcx.sess, self.span, E0605, + type_error_struct!(fcx.tcx.sess, self.span, self.expr_ty, E0605, "non-primitive cast: `{}` as `{}`", self.expr_ty, fcx.ty_to_string(self.cast_ty)) @@ -225,7 +225,7 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { .emit(); } CastError::SizedUnsizedCast => { - struct_span_err!(fcx.tcx.sess, self.span, E0607, + type_error_struct!(fcx.tcx.sess, self.span, self.expr_ty, E0607, "cannot cast thin pointer `{}` to fat pointer `{}`", self.expr_ty, fcx.ty_to_string(self.cast_ty)).emit(); From 8edc3cae3bd853fc0d7714c2135754dce0ba10eb Mon Sep 17 00:00:00 2001 From: Paul Woolcock Date: Fri, 23 Jun 2017 11:01:41 -0400 Subject: [PATCH 033/162] Add compile-fail test for the new feature gate --- .../compile-fail/feature-gate-allow_fail.rs | 17 +++++++++++++++++ src/test/run-pass/test-allow-fail-attr.rs | 1 + 2 files changed, 18 insertions(+) create mode 100644 src/test/compile-fail/feature-gate-allow_fail.rs diff --git a/src/test/compile-fail/feature-gate-allow_fail.rs b/src/test/compile-fail/feature-gate-allow_fail.rs new file mode 100644 index 00000000000..11247402809 --- /dev/null +++ b/src/test/compile-fail/feature-gate-allow_fail.rs @@ -0,0 +1,17 @@ +// 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. + +// check that #[allow_fail] is feature-gated + +#[allow_fail] //~ ERROR allow_fail attribute is currently unstable +fn ok_to_fail() { + assert!(false); +} + diff --git a/src/test/run-pass/test-allow-fail-attr.rs b/src/test/run-pass/test-allow-fail-attr.rs index 7d750d51dcd..aa9cf76617f 100644 --- a/src/test/run-pass/test-allow-fail-attr.rs +++ b/src/test/run-pass/test-allow-fail-attr.rs @@ -9,6 +9,7 @@ // except according to those terms. // compile-flags: --test +#![feature(allow_fail)] #[test] #[allow_fail] From 14c2f99f80c6bb1bcae021ee3174cfc787e1de51 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Thu, 8 Jun 2017 11:31:25 -0400 Subject: [PATCH 034/162] Stabilize Command::envs Closes #38526 --- src/librustc_trans/lib.rs | 1 - src/libstd/process.rs | 4 +--- src/test/run-pass/process-envs.rs | 2 -- 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index 859c6574787..d480f249b44 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -34,7 +34,6 @@ #![feature(rustc_diagnostic_macros)] #![feature(slice_patterns)] #![feature(conservative_impl_trait)] -#![feature(command_envs)] use rustc::dep_graph::WorkProduct; use syntax_pos::symbol::Symbol; diff --git a/src/libstd/process.rs b/src/libstd/process.rs index df6a648b7b1..7adfcc44ad0 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -447,8 +447,6 @@ impl Command { /// Basic usage: /// /// ```no_run - /// #![feature(command_envs)] - /// /// use std::process::{Command, Stdio}; /// use std::env; /// use std::collections::HashMap; @@ -466,7 +464,7 @@ impl Command { /// .spawn() /// .expect("printenv failed to start"); /// ``` - #[unstable(feature = "command_envs", issue = "38526")] + #[stable(feature = "command_envs", since = "1.19.0")] pub fn envs(&mut self, vars: I) -> &mut Command where I: IntoIterator, K: AsRef, V: AsRef { diff --git a/src/test/run-pass/process-envs.rs b/src/test/run-pass/process-envs.rs index a131dcbe4dd..b3785d898ba 100644 --- a/src/test/run-pass/process-envs.rs +++ b/src/test/run-pass/process-envs.rs @@ -10,8 +10,6 @@ // ignore-emscripten -#![feature(command_envs)] - use std::process::Command; use std::env; use std::collections::HashMap; From 05cbdb1badc0e9fc0decf2f25f4901e966191219 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Thu, 8 Jun 2017 11:34:22 -0400 Subject: [PATCH 035/162] Stabilize cmp::Reverse Closes #40893 --- src/libcore/cmp.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 6f35d0417f1..33d2f729e1a 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -335,7 +335,6 @@ impl Ordering { /// Example usage: /// /// ``` -/// #![feature(reverse_cmp_key)] /// use std::cmp::Reverse; /// /// let mut v = vec![1, 2, 3, 4, 5, 6]; @@ -343,10 +342,10 @@ impl Ordering { /// assert_eq!(v, vec![3, 2, 1, 6, 5, 4]); /// ``` #[derive(PartialEq, Eq, Debug)] -#[unstable(feature = "reverse_cmp_key", issue = "40893")] +#[stable(feature = "reverse_cmp_key", since = "1.19.0")] pub struct Reverse(pub T); -#[unstable(feature = "reverse_cmp_key", issue = "40893")] +#[stable(feature = "reverse_cmp_key", since = "1.19.0")] impl PartialOrd for Reverse { #[inline] fn partial_cmp(&self, other: &Reverse) -> Option { @@ -363,7 +362,7 @@ impl PartialOrd for Reverse { fn gt(&self, other: &Self) -> bool { other.0 > self.0 } } -#[unstable(feature = "reverse_cmp_key", issue = "40893")] +#[stable(feature = "reverse_cmp_key", since = "1.19.0")] impl Ord for Reverse { #[inline] fn cmp(&self, other: &Reverse) -> Ordering { From ea4fb8ee2731c4ea1739a70fde1a7fdba8a3f42e Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Thu, 8 Jun 2017 11:35:46 -0400 Subject: [PATCH 036/162] Stabilize OsString::shrink_to_fit Closes #40421 --- src/libstd/ffi/os_str.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index f54d79c201f..2b13ecf9a10 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -230,8 +230,6 @@ impl OsString { /// # Examples /// /// ``` - /// #![feature(osstring_shrink_to_fit)] - /// /// use std::ffi::OsString; /// /// let mut s = OsString::from("foo"); @@ -242,7 +240,7 @@ impl OsString { /// s.shrink_to_fit(); /// assert_eq!(3, s.capacity()); /// ``` - #[unstable(feature = "osstring_shrink_to_fit", issue = "40421")] + #[stable(feature = "osstring_shrink_to_fit", since = "1.19.0")] pub fn shrink_to_fit(&mut self) { self.inner.shrink_to_fit() } From dc411e307ac76af0fd2128da5ea12562c84a48c6 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Thu, 8 Jun 2017 11:41:23 -0400 Subject: [PATCH 037/162] Stabilize ThreadId Closes #21507 --- src/libstd/thread/mod.rs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 743b7c3220a..f4fe52ca3b3 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -825,8 +825,6 @@ pub fn park_timeout(dur: Duration) { /// # Examples /// /// ``` -/// #![feature(thread_id)] -/// /// use std::thread; /// /// let other_thread = thread::spawn(|| { @@ -836,7 +834,7 @@ pub fn park_timeout(dur: Duration) { /// let other_thread_id = other_thread.join().unwrap(); /// assert!(thread::current().id() != other_thread_id); /// ``` -#[unstable(feature = "thread_id", issue = "21507")] +#[stable(feature = "thread_id", since = "1.19.0")] #[derive(Eq, PartialEq, Clone, Copy, Hash, Debug)] pub struct ThreadId(u64); @@ -966,8 +964,6 @@ impl Thread { /// # Examples /// /// ``` - /// #![feature(thread_id)] - /// /// use std::thread; /// /// let other_thread = thread::spawn(|| { @@ -977,7 +973,7 @@ impl Thread { /// let other_thread_id = other_thread.join().unwrap(); /// assert!(thread::current().id() != other_thread_id); /// ``` - #[unstable(feature = "thread_id", issue = "21507")] + #[stable(feature = "thread_id", since = "1.19.0")] pub fn id(&self) -> ThreadId { self.inner.id } @@ -1168,8 +1164,6 @@ impl JoinHandle { /// # Examples /// /// ``` - /// #![feature(thread_id)] - /// /// use std::thread; /// /// let builder = thread::Builder::new(); From 143206d54d7558c2326212df99efc98110904fdb Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 18 Jun 2017 22:01:29 -0700 Subject: [PATCH 038/162] Stabilize RangeArgument Move it and Bound to core::ops while we're at it. Closes #30877 --- src/liballoc/btree/map.rs | 5 +- src/liballoc/btree/set.rs | 3 +- src/liballoc/lib.rs | 51 +---- src/liballoc/range.rs | 138 +------------- src/liballoc/string.rs | 5 +- src/liballoc/vec.rs | 5 +- src/liballoc/vec_deque.rs | 5 +- src/libcollections/lib.rs | 1 + src/libcore/ops/mod.rs | 3 + src/libcore/ops/range.rs | 174 +++++++++++++++++- .../accumulate_vec.rs | 3 +- src/librustc_data_structures/array_vec.rs | 5 +- src/librustc_data_structures/indexed_vec.rs | 3 +- src/librustc_data_structures/lib.rs | 1 - src/libstd/collections/mod.rs | 2 + 15 files changed, 187 insertions(+), 217 deletions(-) diff --git a/src/liballoc/btree/map.rs b/src/liballoc/btree/map.rs index a51c70159db..5243fb6ae0e 100644 --- a/src/liballoc/btree/map.rs +++ b/src/liballoc/btree/map.rs @@ -13,12 +13,11 @@ use core::fmt::Debug; use core::hash::{Hash, Hasher}; use core::iter::{FromIterator, Peekable, FusedIterator}; use core::marker::PhantomData; -use core::ops::Index; +use core::ops::{Index, RangeArgument}; +use core::ops::Bound::{Excluded, Included, Unbounded}; use core::{fmt, intrinsics, mem, ptr}; use borrow::Borrow; -use Bound::{Excluded, Included, Unbounded}; -use range::RangeArgument; use super::node::{self, Handle, NodeRef, marker}; use super::search; diff --git a/src/liballoc/btree/set.rs b/src/liballoc/btree/set.rs index d32460da939..c755d2d8b85 100644 --- a/src/liballoc/btree/set.rs +++ b/src/liballoc/btree/set.rs @@ -16,12 +16,11 @@ use core::cmp::{min, max}; use core::fmt::Debug; use core::fmt; use core::iter::{Peekable, FromIterator, FusedIterator}; -use core::ops::{BitOr, BitAnd, BitXor, Sub}; +use core::ops::{BitOr, BitAnd, BitXor, Sub, RangeArgument}; use borrow::Borrow; use btree_map::{BTreeMap, Keys}; use super::Recover; -use range::RangeArgument; // FIXME(conventions): implement bounded iterators diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index ca52943ea97..6f4e300fd3c 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -203,56 +203,7 @@ mod std { pub use core::ops; // RangeFull } -/// An endpoint of a range of keys. -/// -/// # Examples -/// -/// `Bound`s are range endpoints: -/// -/// ``` -/// #![feature(collections_range)] -/// -/// use std::collections::range::RangeArgument; -/// use std::collections::Bound::*; -/// -/// assert_eq!((..100).start(), Unbounded); -/// assert_eq!((1..12).start(), Included(&1)); -/// assert_eq!((1..12).end(), Excluded(&12)); -/// ``` -/// -/// Using a tuple of `Bound`s as an argument to [`BTreeMap::range`]. -/// Note that in most cases, it's better to use range syntax (`1..5`) instead. -/// -/// ``` -/// use std::collections::BTreeMap; -/// use std::collections::Bound::{Excluded, Included, Unbounded}; -/// -/// let mut map = BTreeMap::new(); -/// map.insert(3, "a"); -/// map.insert(5, "b"); -/// map.insert(8, "c"); -/// -/// for (key, value) in map.range((Excluded(3), Included(8))) { -/// println!("{}: {}", key, value); -/// } -/// -/// assert_eq!(Some((&3, &"a")), map.range((Unbounded, Included(5))).next()); -/// ``` -/// -/// [`BTreeMap::range`]: btree_map/struct.BTreeMap.html#method.range -#[stable(feature = "collections_bound", since = "1.17.0")] -#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] -pub enum Bound { - /// An inclusive bound. - #[stable(feature = "collections_bound", since = "1.17.0")] - Included(T), - /// An exclusive bound. - #[stable(feature = "collections_bound", since = "1.17.0")] - Excluded(T), - /// An infinite endpoint. Indicates that there is no bound in this direction. - #[stable(feature = "collections_bound", since = "1.17.0")] - Unbounded, -} +pub use core::ops::Bound; /// An intermediate trait for specialization of `Extend`. #[doc(hidden)] diff --git a/src/liballoc/range.rs b/src/liballoc/range.rs index f862da0d61e..0a058c47a50 100644 --- a/src/liballoc/range.rs +++ b/src/liballoc/range.rs @@ -11,142 +11,8 @@ #![unstable(feature = "collections_range", reason = "waiting for dust to settle on inclusive ranges", issue = "30877")] +#![rustc_deprecated(reason = "moved to core::ops", since = "1.19.0")] //! Range syntax. -use core::ops::{RangeFull, Range, RangeTo, RangeFrom, RangeInclusive, RangeToInclusive}; -use Bound::{self, Excluded, Included, Unbounded}; - -/// `RangeArgument` is implemented by Rust's built-in range types, produced -/// by range syntax like `..`, `a..`, `..b` or `c..d`. -pub trait RangeArgument { - /// Start index bound. - /// - /// Returns the start value as a `Bound`. - /// - /// # Examples - /// - /// ``` - /// #![feature(alloc)] - /// #![feature(collections_range)] - /// - /// extern crate alloc; - /// - /// # fn main() { - /// use alloc::range::RangeArgument; - /// use alloc::Bound::*; - /// - /// assert_eq!((..10).start(), Unbounded); - /// assert_eq!((3..10).start(), Included(&3)); - /// # } - /// ``` - fn start(&self) -> Bound<&T>; - - /// End index bound. - /// - /// Returns the end value as a `Bound`. - /// - /// # Examples - /// - /// ``` - /// #![feature(alloc)] - /// #![feature(collections_range)] - /// - /// extern crate alloc; - /// - /// # fn main() { - /// use alloc::range::RangeArgument; - /// use alloc::Bound::*; - /// - /// assert_eq!((3..).end(), Unbounded); - /// assert_eq!((3..10).end(), Excluded(&10)); - /// # } - /// ``` - fn end(&self) -> Bound<&T>; -} - -// FIXME add inclusive ranges to RangeArgument - -impl RangeArgument for RangeFull { - fn start(&self) -> Bound<&T> { - Unbounded - } - fn end(&self) -> Bound<&T> { - Unbounded - } -} - -impl RangeArgument for RangeFrom { - fn start(&self) -> Bound<&T> { - Included(&self.start) - } - fn end(&self) -> Bound<&T> { - Unbounded - } -} - -impl RangeArgument for RangeTo { - fn start(&self) -> Bound<&T> { - Unbounded - } - fn end(&self) -> Bound<&T> { - Excluded(&self.end) - } -} - -impl RangeArgument for Range { - fn start(&self) -> Bound<&T> { - Included(&self.start) - } - fn end(&self) -> Bound<&T> { - Excluded(&self.end) - } -} - -#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] -impl RangeArgument for RangeInclusive { - fn start(&self) -> Bound<&T> { - Included(&self.start) - } - fn end(&self) -> Bound<&T> { - Included(&self.end) - } -} - -#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] -impl RangeArgument for RangeToInclusive { - fn start(&self) -> Bound<&T> { - Unbounded - } - fn end(&self) -> Bound<&T> { - Included(&self.end) - } -} - -impl RangeArgument for (Bound, Bound) { - fn start(&self) -> Bound<&T> { - match *self { - (Included(ref start), _) => Included(start), - (Excluded(ref start), _) => Excluded(start), - (Unbounded, _) => Unbounded, - } - } - - fn end(&self) -> Bound<&T> { - match *self { - (_, Included(ref end)) => Included(end), - (_, Excluded(ref end)) => Excluded(end), - (_, Unbounded) => Unbounded, - } - } -} - -impl<'a, T: ?Sized + 'a> RangeArgument for (Bound<&'a T>, Bound<&'a T>) { - fn start(&self) -> Bound<&T> { - self.0 - } - - fn end(&self) -> Bound<&T> { - self.1 - } -} +pub use core::ops::RangeArgument; diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index 79d1ccf637d..1f0894d39d4 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -59,15 +59,14 @@ use core::fmt; use core::hash; use core::iter::{FromIterator, FusedIterator}; -use core::ops::{self, Add, AddAssign, Index, IndexMut}; +use core::ops::{self, Add, AddAssign, Index, IndexMut, RangeArgument}; +use core::ops::Bound::{Excluded, Included, Unbounded}; use core::ptr; use core::str::pattern::Pattern; use std_unicode::lossy; use std_unicode::char::{decode_utf16, REPLACEMENT_CHARACTER}; use borrow::{Cow, ToOwned}; -use range::RangeArgument; -use Bound::{Excluded, Included, Unbounded}; use str::{self, from_boxed_utf8_unchecked, FromStr, Utf8Error, Chars}; use vec::Vec; use boxed::Box; diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 5d1999a4262..e118d406ecf 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -74,7 +74,8 @@ use core::iter::{FromIterator, FusedIterator, TrustedLen}; use core::mem; #[cfg(not(test))] use core::num::Float; -use core::ops::{InPlace, Index, IndexMut, Place, Placer}; +use core::ops::{InPlace, Index, IndexMut, Place, Placer, RangeArgument}; +use core::ops::Bound::{Excluded, Included, Unbounded}; use core::ops; use core::ptr; use core::ptr::Shared; @@ -84,8 +85,6 @@ use borrow::ToOwned; use borrow::Cow; use boxed::Box; use raw_vec::RawVec; -use super::range::RangeArgument; -use Bound::{Excluded, Included, Unbounded}; /// A contiguous growable array type, written `Vec` but pronounced 'vector'. /// diff --git a/src/liballoc/vec_deque.rs b/src/liballoc/vec_deque.rs index 18175a5d01b..d1d334267bc 100644 --- a/src/liballoc/vec_deque.rs +++ b/src/liballoc/vec_deque.rs @@ -21,7 +21,8 @@ use core::cmp::Ordering; use core::fmt; use core::iter::{repeat, FromIterator, FusedIterator}; use core::mem; -use core::ops::{Index, IndexMut, Place, Placer, InPlace}; +use core::ops::{Index, IndexMut, Place, Placer, InPlace, RangeArgument}; +use core::ops::Bound::{Excluded, Included, Unbounded}; use core::ptr; use core::ptr::Shared; use core::slice; @@ -31,8 +32,6 @@ use core::cmp; use raw_vec::RawVec; -use super::range::RangeArgument; -use Bound::{Excluded, Included, Unbounded}; use super::vec::Vec; const INITIAL_CAPACITY: usize = 7; // 2^3 - 1 diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index de5d6df328c..0a939831622 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -46,6 +46,7 @@ pub use alloc::binary_heap; pub use alloc::borrow; pub use alloc::fmt; pub use alloc::linked_list; +#[allow(deprecated)] pub use alloc::range; pub use alloc::slice; pub use alloc::str; diff --git a/src/libcore/ops/mod.rs b/src/libcore/ops/mod.rs index a78f4fe28a6..34f00850579 100644 --- a/src/libcore/ops/mod.rs +++ b/src/libcore/ops/mod.rs @@ -183,6 +183,9 @@ pub use self::index::{Index, IndexMut}; #[stable(feature = "rust1", since = "1.0.0")] pub use self::range::{Range, RangeFrom, RangeFull, RangeTo}; +#[stable(feature = "range_argument", since = "1.19.0")] +pub use self::range::{RangeArgument, Bound}; + #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] pub use self::range::{RangeInclusive, RangeToInclusive}; diff --git a/src/libcore/ops/range.rs b/src/libcore/ops/range.rs index 33258b7a875..65e09da4fff 100644 --- a/src/libcore/ops/range.rs +++ b/src/libcore/ops/range.rs @@ -9,6 +9,7 @@ // except according to those terms. use fmt; +use ops::Bound::{Included, Excluded, Unbounded}; /// An unbounded range. Use `..` (two dots) for its shorthand. /// @@ -71,7 +72,8 @@ impl fmt::Debug for RangeFull { /// assert_eq!(arr[1..3], [ 1,2 ]); // Range /// } /// ``` -#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 +#[derive(Clone, PartialEq, Eq, Hash)] +// not Copy -- see #27186 #[stable(feature = "rust1", since = "1.0.0")] pub struct Range { /// The lower bound of the range (inclusive). @@ -134,7 +136,8 @@ impl> Range { /// assert_eq!(arr[1..3], [ 1,2 ]); /// } /// ``` -#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 +#[derive(Clone, PartialEq, Eq, Hash)] +// not Copy -- see #27186 #[stable(feature = "rust1", since = "1.0.0")] pub struct RangeFrom { /// The lower bound of the range (inclusive). @@ -250,17 +253,16 @@ impl> RangeTo { /// assert_eq!(arr[1...2], [ 1,2 ]); // RangeInclusive /// } /// ``` -#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 +#[derive(Clone, PartialEq, Eq, Hash)] +// not Copy -- see #27186 #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] pub struct RangeInclusive { /// The lower bound of the range (inclusive). - #[unstable(feature = "inclusive_range", - reason = "recently added, follows RFC", + #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] pub start: Idx, /// The upper bound of the range (inclusive). - #[unstable(feature = "inclusive_range", - reason = "recently added, follows RFC", + #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] pub end: Idx, } @@ -333,8 +335,7 @@ impl> RangeInclusive { #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] pub struct RangeToInclusive { /// The upper bound of the range (inclusive) - #[unstable(feature = "inclusive_range", - reason = "recently added, follows RFC", + #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] pub end: Idx, } @@ -365,3 +366,158 @@ impl> RangeToInclusive { // RangeToInclusive cannot impl From> // because underflow would be possible with (..0).into() + +/// `RangeArgument` is implemented by Rust's built-in range types, produced +/// by range syntax like `..`, `a..`, `..b` or `c..d`. +#[stable(feature = "range_argument", since = "1.19.0")] +pub trait RangeArgument { + /// Start index bound. + /// + /// Returns the start value as a `Bound`. + /// + /// # Examples + /// + /// ``` + /// use std::ops::RangeArgument; + /// use std::ops::Bound::*; + /// + /// assert_eq!((..10).start(), Unbounded); + /// assert_eq!((3..10).start(), Included(&3)); + /// ``` + #[stable(feature = "range_argument", since = "1.19.0")] + fn start(&self) -> Bound<&T>; + + /// End index bound. + /// + /// Returns the end value as a `Bound`. + /// + /// # Examples + /// + /// ``` + /// use std::ops::RangeArgument; + /// use std::ops::Bound::*; + /// + /// assert_eq!((3..).end(), Unbounded); + /// assert_eq!((3..10).end(), Excluded(&10)); + /// ``` + #[stable(feature = "range_argument", since = "1.19.0")] + fn end(&self) -> Bound<&T>; +} + +#[stable(feature = "range_argument", since = "1.19.0")] +impl RangeArgument for RangeFull { + fn start(&self) -> Bound<&T> { + Unbounded + } + fn end(&self) -> Bound<&T> { + Unbounded + } +} + +#[stable(feature = "range_argument", since = "1.19.0")] +impl RangeArgument for RangeFrom { + fn start(&self) -> Bound<&T> { + Included(&self.start) + } + fn end(&self) -> Bound<&T> { + Unbounded + } +} + +#[stable(feature = "range_argument", since = "1.19.0")] +impl RangeArgument for RangeTo { + fn start(&self) -> Bound<&T> { + Unbounded + } + fn end(&self) -> Bound<&T> { + Excluded(&self.end) + } +} + +#[stable(feature = "range_argument", since = "1.19.0")] +impl RangeArgument for Range { + fn start(&self) -> Bound<&T> { + Included(&self.start) + } + fn end(&self) -> Bound<&T> { + Excluded(&self.end) + } +} + +#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] +impl RangeArgument for RangeInclusive { + fn start(&self) -> Bound<&T> { + Included(&self.start) + } + fn end(&self) -> Bound<&T> { + Included(&self.end) + } +} + +#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] +impl RangeArgument for RangeToInclusive { + fn start(&self) -> Bound<&T> { + Unbounded + } + fn end(&self) -> Bound<&T> { + Included(&self.end) + } +} + +#[stable(feature = "range_argument", since = "1.19.0")] +impl RangeArgument for (Bound, Bound) { + fn start(&self) -> Bound<&T> { + match *self { + (Included(ref start), _) => Included(start), + (Excluded(ref start), _) => Excluded(start), + (Unbounded, _) => Unbounded, + } + } + + fn end(&self) -> Bound<&T> { + match *self { + (_, Included(ref end)) => Included(end), + (_, Excluded(ref end)) => Excluded(end), + (_, Unbounded) => Unbounded, + } + } +} + +#[stable(feature = "range_argument", since = "1.19.0")] +impl<'a, T: ?Sized + 'a> RangeArgument for (Bound<&'a T>, Bound<&'a T>) { + fn start(&self) -> Bound<&T> { + self.0 + } + + fn end(&self) -> Bound<&T> { + self.1 + } +} + +/// An endpoint of a range of keys. +/// +/// # Examples +/// +/// `Bound`s are range endpoints: +/// +/// ``` +/// use std::ops::RangeArgument; +/// use std::ops::Bound::*; +/// +/// assert_eq!((..100).start(), Unbounded); +/// assert_eq!((1..12).start(), Included(&1)); +/// assert_eq!((1..12).end(), Excluded(&12)); +/// ``` +#[stable(feature = "collections_bound", since = "1.17.0")] +#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] +pub enum Bound { + /// An inclusive bound. + #[stable(feature = "collections_bound", since = "1.17.0")] + Included(T), + /// An exclusive bound. + #[stable(feature = "collections_bound", since = "1.17.0")] + Excluded(T), + /// An infinite endpoint. Indicates that there is no bound in this direction. + #[stable(feature = "collections_bound", since = "1.17.0")] + Unbounded, +} diff --git a/src/librustc_data_structures/accumulate_vec.rs b/src/librustc_data_structures/accumulate_vec.rs index c03c2890ba3..eacd394ad5e 100644 --- a/src/librustc_data_structures/accumulate_vec.rs +++ b/src/librustc_data_structures/accumulate_vec.rs @@ -15,11 +15,10 @@ //! //! The N above is determined by Array's implementor, by way of an associatated constant. -use std::ops::{Deref, DerefMut}; +use std::ops::{Deref, DerefMut, RangeArgument}; use std::iter::{self, IntoIterator, FromIterator}; use std::slice; use std::vec; -use std::collections::range::RangeArgument; use rustc_serialize::{Encodable, Encoder, Decodable, Decoder}; diff --git a/src/librustc_data_structures/array_vec.rs b/src/librustc_data_structures/array_vec.rs index 078bb801751..a9abdf1377e 100644 --- a/src/librustc_data_structures/array_vec.rs +++ b/src/librustc_data_structures/array_vec.rs @@ -13,13 +13,12 @@ use std::marker::Unsize; use std::iter::Extend; use std::ptr::{self, drop_in_place, Shared}; -use std::ops::{Deref, DerefMut, Range}; +use std::ops::{Deref, DerefMut, Range, RangeArgument}; +use std::ops::Bound::{Excluded, Included, Unbounded}; use std::hash::{Hash, Hasher}; use std::slice; use std::fmt; use std::mem; -use std::collections::range::RangeArgument; -use std::collections::Bound::{Excluded, Included, Unbounded}; use std::mem::ManuallyDrop; pub unsafe trait Array { diff --git a/src/librustc_data_structures/indexed_vec.rs b/src/librustc_data_structures/indexed_vec.rs index 29ac650aa70..3bf926fa8bf 100644 --- a/src/librustc_data_structures/indexed_vec.rs +++ b/src/librustc_data_structures/indexed_vec.rs @@ -8,12 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::collections::range::RangeArgument; use std::fmt::Debug; use std::iter::{self, FromIterator}; use std::slice; use std::marker::PhantomData; -use std::ops::{Index, IndexMut, Range}; +use std::ops::{Index, IndexMut, Range, RangeArgument}; use std::fmt; use std::vec; use std::u32; diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index d63b4c9c31b..0bbda547761 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -25,7 +25,6 @@ #![deny(warnings)] #![feature(shared)] -#![feature(collections_range)] #![feature(nonzero)] #![feature(unboxed_closures)] #![feature(fn_traits)] diff --git a/src/libstd/collections/mod.rs b/src/libstd/collections/mod.rs index b8a6a66eaa6..2ed6724b07d 100644 --- a/src/libstd/collections/mod.rs +++ b/src/libstd/collections/mod.rs @@ -436,6 +436,8 @@ pub use self::hash_map::HashMap; pub use self::hash_set::HashSet; #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_deprecated(reason = "moved to std::ops", since = "1.19.0")] +#[allow(deprecated)] pub use alloc::range; mod hash; From c13a913e5b4136ecb81ec835586e596ecef1a4b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 24 Jun 2017 19:28:43 -0700 Subject: [PATCH 039/162] Don't naively point to return type on type error --- src/librustc_typeck/check/coercion.rs | 6 ----- src/librustc_typeck/check/mod.rs | 22 ------------------- src/test/ui/block-result/issue-13624.stderr | 2 -- src/test/ui/block-result/issue-20862.stderr | 5 +---- src/test/ui/block-result/issue-22645.stderr | 3 --- src/test/ui/block-result/issue-3563.stderr | 5 +---- src/test/ui/block-result/issue-5500.stderr | 2 -- .../unexpected-return-on-unit.stderr | 2 -- src/test/ui/impl-trait/equality.stderr | 3 --- src/test/ui/mismatched_types/abridged.stderr | 12 ---------- .../ui/mismatched_types/issue-19109.stderr | 5 +---- .../ui/resolve/token-error-correct-3.stderr | 3 --- 12 files changed, 3 insertions(+), 67 deletions(-) diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index 660f6c5a093..4b5d02f9995 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -1174,12 +1174,6 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E> expected, found, cause.span, blk_id); } - ObligationCauseCode::ReturnType(ret_id) => { - db = fcx.report_mismatched_types(cause, expected, found, err); - if let Some((fn_decl, _)) = fcx.get_fn_decl(ret_id) { - fcx.point_to_type_requirement(&mut db, &fn_decl, expected); - } - } _ => { db = fcx.report_mismatched_types(cause, expected, found, err); } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 50e2e390d02..7c4b6a858d9 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4261,7 +4261,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.suggest_missing_semicolon(err, expression, expected, cause_span); if let Some((fn_decl, is_main)) = self.get_fn_decl(blk_id) { - self.point_to_type_requirement(err, &fn_decl, expected); // `fn main()` must return `()`, do not suggest changing return type if !is_main { self.suggest_missing_return_type(err, &fn_decl, found); @@ -4269,27 +4268,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } - pub fn point_to_type_requirement(&self, - err: &mut DiagnosticBuilder<'tcx>, - fn_decl: &hir::FnDecl, - ty: Ty<'tcx>) { - let msg = if let &hir::FnDecl { - output: hir::FunctionRetTy::DefaultReturn(_), .. - } = fn_decl { - "default " - } else { - "" - }; - let ty = self.resolve_type_vars_if_possible(&ty); - if ty.to_string().len() < 10 { - err.span_label(fn_decl.output.span(), - format!("expected `{}` because of this {}return type", ty, msg)); - } else { - err.span_label(fn_decl.output.span(), - format!("expected because of this {}return type", msg)); - } - } - /// A common error is to forget to add a semicolon at the end of a block: /// /// ``` diff --git a/src/test/ui/block-result/issue-13624.stderr b/src/test/ui/block-result/issue-13624.stderr index 69c6e647cfc..72ff859d7e9 100644 --- a/src/test/ui/block-result/issue-13624.stderr +++ b/src/test/ui/block-result/issue-13624.stderr @@ -1,8 +1,6 @@ error[E0308]: mismatched types --> $DIR/issue-13624.rs:17:5 | -16 | pub fn get_enum_struct_variant() -> () { - | -- expected `()` because of this return type 17 | Enum::EnumStructVariant { x: 1, y: 2, z: 3 } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found enum `a::Enum` | diff --git a/src/test/ui/block-result/issue-20862.stderr b/src/test/ui/block-result/issue-20862.stderr index 57cee8f7aca..e4367f170ce 100644 --- a/src/test/ui/block-result/issue-20862.stderr +++ b/src/test/ui/block-result/issue-20862.stderr @@ -2,10 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-20862.rs:12:5 | 11 | fn foo(x: i32) { - | - - | | - | possibly return type missing here? - | expected `()` because of this default return type + | - possibly return type missing here? 12 | |y| x + y | ^^^^^^^^^ expected (), found closure | diff --git a/src/test/ui/block-result/issue-22645.stderr b/src/test/ui/block-result/issue-22645.stderr index 93da3c6a489..3921a301c92 100644 --- a/src/test/ui/block-result/issue-22645.stderr +++ b/src/test/ui/block-result/issue-22645.stderr @@ -11,9 +11,6 @@ error[E0277]: the trait bound `{integer}: Scalar` is not satisfied error[E0308]: mismatched types --> $DIR/issue-22645.rs:25:3 | -23 | fn main() { - | - expected `()` because of this default return type -24 | let b = Bob + 3.5; 25 | b + 3 //~ ERROR E0277 | ^^^^^ expected (), found struct `Bob` | diff --git a/src/test/ui/block-result/issue-3563.stderr b/src/test/ui/block-result/issue-3563.stderr index d995dee3827..c6ab4cbb2a7 100644 --- a/src/test/ui/block-result/issue-3563.stderr +++ b/src/test/ui/block-result/issue-3563.stderr @@ -8,10 +8,7 @@ error[E0308]: mismatched types --> $DIR/issue-3563.rs:13:9 | 12 | fn a(&self) { - | - - | | - | possibly return type missing here? - | expected `()` because of this default return type + | - possibly return type missing here? 13 | || self.b() | ^^^^^^^^^^^ expected (), found closure | diff --git a/src/test/ui/block-result/issue-5500.stderr b/src/test/ui/block-result/issue-5500.stderr index 6fda2aa00ff..bffe2a82ca8 100644 --- a/src/test/ui/block-result/issue-5500.stderr +++ b/src/test/ui/block-result/issue-5500.stderr @@ -1,8 +1,6 @@ error[E0308]: mismatched types --> $DIR/issue-5500.rs:12:5 | -11 | fn main() { - | - expected `()` because of this default return type 12 | &panic!() | ^^^^^^^^^ expected (), found reference | diff --git a/src/test/ui/block-result/unexpected-return-on-unit.stderr b/src/test/ui/block-result/unexpected-return-on-unit.stderr index e5481ffd316..18d0cc48140 100644 --- a/src/test/ui/block-result/unexpected-return-on-unit.stderr +++ b/src/test/ui/block-result/unexpected-return-on-unit.stderr @@ -1,8 +1,6 @@ error[E0308]: mismatched types --> $DIR/unexpected-return-on-unit.rs:19:5 | -18 | fn bar() { - | - expected `()` because of this default return type 19 | foo() | ^^^^^ expected (), found usize | diff --git a/src/test/ui/impl-trait/equality.stderr b/src/test/ui/impl-trait/equality.stderr index ca37596f1b9..2206234b777 100644 --- a/src/test/ui/impl-trait/equality.stderr +++ b/src/test/ui/impl-trait/equality.stderr @@ -1,9 +1,6 @@ error[E0308]: mismatched types --> $DIR/equality.rs:25:5 | -21 | fn two(x: bool) -> impl Foo { - | -------- expected `i32` because of this return type -... 25 | 0_u32 | ^^^^^ expected i32, found u32 | diff --git a/src/test/ui/mismatched_types/abridged.stderr b/src/test/ui/mismatched_types/abridged.stderr index 6282541ba0e..78b5dcda1d9 100644 --- a/src/test/ui/mismatched_types/abridged.stderr +++ b/src/test/ui/mismatched_types/abridged.stderr @@ -1,8 +1,6 @@ error[E0308]: mismatched types --> $DIR/abridged.rs:26:5 | -25 | fn a() -> Foo { - | --- expected `Foo` because of this return type 26 | Some(Foo { bar: 1 }) | ^^^^^^^^^^^^^^^^^^^^ expected struct `Foo`, found enum `std::option::Option` | @@ -12,8 +10,6 @@ error[E0308]: mismatched types error[E0308]: mismatched types --> $DIR/abridged.rs:30:5 | -29 | fn a2() -> Foo { - | --- expected `Foo` because of this return type 30 | Ok(Foo { bar: 1}) | ^^^^^^^^^^^^^^^^^ expected struct `Foo`, found enum `std::result::Result` | @@ -23,8 +19,6 @@ error[E0308]: mismatched types error[E0308]: mismatched types --> $DIR/abridged.rs:34:5 | -33 | fn b() -> Option { - | ----------- expected because of this return type 34 | Foo { bar: 1 } | ^^^^^^^^^^^^^^ expected enum `std::option::Option`, found struct `Foo` | @@ -34,8 +28,6 @@ error[E0308]: mismatched types error[E0308]: mismatched types --> $DIR/abridged.rs:38:5 | -37 | fn c() -> Result { - | ---------------- expected because of this return type 38 | Foo { bar: 1 } | ^^^^^^^^^^^^^^ expected enum `std::result::Result`, found struct `Foo` | @@ -45,8 +37,6 @@ error[E0308]: mismatched types error[E0308]: mismatched types --> $DIR/abridged.rs:42:5 | -41 | fn d() -> X, String> { - | ---------------------------- expected because of this return type 42 | / X { 43 | | x: X { 44 | | x: "".to_string(), @@ -62,8 +52,6 @@ error[E0308]: mismatched types error[E0308]: mismatched types --> $DIR/abridged.rs:52:5 | -51 | fn e() -> X, String> { - | ---------------------------- expected because of this return type 52 | / X { 53 | | x: X { 54 | | x: "".to_string(), diff --git a/src/test/ui/mismatched_types/issue-19109.stderr b/src/test/ui/mismatched_types/issue-19109.stderr index 5efa3fa6a1d..083c1f95333 100644 --- a/src/test/ui/mismatched_types/issue-19109.stderr +++ b/src/test/ui/mismatched_types/issue-19109.stderr @@ -2,10 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-19109.rs:14:5 | 13 | fn function(t: &mut Trait) { - | - - | | - | help: possibly return type missing here? `-> *mut Trait ` - | expected `()` because of this default return type + | - help: possibly return type missing here? `-> *mut Trait ` 14 | t as *mut Trait | ^^^^^^^^^^^^^^^ expected (), found *-ptr | diff --git a/src/test/ui/resolve/token-error-correct-3.stderr b/src/test/ui/resolve/token-error-correct-3.stderr index 2a50428dbb9..53e9cb21778 100644 --- a/src/test/ui/resolve/token-error-correct-3.stderr +++ b/src/test/ui/resolve/token-error-correct-3.stderr @@ -34,9 +34,6 @@ error[E0425]: cannot find function `is_directory` in this scope error[E0308]: mismatched types --> $DIR/token-error-correct-3.rs:25:13 | -20 | -> io::Result { - | ---------------- expected `()` because of this return type -... 25 | fs::create_dir_all(path.as_ref()).map(|()| true) //~ ERROR: mismatched types | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- help: did you mean to add a semicolon here? `;` | | From bcf0d600f3884709c5faef21219a7613e254b7e0 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 25 Jun 2017 09:25:37 +0200 Subject: [PATCH 040/162] Add reference link --- src/librustc_typeck/diagnostics.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index f9b44f0395f..b2fa2cc7c61 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -4223,6 +4223,9 @@ As the error message indicates, only `u8` can be cast into `char`. Example: let c = 86u8 as char; // ok! assert_eq!(c, 'V'); ``` + +For more information about casts, take a look at The Book: +https://doc.rust-lang.org/book/first-edition/casting-between-types.html "##, E0605: r##" @@ -4249,6 +4252,9 @@ x as u32; // ok! let v = 0 as *const u8; v as *const i8; // ok! ``` + +For more information about casts, take a look at The Book: +https://doc.rust-lang.org/book/first-edition/casting-between-types.html "##, E0606: r##" @@ -4268,6 +4274,9 @@ other. Example: let x = &0u8; let y: u32 = *x as u32; // We dereference it first and then cast it. ``` + +For more information about casts, take a look at The Book: +https://doc.rust-lang.org/book/first-edition/casting-between-types.html "##, E0607: r##" @@ -4292,6 +4301,9 @@ objects are DSTs. In the case of slices, the additional information the fat pointer holds is their size. To fix this error, don't try to cast directly between thin and fat pointers. + +For more information about casts, take a look at The Book: +https://doc.rust-lang.org/book/first-edition/casting-between-types.html "##, E0609: r##" From 3d25238d6d702b4a60b185c08a8f50a4d16e2600 Mon Sep 17 00:00:00 2001 From: Andre Bogus Date: Sun, 25 Jun 2017 17:37:03 +0200 Subject: [PATCH 041/162] fixed some clippy warnings in compiletest --- src/tools/compiletest/src/errors.rs | 6 +- src/tools/compiletest/src/header.rs | 27 +++---- src/tools/compiletest/src/json.rs | 2 +- src/tools/compiletest/src/main.rs | 24 +++--- src/tools/compiletest/src/procsrv.rs | 3 +- src/tools/compiletest/src/runtest.rs | 110 +++++++++++++-------------- 6 files changed, 79 insertions(+), 93 deletions(-) diff --git a/src/tools/compiletest/src/errors.rs b/src/tools/compiletest/src/errors.rs index 29ca54fda8d..0b9b9599be6 100644 --- a/src/tools/compiletest/src/errors.rs +++ b/src/tools/compiletest/src/errors.rs @@ -35,7 +35,7 @@ impl FromStr for ErrorKind { "ERROR" => Ok(ErrorKind::Error), "NOTE" => Ok(ErrorKind::Note), "SUGGESTION" => Ok(ErrorKind::Suggestion), - "WARN" => Ok(ErrorKind::Warning), + "WARN" | "WARNING" => Ok(ErrorKind::Warning), _ => Err(()), } @@ -95,7 +95,7 @@ pub fn load_errors(testfile: &Path, cfg: Option<&str>) -> Vec { let tag = match cfg { Some(rev) => format!("//[{}]~", rev), - None => format!("//~"), + None => "//~".to_string(), }; rdr.lines() @@ -153,7 +153,7 @@ fn parse_expected(last_nonfollow_error: Option, let msg = msg.trim().to_owned(); let (which, line_num) = if follow { - assert!(adjusts == 0, "use either //~| or //~^, not both."); + assert_eq!(adjusts, 0, "use either //~| or //~^, not both."); let line_num = last_nonfollow_error.expect("encountered //~| without \ preceding //~^ line."); (FollowPrevious(line_num), line_num) diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index aa33580b337..ce33787a7d3 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -258,7 +258,7 @@ impl TestProps { check_stdout: false, no_prefer_dynamic: false, pretty_expanded: false, - pretty_mode: format!("normal"), + pretty_mode: "normal".to_string(), pretty_compare_only: false, forbid_output: vec![], incremental_dir: None, @@ -381,14 +381,11 @@ impl TestProps { } }); - for key in vec!["RUST_TEST_NOCAPTURE", "RUST_TEST_THREADS"] { - match env::var(key) { - Ok(val) => { - if self.exec_env.iter().find(|&&(ref x, _)| *x == key).is_none() { - self.exec_env.push((key.to_owned(), val)) - } + for key in &["RUST_TEST_NOCAPTURE", "RUST_TEST_THREADS"] { + if let Ok(val) = env::var(key) { + if self.exec_env.iter().find(|&&(ref x, _)| x == key).is_none() { + self.exec_env.push(((*key).to_owned(), val)) } - Err(..) => {} } } } @@ -409,7 +406,7 @@ fn iter_header(testfile: &Path, cfg: Option<&str>, it: &mut FnMut(&str)) { return; } else if ln.starts_with("//[") { // A comment like `//[foo]` is specific to revision `foo` - if let Some(close_brace) = ln.find("]") { + if let Some(close_brace) = ln.find(']') { let lncfg = &ln[3..close_brace]; let matches = match cfg { Some(s) => s == &lncfg[..], @@ -521,12 +518,10 @@ impl Config { fn parse_pp_exact(&self, line: &str, testfile: &Path) -> Option { if let Some(s) = self.parse_name_value_directive(line, "pp-exact") { Some(PathBuf::from(&s)) + } else if self.parse_name_directive(line, "pp-exact") { + testfile.file_name().map(PathBuf::from) } else { - if self.parse_name_directive(line, "pp-exact") { - testfile.file_name().map(PathBuf::from) - } else { - None - } + None } } @@ -555,8 +550,8 @@ pub fn lldb_version_to_int(version_string: &str) -> isize { let error_string = format!("Encountered LLDB version string with unexpected format: {}", version_string); let error_string = error_string; - let major: isize = version_string.parse().ok().expect(&error_string); - return major; + let major: isize = version_string.parse().expect(&error_string); + major } fn expand_variables(mut value: String, config: &Config) -> String { diff --git a/src/tools/compiletest/src/json.rs b/src/tools/compiletest/src/json.rs index 06cbd9a3df4..23782c3ccc9 100644 --- a/src/tools/compiletest/src/json.rs +++ b/src/tools/compiletest/src/json.rs @@ -65,7 +65,7 @@ pub fn parse_output(file_name: &str, output: &str, proc_res: &ProcRes) -> Vec Vec { // The compiler sometimes intermingles non-JSON stuff into the // output. This hack just skips over such lines. Yuck. - if line.chars().next() == Some('{') { + if line.starts_with('{') { match json::decode::(line) { Ok(diagnostic) => { let mut expected_errors = vec![]; diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index c88ffba357a..692e31ebad0 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -168,7 +168,7 @@ pub fn parse_config(args: Vec ) -> Config { src_base: opt_path(matches, "src-base"), build_base: opt_path(matches, "build-base"), stage_id: matches.opt_str("stage-id").unwrap(), - mode: matches.opt_str("mode").unwrap().parse().ok().expect("invalid mode"), + mode: matches.opt_str("mode").unwrap().parse().expect("invalid mode"), run_ignored: matches.opt_present("ignored"), filter: matches.free.first().cloned(), filter_exact: matches.opt_present("exact"), @@ -208,7 +208,7 @@ pub fn parse_config(args: Vec ) -> Config { pub fn log_config(config: &Config) { let c = config; - logv(c, format!("configuration:")); + logv(c, "configuration:".to_string()); logv(c, format!("compile_lib_path: {:?}", config.compile_lib_path)); logv(c, format!("run_lib_path: {:?}", config.run_lib_path)); logv(c, format!("rustc_path: {:?}", config.rustc_path.display())); @@ -238,10 +238,10 @@ pub fn log_config(config: &Config) { config.adb_device_status)); logv(c, format!("verbose: {}", config.verbose)); logv(c, format!("quiet: {}", config.quiet)); - logv(c, format!("\n")); + logv(c, "\n".to_string()); } -pub fn opt_str<'a>(maybestr: &'a Option) -> &'a str { +pub fn opt_str(maybestr: &Option) -> &str { match *maybestr { None => "(none)", Some(ref s) => s, @@ -465,11 +465,9 @@ pub fn make_test(config: &Config, testpaths: &TestPaths) -> test::TestDescAndFn }; // Debugging emscripten code doesn't make sense today - let mut ignore = early_props.ignore || !up_to_date(config, testpaths, &early_props); - if (config.mode == DebugInfoGdb || config.mode == DebugInfoLldb) && - config.target.contains("emscripten") { - ignore = true; - } + let ignore = early_props.ignore || !up_to_date(config, testpaths, &early_props) || + (config.mode == DebugInfoGdb || config.mode == DebugInfoLldb) && + config.target.contains("emscripten"); test::TestDescAndFn { desc: test::TestDesc { @@ -487,7 +485,7 @@ fn stamp(config: &Config, testpaths: &TestPaths) -> PathBuf { .to_str().unwrap(), config.stage_id); config.build_base.canonicalize() - .unwrap_or(config.build_base.clone()) + .unwrap_or_else(|_| config.build_base.clone()) .join(stamp_name) } @@ -512,7 +510,7 @@ fn up_to_date(config: &Config, testpaths: &TestPaths, props: &EarlyProps) -> boo fn mtime(path: &Path) -> FileTime { fs::metadata(path).map(|f| { FileTime::from_last_modification_time(&f) - }).unwrap_or(FileTime::zero()) + }).unwrap_or_else(|_| FileTime::zero()) } pub fn make_test_name(config: &Config, testpaths: &TestPaths) -> test::TestName { @@ -560,7 +558,7 @@ fn analyze_gdb(gdb: Option) -> (Option, Option, bool) { let gdb_native_rust = version.map_or(false, |v| v >= MIN_GDB_WITH_RUST); - return (Some(gdb.to_owned()), version, gdb_native_rust); + (Some(gdb.to_owned()), version, gdb_native_rust) } fn extract_gdb_version(full_version_line: &str) -> Option { @@ -600,7 +598,7 @@ fn extract_gdb_version(full_version_line: &str) -> Option { Some(idx) => if line.as_bytes()[idx] == b'.' { let patch = &line[idx + 1..]; - let patch_len = patch.find(|c: char| !c.is_digit(10)).unwrap_or(patch.len()); + let patch_len = patch.find(|c: char| !c.is_digit(10)).unwrap_or_else(|| patch.len()); let patch = &patch[..patch_len]; let patch = if patch_len > 3 || patch_len == 0 { None } else { Some(patch) }; diff --git a/src/tools/compiletest/src/procsrv.rs b/src/tools/compiletest/src/procsrv.rs index dbda8f4d802..35f6ed243fe 100644 --- a/src/tools/compiletest/src/procsrv.rs +++ b/src/tools/compiletest/src/procsrv.rs @@ -9,7 +9,6 @@ // except according to those terms. use std::env; -use std::ffi::OsString; use std::io::prelude::*; use std::io; use std::path::PathBuf; @@ -31,7 +30,7 @@ fn add_target_env(cmd: &mut Command, lib_path: &str, aux_path: Option<&str>) { // Need to be sure to put both the lib_path and the aux path in the dylib // search path for the child. let var = dylib_env_var(); - let mut path = env::split_paths(&env::var_os(var).unwrap_or(OsString::new())) + let mut path = env::split_paths(&env::var_os(var).unwrap_or_default()) .collect::>(); if let Some(p) = aux_path { path.insert(0, PathBuf::from(p)) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 0692e07253f..bb8591ef1fe 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -68,7 +68,7 @@ pub fn run(config: Config, testpaths: &TestPaths) { } else { for revision in &base_props.revisions { let mut revision_props = base_props.clone(); - revision_props.load_from(&testpaths.file, Some(&revision), &config); + revision_props.load_from(&testpaths.file, Some(revision), &config); let rev_cx = TestCx { config: &config, props: &revision_props, @@ -81,7 +81,7 @@ pub fn run(config: Config, testpaths: &TestPaths) { base_cx.complete_all(); - File::create(::stamp(&config, &testpaths)).unwrap(); + File::create(::stamp(&config, testpaths)).unwrap(); } struct TestCx<'test> { @@ -101,9 +101,8 @@ impl<'test> TestCx<'test> { /// invoked once before any revisions have been processed fn init_all(&self) { assert!(self.revision.is_none(), "init_all invoked for a revision"); - match self.config.mode { - Incremental => self.init_incremental_test(), - _ => { } + if let Incremental = self.config.mode { + self.init_incremental_test() } } @@ -111,7 +110,7 @@ impl<'test> TestCx<'test> { /// revisions, exactly once, with revision == None). fn run_revision(&self) { match self.config.mode { - CompileFail => self.run_cfail_test(), + CompileFail | ParseFail => self.run_cfail_test(), RunFail => self.run_rfail_test(), RunPass => self.run_rpass_test(), @@ -352,10 +351,10 @@ impl<'test> TestCx<'test> { aux_dir.to_str().unwrap().to_owned()]; args.extend(self.split_maybe_args(&self.config.target_rustcflags)); args.extend(self.props.compile_flags.iter().cloned()); - return ProcArgs { + ProcArgs { prog: self.config.rustc_path.to_str().unwrap().to_owned(), args: args, - }; + } } fn compare_source(&self, @@ -407,17 +406,17 @@ actual:\n\ aux_dir.to_str().unwrap().to_owned()]; if let Some(revision) = self.revision { args.extend(vec![ - format!("--cfg"), - format!("{}", revision), + "--cfg".to_string(), + revision.to_string(), ]); } args.extend(self.split_maybe_args(&self.config.target_rustcflags)); args.extend(self.props.compile_flags.iter().cloned()); // FIXME (#9639): This needs to handle non-utf8 paths - return ProcArgs { + ProcArgs { prog: self.config.rustc_path.to_str().unwrap().to_owned(), args: args, - }; + } } fn run_debuginfo_gdb_test(&self) { @@ -708,7 +707,7 @@ actual:\n\ } } - return None; + None } fn run_debuginfo_lldb_test(&self) { @@ -875,13 +874,13 @@ actual:\n\ for &(ref command_directive, ref check_directive) in &directives { self.config.parse_name_value_directive( &line, - &command_directive).map(|cmd| { + command_directive).map(|cmd| { commands.push(cmd) }); self.config.parse_name_value_directive( &line, - &check_directive).map(|cmd| { + check_directive).map(|cmd| { check_lines.push(cmd) }); } @@ -962,8 +961,7 @@ actual:\n\ (line, 0) }; - for fragment_index in first_fragment .. check_fragments.len() { - let current_fragment = check_fragments[fragment_index]; + for current_fragment in &check_fragments[first_fragment..] { match rest.find(current_fragment) { Some(pos) => { rest = &rest[pos + current_fragment.len() .. ]; @@ -976,7 +974,7 @@ actual:\n\ return false; } - return true; + true } } @@ -1059,7 +1057,7 @@ actual:\n\ let expect_note = expected_errors.iter().any(|ee| ee.kind == Some(ErrorKind::Note)); // Parse the JSON output from the compiler and extract out the messages. - let actual_errors = json::parse_output(&file_name, &proc_res.stderr, &proc_res); + let actual_errors = json::parse_output(&file_name, &proc_res.stderr, proc_res); let mut unexpected = Vec::new(); let mut found = vec![false; expected_errors.len()]; for actual_error in &actual_errors { @@ -1092,7 +1090,7 @@ actual:\n\ .map_or(String::from("message"), |k| k.to_string()), actual_error.msg)); - unexpected.push(actual_error.clone()); + unexpected.push(actual_error); } } } @@ -1110,20 +1108,20 @@ actual:\n\ .map_or("message".into(), |k| k.to_string()), expected_error.msg)); - not_found.push(expected_error.clone()); + not_found.push(expected_error); } } - if unexpected.len() > 0 || not_found.len() > 0 { + if !unexpected.is_empty() || !not_found.is_empty() { self.error( &format!("{} unexpected errors found, {} expected errors not found", unexpected.len(), not_found.len())); - print!("status: {}\ncommand: {}\n", + println!("status: {}\ncommand: {}", proc_res.status, proc_res.cmdline); - if unexpected.len() > 0 { + if !unexpected.is_empty() { println!("unexpected errors (from JSON output): {:#?}\n", unexpected); } - if not_found.len() > 0 { + if !not_found.is_empty() { println!("not found errors (from test file): {:#?}\n", not_found); } panic!(); @@ -1142,9 +1140,9 @@ actual:\n\ match actual_error.kind { Some(ErrorKind::Help) => expect_help, Some(ErrorKind::Note) => expect_note, - Some(ErrorKind::Error) => true, + Some(ErrorKind::Error) | Some(ErrorKind::Warning) => true, - Some(ErrorKind::Suggestion) => false, + Some(ErrorKind::Suggestion) | None => false } } @@ -1287,7 +1285,8 @@ actual:\n\ self.config); let mut crate_type = if aux_props.no_prefer_dynamic { Vec::new() - } else { + } else if (self.config.target.contains("musl") && !aux_props.force_host) || + self.config.target.contains("emscripten") { // We primarily compile all auxiliary libraries as dynamic libraries // to avoid code size bloat and large binaries as much as possible // for the test suite (otherwise including libstd statically in all @@ -1297,13 +1296,9 @@ actual:\n\ // dynamic libraries so we just go back to building a normal library. Note, // however, that for MUSL if the library is built with `force_host` then // it's ok to be a dylib as the host should always support dylibs. - if (self.config.target.contains("musl") && !aux_props.force_host) || - self.config.target.contains("emscripten") - { - vec!["--crate-type=lib".to_owned()] - } else { - vec!["--crate-type=dylib".to_owned()] - } + vec!["--crate-type=lib".to_owned()] + } else { + vec!["--crate-type=dylib".to_owned()] }; crate_type.extend(extra_link_args.clone()); let aux_output = { @@ -1344,7 +1339,7 @@ actual:\n\ lib_path: &str, aux_path: Option<&str>, input: Option) -> ProcRes { - return self.program_output(lib_path, prog, aux_path, args, procenv, input); + self.program_output(lib_path, prog, aux_path, args, procenv, input) } fn make_compile_args(&self, @@ -1367,7 +1362,7 @@ actual:\n\ // Optionally prevent default --target if specified in test compile-flags. let custom_target = self.props.compile_flags .iter() - .fold(false, |acc, ref x| acc || x.starts_with("--target")); + .fold(false, |acc, x| acc || x.starts_with("--target")); if !custom_target { args.extend(vec![ @@ -1377,14 +1372,14 @@ actual:\n\ if let Some(revision) = self.revision { args.extend(vec![ - format!("--cfg"), - format!("{}", revision), + "--cfg".to_string(), + revision.to_string(), ]); } if let Some(ref incremental_dir) = self.props.incremental_dir { args.extend(vec![ - format!("-Z"), + "-Z".to_string(), format!("incremental={}", incremental_dir.display()), ]); } @@ -1457,10 +1452,10 @@ actual:\n\ args.extend(self.split_maybe_args(&self.config.target_rustcflags)); } args.extend(self.props.compile_flags.iter().cloned()); - return ProcArgs { + ProcArgs { prog: self.config.rustc_path.to_str().unwrap().to_owned(), args: args, - }; + } } fn make_lib_name(&self, auxfile: &Path) -> PathBuf { @@ -1508,10 +1503,10 @@ actual:\n\ args.extend(self.split_maybe_args(&self.props.run_flags)); let prog = args.remove(0); - return ProcArgs { + ProcArgs { prog: prog, args: args, - }; + } } fn split_maybe_args(&self, argstr: &Option) -> Vec { @@ -1558,12 +1553,12 @@ actual:\n\ env, input).expect(&format!("failed to exec `{}`", prog)); self.dump_output(&out, &err); - return ProcRes { + ProcRes { status: status, stdout: out, stderr: err, cmdline: cmdline, - }; + } } fn make_cmdline(&self, libpath: &str, prog: &str, args: &[String]) -> String { @@ -1764,7 +1759,7 @@ actual:\n\ self.fatal_proc_rec("rustdoc failed!", &proc_res); } - if self.props.check_test_line_numbers_match == true { + if self.props.check_test_line_numbers_match { self.check_rustdoc_test_option(proc_res); } else { let root = self.find_rust_src_root().unwrap(); @@ -1791,7 +1786,7 @@ actual:\n\ .filter_map(|(line_nb, line)| { if (line.trim_left().starts_with("pub mod ") || line.trim_left().starts_with("mod ")) && - line.ends_with(";") { + line.ends_with(';') { if let Some(ref mut other_files) = other_files { other_files.push(line.rsplit("mod ") .next() @@ -1840,7 +1835,7 @@ actual:\n\ } let mut tested = 0; - for _ in res.stdout.split("\n") + for _ in res.stdout.split('\n') .filter(|s| s.starts_with("test ")) .inspect(|s| { let tmp: Vec<&str> = s.split(" - ").collect(); @@ -1853,7 +1848,7 @@ actual:\n\ iter.next(); let line = iter.next() .unwrap_or(")") - .split(")") + .split(')') .next() .unwrap_or("0") .parse() @@ -1873,7 +1868,7 @@ actual:\n\ self.fatal_proc_rec(&format!("No test has been found... {:?}", files), &res); } else { for (entry, v) in &files { - if v.len() != 0 { + if !v.is_empty() { self.fatal_proc_rec(&format!("Not found test at line{} \"{}\":{:?}", if v.len() > 1 { "s" } else { "" }, entry, v), &res); @@ -1916,11 +1911,10 @@ actual:\n\ .find(|ti| ti.name == expected_item.name); if let Some(actual_item) = actual_item_with_same_name { - if !expected_item.codegen_units.is_empty() { - // Also check for codegen units - if expected_item.codegen_units != actual_item.codegen_units { - wrong_cgus.push((expected_item.clone(), actual_item.clone())); - } + if !expected_item.codegen_units.is_empty() && + // Also check for codegen units + expected_item.codegen_units != actual_item.codegen_units { + wrong_cgus.push((expected_item.clone(), actual_item.clone())); } } else { missing.push(expected_item.string.clone()); @@ -2005,7 +1999,7 @@ actual:\n\ let cgus = if parts.len() > 1 { let cgus_str = parts[1]; - cgus_str.split(" ") + cgus_str.split(' ') .map(str::trim) .filter(|s| !s.is_empty()) .map(str::to_owned) @@ -2323,7 +2317,7 @@ actual:\n\ } } - fn compare_mir_test_output(&self, test_name: &str, expected_content: &Vec<&str>) { + fn compare_mir_test_output(&self, test_name: &str, expected_content: &[&str]) { let mut output_file = PathBuf::new(); output_file.push(self.get_mir_dump_dir()); output_file.push(test_name); From 4154f895d388b1a8634a95ff76892419bebe9cc3 Mon Sep 17 00:00:00 2001 From: Paul Woolcock Date: Sat, 24 Jun 2017 20:37:15 -0400 Subject: [PATCH 042/162] only show allowed failure count if there are allowed failures --- src/libtest/lib.rs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 0567be4e604..92cfb862b16 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -789,14 +789,24 @@ impl ConsoleTestState { } else { self.write_pretty("FAILED", term::color::RED)?; } - let s = format!( + let s = if self.allowed_fail > 0 { + format!( ". {} passed; {} failed ({} allowed); {} ignored; {} measured; {} filtered out\n\n", self.passed, - self.failed, + self.failed + self.allowed_fail, self.allowed_fail, self.ignored, self.measured, - self.filtered_out); + self.filtered_out) + } else { + format!( + ". {} passed; {} failed; {} ignored; {} measured; {} filtered out\n\n", + self.passed, + self.failed, + self.ignored, + self.measured, + self.filtered_out) + }; self.write_plain(&s)?; return Ok(success); } From 8aa39ad3d8a104b4676186df959cc4b248495381 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 25 Jun 2017 10:58:12 -0700 Subject: [PATCH 043/162] Stop disabling fill in jemalloc The underlying bug has been fixed for over 2 years! --- src/liballoc_jemalloc/build.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/liballoc_jemalloc/build.rs b/src/liballoc_jemalloc/build.rs index 23677bca9f1..085f62f4b0f 100644 --- a/src/liballoc_jemalloc/build.rs +++ b/src/liballoc_jemalloc/build.rs @@ -137,8 +137,6 @@ fn main() { cmd.arg("--enable-debug"); } - // Turn off broken quarantine (see jemalloc/jemalloc#161) - cmd.arg("--disable-fill"); cmd.arg(format!("--host={}", build_helper::gnu_target(&target))); cmd.arg(format!("--build={}", build_helper::gnu_target(&host))); From d24d408af387e99e7237f21e9a8d13a35552e01a Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 25 Jun 2017 11:33:47 -0700 Subject: [PATCH 044/162] std: Fix implementation of `Alloc::alloc_one` This had an accidental `u8 as *mut T` where it was intended to have just a normal pointer-to-pointer cast. Closes #42827 --- src/liballoc/allocator.rs | 2 +- src/test/run-pass/allocator-alloc-one.rs | 27 ++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 src/test/run-pass/allocator-alloc-one.rs diff --git a/src/liballoc/allocator.rs b/src/liballoc/allocator.rs index 9bddce29957..bf38629ed38 100644 --- a/src/liballoc/allocator.rs +++ b/src/liballoc/allocator.rs @@ -873,7 +873,7 @@ pub unsafe trait Alloc { { let k = Layout::new::(); if k.size() > 0 { - unsafe { self.alloc(k).map(|p|Unique::new(*p as *mut T)) } + unsafe { self.alloc(k).map(|p| Unique::new(p as *mut T)) } } else { Err(AllocErr::invalid_input("zero-sized type invalid for alloc_one")) } diff --git a/src/test/run-pass/allocator-alloc-one.rs b/src/test/run-pass/allocator-alloc-one.rs new file mode 100644 index 00000000000..7cc547dcc04 --- /dev/null +++ b/src/test/run-pass/allocator-alloc-one.rs @@ -0,0 +1,27 @@ +// Copyright 2017 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. + +#![feature(alloc, allocator_api, heap_api, unique)] + +extern crate alloc; + +use alloc::heap::HeapAlloc; +use alloc::allocator::Alloc; + +fn main() { + unsafe { + let ptr = HeapAlloc.alloc_one::().unwrap_or_else(|e| { + HeapAlloc.oom(e) + }); + *ptr.as_ptr() = 4; + assert_eq!(*ptr.as_ptr(), 4); + HeapAlloc.dealloc_one(ptr); + } +} From 0d985c9e8760da77b0df8920465700728e2da4f1 Mon Sep 17 00:00:00 2001 From: Casey Rodarmor Date: Sun, 25 Jun 2017 14:23:43 -0700 Subject: [PATCH 045/162] Reword OsStr docs to clarify that utf8 may contain nulls --- src/libstd/ffi/os_str.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index f54d79c201f..e9296f33b9e 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -29,7 +29,7 @@ use sys_common::{AsInner, IntoInner, FromInner}; /// * On Windows, strings are often arbitrary sequences of non-zero 16-bit /// values, interpreted as UTF-16 when it is valid to do so. /// -/// * In Rust, strings are always valid UTF-8, but may contain zeros. +/// * In Rust, strings are always valid UTF-8, which may contain zeros. /// /// `OsString` and [`OsStr`] bridge this gap by simultaneously representing Rust /// and platform-native string values, and in particular allowing a Rust string From 723833f4e1ab867e9dafc7fed863321d96d507e8 Mon Sep 17 00:00:00 2001 From: Stjepan Glavina Date: Mon, 26 Jun 2017 11:20:31 +0200 Subject: [PATCH 046/162] Move thread_rng() outside the loop --- src/test/run-pass/vector-sort-panic-safe.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/run-pass/vector-sort-panic-safe.rs b/src/test/run-pass/vector-sort-panic-safe.rs index 3458199bdaf..4387a43f03b 100644 --- a/src/test/run-pass/vector-sort-panic-safe.rs +++ b/src/test/run-pass/vector-sort-panic-safe.rs @@ -141,10 +141,11 @@ fn main() { } })); + let mut rng = thread_rng(); + for len in (1..20).chain(70..MAX_LEN) { for &modulus in &[5, 20, 50] { for &has_runs in &[false, true] { - let mut rng = thread_rng(); let mut input = (0..len) .map(|id| { DropCounter { From 38b468832f34d0f9bfcaa9e3c47a246546f52b0b Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Mon, 26 Jun 2017 10:26:15 -0600 Subject: [PATCH 047/162] Update Cargo --- src/Cargo.lock | 109 +++++++++++++++++++++++++++--------------------- src/tools/cargo | 2 +- 2 files changed, 63 insertions(+), 48 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index dd6e72a5614..386450f4a65 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -129,7 +129,7 @@ dependencies = [ "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -157,7 +157,7 @@ dependencies = [ [[package]] name = "cargo" version = "0.21.0" -source = "git+https://github.com/rust-lang/cargo#50b1c24d146fa072db71f12005deed319ac5ba9a" +source = "git+https://github.com/rust-lang/cargo#abf01e1eddb3145c83f71b469ea7bee37141e5e1" replace = "cargo 0.21.0" [[package]] @@ -170,8 +170,8 @@ dependencies = [ "cargotest 0.1.0", "crates-io 0.10.0", "crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "curl 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "docopt 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "curl 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "docopt 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -188,7 +188,7 @@ dependencies = [ "libgit2-sys 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "openssl 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)", "psapi-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -201,8 +201,8 @@ dependencies = [ "tar 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -224,7 +224,7 @@ dependencies = [ "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "tar 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -301,12 +301,12 @@ dependencies = [ name = "crates-io" version = "0.10.0" dependencies = [ - "curl 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "curl 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -316,19 +316,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "curl" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "curl-sys 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)", + "curl-sys 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)", + "socket2 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "curl-sys" -version = "0.3.12" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", @@ -365,7 +366,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "docopt" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -474,7 +475,7 @@ dependencies = [ "libgit2-sys 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -482,10 +483,10 @@ name = "git2-curl" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "curl 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "curl 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "git2 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -582,7 +583,7 @@ dependencies = [ "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -609,7 +610,7 @@ version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", - "curl-sys 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)", + "curl-sys 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", "libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -798,7 +799,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "num_cpus" -version = "1.5.1" +version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", @@ -944,11 +945,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "racer" -version = "2.0.8" +version = "2.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "clap 2.24.2 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "syntex_errors 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1023,17 +1025,17 @@ dependencies = [ "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "languageserver-types 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "racer 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "racer 2.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "rls-analysis 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "rls-data 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-vfs 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustfmt-nightly 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rls-vfs 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rustfmt-nightly 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1079,10 +1081,10 @@ dependencies = [ [[package]] name = "rls-vfs" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "racer 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "racer 2.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1472,7 +1474,7 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "0.1.3" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1486,8 +1488,8 @@ dependencies = [ "serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "strings 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1588,6 +1590,18 @@ name = "shell-escape" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "socket2" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "stable_deref_trait" version = "1.0.0" @@ -1706,7 +1720,7 @@ dependencies = [ "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "syntex_pos 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)", - "term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1729,7 +1743,7 @@ dependencies = [ "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "syntex_errors 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)", "syntex_pos 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)", - "term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1757,7 +1771,7 @@ version = "0.0.0" [[package]] name = "term" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1855,7 +1869,7 @@ dependencies = [ [[package]] name = "toml" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1916,7 +1930,7 @@ dependencies = [ [[package]] name = "url" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "idna 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1930,7 +1944,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2035,12 +2049,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum clap 2.24.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b8f69e518f967224e628896b54e41ff6acfb4dcfefc5076325c36525dac900f" "checksum cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b8ebbb35d3dc9cd09497168f33de1acb79b265d350ab0ac34133b98f8509af1f" "checksum crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0c5ea215664ca264da8a9d9c3be80d2eaf30923c259d03e870388eb927508f97" -"checksum curl 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c90e1240ef340dd4027ade439e5c7c2064dd9dc652682117bd50d1486a3add7b" -"checksum curl-sys 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)" = "f00c8ba847fb0730c293069b4d1203dc01bf3c2e1f90b4e55f426ed8f4a1eeac" +"checksum curl 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6689276ab61f97c660669a5ecc117c36875dfc1ba301c986b16c653415bdf9d7" +"checksum curl-sys 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "cbd8b8d593de3bbf49252b92f398ef47f0c6c1ebdfd0f9282b9b9348aad8d71c" "checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850" "checksum derive-new 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "41be6ca3b99e0c0483fb2389685448f650459c3ecbe4e18d7705d8010ec4ab8e" "checksum diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0a515461b6c8c08419850ced27bc29e86166dcdcde8fbe76f8b1f0589bb49472" -"checksum docopt 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "63e408eee8a772c5c61f62353992e3ebf51ef5c832dd04d986b3dc7d48c5b440" +"checksum docopt 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3b5b93718f8b3e5544fcc914c43de828ca6c6ace23e0332c6080a2977b49787a" "checksum dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80c8b71fd71146990a9742fc06dcbbde19161a267e0ad4e572c35162f4578c90" "checksum enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180" "checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f" @@ -2084,7 +2098,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)" = "f7d1891bd7b936f12349b7d1403761c8a0b85a18b148e9da4429d5d102c1a41e" "checksum num-rational 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)" = "33c881e104a26e1accc09449374c095ff2312c8e0c27fab7bbefe16eac7c776d" "checksum num-traits 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "1708c0628602a98b52fad936cf3edb9a107af06e52e49fdf0707e884456a6af6" -"checksum num_cpus 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6e416ba127a4bb3ff398cb19546a8d0414f73352efe2857f4060d36f5fe5983a" +"checksum num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aec53c34f2d0247c5ca5d32cca1478762f301740468ee9ee6dcb7a0dd7a0c584" "checksum open 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3478ed1686bd1300c8a981a940abc92b06fac9cbef747f4c668d4e032ff7b842" "checksum openssl 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)" = "11ba043cb65fc9af71a431b8a36ffe8686cd4751cdf70a473ec1d01066ac7e41" "checksum openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d98df0270d404ccd3c050a41d579c52d1db15375168bb3471e04ec0f5f378daf" @@ -2099,7 +2113,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum quick-error 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c36987d4978eb1be2e422b1e0423a557923a5c3e7e6f31d5699e9aafaefa469" "checksum quote 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4c5cf478fe1006dbcc72567121d23dbdae5f1632386068c5c86ff4f645628504" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" -"checksum racer 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "edf2dfc188373ef96168bec3646a0415c5c21111c6144c0c36104fc720587ecd" +"checksum racer 2.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9079a128fdb6f0c8850010e1478b215d4c00134654bf995bfda41824951ce9bd" "checksum rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "022e0636ec2519ddae48154b028864bdce4eaf7d35226ab8e65c611be97b189d" "checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f" "checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b" @@ -2109,10 +2123,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rls-data 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "374a8fad31cc0681a7bfd8a04079dd4afd0e981d34e18a171b1a467445bdf51e" "checksum rls-data 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e502ac679bc35e023e982506c32d0278ef89e29af1e4ad21cb70c44b525b87a9" "checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a" -"checksum rls-vfs 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ace07060dd154731b39254864245cbdd33c8f5f64fe1f630a089c72e2468f854" +"checksum rls-vfs 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1f19246a0fda45f2fb6eb34addef2a692c044cbf1c90ec7695583450fb5f23e7" "checksum rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3058a43ada2c2d0b92b3ae38007a2d0fa5e9db971be260e0171408a4ff471c95" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" -"checksum rustfmt-nightly 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "277deb9c0ee9c4788ee94faef5988fa334179cd7363bf281a2cae027edbbc8bf" +"checksum rustfmt-nightly 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "31ac6fe40a9844ee2de3d51d0be2bbcdb361bad6f3667a02db8c4e2330afbbb5" "checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7" "checksum scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d" "checksum semver 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3fdd61b85a0fa777f7fb7c454b9189b2941b110d1385ce84d7f76efdf1606a85" @@ -2125,6 +2139,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum serde_json 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ad8bcf487be7d2e15d3d543f04312de991d631cfe1b43ea0ade69e6a8a5b16a1" "checksum serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "48b04779552e92037212c3615370f6bd57a40ebba7f20e554ff9f55e41a69a7b" "checksum shell-escape 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "dd5cc96481d54583947bfe88bf30c23d53f883c6cd0145368b69989d97b84ef8" +"checksum socket2 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "12cdbddbaa27bf94cc194b8e37f5811db6fe83cea96cf99cf1f8e92b65a41371" "checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b" "checksum strings 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "da75d8bf2c4d210d63dd09581a041b036001f9f6e03d9b151dbff810fb7ba26a" "checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694" @@ -2136,7 +2151,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum syntex_syntax 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)" = "76a302e717e348aa372ff577791c3832395650073b8d8432f8b3cb170b34afde" "checksum tar 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "281285b717926caa919ad905ef89c63d75805c7d89437fb873100925a53f2b1b" "checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6" -"checksum term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d168af3930b369cfe245132550579d47dfd873d69470755a19c2c6568dbbd989" +"checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1" "checksum term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2b6b55df3198cc93372e85dd2ed817f0e38ce8cc0f22eb32391bfad9c4bf209" "checksum termcolor 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9a5193a56b8d82014662c4b933dea6bec851daf018a2b01722e007daaf5f9dca" "checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03" @@ -2146,7 +2161,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)" = "0590d72182e50e879c4da3b11c6488dae18fccb1ae0c7a3eda18e16795844796" "checksum toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "736b60249cb25337bc196faa43ee12c705e426f3d55c214d73a4e7be06f92cb4" "checksum toml 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bd86ad9ebee246fdedd610e0f6d0587b754a3d81438db930a244d0480ed7878f" -"checksum toml 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4cc5dbfb20a481e64b99eb7ae280859ec76730c7191570ba5edaa962394edb0a" +"checksum toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b0601da6c97135c8d330c7a13a013ca6cd4143221b01de2f8d4edc50a9e551c7" "checksum typed-arena 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5934776c3ac1bea4a9d56620d6bf2d483b20d394e49581db40f187e1118ff667" "checksum unicode-bidi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a6a2c4e3710edd365cd7e78383153ed739fa31af19f9172f72d3575060f5a43a" "checksum unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "51ccda9ef9efa3f7ef5d91e8f9b83bbe6955f9bf86aec89d5cce2c874625920f" @@ -2155,7 +2170,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "36dff09cafb4ec7c8cf0023eb0b686cb6ce65499116a12201c9e11840ca01beb" "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" "checksum unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91" -"checksum url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a69a2e36a5e5ed3f3063c8c64a3b028c4d50d689fa6c862abd7cfe65f882595c" +"checksum url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eeb819346883532a271eb626deb43c4a1bb4c4dd47c519bd78137c3e72a4fe27" "checksum url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "74e7d099f1ee52f823d4bdd60c93c3602043c728f5db3b97bdb548467f7bddea" "checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f" "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" diff --git a/src/tools/cargo b/src/tools/cargo index 534ce68621c..abf01e1eddb 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 534ce68621ce4feec0b7e8627cfd3b077d4f3900 +Subproject commit abf01e1eddb3145c83f71b469ea7bee37141e5e1 From 3f1cb30b14aed8ce1e7567e47981cf602f74aea4 Mon Sep 17 00:00:00 2001 From: kennytm Date: Tue, 27 Jun 2017 02:44:42 +0800 Subject: [PATCH 048/162] compiletest: show details if GDB failed to execute. --- src/tools/compiletest/src/runtest.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 0692e07253f..4961609c77f 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -692,7 +692,7 @@ actual:\n\ } if !debugger_run_result.status.success() { - self.fatal("gdb failed to execute"); + self.fatal_proc_rec("gdb failed to execute", &debugger_run_result); } self.check_debugger_output(&debugger_run_result, &check_lines); From 32b8579b6826091e11ea6d90a2d64f4975894032 Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Mon, 26 Jun 2017 13:30:21 -0700 Subject: [PATCH 049/162] make lint on-by-default/implied-by messages appear only once From review discussion on #38103 (https://github.com/rust-lang/rust/pull/38103#discussion_r94845060). --- src/librustc/lint/context.rs | 26 +++++----- src/librustc/session/mod.rs | 60 +++++++++++++++++------- src/test/ui/lint/lint-group-style.stderr | 10 ++-- src/test/ui/path-lookahead.stderr | 2 - src/test/ui/span/issue-24690.stderr | 6 +-- 5 files changed, 63 insertions(+), 41 deletions(-) diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index a9e0ef51102..1a0ab8c413d 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -513,7 +513,6 @@ pub fn raw_struct_lint<'a, S>(sess: &'a Session, } let name = lint.name_lower(); - let mut def = None; // Except for possible note details, forbid behaves like deny. let effective_level = if level == Forbid { Deny } else { level }; @@ -528,7 +527,8 @@ pub fn raw_struct_lint<'a, S>(sess: &'a Session, match source { Default => { - err.note(&format!("#[{}({})] on by default", level.as_str(), name)); + sess.diag_note_once(&mut err, lint, + &format!("#[{}({})] on by default", level.as_str(), name)); }, CommandLine(lint_flag_val) => { let flag = match level { @@ -537,20 +537,24 @@ pub fn raw_struct_lint<'a, S>(sess: &'a Session, }; let hyphen_case_lint_name = name.replace("_", "-"); if lint_flag_val.as_str() == name { - err.note(&format!("requested on the command line with `{} {}`", - flag, hyphen_case_lint_name)); + sess.diag_note_once(&mut err, lint, + &format!("requested on the command line with `{} {}`", + flag, hyphen_case_lint_name)); } else { let hyphen_case_flag_val = lint_flag_val.as_str().replace("_", "-"); - err.note(&format!("`{} {}` implied by `{} {}`", - flag, hyphen_case_lint_name, flag, hyphen_case_flag_val)); + sess.diag_note_once(&mut err, lint, + &format!("`{} {}` implied by `{} {}`", + flag, hyphen_case_lint_name, flag, + hyphen_case_flag_val)); } }, Node(lint_attr_name, src) => { - def = Some(src); + sess.diag_span_note_once(&mut err, lint, src, "lint level defined here"); if lint_attr_name.as_str() != name { let level_str = level.as_str(); - err.note(&format!("#[{}({})] implied by #[{}({})]", - level_str, name, level_str, lint_attr_name)); + sess.diag_note_once(&mut err, lint, + &format!("#[{}({})] implied by #[{}({})]", + level_str, name, level_str, lint_attr_name)); } } } @@ -566,10 +570,6 @@ pub fn raw_struct_lint<'a, S>(sess: &'a Session, err.note(&citation); } - if let Some(span) = def { - sess.diag_span_note_once(&mut err, lint, span, "lint level defined here"); - } - err } diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 70c07982f83..fb513f573d7 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -79,10 +79,10 @@ pub struct Session { pub working_dir: (String, bool), pub lint_store: RefCell, pub lints: RefCell, - /// Set of (LintId, span, message) tuples tracking lint (sub)diagnostics - /// that have been set once, but should not be set again, in order to avoid - /// redundantly verbose output (Issue #24690). - pub one_time_diagnostics: RefCell>, + /// Set of (LintId, Option, message) tuples tracking lint + /// (sub)diagnostics that have been set once, but should not be set again, + /// in order to avoid redundantly verbose output (Issue #24690). + pub one_time_diagnostics: RefCell, String)>>, pub plugin_llvm_passes: RefCell>, pub plugin_attributes: RefCell>, pub crate_types: RefCell>, @@ -157,6 +157,13 @@ pub struct PerfStats { pub decode_def_path_tables_time: Cell, } +/// Enum to support dispatch of one-time diagnostics (in Session.diag_once) +enum DiagnosticBuilderMethod { + Note, + SpanNote, + // add more variants as needed to support one-time diagnostics +} + impl Session { pub fn local_crate_disambiguator(&self) -> Symbol { *self.crate_disambiguator.borrow() @@ -329,34 +336,53 @@ impl Session { &self.parse_sess.span_diagnostic } - /// Analogous to calling `.span_note` on the given DiagnosticBuilder, but - /// deduplicates on lint ID, span, and message for this `Session` if we're - /// not outputting in JSON mode. - // - // FIXME: if the need arises for one-time diagnostics other than - // `span_note`, we almost certainly want to generalize this - // "check/insert-into the one-time diagnostics map, then set message if - // it's not already there" code to accomodate all of them - pub fn diag_span_note_once<'a, 'b>(&'a self, - diag_builder: &'b mut DiagnosticBuilder<'a>, - lint: &'static lint::Lint, span: Span, message: &str) { + /// Analogous to calling methods on the given `DiagnosticBuilder`, but + /// deduplicates on lint ID, span (if any), and message for this `Session` + /// if we're not outputting in JSON mode. + fn diag_once<'a, 'b>(&'a self, + diag_builder: &'b mut DiagnosticBuilder<'a>, + method: DiagnosticBuilderMethod, + lint: &'static lint::Lint, message: &str, span: Option) { + let mut do_method = || { + match method { + DiagnosticBuilderMethod::Note => { + diag_builder.note(message); + }, + DiagnosticBuilderMethod::SpanNote => { + diag_builder.span_note(span.expect("span_note expects a span"), message); + } + } + }; + match self.opts.error_format { // when outputting JSON for tool consumption, the tool might want // the duplicates config::ErrorOutputType::Json => { - diag_builder.span_note(span, &message); + do_method() }, _ => { let lint_id = lint::LintId::of(lint); let id_span_message = (lint_id, span, message.to_owned()); let fresh = self.one_time_diagnostics.borrow_mut().insert(id_span_message); if fresh { - diag_builder.span_note(span, &message); + do_method() } } } } + pub fn diag_span_note_once<'a, 'b>(&'a self, + diag_builder: &'b mut DiagnosticBuilder<'a>, + lint: &'static lint::Lint, span: Span, message: &str) { + self.diag_once(diag_builder, DiagnosticBuilderMethod::SpanNote, lint, message, Some(span)); + } + + pub fn diag_note_once<'a, 'b>(&'a self, + diag_builder: &'b mut DiagnosticBuilder<'a>, + lint: &'static lint::Lint, message: &str) { + self.diag_once(diag_builder, DiagnosticBuilderMethod::Note, lint, message, None); + } + pub fn codemap<'a>(&'a self) -> &'a codemap::CodeMap { self.parse_sess.codemap() } diff --git a/src/test/ui/lint/lint-group-style.stderr b/src/test/ui/lint/lint-group-style.stderr index dec44c317e4..636370de302 100644 --- a/src/test/ui/lint/lint-group-style.stderr +++ b/src/test/ui/lint/lint-group-style.stderr @@ -4,12 +4,12 @@ error: function `CamelCase` should have a snake case name such as `camel_case` 14 | fn CamelCase() {} | ^^^^^^^^^^^^^^^^^ | - = note: #[deny(non_snake_case)] implied by #[deny(bad_style)] note: lint level defined here --> $DIR/lint-group-style.rs:11:9 | 11 | #![deny(bad_style)] | ^^^^^^^^^ + = note: #[deny(non_snake_case)] implied by #[deny(bad_style)] error: function `CamelCase` should have a snake case name such as `camel_case` --> $DIR/lint-group-style.rs:22:9 @@ -17,12 +17,12 @@ error: function `CamelCase` should have a snake case name such as `camel_case` 22 | fn CamelCase() {} | ^^^^^^^^^^^^^^^^^ | - = note: #[forbid(non_snake_case)] implied by #[forbid(bad_style)] note: lint level defined here --> $DIR/lint-group-style.rs:20:14 | 20 | #[forbid(bad_style)] | ^^^^^^^^^ + = note: #[forbid(non_snake_case)] implied by #[forbid(bad_style)] error: static variable `bad` should have an upper case name such as `BAD` --> $DIR/lint-group-style.rs:24:9 @@ -30,12 +30,12 @@ error: static variable `bad` should have an upper case name such as `BAD` 24 | static bad: isize = 1; | ^^^^^^^^^^^^^^^^^^^^^^ | - = note: #[forbid(non_upper_case_globals)] implied by #[forbid(bad_style)] note: lint level defined here --> $DIR/lint-group-style.rs:20:14 | 20 | #[forbid(bad_style)] | ^^^^^^^^^ + = note: #[forbid(non_upper_case_globals)] implied by #[forbid(bad_style)] warning: function `CamelCase` should have a snake case name such as `camel_case` --> $DIR/lint-group-style.rs:30:9 @@ -43,12 +43,12 @@ warning: function `CamelCase` should have a snake case name such as `camel_case` 30 | fn CamelCase() {} | ^^^^^^^^^^^^^^^^^ | - = note: #[warn(non_snake_case)] implied by #[warn(bad_style)] note: lint level defined here --> $DIR/lint-group-style.rs:28:17 | 28 | #![warn(bad_style)] | ^^^^^^^^^ + = note: #[warn(non_snake_case)] implied by #[warn(bad_style)] warning: type `snake_case` should have a camel case name such as `SnakeCase` --> $DIR/lint-group-style.rs:32:9 @@ -56,12 +56,12 @@ warning: type `snake_case` should have a camel case name such as `SnakeCase` 32 | struct snake_case; | ^^^^^^^^^^^^^^^^^^ | - = note: #[warn(non_camel_case_types)] implied by #[warn(bad_style)] note: lint level defined here --> $DIR/lint-group-style.rs:28:17 | 28 | #![warn(bad_style)] | ^^^^^^^^^ + = note: #[warn(non_camel_case_types)] implied by #[warn(bad_style)] error: aborting due to previous error(s) diff --git a/src/test/ui/path-lookahead.stderr b/src/test/ui/path-lookahead.stderr index 1e19977e84a..8fd1b8de687 100644 --- a/src/test/ui/path-lookahead.stderr +++ b/src/test/ui/path-lookahead.stderr @@ -23,6 +23,4 @@ warning: function is never used: `no_parens` 20 | | return ::to_string(&arg); 21 | | } | |_^ - | - = note: #[warn(dead_code)] on by default diff --git a/src/test/ui/span/issue-24690.stderr b/src/test/ui/span/issue-24690.stderr index 598f9f51307..edc150f65ea 100644 --- a/src/test/ui/span/issue-24690.stderr +++ b/src/test/ui/span/issue-24690.stderr @@ -4,20 +4,18 @@ error: variable `theTwo` should have a snake case name such as `the_two` 19 | let theTwo = 2; | ^^^^^^ | - = note: #[deny(non_snake_case)] implied by #[deny(warnings)] note: lint level defined here --> $DIR/issue-24690.rs:16:9 | 16 | #![deny(warnings)] | ^^^^^^^^ + = note: #[deny(non_snake_case)] implied by #[deny(warnings)] error: variable `theOtherTwo` should have a snake case name such as `the_other_two` --> $DIR/issue-24690.rs:20:9 | 20 | let theOtherTwo = 2; | ^^^^^^^^^^^ - | - = note: #[deny(non_snake_case)] implied by #[deny(warnings)] error: unused variable: `theOtherTwo` --> $DIR/issue-24690.rs:20:9 @@ -25,12 +23,12 @@ error: unused variable: `theOtherTwo` 20 | let theOtherTwo = 2; | ^^^^^^^^^^^ | - = note: #[deny(unused_variables)] implied by #[deny(warnings)] note: lint level defined here --> $DIR/issue-24690.rs:16:9 | 16 | #![deny(warnings)] | ^^^^^^^^ + = note: #[deny(unused_variables)] implied by #[deny(warnings)] error: aborting due to previous error(s) From 330dab837fb872051b365715f1532eb8156c33ae Mon Sep 17 00:00:00 2001 From: Behnam Esfahbod Date: Mon, 26 Jun 2017 18:27:01 -0600 Subject: [PATCH 050/162] [libcore/cmp] Expand Ord/PartialOrd Derivable doc for enum types Expand Derivable docblock section for `Ord` and `PartialOrd` to cover `enum` types, in addition to the existing language explaining it for `struct` types. --- src/libcore/cmp.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 6f35d0417f1..2e691ea4af2 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -380,8 +380,9 @@ impl Ord for Reverse { /// /// ## Derivable /// -/// This trait can be used with `#[derive]`. When `derive`d, it will produce a lexicographic -/// ordering based on the top-to-bottom declaration order of the struct's members. +/// This trait can be used with `#[derive]`. When `derive`d on structs, it will produce a +/// lexicographic ordering based on the top-to-bottom declaration order of the struct's members. +/// When `derive`d on enums, variants are ordered by their top-to-bottom declaration order. /// /// ## How can I implement `Ord`? /// @@ -513,8 +514,9 @@ impl PartialOrd for Ordering { /// /// ## Derivable /// -/// This trait can be used with `#[derive]`. When `derive`d, it will produce a lexicographic -/// ordering based on the top-to-bottom declaration order of the struct's members. +/// This trait can be used with `#[derive]`. When `derive`d on structs, it will produce a +/// lexicographic ordering based on the top-to-bottom declaration order of the struct's members. +/// When `derive`d on enums, variants are ordered by their top-to-bottom declaration order. /// /// ## How can I implement `PartialOrd`? /// From 1715559f82a7576c8d64430dbff05bc007f1a6e9 Mon Sep 17 00:00:00 2001 From: Andre Bogus Date: Tue, 27 Jun 2017 07:16:54 +0200 Subject: [PATCH 051/162] address tidy error & comment --- src/tools/compiletest/src/header.rs | 4 +--- src/tools/compiletest/src/main.rs | 3 ++- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index ce33787a7d3..c9e24492207 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -549,9 +549,7 @@ impl Config { pub fn lldb_version_to_int(version_string: &str) -> isize { let error_string = format!("Encountered LLDB version string with unexpected format: {}", version_string); - let error_string = error_string; - let major: isize = version_string.parse().expect(&error_string); - major + version_string.parse().expect(&error_string); } fn expand_variables(mut value: String, config: &Config) -> String { diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 692e31ebad0..defb405c09d 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -598,7 +598,8 @@ fn extract_gdb_version(full_version_line: &str) -> Option { Some(idx) => if line.as_bytes()[idx] == b'.' { let patch = &line[idx + 1..]; - let patch_len = patch.find(|c: char| !c.is_digit(10)).unwrap_or_else(|| patch.len()); + let patch_len = patch.find(|c: char| !c.is_digit(10)) + .unwrap_or_else(|| patch.len()); let patch = &patch[..patch_len]; let patch = if patch_len > 3 || patch_len == 0 { None } else { Some(patch) }; From 71252d9b80020d932aa7960a3930684489a6e167 Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Tue, 27 Jun 2017 12:09:56 +0200 Subject: [PATCH 052/162] Document possible `io::ErrorKind`s of `fs::open` Try to make clear that this isn't an API guarantee for now, as we likely want to refine these errors in the future, e.g. `ENOSPC` "No space left on device". CC #40322 --- src/libstd/fs.rs | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index 5b8c0c33990..f1ec4d2dff0 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -653,15 +653,29 @@ impl OpenOptions { /// # Errors /// /// This function will return an error under a number of different - /// circumstances, to include but not limited to: + /// circumstances. Some of these error conditions are listed here, together + /// with their [`ErrorKind`]. The mapping to `ErrorKind`s is not part of + /// the compatiblity contract of the function, especially the `Other` kind + /// might change to more specific kinds in the future. /// - /// * Opening a file that does not exist without setting `create` or - /// `create_new`. - /// * Attempting to open a file with access that the user lacks - /// permissions for - /// * Filesystem-level errors (full disk, etc) - /// * Invalid combinations of open options (truncate without write access, - /// no access mode set, etc) + /// * `NotFound`: The specified file does not exist and neither `create` or + /// `create_new` is set, + /// * `NotFound`: One of the directory components of the file path does not + /// exist. + /// * `PermissionDenied`: The user lacks permission to get the specified + /// access rights for the file. + /// * `PermissionDenied`: The user lacks permission to open one of the + /// directory components of the specified path. + /// * `AlreadyExists`: `create_new` was specified and the file already + /// exists. + /// * `InvalidInput`: Invalid combinations of open options (truncate + /// without write access, no access mode set, etc.). + /// * `Other`: One of the directory components of the specified file path + /// was not, in fact, a directory. + /// * `Other`: Filesystem-level errors: full disk, write permission + /// requested on a read-only file system, exceeded disk quota, too many + /// open files, too long filename, too many symbolic links in the + /// specified path (Unix-like systems only), etc. /// /// # Examples /// @@ -670,6 +684,8 @@ impl OpenOptions { /// /// let file = OpenOptions::new().open("foo.txt"); /// ``` + /// + /// [`ErrorKind`]: ../io/enum.ErrorKind.html #[stable(feature = "rust1", since = "1.0.0")] pub fn open>(&self, path: P) -> io::Result { self._open(path.as_ref()) From 8e53a03d15bfd425c99fc4f5a7d6a1ec71cbe720 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sat, 13 May 2017 13:12:29 +0300 Subject: [PATCH 053/162] rustc: rename closure_type to fn_sig. --- src/librustc/infer/mod.rs | 8 ++++++-- src/librustc/traits/project.rs | 2 +- src/librustc/traits/select.rs | 2 +- src/librustc/ty/maps.rs | 7 +++---- src/librustc_metadata/cstore_impl.rs | 2 +- src/librustc_metadata/decoder.rs | 10 +++++----- src/librustc_metadata/encoder.rs | 2 +- src/librustc_metadata/schema.rs | 4 ++-- src/librustc_trans/common.rs | 2 +- src/librustc_trans/mir/constant.rs | 2 +- src/librustc_trans/monomorphize.rs | 2 +- src/librustc_typeck/check/callee.rs | 2 +- src/librustc_typeck/check/coercion.rs | 2 +- src/librustc_typeck/check/mod.rs | 8 ++++---- 14 files changed, 29 insertions(+), 26 deletions(-) diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index f96e8c389d6..d5020b12ee0 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -1369,7 +1369,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { Some(self.tcx.closure_kind(def_id)) } - pub fn closure_type(&self, def_id: DefId) -> ty::PolyFnSig<'tcx> { + /// Obtain the signature of a function or closure. + /// For closures, unlike `tcx.fn_sig(def_id)`, this method will + /// work during the type-checking of the enclosing function and + /// return the closure signature in its partially inferred state. + pub fn fn_sig(&self, def_id: DefId) -> ty::PolyFnSig<'tcx> { if let Some(tables) = self.in_progress_tables { if let Some(id) = self.tcx.hir.as_local_node_id(def_id) { if let Some(&ty) = tables.borrow().closure_tys.get(&id) { @@ -1378,7 +1382,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } } - self.tcx.closure_type(def_id) + self.tcx.fn_sig(def_id) } } diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index 787452121d3..f71f75dbaa8 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -1149,7 +1149,7 @@ fn confirm_closure_candidate<'cx, 'gcx, 'tcx>( -> Progress<'tcx> { let closure_typer = selcx.closure_typer(); - let closure_type = closure_typer.closure_type(vtable.closure_def_id) + let closure_type = closure_typer.fn_sig(vtable.closure_def_id) .subst(selcx.tcx(), vtable.substs.substs); let Normalized { value: closure_type, diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 10710d963a0..c68b8ee14b8 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -2799,7 +2799,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { substs: ty::ClosureSubsts<'tcx>) -> ty::PolyTraitRef<'tcx> { - let closure_type = self.infcx.closure_type(closure_def_id) + let closure_type = self.infcx.fn_sig(closure_def_id) .subst(self.tcx(), substs.substs); let ty::Binder((trait_ref, _)) = self.tcx().closure_trait_ref_and_return_type(obligation.predicate.def_id(), diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index 524cf57472b..a6c59d4c223 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -875,13 +875,12 @@ define_maps! { <'tcx> /// for trans. This is also the only query that can fetch non-local MIR, at present. [] optimized_mir: Mir(DefId) -> &'tcx mir::Mir<'tcx>, - /// Records the type of each closure. The def ID is the ID of the + /// Type of each closure. The def ID is the ID of the /// expression defining the closure. [] closure_kind: ItemSignature(DefId) -> ty::ClosureKind, - /// Records the type of each closure. The def ID is the ID of the - /// expression defining the closure. - [] closure_type: ItemSignature(DefId) -> ty::PolyFnSig<'tcx>, + /// The signature of functions and closures. + [] fn_sig: ItemSignature(DefId) -> ty::PolyFnSig<'tcx>, /// Caches CoerceUnsized kinds for impls on custom types. [] coerce_unsized_info: ItemSignature(DefId) diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index c49712086d5..502eab44dac 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -106,7 +106,7 @@ provide! { <'tcx> tcx, def_id, cdata, mir_const_qualif => { cdata.mir_const_qualif(def_id.index) } typeck_tables_of => { cdata.item_body_tables(def_id.index, tcx) } closure_kind => { cdata.closure_kind(def_id.index) } - closure_type => { cdata.closure_ty(def_id.index, tcx) } + fn_sig => { cdata.fn_sig(def_id.index, tcx) } inherent_impls => { Rc::new(cdata.get_inherent_implementations_for_type(def_id.index)) } is_const_fn => { cdata.is_const_fn(def_id.index) } is_foreign_item => { cdata.is_foreign_item(def_id.index) } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 728ab30bb17..77f01d5c28c 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -1084,12 +1084,12 @@ impl<'a, 'tcx> CrateMetadata { } } - pub fn closure_ty(&self, - closure_id: DefIndex, - tcx: TyCtxt<'a, 'tcx, 'tcx>) - -> ty::PolyFnSig<'tcx> { + pub fn fn_sig(&self, + closure_id: DefIndex, + tcx: TyCtxt<'a, 'tcx, 'tcx>) + -> ty::PolyFnSig<'tcx> { match self.entry(closure_id).kind { - EntryKind::Closure(data) => data.decode(self).ty.decode((self, tcx)), + EntryKind::Closure(data) => data.decode(self).sig.decode((self, tcx)), _ => bug!(), } } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 2a504c4c077..860b553959f 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -1175,7 +1175,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { let data = ClosureData { kind: tcx.closure_kind(def_id), - ty: self.lazy(&tcx.closure_type(def_id)), + sig: self.lazy(&tcx.fn_sig(def_id)), }; Entry { diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index 1337f90efa7..36977cb5db2 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -553,6 +553,6 @@ impl_stable_hash_for!(struct MethodData { fn_data, container, has_self }); #[derive(RustcEncodable, RustcDecodable)] pub struct ClosureData<'tcx> { pub kind: ty::ClosureKind, - pub ty: Lazy>, + pub sig: Lazy>, } -impl_stable_hash_for!(struct ClosureData<'tcx> { kind, ty }); +impl_stable_hash_for!(struct ClosureData<'tcx> { kind, sig }); diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs index a6f3fb709a0..0db74c9454a 100644 --- a/src/librustc_trans/common.rs +++ b/src/librustc_trans/common.rs @@ -500,7 +500,7 @@ pub fn ty_fn_sig<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty::TyFnPtr(sig) => sig, ty::TyClosure(def_id, substs) => { let tcx = ccx.tcx(); - let sig = tcx.closure_type(def_id).subst(tcx, substs.substs); + let sig = tcx.fn_sig(def_id).subst(tcx, substs.substs); let env_region = ty::ReLateBound(ty::DebruijnIndex::new(1), ty::BrEnv); let env_ty = match tcx.closure_kind(def_id) { diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index 16ef32ccf57..60886b2b35f 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -579,7 +579,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { .find(|it| it.kind == ty::AssociatedKind::Method) .unwrap().def_id; // Now create its substs [Closure, Tuple] - let input = tcx.closure_type(def_id) + let input = tcx.fn_sig(def_id) .subst(tcx, substs.substs).input(0); let input = tcx.erase_late_bound_regions_and_normalize(&input); let substs = tcx.mk_substs([operand.ty, input] diff --git a/src/librustc_trans/monomorphize.rs b/src/librustc_trans/monomorphize.rs index d27eeb2b646..a5fe70a2fd7 100644 --- a/src/librustc_trans/monomorphize.rs +++ b/src/librustc_trans/monomorphize.rs @@ -40,7 +40,7 @@ fn fn_once_adapter_instance<'a, 'tcx>( let self_ty = tcx.mk_closure_from_closure_substs( closure_did, substs); - let sig = tcx.closure_type(closure_did).subst(tcx, substs.substs); + let sig = tcx.fn_sig(closure_did).subst(tcx, substs.substs); let sig = tcx.erase_late_bound_regions_and_normalize(&sig); assert_eq!(sig.inputs().len(), 1); let substs = tcx.mk_substs([ diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 385ed7eb0e3..7cd372f3f00 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -108,7 +108,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // haven't yet decided on whether the closure is fn vs // fnmut vs fnonce. If so, we have to defer further processing. if self.closure_kind(def_id).is_none() { - let closure_ty = self.closure_type(def_id).subst(self.tcx, substs.substs); + let closure_ty = self.fn_sig(def_id).subst(self.tcx, substs.substs); let fn_sig = self.replace_late_bound_regions_with_fresh_var(call_expr.span, infer::FnCall, &closure_ty) diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index 30ac7b4bfb9..c5fd1f56320 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -639,7 +639,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { // `extern "rust-call" fn((arg0,arg1,...)) -> _` // to // `fn(arg0,arg1,...) -> _` - let sig = self.closure_type(def_id_a).subst(self.tcx, substs_a.substs); + let sig = self.fn_sig(def_id_a).subst(self.tcx, substs_a.substs); let converted_sig = sig.map_bound(|s| { let params_iter = match s.inputs()[0].sty { ty::TyTuple(params, _) => { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 2bf24d5b350..b92a78987a3 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -718,16 +718,16 @@ pub fn provide(providers: &mut Providers) { typeck_item_bodies, typeck_tables_of, has_typeck_tables, - closure_type, + fn_sig, closure_kind, adt_destructor, ..*providers }; } -fn closure_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - def_id: DefId) - -> ty::PolyFnSig<'tcx> { +fn fn_sig<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId) + -> ty::PolyFnSig<'tcx> { let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); tcx.typeck_tables_of(def_id).closure_tys[&node_id] } From 33ecf72e8e26b5bf5449ae27297e83c9f78aa3ad Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sat, 13 May 2017 17:11:52 +0300 Subject: [PATCH 054/162] rustc: move the PolyFnSig out of TyFnDef. --- src/librustc/ich/impls_ty.rs | 3 +- src/librustc/middle/effect.rs | 28 ++--- src/librustc/middle/intrinsicck.rs | 27 ++--- src/librustc/traits/object_safety.rs | 2 +- src/librustc/traits/project.rs | 12 +- src/librustc/traits/select.rs | 33 +++--- src/librustc/ty/context.rs | 5 +- src/librustc/ty/fast_reject.rs | 3 +- src/librustc/ty/flags.rs | 3 +- src/librustc/ty/item_path.rs | 2 +- src/librustc/ty/mod.rs | 2 +- src/librustc/ty/relate.rs | 6 +- src/librustc/ty/structural_impls.rs | 10 +- src/librustc/ty/sty.rs | 11 +- src/librustc/ty/util.rs | 2 +- src/librustc/ty/walk.rs | 3 +- src/librustc/util/ppaux.rs | 10 +- .../borrowck/mir/dataflow/sanity_check.rs | 17 +-- src/librustc_const_eval/pattern.rs | 6 +- src/librustc_lint/builtin.rs | 18 +-- src/librustc_lint/types.rs | 2 +- src/librustc_metadata/decoder.rs | 14 ++- src/librustc_metadata/encoder.rs | 21 +++- src/librustc_metadata/schema.rs | 34 +++--- src/librustc_mir/build/expr/into.rs | 13 +- src/librustc_mir/hair/cx/expr.rs | 3 +- src/librustc_mir/shim.rs | 17 ++- src/librustc_mir/transform/inline.rs | 7 +- src/librustc_mir/transform/qualify_consts.rs | 4 +- src/librustc_mir/transform/type_check.rs | 2 +- src/librustc_privacy/lib.rs | 16 ++- src/librustc_trans/back/symbol_names.rs | 7 ++ src/librustc_trans/collector.rs | 2 +- src/librustc_trans/common.rs | 4 +- src/librustc_trans/debuginfo/metadata.rs | 9 +- src/librustc_trans/debuginfo/type_names.rs | 4 +- src/librustc_trans/intrinsic.rs | 7 +- src/librustc_trans/mir/block.rs | 14 +-- src/librustc_trans/mir/constant.rs | 4 +- src/librustc_trans/mir/rvalue.rs | 2 +- src/librustc_trans/monomorphize.rs | 8 +- src/librustc_trans/trans_item.rs | 5 +- src/librustc_typeck/check/_match.rs | 2 +- src/librustc_typeck/check/callee.rs | 4 +- src/librustc_typeck/check/cast.rs | 3 +- src/librustc_typeck/check/coercion.rs | 86 +++++++------- src/librustc_typeck/check/compare_method.rs | 24 +--- src/librustc_typeck/check/demand.rs | 7 +- src/librustc_typeck/check/intrinsic.rs | 43 +++---- src/librustc_typeck/check/method/confirm.rs | 2 +- src/librustc_typeck/check/method/mod.rs | 2 +- src/librustc_typeck/check/method/probe.rs | 4 +- src/librustc_typeck/check/mod.rs | 15 +-- src/librustc_typeck/check/wfcheck.rs | 16 ++- src/librustc_typeck/collect.rs | 112 +++++++++++++----- src/librustc_typeck/diagnostics.rs | 1 + src/librustc_typeck/lib.rs | 22 ++-- src/librustc_typeck/variance/constraints.rs | 2 +- src/librustdoc/clean/inline.rs | 2 +- src/librustdoc/clean/mod.rs | 28 +++-- src/test/compile-fail/invalid-intrinsic.rs | 4 +- 61 files changed, 427 insertions(+), 354 deletions(-) diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 4e78d79ef87..4f365a97f4c 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -524,10 +524,9 @@ for ty::TypeVariants<'tcx> region.hash_stable(hcx, hasher); pointee_ty.hash_stable(hcx, hasher); } - TyFnDef(def_id, substs, ref sig) => { + TyFnDef(def_id, substs) => { def_id.hash_stable(hcx, hasher); substs.hash_stable(hcx, hasher); - sig.hash_stable(hcx, hasher); } TyFnPtr(ref sig) => { sig.hash_stable(hcx, hasher); diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs index 74e1225f394..eab5a8f9103 100644 --- a/src/librustc/middle/effect.rs +++ b/src/librustc/middle/effect.rs @@ -12,7 +12,7 @@ //! `unsafe`. use self::RootUnsafeContext::*; -use ty::{self, Ty, TyCtxt}; +use ty::{self, TyCtxt}; use lint; use syntax::ast; @@ -40,14 +40,6 @@ enum RootUnsafeContext { UnsafeBlock(ast::NodeId), } -fn type_is_unsafe_function(ty: Ty) -> bool { - match ty.sty { - ty::TyFnDef(.., f) | - ty::TyFnPtr(f) => f.unsafety() == hir::Unsafety::Unsafe, - _ => false, - } -} - struct EffectCheckVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, tables: &'a ty::TypeckTables<'tcx>, @@ -174,10 +166,11 @@ impl<'a, 'tcx> Visitor<'tcx> for EffectCheckVisitor<'a, 'tcx> { match expr.node { hir::ExprMethodCall(..) => { let def_id = self.tables.type_dependent_defs[&expr.id].def_id(); - let base_type = self.tcx.type_of(def_id); - debug!("effect: method call case, base type is {:?}", - base_type); - if type_is_unsafe_function(base_type) { + let sig = self.tcx.fn_sig(def_id); + debug!("effect: method call case, signature is {:?}", + sig); + + if sig.0.unsafety == hir::Unsafety::Unsafe { self.require_unsafe(expr.span, "invocation of unsafe method") } @@ -186,8 +179,13 @@ impl<'a, 'tcx> Visitor<'tcx> for EffectCheckVisitor<'a, 'tcx> { let base_type = self.tables.expr_ty_adjusted(base); debug!("effect: call case, base type is {:?}", base_type); - if type_is_unsafe_function(base_type) { - self.require_unsafe(expr.span, "call to unsafe function") + match base_type.sty { + ty::TyFnDef(..) | ty::TyFnPtr(_) => { + if base_type.fn_sig(self.tcx).unsafety() == hir::Unsafety::Unsafe { + self.require_unsafe(expr.span, "call to unsafe function") + } + } + _ => {} } } hir::ExprUnary(hir::UnDeref, ref base) => { diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs index f180ae53b8a..fde207e4b2f 100644 --- a/src/librustc/middle/intrinsicck.rs +++ b/src/librustc/middle/intrinsicck.rs @@ -66,11 +66,8 @@ fn unpack_option_like<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl<'a, 'tcx> ExprVisitor<'a, 'tcx> { fn def_id_is_transmute(&self, def_id: DefId) -> bool { - let intrinsic = match self.tcx.type_of(def_id).sty { - ty::TyFnDef(.., bfty) => bfty.abi() == RustIntrinsic, - _ => return false - }; - intrinsic && self.tcx.item_name(def_id) == "transmute" + self.tcx.fn_sig(def_id).abi() == RustIntrinsic && + self.tcx.item_name(def_id) == "transmute" } fn check_transmute(&self, span: Span, from: Ty<'tcx>, to: Ty<'tcx>) { @@ -153,22 +150,14 @@ impl<'a, 'tcx> Visitor<'tcx> for ExprVisitor<'a, 'tcx> { } else { Def::Err }; - match def { - Def::Fn(did) if self.def_id_is_transmute(did) => { + if let Def::Fn(did) = def { + if self.def_id_is_transmute(did) { let typ = self.tables.node_id_to_type(expr.id); - let typ = self.tcx.lift_to_global(&typ).unwrap(); - match typ.sty { - ty::TyFnDef(.., sig) if sig.abi() == RustIntrinsic => { - let from = sig.inputs().skip_binder()[0]; - let to = *sig.output().skip_binder(); - self.check_transmute(expr.span, from, to); - } - _ => { - span_bug!(expr.span, "transmute wasn't a bare fn?!"); - } - } + let sig = typ.fn_sig(self.tcx); + let from = sig.inputs().skip_binder()[0]; + let to = *sig.output().skip_binder(); + self.check_transmute(expr.span, from, to); } - _ => {} } intravisit::walk_expr(self, expr); diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index 0e3a53129d1..c6c052fa4b1 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -260,7 +260,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // The `Self` type is erased, so it should not appear in list of // arguments or return type apart from the receiver. - let ref sig = self.type_of(method.def_id).fn_sig(); + let ref sig = self.fn_sig(method.def_id); for input_ty in &sig.skip_binder().inputs()[1..] { if self.contains_illegal_self_type_reference(trait_def_id, input_ty) { return Some(MethodViolationCode::ReferencesSelf); diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index f71f75dbaa8..c356e53234d 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -1137,9 +1137,19 @@ fn confirm_fn_pointer_candidate<'cx, 'gcx, 'tcx>( -> Progress<'tcx> { let fn_type = selcx.infcx().shallow_resolve(fn_pointer_vtable.fn_ty); - let sig = fn_type.fn_sig(); + let sig = fn_type.fn_sig(selcx.tcx()); + let Normalized { + value: sig, + obligations + } = normalize_with_depth(selcx, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth+1, + &sig); + confirm_callable_candidate(selcx, obligation, sig, util::TupleArgumentsFlag::Yes) .with_addl_obligations(fn_pointer_vtable.nested) + .with_addl_obligations(obligations) } fn confirm_closure_candidate<'cx, 'gcx, 'tcx>( diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index c68b8ee14b8..a66b6b86354 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -1404,19 +1404,15 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } // provide an impl, but only for suitable `fn` pointers - ty::TyFnDef(.., ty::Binder(ty::FnSig { - unsafety: hir::Unsafety::Normal, - abi: Abi::Rust, - variadic: false, - .. - })) | - ty::TyFnPtr(ty::Binder(ty::FnSig { - unsafety: hir::Unsafety::Normal, - abi: Abi::Rust, - variadic: false, - .. - })) => { - candidates.vec.push(FnPointerCandidate); + ty::TyFnDef(..) | ty::TyFnPtr(_) => { + if let ty::Binder(ty::FnSig { + unsafety: hir::Unsafety::Normal, + abi: Abi::Rust, + variadic: false, + .. + }) = self_ty.fn_sig(self.tcx()) { + candidates.vec.push(FnPointerCandidate); + } } _ => { } @@ -2348,7 +2344,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // ok to skip binder; it is reintroduced below let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder()); - let sig = self_ty.fn_sig(); + let sig = self_ty.fn_sig(self.tcx()); let trait_ref = self.tcx().closure_trait_ref_and_return_type(obligation.predicate.def_id(), self_ty, @@ -2356,11 +2352,18 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { util::TupleArgumentsFlag::Yes) .map_bound(|(trait_ref, _)| trait_ref); + let Normalized { value: trait_ref, obligations } = + project::normalize_with_depth(self, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + &trait_ref); + self.confirm_poly_trait_refs(obligation.cause.clone(), obligation.param_env, obligation.predicate.to_poly_trait_ref(), trait_ref)?; - Ok(VtableFnPointerData { fn_ty: self_ty, nested: vec![] }) + Ok(VtableFnPointerData { fn_ty: self_ty, nested: obligations }) } fn confirm_closure_candidate(&mut self, diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 2d81606329e..5f869fc5567 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1378,9 +1378,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn mk_fn_def(self, def_id: DefId, - substs: &'tcx Substs<'tcx>, - fty: PolyFnSig<'tcx>) -> Ty<'tcx> { - self.mk_ty(TyFnDef(def_id, substs, fty)) + substs: &'tcx Substs<'tcx>) -> Ty<'tcx> { + self.mk_ty(TyFnDef(def_id, substs)) } pub fn mk_fn_ptr(self, fty: PolyFnSig<'tcx>) -> Ty<'tcx> { diff --git a/src/librustc/ty/fast_reject.rs b/src/librustc/ty/fast_reject.rs index 3d2cc4c598a..68f85ba7d33 100644 --- a/src/librustc/ty/fast_reject.rs +++ b/src/librustc/ty/fast_reject.rs @@ -68,6 +68,7 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, // view of possibly unifying simplify_type(tcx, mt.ty, can_simplify_params) } + ty::TyFnDef(def_id, _) | ty::TyClosure(def_id, _) => { Some(ClosureSimplifiedType(def_id)) } @@ -75,7 +76,7 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, ty::TyTuple(ref tys, _) => { Some(TupleSimplifiedType(tys.len())) } - ty::TyFnDef(.., ref f) | ty::TyFnPtr(ref f) => { + ty::TyFnPtr(ref f) => { Some(FunctionSimplifiedType(f.skip_binder().inputs().len())) } ty::TyProjection(_) | ty::TyParam(_) => { diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index 46afa6ee7d0..d5aa9f55ff0 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -155,9 +155,8 @@ impl FlagComputation { self.add_tys(&ts[..]); } - &ty::TyFnDef(_, substs, f) => { + &ty::TyFnDef(_, substs) => { self.add_substs(substs); - self.add_fn_sig(f); } &ty::TyFnPtr(f) => { diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index 09a3bcd0613..b9896e0cecf 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -348,7 +348,7 @@ pub fn characteristic_def_id_of_type(ty: Ty) -> Option { .filter_map(|ty| characteristic_def_id_of_type(ty)) .next(), - ty::TyFnDef(def_id, ..) | + ty::TyFnDef(def_id, _) | ty::TyClosure(def_id, _) => Some(def_id), ty::TyBool | diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 13e46a265c6..f4d0867d130 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -206,7 +206,7 @@ impl AssociatedItem { // late-bound regions, and we don't want method signatures to show up // `as for<'r> fn(&'r MyType)`. Pretty-printing handles late-bound // regions just fine, showing `fn(&MyType)`. - format!("{}", tcx.type_of(self.def_id).fn_sig().skip_binder()) + format!("{}", tcx.fn_sig(self.def_id).skip_binder()) } ty::AssociatedKind::Type => format!("type {};", self.name.to_string()), ty::AssociatedKind::Const => { diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index d4f06a902ee..9345e504701 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -440,13 +440,11 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R, } } - (&ty::TyFnDef(a_def_id, a_substs, a_fty), - &ty::TyFnDef(b_def_id, b_substs, b_fty)) + (&ty::TyFnDef(a_def_id, a_substs), &ty::TyFnDef(b_def_id, b_substs)) if a_def_id == b_def_id => { let substs = relate_substs(relation, None, a_substs, b_substs)?; - let fty = relation.relate(&a_fty, &b_fty)?; - Ok(tcx.mk_fn_def(a_def_id, substs, fty)) + Ok(tcx.mk_fn_def(a_def_id, substs)) } (&ty::TyFnPtr(a_fty), &ty::TyFnPtr(b_fty)) => diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 1e268924390..d05262965d7 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -531,10 +531,8 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { ty::TyDynamic(ref trait_ty, ref region) => ty::TyDynamic(trait_ty.fold_with(folder), region.fold_with(folder)), ty::TyTuple(ts, defaulted) => ty::TyTuple(ts.fold_with(folder), defaulted), - ty::TyFnDef(def_id, substs, f) => { - ty::TyFnDef(def_id, - substs.fold_with(folder), - f.fold_with(folder)) + ty::TyFnDef(def_id, substs) => { + ty::TyFnDef(def_id, substs.fold_with(folder)) } ty::TyFnPtr(f) => ty::TyFnPtr(f.fold_with(folder)), ty::TyRef(ref r, tm) => { @@ -568,9 +566,7 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { ty::TyDynamic(ref trait_ty, ref reg) => trait_ty.visit_with(visitor) || reg.visit_with(visitor), ty::TyTuple(ts, _) => ts.visit_with(visitor), - ty::TyFnDef(_, substs, ref f) => { - substs.visit_with(visitor) || f.visit_with(visitor) - } + ty::TyFnDef(_, substs) => substs.visit_with(visitor), ty::TyFnPtr(ref f) => f.visit_with(visitor), ty::TyRef(r, ref tm) => r.visit_with(visitor) || tm.visit_with(visitor), ty::TyClosure(_did, ref substs) => substs.visit_with(visitor), diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 6923a6d21d6..ed3312d88a3 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -14,7 +14,7 @@ use hir::def_id::DefId; use hir::map::DefPathHash; use middle::region; -use ty::subst::Substs; +use ty::subst::{Substs, Subst}; use ty::{self, AdtDef, TypeFlags, Ty, TyCtxt, TypeFoldable}; use ty::{Slice, TyS}; use ty::subst::Kind; @@ -138,7 +138,7 @@ pub enum TypeVariants<'tcx> { /// The anonymous type of a function declaration/definition. Each /// function has a unique type. - TyFnDef(DefId, &'tcx Substs<'tcx>, PolyFnSig<'tcx>), + TyFnDef(DefId, &'tcx Substs<'tcx>), /// A pointer to a function. Written as `fn() -> i32`. TyFnPtr(PolyFnSig<'tcx>), @@ -1329,9 +1329,12 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { } } - pub fn fn_sig(&self) -> PolyFnSig<'tcx> { + pub fn fn_sig(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> PolyFnSig<'tcx> { match self.sty { - TyFnDef(.., f) | TyFnPtr(f) => f, + TyFnDef(def_id, substs) => { + tcx.fn_sig(def_id).subst(tcx, substs) + } + TyFnPtr(f) => f, _ => bug!("Ty::fn_sig() called on non-fn type: {:?}", self) } } diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 1bbc7673485..98ef7918fef 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -679,7 +679,7 @@ impl<'a, 'gcx, 'tcx, W> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tcx, W> TyRef(_, m) => self.hash(m.mutbl), TyClosure(def_id, _) | TyAnon(def_id, _) | - TyFnDef(def_id, ..) => self.def_id(def_id), + TyFnDef(def_id, _) => self.def_id(def_id), TyAdt(d, _) => self.def_id(d.did), TyFnPtr(f) => { self.hash(f.unsafety()); diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs index d7954953aba..71844abfe53 100644 --- a/src/librustc/ty/walk.rs +++ b/src/librustc/ty/walk.rs @@ -115,9 +115,8 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) { ty::TyTuple(ts, _) => { stack.extend(ts.iter().cloned().rev()); } - ty::TyFnDef(_, substs, ft) => { + ty::TyFnDef(_, substs) => { stack.extend(substs.types().rev()); - push_sig_subtypes(stack, ft); } ty::TyFnPtr(ft) => { push_sig_subtypes(stack, ft); diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 1fa63577196..eb6bffc29c5 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -753,8 +753,14 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> { } write!(f, ")") } - TyFnDef(def_id, substs, ref bare_fn) => { - write!(f, "{} {{", bare_fn.0)?; + TyFnDef(def_id, substs) => { + ty::tls::with(|tcx| { + let mut sig = tcx.fn_sig(def_id); + if let Some(substs) = tcx.lift(&substs) { + sig = sig.subst(tcx, substs); + } + write!(f, "{} {{", sig.0) + })?; parameterized(f, substs, def_id, &[])?; write!(f, "}}") } diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs b/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs index 2c55460fb30..4bef191b113 100644 --- a/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs +++ b/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs @@ -161,18 +161,13 @@ fn is_rustc_peek<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, terminator: &'a Option>) -> Option<(&'a [mir::Operand<'tcx>], Span)> { if let Some(mir::Terminator { ref kind, source_info, .. }) = *terminator { - if let mir::TerminatorKind::Call { func: ref oper, ref args, .. } = *kind - { - if let mir::Operand::Constant(ref func) = *oper - { - if let ty::TyFnDef(def_id, _, sig) = func.ty.sty - { - let abi = sig.abi(); + if let mir::TerminatorKind::Call { func: ref oper, ref args, .. } = *kind { + if let mir::Operand::Constant(ref func) = *oper { + if let ty::TyFnDef(def_id, _) = func.ty.sty { + let abi = tcx.fn_sig(def_id).abi(); let name = tcx.item_name(def_id); - if abi == Abi::RustIntrinsic || abi == Abi::PlatformIntrinsic { - if name == "rustc_peek" { - return Some((args, source_info.span)); - } + if abi == Abi::RustIntrinsic && name == "rustc_peek" { + return Some((args, source_info.span)); } } } diff --git a/src/librustc_const_eval/pattern.rs b/src/librustc_const_eval/pattern.rs index d175920e8a6..0a966b0c170 100644 --- a/src/librustc_const_eval/pattern.rs +++ b/src/librustc_const_eval/pattern.rs @@ -12,7 +12,7 @@ use eval; use rustc::middle::const_val::{ConstEvalErr, ConstVal}; use rustc::mir::{Field, BorrowKind, Mutability}; -use rustc::ty::{self, TyCtxt, AdtDef, Ty, TypeVariants, Region}; +use rustc::ty::{self, TyCtxt, AdtDef, Ty, Region}; use rustc::ty::subst::{Substs, Kind}; use rustc::hir::{self, PatKind, RangeEnd}; use rustc::hir::def::{Def, CtorKind}; @@ -549,8 +549,8 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { let adt_def = self.tcx.adt_def(enum_id); if adt_def.variants.len() > 1 { let substs = match ty.sty { - TypeVariants::TyAdt(_, substs) => substs, - TypeVariants::TyFnDef(_, substs, _) => substs, + ty::TyAdt(_, substs) | + ty::TyFnDef(_, substs) => substs, _ => bug!("inappropriate type for def: {:?}", ty.sty), }; PatternKind::Variant { diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 9800012917c..ad154f9b815 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -1154,24 +1154,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableTransmutes { if !def_id_is_transmute(cx, did) { return None; } - let typ = cx.tables.node_id_to_type(expr.id); - match typ.sty { - ty::TyFnDef(.., bare_fn) if bare_fn.abi() == RustIntrinsic => { - let from = bare_fn.inputs().skip_binder()[0]; - let to = *bare_fn.output().skip_binder(); - return Some((&from.sty, &to.sty)); - } - _ => (), - } + let sig = cx.tables.node_id_to_type(expr.id).fn_sig(cx.tcx); + let from = sig.inputs().skip_binder()[0]; + let to = *sig.output().skip_binder(); + return Some((&from.sty, &to.sty)); } None } fn def_id_is_transmute(cx: &LateContext, def_id: DefId) -> bool { - match cx.tcx.type_of(def_id).sty { - ty::TyFnDef(.., bfty) if bfty.abi() == RustIntrinsic => (), - _ => return false, - } + cx.tcx.fn_sig(def_id).abi() == RustIntrinsic && cx.tcx.item_name(def_id) == "transmute" } } diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 32bde42b526..ac3977bd216 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -659,7 +659,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { fn check_foreign_fn(&mut self, id: ast::NodeId, decl: &hir::FnDecl) { let def_id = self.cx.tcx.hir.local_def_id(id); - let sig = self.cx.tcx.type_of(def_id).fn_sig(); + let sig = self.cx.tcx.fn_sig(def_id); let sig = self.cx.tcx.erase_late_bound_regions(&sig); for (input_ty, input_hir) in sig.inputs().iter().zip(&decl.inputs) { diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 77f01d5c28c..3e6d06ec86f 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -1085,13 +1085,19 @@ impl<'a, 'tcx> CrateMetadata { } pub fn fn_sig(&self, - closure_id: DefIndex, + id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ty::PolyFnSig<'tcx> { - match self.entry(closure_id).kind { - EntryKind::Closure(data) => data.decode(self).sig.decode((self, tcx)), + let sig = match self.entry(id).kind { + EntryKind::Fn(data) | + EntryKind::ForeignFn(data) => data.decode(self).sig, + EntryKind::Method(data) => data.decode(self).fn_data.sig, + EntryKind::Variant(data) | + EntryKind::Struct(data, _) => data.decode(self).ctor_sig.unwrap(), + EntryKind::Closure(data) => data.decode(self).sig, _ => bug!(), - } + }; + sig.decode((self, tcx)) } #[inline] diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 860b553959f..34b25a4b7e4 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -16,6 +16,7 @@ use schema::*; use rustc::middle::cstore::{LinkMeta, LinkagePreference, NativeLibrary, EncodedMetadata, EncodedMetadataHashes, EncodedMetadataHash}; +use rustc::hir::def::CtorKind; use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId, LOCAL_CRATE}; use rustc::hir::map::definitions::{DefPathTable, GlobalMetaDataKind}; use rustc::ich::Fingerprint; @@ -499,6 +500,11 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { ctor_kind: variant.ctor_kind, discr: variant.discr, struct_ctor: None, + ctor_sig: if variant.ctor_kind == CtorKind::Fn { + Some(self.lazy(&tcx.fn_sig(def_id))) + } else { + None + } }; let enum_id = tcx.hir.as_local_node_id(enum_did).unwrap(); @@ -617,6 +623,11 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { ctor_kind: variant.ctor_kind, discr: variant.discr, struct_ctor: Some(def_id.index), + ctor_sig: if variant.ctor_kind == CtorKind::Fn { + Some(self.lazy(&tcx.fn_sig(def_id))) + } else { + None + } }; let struct_id = tcx.hir.as_local_node_id(adt_def_id).unwrap(); @@ -695,7 +706,8 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { }; FnData { constness: hir::Constness::NotConst, - arg_names: arg_names + arg_names: arg_names, + sig: self.lazy(&tcx.fn_sig(def_id)), } } else { bug!() @@ -747,6 +759,8 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> { debug!("IsolatedEncoder::encode_info_for_impl_item({:?})", def_id); + let tcx = self.tcx; + let node_id = self.tcx.hir.as_local_node_id(def_id).unwrap(); let ast_item = self.tcx.hir.expect_impl_item(node_id); let impl_item = self.tcx.associated_item(def_id); @@ -768,6 +782,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { FnData { constness: sig.constness, arg_names: self.encode_fn_arg_names_for_body(body), + sig: self.lazy(&tcx.fn_sig(def_id)), } } else { bug!() @@ -881,6 +896,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { let data = FnData { constness: constness, arg_names: self.encode_fn_arg_names_for_body(body), + sig: self.lazy(&tcx.fn_sig(def_id)), }; EntryKind::Fn(self.lazy(&data)) @@ -910,6 +926,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { ctor_kind: variant.ctor_kind, discr: variant.discr, struct_ctor: struct_ctor, + ctor_sig: None, }), repr_options) } hir::ItemUnion(..) => { @@ -920,6 +937,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { ctor_kind: variant.ctor_kind, discr: variant.discr, struct_ctor: None, + ctor_sig: None, }), repr_options) } hir::ItemDefaultImpl(..) => { @@ -1363,6 +1381,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { let data = FnData { constness: hir::Constness::NotConst, arg_names: self.encode_fn_arg_names(names), + sig: self.lazy(&tcx.fn_sig(def_id)), }; EntryKind::ForeignFn(self.lazy(&data)) } diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index 36977cb5db2..9ef5b940830 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -343,18 +343,18 @@ pub enum EntryKind<'tcx> { Type, Enum(ReprOptions), Field, - Variant(Lazy), - Struct(Lazy, ReprOptions), - Union(Lazy, ReprOptions), - Fn(Lazy), - ForeignFn(Lazy), + Variant(Lazy>), + Struct(Lazy>, ReprOptions), + Union(Lazy>, ReprOptions), + Fn(Lazy>), + ForeignFn(Lazy>), Mod(Lazy), MacroDef(Lazy), Closure(Lazy>), Trait(Lazy>), Impl(Lazy>), DefaultImpl(Lazy>), - Method(Lazy), + Method(Lazy>), AssociatedType(AssociatedContainer), AssociatedConst(AssociatedContainer, u8), } @@ -439,27 +439,33 @@ pub struct MacroDef { impl_stable_hash_for!(struct MacroDef { body, legacy }); #[derive(RustcEncodable, RustcDecodable)] -pub struct FnData { +pub struct FnData<'tcx> { pub constness: hir::Constness, pub arg_names: LazySeq, + pub sig: Lazy>, } -impl_stable_hash_for!(struct FnData { constness, arg_names }); +impl_stable_hash_for!(struct FnData<'tcx> { constness, arg_names, sig }); #[derive(RustcEncodable, RustcDecodable)] -pub struct VariantData { +pub struct VariantData<'tcx> { pub ctor_kind: CtorKind, pub discr: ty::VariantDiscr, /// If this is a struct's only variant, this /// is the index of the "struct ctor" item. pub struct_ctor: Option, + + /// If this is a tuple struct or variant + /// ctor, this is its "function" signature. + pub ctor_sig: Option>>, } -impl_stable_hash_for!(struct VariantData { +impl_stable_hash_for!(struct VariantData<'tcx> { ctor_kind, discr, - struct_ctor + struct_ctor, + ctor_sig }); #[derive(RustcEncodable, RustcDecodable)] @@ -543,12 +549,12 @@ impl AssociatedContainer { } #[derive(RustcEncodable, RustcDecodable)] -pub struct MethodData { - pub fn_data: FnData, +pub struct MethodData<'tcx> { + pub fn_data: FnData<'tcx>, pub container: AssociatedContainer, pub has_self: bool, } -impl_stable_hash_for!(struct MethodData { fn_data, container, has_self }); +impl_stable_hash_for!(struct MethodData<'tcx> { fn_data, container, has_self }); #[derive(RustcEncodable, RustcDecodable)] pub struct ClosureData<'tcx> { diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index b7abc707a38..326c1df69eb 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -205,11 +205,14 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // FIXME(canndrew): This is_never should probably be an is_uninhabited let diverges = expr.ty.is_never(); let intrinsic = match ty.sty { - ty::TyFnDef(def_id, _, ref f) if - f.abi() == Abi::RustIntrinsic || - f.abi() == Abi::PlatformIntrinsic => - { - Some(this.hir.tcx().item_name(def_id).as_str()) + ty::TyFnDef(def_id, _) => { + let f = ty.fn_sig(this.hir.tcx()); + if f.abi() == Abi::RustIntrinsic || + f.abi() == Abi::PlatformIntrinsic { + Some(this.hir.tcx().item_name(def_id).as_str()) + } else { + None + } } _ => None }; diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 474feefabbb..0010f312ef9 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -19,7 +19,6 @@ use rustc::middle::const_val::ConstVal; use rustc::ty::{self, AdtKind, VariantDef, Ty}; use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow}; use rustc::ty::cast::CastKind as TyCastKind; -use rustc::ty::subst::Subst; use rustc::hir; impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { @@ -586,7 +585,7 @@ fn method_callee<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, }); Expr { temp_lifetime: temp_lifetime, - ty: cx.tcx.type_of(def_id).subst(cx.tcx, substs), + ty: cx.tcx().mk_fn_def(def_id, substs), span: expr.span, kind: ExprKind::Literal { literal: Literal::Value { diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 54779cbe301..11ad5d1509d 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -58,7 +58,7 @@ fn make_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, // types in the MIR. They will be substituted again with // the param-substs, but because they are concrete, this // will not do any harm. - let sig = tcx.erase_late_bound_regions(&ty.fn_sig()); + let sig = tcx.erase_late_bound_regions(&ty.fn_sig(tcx)); let arg_tys = sig.inputs(); build_call_shim( @@ -153,8 +153,8 @@ fn build_drop_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, } else { Substs::identity_for_item(tcx, def_id) }; - let fn_ty = tcx.type_of(def_id).subst(tcx, substs); - let sig = tcx.erase_late_bound_regions(&fn_ty.fn_sig()); + let sig = tcx.fn_sig(def_id).subst(tcx, substs); + let sig = tcx.erase_late_bound_regions(&sig); let span = tcx.def_span(def_id); let source_info = SourceInfo { span, scope: ARGUMENT_VISIBILITY_SCOPE }; @@ -276,8 +276,8 @@ fn build_call_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, call_kind={:?}, untuple_args={:?})", def_id, rcvr_adjustment, call_kind, untuple_args); - let fn_ty = tcx.type_of(def_id); - let sig = tcx.erase_late_bound_regions(&fn_ty.fn_sig()); + let sig = tcx.fn_sig(def_id); + let sig = tcx.erase_late_bound_regions(&sig); let span = tcx.def_span(def_id); debug!("build_call_shim: sig={:?}", sig); @@ -409,11 +409,8 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>, { let tcx = infcx.tcx; let def_id = tcx.hir.local_def_id(ctor_id); - let sig = match tcx.type_of(def_id).sty { - ty::TyFnDef(_, _, fty) => tcx.no_late_bound_regions(&fty) - .expect("LBR in ADT constructor signature"), - _ => bug!("unexpected type for ctor {:?}", def_id) - }; + let sig = tcx.no_late_bound_regions(&tcx.fn_sig(def_id)) + .expect("LBR in ADT constructor signature"); let sig = tcx.erase_regions(&sig); let (adt_def, substs) = match sig.output().sty { diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 0ac35a5fdd4..5f80c7bee14 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -87,7 +87,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { let terminator = bb_data.terminator(); if let TerminatorKind::Call { func: Operand::Constant(ref f), .. } = terminator.kind { - if let ty::TyFnDef(callee_def_id, substs, _) = f.ty.sty { + if let ty::TyFnDef(callee_def_id, substs) = f.ty.sty { callsites.push_back(CallSite { callee: callee_def_id, substs: substs, @@ -131,7 +131,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { let terminator = bb_data.terminator(); if let TerminatorKind::Call { func: Operand::Constant(ref f), .. } = terminator.kind { - if let ty::TyFnDef(callee_def_id, substs, _) = f.ty.sty { + if let ty::TyFnDef(callee_def_id, substs) = f.ty.sty { // Don't inline the same function multiple times. if callsite.callee != callee_def_id { callsites.push_back(CallSite { @@ -270,8 +270,9 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { } TerminatorKind::Call {func: Operand::Constant(ref f), .. } => { - if let ty::TyFnDef(.., f) = f.ty.sty { + if let ty::TyFnDef(def_id, _) = f.ty.sty { // Don't give intrinsics the extra penalty for calls + let f = tcx.fn_sig(def_id); if f.abi() == Abi::RustIntrinsic || f.abi() == Abi::PlatformIntrinsic { cost += INSTR_COST; } else { diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 05a6cdd57ff..91d6ce60b39 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -750,8 +750,8 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { let fn_ty = func.ty(self.mir, self.tcx); let (is_shuffle, is_const_fn) = match fn_ty.sty { - ty::TyFnDef(def_id, _, f) => { - (f.abi() == Abi::PlatformIntrinsic && + ty::TyFnDef(def_id, _) => { + (self.tcx.fn_sig(def_id).abi() == Abi::PlatformIntrinsic && self.tcx.item_name(def_id).as_str().starts_with("simd_shuffle"), self.tcx.is_const_fn(def_id)) } diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs index efde39ad6a4..7e6fccf3019 100644 --- a/src/librustc_mir/transform/type_check.rs +++ b/src/librustc_mir/transform/type_check.rs @@ -462,7 +462,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { let func_ty = func.ty(mir, tcx); debug!("check_terminator: call, func_ty={:?}", func_ty); let sig = match func_ty.sty { - ty::TyFnDef(.., sig) | ty::TyFnPtr(sig) => sig, + ty::TyFnDef(..) | ty::TyFnPtr(_) => func_ty.fn_sig(tcx), _ => { span_mirbug!(self, term, "call to non-function {:?}", func_ty); return; diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index fb7258d4266..9eb96fea527 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -400,7 +400,13 @@ impl<'b, 'a, 'tcx> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> { } fn ty(&mut self) -> &mut Self { - self.ev.tcx.type_of(self.item_def_id).visit_with(self); + let ty = self.ev.tcx.type_of(self.item_def_id); + ty.visit_with(self); + if let ty::TyFnDef(def_id, _) = ty.sty { + if def_id == self.item_def_id { + self.ev.tcx.fn_sig(def_id).visit_with(self); + } + } self } @@ -910,7 +916,13 @@ impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> { } fn ty(&mut self) -> &mut Self { - self.tcx.type_of(self.item_def_id).visit_with(self); + let ty = self.tcx.type_of(self.item_def_id); + ty.visit_with(self); + if let ty::TyFnDef(def_id, _) = ty.sty { + if def_id == self.item_def_id { + self.tcx.fn_sig(def_id).visit_with(self); + } + } self } diff --git a/src/librustc_trans/back/symbol_names.rs b/src/librustc_trans/back/symbol_names.rs index 8e14335ceac..10b66fb1991 100644 --- a/src/librustc_trans/back/symbol_names.rs +++ b/src/librustc_trans/back/symbol_names.rs @@ -154,6 +154,13 @@ fn get_symbol_hash<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, assert!(!item_type.has_erasable_regions()); hasher.visit_ty(item_type); + // If this is a function, we hash the signature as well. + // This is not *strictly* needed, but it may help in some + // situations, see the `run-make/a-b-a-linker-guard` test. + if let ty::TyFnDef(..) = item_type.sty { + item_type.fn_sig(tcx).visit_with(&mut hasher); + } + // also include any type parameters (for generic items) if let Some(substs) = substs { assert!(!substs.has_erasable_regions()); diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index d723cf32571..3c502eec549 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -587,7 +587,7 @@ fn visit_fn_use<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, is_direct_call: bool, output: &mut Vec>) { - if let ty::TyFnDef(def_id, substs, _) = ty.sty { + if let ty::TyFnDef(def_id, substs) = ty.sty { let instance = monomorphize::resolve(scx, def_id, substs); visit_instance_use(scx, instance, is_direct_call, output); } diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs index 0db74c9454a..9b0803908b1 100644 --- a/src/librustc_trans/common.rs +++ b/src/librustc_trans/common.rs @@ -495,9 +495,9 @@ pub fn ty_fn_sig<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, -> ty::PolyFnSig<'tcx> { match ty.sty { - ty::TyFnDef(_, _, sig) => sig, + ty::TyFnDef(..) | // Shims currently have type TyFnPtr. Not sure this should remain. - ty::TyFnPtr(sig) => sig, + ty::TyFnPtr(_) => ty.fn_sig(ccx.tcx()), ty::TyClosure(def_id, substs) => { let tcx = ccx.tcx(); let sig = tcx.fn_sig(def_id).subst(tcx, substs.substs); diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index 95ceec610ea..0cc19936011 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -488,7 +488,6 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, debug!("type_metadata: {:?}", t); - let sty = &t.sty; let ptr_metadata = |ty: Ty<'tcx>| { match ty.sty { ty::TySlice(typ) => { @@ -518,7 +517,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } }; - let MetadataCreationResult { metadata, already_stored_in_typemap } = match *sty { + let MetadataCreationResult { metadata, already_stored_in_typemap } = match t.sty { ty::TyNever | ty::TyBool | ty::TyChar | @@ -557,10 +556,10 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, Err(metadata) => return metadata, } } - ty::TyFnDef(.., sig) | ty::TyFnPtr(sig) => { + ty::TyFnDef(..) | ty::TyFnPtr(_) => { let fn_metadata = subroutine_type_metadata(cx, unique_type_id, - sig, + t.fn_sig(cx.tcx()), usage_site_span).metadata; match debug_context(cx).type_map .borrow() @@ -610,7 +609,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, usage_site_span).finalize(cx) } _ => { - bug!("debuginfo: unexpected type in type_metadata: {:?}", sty) + bug!("debuginfo: unexpected type in type_metadata: {:?}", t) } }; diff --git a/src/librustc_trans/debuginfo/type_names.rs b/src/librustc_trans/debuginfo/type_names.rs index 13ff6646e66..bfca4fec706 100644 --- a/src/librustc_trans/debuginfo/type_names.rs +++ b/src/librustc_trans/debuginfo/type_names.rs @@ -96,8 +96,8 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, push_type_params(cx, principal.substs, output); } }, - ty::TyFnDef(.., sig) | - ty::TyFnPtr(sig) => { + ty::TyFnDef(..) | ty::TyFnPtr(_) => { + let sig = t.fn_sig(cx.tcx()); if sig.unsafety() == hir::Unsafety::Unsafe { output.push_str("unsafe "); } diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs index de908bb24a7..9956c28e641 100644 --- a/src/librustc_trans/intrinsic.rs +++ b/src/librustc_trans/intrinsic.rs @@ -95,11 +95,12 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, let ccx = bcx.ccx; let tcx = ccx.tcx(); - let (def_id, substs, sig) = match callee_ty.sty { - ty::TyFnDef(def_id, substs, sig) => (def_id, substs, sig), + let (def_id, substs) = match callee_ty.sty { + ty::TyFnDef(def_id, substs) => (def_id, substs), _ => bug!("expected fn item type, found {}", callee_ty) }; + let sig = callee_ty.fn_sig(tcx); let sig = tcx.erase_late_bound_regions_and_normalize(&sig); let arg_tys = sig.inputs(); let ret_ty = sig.output(); @@ -986,7 +987,7 @@ fn generic_simd_intrinsic<'a, 'tcx>( let tcx = bcx.tcx(); - let sig = tcx.erase_late_bound_regions_and_normalize(&callee_ty.fn_sig()); + let sig = tcx.erase_late_bound_regions_and_normalize(&callee_ty.fn_sig(tcx)); let arg_tys = sig.inputs(); // every intrinsic takes a SIMD vector as its first argument diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs index 8863c7ffae6..16972a1b1ae 100644 --- a/src/librustc_trans/mir/block.rs +++ b/src/librustc_trans/mir/block.rs @@ -404,20 +404,18 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { // Create the callee. This is a fn ptr or zero-sized and hence a kind of scalar. let callee = self.trans_operand(&bcx, func); - let (instance, mut llfn, sig) = match callee.ty.sty { - ty::TyFnDef(def_id, substs, sig) => { + let (instance, mut llfn) = match callee.ty.sty { + ty::TyFnDef(def_id, substs) => { (Some(monomorphize::resolve(bcx.ccx.shared(), def_id, substs)), - None, - sig) + None) } - ty::TyFnPtr(sig) => { - (None, - Some(callee.immediate()), - sig) + ty::TyFnPtr(_) => { + (None, Some(callee.immediate())) } _ => bug!("{} is not callable", callee.ty) }; let def = instance.map(|i| i.def); + let sig = callee.ty.fn_sig(bcx.tcx()); let sig = bcx.tcx().erase_late_bound_regions_and_normalize(&sig); let abi = sig.abi; diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index 60886b2b35f..fcb4b25e6fe 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -334,7 +334,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { let fn_ty = func.ty(self.mir, tcx); let fn_ty = self.monomorphize(&fn_ty); let (def_id, substs) = match fn_ty.sty { - ty::TyFnDef(def_id, substs, _) => (def_id, substs), + ty::TyFnDef(def_id, substs) => (def_id, substs), _ => span_bug!(span, "calling {:?} (of type {}) in constant", func, fn_ty) }; @@ -560,7 +560,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { let val = match *kind { mir::CastKind::ReifyFnPointer => { match operand.ty.sty { - ty::TyFnDef(def_id, substs, _) => { + ty::TyFnDef(def_id, substs) => { callee::resolve_and_get_fn(self.ccx, def_id, substs) } _ => { diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs index 61e537c9cc0..4bd5091a4f3 100644 --- a/src/librustc_trans/mir/rvalue.rs +++ b/src/librustc_trans/mir/rvalue.rs @@ -180,7 +180,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { let val = match *kind { mir::CastKind::ReifyFnPointer => { match operand.ty.sty { - ty::TyFnDef(def_id, substs, _) => { + ty::TyFnDef(def_id, substs) => { OperandValue::Immediate( callee::resolve_and_get_fn(bcx.ccx, def_id, substs)) } diff --git a/src/librustc_trans/monomorphize.rs b/src/librustc_trans/monomorphize.rs index a5fe70a2fd7..1f6a262162d 100644 --- a/src/librustc_trans/monomorphize.rs +++ b/src/librustc_trans/monomorphize.rs @@ -165,9 +165,11 @@ pub fn resolve<'a, 'tcx>( } else { let item_type = def_ty(scx, def_id, substs); let def = match item_type.sty { - ty::TyFnDef(_, _, f) if - f.abi() == Abi::RustIntrinsic || - f.abi() == Abi::PlatformIntrinsic => + ty::TyFnDef(..) if { + let f = item_type.fn_sig(scx.tcx()); + f.abi() == Abi::RustIntrinsic || + f.abi() == Abi::PlatformIntrinsic + } => { debug!(" => intrinsic"); ty::InstanceDef::Intrinsic(def_id) diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs index 0dc2bc85e30..f59f6850da1 100644 --- a/src/librustc_trans/trans_item.rs +++ b/src/librustc_trans/trans_item.rs @@ -401,8 +401,9 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { output); } }, - ty::TyFnDef(.., sig) | - ty::TyFnPtr(sig) => { + ty::TyFnDef(..) | + ty::TyFnPtr(_) => { + let sig = t.fn_sig(self.tcx); if sig.unsafety() == hir::Unsafety::Unsafe { output.push_str("unsafe "); } diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index bdd8169b84f..68726a7b1c4 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -619,7 +619,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Type check the path. let pat_ty = self.instantiate_value_path(segments, opt_ty, def, pat.span, pat.id); // Replace constructor type with constructed type for tuple struct patterns. - let pat_ty = pat_ty.fn_sig().output(); + let pat_ty = pat_ty.fn_sig(tcx).output(); let pat_ty = tcx.no_late_bound_regions(&pat_ty).expect("expected fn type"); self.demand_eqtype(pat.span, expected, pat_ty); diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 7cd372f3f00..a0801a74866 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -196,8 +196,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { expected: Expectation<'tcx>) -> Ty<'tcx> { let (fn_sig, def_span) = match callee_ty.sty { - ty::TyFnDef(def_id, .., sig) => { - (sig, self.tcx.hir.span_if_local(def_id)) + ty::TyFnDef(def_id, _) => { + (callee_ty.fn_sig(self.tcx), self.tcx.hir.span_if_local(def_id)) } ty::TyFnPtr(sig) => (sig, None), ref t => { diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index ea08f1f624e..46d304976dc 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -356,8 +356,9 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { (Some(t_from), Some(t_cast)) => (t_from, t_cast), // Function item types may need to be reified before casts. (None, Some(t_cast)) => { - if let ty::TyFnDef(.., f) = self.expr_ty.sty { + if let ty::TyFnDef(..) = self.expr_ty.sty { // Attempt a coercion to a fn pointer type. + let f = self.expr_ty.fn_sig(fcx.tcx); let res = fcx.try_coerce(self.expr, self.expr_ty, self.expr_diverges, diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index c5fd1f56320..17d02223716 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -210,13 +210,13 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { } match a.sty { - ty::TyFnDef(.., a_f) => { + ty::TyFnDef(..) => { // Function items are coercible to any closure // type; function pointers are not (that would // require double indirection). // Additionally, we permit coercion of function // items to drop the unsafe qualifier. - self.coerce_from_fn_item(a, a_f, b) + self.coerce_from_fn_item(a, b) } ty::TyFnPtr(a_f) => { // We permit coercion of fn pointers to drop the @@ -600,7 +600,6 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { fn coerce_from_fn_item(&self, a: Ty<'tcx>, - fn_ty_a: ty::PolyFnSig<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> { //! Attempts to coerce from the type of a Rust function item @@ -612,9 +611,17 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { match b.sty { ty::TyFnPtr(_) => { - let a_fn_pointer = self.tcx.mk_fn_ptr(fn_ty_a); - self.coerce_from_safe_fn(a_fn_pointer, fn_ty_a, b, - simple(Adjust::ReifyFnPointer), simple(Adjust::ReifyFnPointer)) + let a_sig = a.fn_sig(self.tcx); + let InferOk { value: a_sig, mut obligations } = + self.normalize_associated_types_in_as_infer_ok(self.cause.span, &a_sig); + + let a_fn_pointer = self.tcx.mk_fn_ptr(a_sig); + let InferOk { value, obligations: o2 } = + self.coerce_from_safe_fn(a_fn_pointer, a_sig, b, + simple(Adjust::ReifyFnPointer), simple(Adjust::ReifyFnPointer))?; + + obligations.extend(o2); + Ok(InferOk { value, obligations }) } _ => self.unify_and(a, b, identity), } @@ -775,42 +782,41 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Special-case that coercion alone cannot handle: // Two function item types of differing IDs or Substs. - match (&prev_ty.sty, &new_ty.sty) { - (&ty::TyFnDef(a_def_id, a_substs, a_fty), &ty::TyFnDef(b_def_id, b_substs, b_fty)) => { - // The signature must always match. - let fty = self.at(cause, self.param_env) - .trace(prev_ty, new_ty) - .lub(&a_fty, &b_fty) - .map(|ok| self.register_infer_ok_obligations(ok))?; + if let (&ty::TyFnDef(..), &ty::TyFnDef(..)) = (&prev_ty.sty, &new_ty.sty) { + // Don't reify if the function types have a LUB, i.e. they + // are the same function and their parameters have a LUB. + let lub_ty = self.commit_if_ok(|_| { + self.at(cause, self.param_env) + .lub(prev_ty, new_ty) + .map(|ok| self.register_infer_ok_obligations(ok)) + }); - if a_def_id == b_def_id { - // Same function, maybe the parameters match. - let substs = self.commit_if_ok(|_| { - self.at(cause, self.param_env) - .trace(prev_ty, new_ty) - .lub(&a_substs, &b_substs) - .map(|ok| self.register_infer_ok_obligations(ok)) - }); - - if let Ok(substs) = substs { - // We have a LUB of prev_ty and new_ty, just return it. - return Ok(self.tcx.mk_fn_def(a_def_id, substs, fty)); - } - } - - // Reify both sides and return the reified fn pointer type. - let fn_ptr = self.tcx.mk_fn_ptr(fty); - for expr in exprs.iter().map(|e| e.as_coercion_site()).chain(Some(new)) { - // The only adjustment that can produce an fn item is - // `NeverToAny`, so this should always be valid. - self.apply_adjustments(expr, vec![Adjustment { - kind: Adjust::ReifyFnPointer, - target: fn_ptr - }]); - } - return Ok(fn_ptr); + if lub_ty.is_ok() { + // We have a LUB of prev_ty and new_ty, just return it. + return lub_ty; } - _ => {} + + // The signature must match. + let a_sig = prev_ty.fn_sig(self.tcx); + let a_sig = self.normalize_associated_types_in(new.span, &a_sig); + let b_sig = new_ty.fn_sig(self.tcx); + let b_sig = self.normalize_associated_types_in(new.span, &b_sig); + let sig = self.at(cause, self.param_env) + .trace(prev_ty, new_ty) + .lub(&a_sig, &b_sig) + .map(|ok| self.register_infer_ok_obligations(ok))?; + + // Reify both sides and return the reified fn pointer type. + let fn_ptr = self.tcx.mk_fn_ptr(sig); + for expr in exprs.iter().map(|e| e.as_coercion_site()).chain(Some(new)) { + // The only adjustment that can produce an fn item is + // `NeverToAny`, so this should always be valid. + self.apply_adjustments(expr, vec![Adjustment { + kind: Adjust::ReifyFnPointer, + target: fn_ptr + }]); + } + return Ok(fn_ptr); } let mut coerce = Coerce::new(self, cause.clone()); diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 29742469f84..fd5147d76e8 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -256,17 +256,10 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Compute skolemized form of impl and trait method tys. let tcx = infcx.tcx; - let m_sig = |method: &ty::AssociatedItem| { - match tcx.type_of(method.def_id).sty { - ty::TyFnDef(_, _, f) => f, - _ => bug!() - } - }; - let (impl_sig, _) = infcx.replace_late_bound_regions_with_fresh_var(impl_m_span, infer::HigherRankedType, - &m_sig(impl_m)); + &tcx.fn_sig(impl_m.def_id)); let impl_sig = inh.normalize_associated_types_in(impl_m_span, impl_m_node_id, @@ -277,7 +270,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let trait_sig = inh.liberate_late_bound_regions( impl_m.def_id, - &m_sig(trait_m)); + &tcx.fn_sig(trait_m.def_id)); let trait_sig = trait_sig.subst(tcx, trait_to_skol_substs); let trait_sig = @@ -507,8 +500,7 @@ fn compare_self_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty::ImplContainer(_) => impl_trait_ref.self_ty(), ty::TraitContainer(_) => tcx.mk_self_type() }; - let method_ty = tcx.type_of(method.def_id); - let self_arg_ty = *method_ty.fn_sig().input(0).skip_binder(); + let self_arg_ty = *tcx.fn_sig(method.def_id).input(0).skip_binder(); match ExplicitSelf::determine(untransformed_self_ty, self_arg_ty) { ExplicitSelf::ByValue => "self".to_string(), ExplicitSelf::ByReference(_, hir::MutImmutable) => "&self".to_string(), @@ -637,14 +629,8 @@ fn compare_number_of_method_arguments<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_m: &ty::AssociatedItem, trait_item_span: Option) -> Result<(), ErrorReported> { - let m_fty = |method: &ty::AssociatedItem| { - match tcx.type_of(method.def_id).sty { - ty::TyFnDef(_, _, f) => f, - _ => bug!() - } - }; - let impl_m_fty = m_fty(impl_m); - let trait_m_fty = m_fty(trait_m); + let impl_m_fty = tcx.fn_sig(impl_m.def_id); + let trait_m_fty = tcx.fn_sig(trait_m.def_id); let trait_number_args = trait_m_fty.inputs().skip_binder().len(); let impl_number_args = impl_m_fty.inputs().skip_binder().len(); if trait_number_args != impl_number_args { diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 1b6f96cf651..287c591c118 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -143,12 +143,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn has_no_input_arg(&self, method: &AssociatedItem) -> bool { match method.def() { Def::Method(def_id) => { - match self.tcx.type_of(def_id).sty { - ty::TypeVariants::TyFnDef(_, _, sig) => { - sig.inputs().skip_binder().len() == 1 - } - _ => false, - } + self.tcx.fn_sig(def_id).inputs().skip_binder().len() == 1 } _ => false, } diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index 4d9f50b0fc0..3acfbd1d844 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -13,7 +13,6 @@ use intrinsics; use rustc::traits::{ObligationCause, ObligationCauseCode}; -use rustc::ty::subst::Substs; use rustc::ty::{self, TyCtxt, Ty}; use rustc::util::nodemap::FxHashMap; use require_same_types; @@ -35,22 +34,22 @@ fn equate_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, output: Ty<'tcx>) { let def_id = tcx.hir.local_def_id(it.id); - let substs = Substs::for_item(tcx, def_id, - |_, _| tcx.types.re_erased, - |def, _| tcx.mk_param_from_def(def)); + match it.node { + hir::ForeignItemFn(..) => {} + _ => { + struct_span_err!(tcx.sess, it.span, E0619, + "intrinsic must be a function") + .span_label(it.span, "expected a function") + .emit(); + return; + } + } - let fty = tcx.mk_fn_def(def_id, substs, ty::Binder(tcx.mk_fn_sig( - inputs.into_iter(), - output, - false, - hir::Unsafety::Unsafe, - abi - ))); let i_n_tps = tcx.generics_of(def_id).types.len(); if i_n_tps != n_tps { let span = match it.node { hir::ForeignItemFn(_, _, ref generics) => generics.span, - hir::ForeignItemStatic(..) => it.span + _ => bug!() }; struct_span_err!(tcx.sess, span, E0094, @@ -59,14 +58,18 @@ fn equate_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, i_n_tps, n_tps) .span_label(span, format!("expected {} type parameter", n_tps)) .emit(); - } else { - require_same_types(tcx, - &ObligationCause::new(it.span, - it.id, - ObligationCauseCode::IntrinsicType), - tcx.type_of(def_id), - fty); + return; } + + let fty = tcx.mk_fn_ptr(ty::Binder(tcx.mk_fn_sig( + inputs.into_iter(), + output, + false, + hir::Unsafety::Unsafe, + abi + ))); + let cause = ObligationCause::new(it.span, it.id, ObligationCauseCode::IntrinsicType); + require_same_types(tcx, &cause, tcx.mk_fn_ptr(tcx.fn_sig(def_id)), fty); } /// Remember to add all intrinsics here, in librustc_trans/trans/intrinsic.rs, @@ -376,7 +379,7 @@ pub fn check_platform_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let mut structural_to_nomimal = FxHashMap(); - let sig = tcx.type_of(def_id).fn_sig(); + let sig = tcx.fn_sig(def_id); let sig = tcx.no_late_bound_regions(&sig).unwrap(); if intr.inputs.len() != sig.inputs().len() { span_err!(tcx.sess, it.span, E0444, diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 36bd6657389..209245187b1 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -375,7 +375,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { debug!("method_predicates after subst = {:?}", method_predicates); - let sig = self.tcx.type_of(def_id).fn_sig(); + let sig = self.tcx.fn_sig(def_id); // Instantiate late-bound regions and substitute the trait // parameters into the method type to get the actual method type. diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 73c1215f275..4f4169ac93d 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -235,7 +235,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // NB: Instantiate late-bound regions first so that // `instantiate_type_scheme` can normalize associated types that // may reference those regions. - let fn_sig = tcx.type_of(def_id).fn_sig(); + let fn_sig = tcx.fn_sig(def_id); let fn_sig = self.replace_late_bound_regions_with_fresh_var(span, infer::FnCall, &fn_sig).0; diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 2518a1739f7..ee9a347ae95 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -673,7 +673,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { expected: ty::Ty<'tcx>) -> bool { match method.def() { Def::Method(def_id) => { - let fty = self.tcx.type_of(def_id).fn_sig(); + let fty = self.tcx.fn_sig(def_id); self.probe(|_| { let substs = self.fresh_substs_for_item(self.span, method.def_id); let output = fty.output().subst(self.tcx, substs); @@ -1288,7 +1288,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { impl_ty: Ty<'tcx>, substs: &Substs<'tcx>) -> Ty<'tcx> { - let self_ty = self.tcx.type_of(method).fn_sig().input(0); + let self_ty = self.tcx.fn_sig(method).input(0); debug!("xform_self_ty(impl_ty={:?}, self_ty={:?}, substs={:?})", impl_ty, self_ty, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index b92a78987a3..701de029b2b 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -718,20 +718,12 @@ pub fn provide(providers: &mut Providers) { typeck_item_bodies, typeck_tables_of, has_typeck_tables, - fn_sig, closure_kind, adt_destructor, ..*providers }; } -fn fn_sig<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - def_id: DefId) - -> ty::PolyFnSig<'tcx> { - let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); - tcx.typeck_tables_of(def_id).closure_tys[&node_id] -} - fn closure_kind<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> ty::ClosureKind { @@ -844,7 +836,7 @@ fn typeck_tables_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, Inherited::build(tcx, def_id).enter(|inh| { let param_env = tcx.param_env(def_id); let fcx = if let Some(decl) = fn_decl { - let fn_sig = tcx.type_of(def_id).fn_sig(); + let fn_sig = tcx.fn_sig(def_id); check_abi(tcx, span, fn_sig.abi()); @@ -2173,7 +2165,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { -> ty::TypeAndMut<'tcx> { // extract method return type, which will be &T; - // all LB regions should have been instantiated during method lookup let ret_ty = method.sig.output(); // method returns &T, but the type as visible to user is T, so deref @@ -2580,8 +2571,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ty::TyUint(ast::UintTy::U8) | ty::TyUint(ast::UintTy::U16) => { variadic_error(tcx.sess, arg.span, arg_ty, "c_uint"); } - ty::TyFnDef(.., f) => { - let ptr_ty = self.tcx.mk_fn_ptr(f); + ty::TyFnDef(..) => { + let ptr_ty = self.tcx.mk_fn_ptr(arg_ty.fn_sig(self.tcx)); let ptr_ty = self.resolve_type_vars_if_possible(&ptr_ty); variadic_error(tcx.sess, arg.span, arg_ty, &format!("{}", ptr_ty)); } diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 26f708e9345..cbda1227742 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -177,12 +177,11 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> { } ty::AssociatedKind::Method => { reject_shadowing_type_parameters(fcx.tcx, item.def_id); - let method_ty = fcx.tcx.type_of(item.def_id); - let method_ty = fcx.normalize_associated_types_in(span, &method_ty); + let sig = fcx.tcx.fn_sig(item.def_id); + let sig = fcx.normalize_associated_types_in(span, &sig); let predicates = fcx.tcx.predicates_of(item.def_id) .instantiate_identity(fcx.tcx); let predicates = fcx.normalize_associated_types_in(span, &predicates); - let sig = method_ty.fn_sig(); this.check_fn_or_method(fcx, span, sig, &predicates, item.def_id, &mut implied_bounds); let sig_if_method = sig_if_method.expect("bad signature for method"); @@ -331,9 +330,8 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> { fn check_item_fn(&mut self, item: &hir::Item) { self.for_item(item).with_fcx(|fcx, this| { let def_id = fcx.tcx.hir.local_def_id(item.id); - let ty = fcx.tcx.type_of(def_id); - let item_ty = fcx.normalize_associated_types_in(item.span, &ty); - let sig = item_ty.fn_sig(); + let sig = fcx.tcx.fn_sig(def_id); + let sig = fcx.normalize_associated_types_in(item.span, &sig); let predicates = fcx.tcx.predicates_of(def_id).instantiate_identity(fcx.tcx); let predicates = fcx.normalize_associated_types_in(item.span, &predicates); @@ -461,9 +459,9 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> { let span = method_sig.decl.inputs[0].span; - let method_ty = fcx.tcx.type_of(method.def_id); - let fty = fcx.normalize_associated_types_in(span, &method_ty); - let sig = fcx.liberate_late_bound_regions(method.def_id, &fty.fn_sig()); + let sig = fcx.tcx.fn_sig(method.def_id); + let sig = fcx.normalize_associated_types_in(span, &sig); + let sig = fcx.liberate_late_bound_regions(method.def_id, &sig); debug!("check_method_receiver: sig={:?}", sig); diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index fb3bcd31e21..fd6dda5ccf4 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -97,6 +97,7 @@ pub fn provide(providers: &mut Providers) { type_param_predicates, trait_def, adt_def, + fn_sig, impl_trait_ref, impl_polarity, is_foreign_item, @@ -447,6 +448,9 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId) { tcx.generics_of(def_id); tcx.type_of(def_id); tcx.predicates_of(def_id); + if let hir::ForeignItemFn(..) = item.node { + tcx.fn_sig(def_id); + } } } hir::ItemEnum(ref enum_definition, _) => { @@ -497,6 +501,9 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId) { tcx.generics_of(def_id); tcx.type_of(def_id); tcx.predicates_of(def_id); + if let hir::ItemFn(..) = it.node { + tcx.fn_sig(def_id); + } } } } @@ -511,6 +518,9 @@ fn convert_trait_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_item_id: ast: hir::TraitItemKind::Type(_, Some(_)) | hir::TraitItemKind::Method(..) => { tcx.type_of(def_id); + if let hir::TraitItemKind::Method(..) = trait_item.node { + tcx.fn_sig(def_id); + } } hir::TraitItemKind::Type(_, None) => {} @@ -524,6 +534,9 @@ fn convert_impl_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_item_id: ast::N tcx.generics_of(def_id); tcx.type_of(def_id); tcx.predicates_of(def_id); + if let hir::ImplItemKind::Method(..) = tcx.hir.expect_impl_item(impl_item_id).node { + tcx.fn_sig(def_id); + } } fn convert_variant_ctor<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -963,10 +976,9 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, match tcx.hir.get(node_id) { NodeTraitItem(item) => { match item.node { - TraitItemKind::Method(ref sig, _) => { - let fty = AstConv::ty_of_fn(&icx, sig.unsafety, sig.abi, &sig.decl); + TraitItemKind::Method(..) => { let substs = Substs::identity_for_item(tcx, def_id); - tcx.mk_fn_def(def_id, substs, fty) + tcx.mk_fn_def(def_id, substs) } TraitItemKind::Const(ref ty, _) | TraitItemKind::Type(_, Some(ref ty)) => icx.to_ty(ty), @@ -978,10 +990,9 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, NodeImplItem(item) => { match item.node { - ImplItemKind::Method(ref sig, _) => { - let fty = AstConv::ty_of_fn(&icx, sig.unsafety, sig.abi, &sig.decl); + ImplItemKind::Method(..) => { let substs = Substs::identity_for_item(tcx, def_id); - tcx.mk_fn_def(def_id, substs, fty) + tcx.mk_fn_def(def_id, substs) } ImplItemKind::Const(ref ty, _) => icx.to_ty(ty), ImplItemKind::Type(ref ty) => { @@ -1001,10 +1012,9 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ItemTy(ref t, _) | ItemImpl(.., ref t, _) => { icx.to_ty(t) } - ItemFn(ref decl, unsafety, _, abi, _, _) => { - let tofd = AstConv::ty_of_fn(&icx, unsafety, abi, &decl); + ItemFn(..) => { let substs = Substs::identity_for_item(tcx, def_id); - tcx.mk_fn_def(def_id, substs, tofd) + tcx.mk_fn_def(def_id, substs) } ItemEnum(..) | ItemStruct(..) | @@ -1029,11 +1039,10 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } NodeForeignItem(foreign_item) => { - let abi = tcx.hir.get_foreign_abi(node_id); - match foreign_item.node { - ForeignItemFn(ref fn_decl, _, _) => { - compute_type_of_foreign_fn_decl(tcx, def_id, fn_decl, abi) + ForeignItemFn(..) => { + let substs = Substs::identity_for_item(tcx, def_id); + tcx.mk_fn_def(def_id, substs) } ForeignItemStatic(ref t, _) => icx.to_ty(t) } @@ -1041,21 +1050,13 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, NodeStructCtor(&ref def) | NodeVariant(&Spanned { node: hir::Variant_ { data: ref def, .. }, .. }) => { - let ty = tcx.type_of(tcx.hir.get_parent_did(node_id)); match *def { - VariantData::Unit(..) | VariantData::Struct(..) => ty, - VariantData::Tuple(ref fields, _) => { - let inputs = fields.iter().map(|f| { - tcx.type_of(tcx.hir.local_def_id(f.id)) - }); + VariantData::Unit(..) | VariantData::Struct(..) => { + tcx.type_of(tcx.hir.get_parent_did(node_id)) + } + VariantData::Tuple(..) => { let substs = Substs::identity_for_item(tcx, def_id); - tcx.mk_fn_def(def_id, substs, ty::Binder(tcx.mk_fn_sig( - inputs, - ty, - false, - hir::Unsafety::Normal, - abi::Abi::Rust - ))) + tcx.mk_fn_def(def_id, substs) } } } @@ -1105,6 +1106,58 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } +fn fn_sig<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId) + -> ty::PolyFnSig<'tcx> { + use rustc::hir::map::*; + use rustc::hir::*; + + let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); + + let icx = ItemCtxt::new(tcx, def_id); + + match tcx.hir.get(node_id) { + NodeTraitItem(&hir::TraitItem { node: TraitItemKind::Method(ref sig, _), .. }) | + NodeImplItem(&hir::ImplItem { node: ImplItemKind::Method(ref sig, _), .. }) => { + AstConv::ty_of_fn(&icx, sig.unsafety, sig.abi, &sig.decl) + } + + NodeItem(&hir::Item { node: ItemFn(ref decl, unsafety, _, abi, _, _), .. }) => { + AstConv::ty_of_fn(&icx, unsafety, abi, decl) + } + + NodeForeignItem(&hir::ForeignItem { node: ForeignItemFn(ref fn_decl, _, _), .. }) => { + let abi = tcx.hir.get_foreign_abi(node_id); + compute_sig_of_foreign_fn_decl(tcx, def_id, fn_decl, abi) + } + + NodeStructCtor(&VariantData::Tuple(ref fields, _)) | + NodeVariant(&Spanned { node: hir::Variant_ { + data: VariantData::Tuple(ref fields, _), .. + }, .. }) => { + let ty = tcx.type_of(tcx.hir.get_parent_did(node_id)); + let inputs = fields.iter().map(|f| { + tcx.type_of(tcx.hir.local_def_id(f.id)) + }); + ty::Binder(tcx.mk_fn_sig( + inputs, + ty, + false, + hir::Unsafety::Normal, + abi::Abi::Rust + )) + } + + NodeExpr(&hir::Expr { node: hir::ExprClosure(..), .. }) => { + tcx.typeck_tables_of(def_id).closure_tys[&node_id] + } + + x => { + bug!("unexpected sort of node in fn_sig(): {:?}", x); + } + } +} + fn impl_trait_ref<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Option> { @@ -1502,12 +1555,12 @@ fn predicates_from_bound<'tcx>(astconv: &AstConv<'tcx, 'tcx>, } } -fn compute_type_of_foreign_fn_decl<'a, 'tcx>( +fn compute_sig_of_foreign_fn_decl<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, decl: &hir::FnDecl, abi: abi::Abi) - -> Ty<'tcx> + -> ty::PolyFnSig<'tcx> { let fty = AstConv::ty_of_fn(&ItemCtxt::new(tcx, def_id), hir::Unsafety::Unsafe, abi, decl); @@ -1533,8 +1586,7 @@ fn compute_type_of_foreign_fn_decl<'a, 'tcx>( } } - let substs = Substs::identity_for_item(tcx, def_id); - tcx.mk_fn_def(def_id, substs, fty) + fty } fn is_foreign_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index b2fa2cc7c61..bf5adc8644d 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -4736,4 +4736,5 @@ register_diagnostics! { E0568, // auto-traits can not have predicates, E0588, // packed struct cannot transitively contain a `[repr(align)]` struct E0592, // duplicate definitions with name `{}` + E0619, // intrinsic must be a function } diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 9e99af633d5..519e1ca6e5a 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -198,22 +198,21 @@ fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } _ => () } - let substs = tcx.intern_substs(&[]); - let se_ty = tcx.mk_fn_def(main_def_id, substs, - ty::Binder(tcx.mk_fn_sig( + let se_ty = tcx.mk_fn_ptr(ty::Binder( + tcx.mk_fn_sig( iter::empty(), tcx.mk_nil(), false, hir::Unsafety::Normal, Abi::Rust - )) - ); + ) + )); require_same_types( tcx, &ObligationCause::new(main_span, main_id, ObligationCauseCode::MainFunctionType), se_ty, - main_t); + tcx.mk_fn_ptr(tcx.fn_sig(main_def_id))); } _ => { span_bug!(main_span, @@ -248,9 +247,8 @@ fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, _ => () } - let substs = tcx.intern_substs(&[]); - let se_ty = tcx.mk_fn_def(start_def_id, substs, - ty::Binder(tcx.mk_fn_sig( + let se_ty = tcx.mk_fn_ptr(ty::Binder( + tcx.mk_fn_sig( [ tcx.types.isize, tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8)) @@ -259,14 +257,14 @@ fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, false, hir::Unsafety::Normal, Abi::Rust - )) - ); + ) + )); require_same_types( tcx, &ObligationCause::new(start_span, start_id, ObligationCauseCode::StartFunctionType), se_ty, - start_t); + tcx.mk_fn_ptr(tcx.fn_sig(start_def_id))); } _ => { span_bug!(start_span, diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index c434edb1c31..4c09d90f853 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -382,6 +382,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { // leaf type -- noop } + ty::TyFnDef(..) | ty::TyClosure(..) | ty::TyAnon(..) => { bug!("Unexpected closure type in variance computation"); @@ -466,7 +467,6 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { } } - ty::TyFnDef(.., sig) | ty::TyFnPtr(sig) => { self.add_constraints_from_sig(current, sig, variance); } diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index aeade470482..fa5a999adf1 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -149,7 +149,7 @@ pub fn build_external_trait(cx: &DocContext, did: DefId) -> clean::Trait { } fn build_external_function(cx: &DocContext, did: DefId) -> clean::Function { - let sig = cx.tcx.type_of(did).fn_sig(); + let sig = cx.tcx.fn_sig(did); let constness = if cx.tcx.is_const_fn(did) { hir::Constness::Const diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 8fc8ccd0cfd..478e2fc5085 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1367,7 +1367,7 @@ impl<'tcx> Clean for ty::AssociatedItem { ty::AssociatedKind::Method => { let generics = (cx.tcx.generics_of(self.def_id), &cx.tcx.predicates_of(self.def_id)).clean(cx); - let sig = cx.tcx.type_of(self.def_id).fn_sig(); + let sig = cx.tcx.fn_sig(self.def_id); let mut decl = (self.def_id, sig).clean(cx); if self.method_has_self_argument { @@ -1842,17 +1842,21 @@ impl<'tcx> Clean for ty::Ty<'tcx> { mutability: mt.mutbl.clean(cx), type_: box mt.ty.clean(cx), }, - ty::TyFnDef(.., sig) | - ty::TyFnPtr(sig) => BareFunction(box BareFunctionDecl { - unsafety: sig.unsafety(), - generics: Generics { - lifetimes: Vec::new(), - type_params: Vec::new(), - where_predicates: Vec::new() - }, - decl: (cx.tcx.hir.local_def_id(ast::CRATE_NODE_ID), sig).clean(cx), - abi: sig.abi(), - }), + ty::TyFnDef(..) | + ty::TyFnPtr(_) => { + let ty = cx.tcx.lift(self).unwrap(); + let sig = ty.fn_sig(cx.tcx); + BareFunction(box BareFunctionDecl { + unsafety: sig.unsafety(), + generics: Generics { + lifetimes: Vec::new(), + type_params: Vec::new(), + where_predicates: Vec::new() + }, + decl: (cx.tcx.hir.local_def_id(ast::CRATE_NODE_ID), sig).clean(cx), + abi: sig.abi(), + }) + } ty::TyAdt(def, substs) => { let did = def.did; let kind = match def.adt_kind() { diff --git a/src/test/compile-fail/invalid-intrinsic.rs b/src/test/compile-fail/invalid-intrinsic.rs index 2aa2546cb9f..c42d78c323e 100644 --- a/src/test/compile-fail/invalid-intrinsic.rs +++ b/src/test/compile-fail/invalid-intrinsic.rs @@ -11,6 +11,6 @@ #![feature(intrinsics)] extern "rust-intrinsic" { pub static breakpoint : unsafe extern "rust-intrinsic" fn(); - //~^ ERROR intrinsic has wrong type + //~^ ERROR intrinsic must be a function } -fn main() { unsafe { breakpoint(); } } \ No newline at end of file +fn main() { unsafe { breakpoint(); } } From a9d4069975af1ef0192984ad033fd30ceca4fa78 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 2 Jun 2017 22:05:41 +0300 Subject: [PATCH 055/162] rustc_typeck: support functions in variance computation. --- src/librustc/ty/relate.rs | 6 +- src/librustc_metadata/encoder.rs | 31 +- src/librustc_typeck/variance/constraints.rs | 390 +++++++----------- src/librustc_typeck/variance/mod.rs | 88 ++-- src/librustc_typeck/variance/solve.rs | 71 ++-- src/librustc_typeck/variance/terms.rs | 162 +++----- .../compile-fail/variance-region-bounds.rs | 25 -- .../compile-fail/variance-trait-bounds.rs | 20 +- .../compile-fail/variance-types-bounds.rs | 27 +- 9 files changed, 316 insertions(+), 504 deletions(-) delete mode 100644 src/test/compile-fail/variance-region-bounds.rs diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index 9345e504701..2e9780572c9 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -291,7 +291,7 @@ impl<'tcx> Relate<'tcx> for ty::TraitRef<'tcx> { if a.def_id != b.def_id { Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id))) } else { - let substs = relation.relate_item_substs(a.def_id, a.substs, b.substs)?; + let substs = relate_substs(relation, None, a.substs, b.substs)?; Ok(ty::TraitRef { def_id: a.def_id, substs: substs }) } } @@ -308,7 +308,7 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialTraitRef<'tcx> { if a.def_id != b.def_id { Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id))) } else { - let substs = relation.relate_item_substs(a.def_id, a.substs, b.substs)?; + let substs = relate_substs(relation, None, a.substs, b.substs)?; Ok(ty::ExistentialTraitRef { def_id: a.def_id, substs: substs }) } } @@ -443,7 +443,7 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R, (&ty::TyFnDef(a_def_id, a_substs), &ty::TyFnDef(b_def_id, b_substs)) if a_def_id == b_def_id => { - let substs = relate_substs(relation, None, a_substs, b_substs)?; + let substs = relation.relate_item_substs(a_def_id, a_substs, b_substs)?; Ok(tcx.mk_fn_def(a_def_id, substs)) } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 34b25a4b7e4..e9701b95002 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -524,7 +524,11 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { ty: Some(self.encode_item_type(def_id)), inherent_impls: LazySeq::empty(), - variances: LazySeq::empty(), + variances: if variant.ctor_kind == CtorKind::Fn { + self.encode_variances_of(def_id) + } else { + LazySeq::empty() + }, generics: Some(self.encode_generics(def_id)), predicates: Some(self.encode_predicates(def_id)), @@ -652,7 +656,11 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { ty: Some(self.encode_item_type(def_id)), inherent_impls: LazySeq::empty(), - variances: LazySeq::empty(), + variances: if variant.ctor_kind == CtorKind::Fn { + self.encode_variances_of(def_id) + } else { + LazySeq::empty() + }, generics: Some(self.encode_generics(def_id)), predicates: Some(self.encode_predicates(def_id)), @@ -744,7 +752,11 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { } }, inherent_impls: LazySeq::empty(), - variances: LazySeq::empty(), + variances: if trait_item.kind == ty::AssociatedKind::Method { + self.encode_variances_of(def_id) + } else { + LazySeq::empty() + }, generics: Some(self.encode_generics(def_id)), predicates: Some(self.encode_predicates(def_id)), @@ -821,7 +833,11 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { ty: Some(self.encode_item_type(def_id)), inherent_impls: LazySeq::empty(), - variances: LazySeq::empty(), + variances: if impl_item.kind == ty::AssociatedKind::Method { + self.encode_variances_of(def_id) + } else { + LazySeq::empty() + }, generics: Some(self.encode_generics(def_id)), predicates: Some(self.encode_predicates(def_id)), @@ -1055,7 +1071,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { hir::ItemEnum(..) | hir::ItemStruct(..) | hir::ItemUnion(..) | - hir::ItemTrait(..) => self.encode_variances_of(def_id), + hir::ItemFn(..) => self.encode_variances_of(def_id), _ => LazySeq::empty(), }, generics: match item.node { @@ -1400,7 +1416,10 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { ty: Some(self.encode_item_type(def_id)), inherent_impls: LazySeq::empty(), - variances: LazySeq::empty(), + variances: match nitem.node { + hir::ForeignItemFn(..) => self.encode_variances_of(def_id), + _ => LazySeq::empty(), + }, generics: Some(self.encode_generics(def_id)), predicates: Some(self.encode_predicates(def_id)), diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index 4c09d90f853..f4963619370 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -14,11 +14,9 @@ //! We walk the set of items and, for each member, generate new constraints. use hir::def_id::DefId; -use middle::resolve_lifetime as rl; use rustc::dep_graph::{AssertDepGraphSafe, DepKind}; use rustc::ty::subst::Substs; use rustc::ty::{self, Ty, TyCtxt}; -use rustc::hir::map as hir_map; use syntax::ast; use rustc::hir; use rustc::hir::itemlikevisit::ItemLikeVisitor; @@ -61,10 +59,10 @@ pub struct Constraint<'a> { /// } /// /// then while we are visiting `Bar`, the `CurrentItem` would have -/// the def-id and generics of `Foo`. -pub struct CurrentItem<'a> { +/// the def-id and the start of `Foo`'s inferreds. +pub struct CurrentItem { def_id: DefId, - generics: &'a ty::Generics, + inferred_start: InferredIndex, } pub fn add_constraints_from_crate<'a, 'tcx>(terms_cx: TermsContext<'a, 'tcx>) @@ -91,8 +89,59 @@ pub fn add_constraints_from_crate<'a, 'tcx>(terms_cx: TermsContext<'a, 'tcx>) impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ConstraintContext<'a, 'tcx> { fn visit_item(&mut self, item: &hir::Item) { + match item.node { + hir::ItemStruct(ref struct_def, _) | + hir::ItemUnion(ref struct_def, _) => { + self.visit_node_helper(item.id); + + if let hir::VariantData::Tuple(..) = *struct_def { + self.visit_node_helper(struct_def.id()); + } + } + + hir::ItemEnum(ref enum_def, _) => { + self.visit_node_helper(item.id); + + for variant in &enum_def.variants { + if let hir::VariantData::Tuple(..) = variant.node.data { + self.visit_node_helper(variant.node.data.id()); + } + } + } + + hir::ItemFn(..) => { + self.visit_node_helper(item.id); + } + + hir::ItemForeignMod(ref foreign_mod) => { + for foreign_item in &foreign_mod.items { + if let hir::ForeignItemFn(..) = foreign_item.node { + self.visit_node_helper(foreign_item.id); + } + } + } + + _ => {} + } + } + + fn visit_trait_item(&mut self, trait_item: &hir::TraitItem) { + if let hir::TraitItemKind::Method(..) = trait_item.node { + self.visit_node_helper(trait_item.id); + } + } + + fn visit_impl_item(&mut self, impl_item: &hir::ImplItem) { + if let hir::ImplItemKind::Method(..) = impl_item.node { + self.visit_node_helper(impl_item.id); + } + } +} + +impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { + fn visit_node_helper(&mut self, id: ast::NodeId) { let tcx = self.terms_cx.tcx; - let def_id = tcx.hir.local_def_id(item.id); + let def_id = tcx.hir.local_def_id(id); // Encapsulate constructing the constraints into a task we can // reference later. This can go away once the red-green @@ -100,20 +149,11 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ConstraintContext<'a, 'tcx> { // // See README.md for a detailed discussion // on dep-graph management. - match item.node { - hir::ItemEnum(..) | - hir::ItemStruct(..) | - hir::ItemUnion(..) => { - let dep_node = def_id.to_dep_node(tcx, DepKind::ItemVarianceConstraints); - tcx.dep_graph.with_task(dep_node, - AssertDepGraphSafe(self), - def_id, - visit_item_task); - } - _ => { - // Nothing to do here, skip the task. - } - } + let dep_node = def_id.to_dep_node(tcx, DepKind::ItemVarianceConstraints); + tcx.dep_graph.with_task(dep_node, + AssertDepGraphSafe(self), + def_id, + visit_item_task); fn visit_item_task<'a, 'tcx>(ccx: AssertDepGraphSafe<&mut ConstraintContext<'a, 'tcx>>, def_id: DefId) @@ -122,197 +162,57 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ConstraintContext<'a, 'tcx> { } } - fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) { - } - - fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { - } -} - -/// Is `param_id` a lifetime according to `map`? -fn is_lifetime(map: &hir_map::Map, param_id: ast::NodeId) -> bool { - match map.find(param_id) { - Some(hir_map::NodeLifetime(..)) => true, - _ => false, - } -} - -impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> { self.terms_cx.tcx } fn build_constraints_for_item(&mut self, def_id: DefId) { let tcx = self.tcx(); - let id = self.tcx().hir.as_local_node_id(def_id).unwrap(); - let item = tcx.hir.expect_item(id); - debug!("visit_item item={}", tcx.hir.node_to_string(item.id)); + debug!("build_constraints_for_item({})", tcx.item_path_str(def_id)); - match item.node { - hir::ItemEnum(..) | - hir::ItemStruct(..) | - hir::ItemUnion(..) => { - let generics = tcx.generics_of(def_id); - let current_item = &CurrentItem { def_id, generics }; + // Skip items with no generics - there's nothing to infer in them. + if tcx.generics_of(def_id).count() == 0 { + return; + } + let id = tcx.hir.as_local_node_id(def_id).unwrap(); + let inferred_start = self.terms_cx.inferred_starts[&id]; + let current_item = &CurrentItem { def_id, inferred_start }; + match tcx.type_of(def_id).sty { + ty::TyAdt(def, _) => { // Not entirely obvious: constraints on structs/enums do not // affect the variance of their type parameters. See discussion // in comment at top of module. // // self.add_constraints_from_generics(generics); - for field in tcx.adt_def(def_id).all_fields() { + for field in def.all_fields() { self.add_constraints_from_ty(current_item, tcx.type_of(field.did), self.covariant); } } - hir::ItemTrait(..) | - hir::ItemExternCrate(_) | - hir::ItemUse(..) | - hir::ItemStatic(..) | - hir::ItemConst(..) | - hir::ItemFn(..) | - hir::ItemMod(..) | - hir::ItemForeignMod(..) | - hir::ItemGlobalAsm(..) | - hir::ItemTy(..) | - hir::ItemImpl(..) | - hir::ItemDefaultImpl(..) => { - span_bug!(item.span, "`build_constraints_for_item` invoked for non-type-def"); - } - } - } - - /// Load the generics for another item, adding a corresponding - /// relation into the dependencies to indicate that the variance - /// for `current` relies on `def_id`. - fn read_generics(&mut self, current: &CurrentItem, def_id: DefId) -> &'tcx ty::Generics { - let generics = self.tcx().generics_of(def_id); - if self.tcx().dep_graph.is_fully_enabled() { - self.dependencies.add(current.def_id, def_id); - } - generics - } - - fn opt_inferred_index(&self, param_id: ast::NodeId) -> Option<&InferredIndex> { - self.terms_cx.inferred_map.get(¶m_id) - } - - fn find_binding_for_lifetime(&self, param_id: ast::NodeId) -> ast::NodeId { - let tcx = self.terms_cx.tcx; - assert!(is_lifetime(&tcx.hir, param_id)); - match tcx.named_region_map.defs.get(¶m_id) { - Some(&rl::Region::EarlyBound(_, lifetime_decl_id)) => lifetime_decl_id, - Some(_) => bug!("should not encounter non early-bound cases"), - - // The lookup should only fail when `param_id` is - // itself a lifetime binding: use it as the decl_id. - None => param_id, - } - - } - - /// Is `param_id` a type parameter for which we infer variance? - fn is_to_be_inferred(&self, param_id: ast::NodeId) -> bool { - let result = self.terms_cx.inferred_map.contains_key(¶m_id); - - // To safe-guard against invalid inferred_map constructions, - // double-check if variance is inferred at some use of a type - // parameter (by inspecting parent of its binding declaration - // to see if it is introduced by a type or by a fn/impl). - - let check_result = |this: &ConstraintContext| -> bool { - let tcx = this.terms_cx.tcx; - let decl_id = this.find_binding_for_lifetime(param_id); - // Currently only called on lifetimes; double-checking that. - assert!(is_lifetime(&tcx.hir, param_id)); - let parent_id = tcx.hir.get_parent(decl_id); - let parent = tcx.hir - .find(parent_id) - .unwrap_or_else(|| bug!("tcx.hir missing entry for id: {}", parent_id)); - - let is_inferred; - macro_rules! cannot_happen { () => { { - bug!("invalid parent: {} for {}", - tcx.hir.node_to_string(parent_id), - tcx.hir.node_to_string(param_id)); - } } } - - match parent { - hir_map::NodeItem(p) => { - match p.node { - hir::ItemTy(..) | - hir::ItemEnum(..) | - hir::ItemStruct(..) | - hir::ItemUnion(..) | - hir::ItemTrait(..) => is_inferred = true, - hir::ItemFn(..) => is_inferred = false, - _ => cannot_happen!(), - } - } - hir_map::NodeTraitItem(..) => is_inferred = false, - hir_map::NodeImplItem(..) => is_inferred = false, - _ => cannot_happen!(), + ty::TyFnDef(..) => { + self.add_constraints_from_sig(current_item, + tcx.fn_sig(def_id), + self.covariant); } - return is_inferred; - }; - - assert_eq!(result, check_result(self)); - - return result; - } - - /// Returns a variance term representing the declared variance of the type/region parameter - /// with the given id. - fn declared_variance(&self, - param_def_id: DefId, - item_def_id: DefId, - index: usize) - -> VarianceTermPtr<'a> { - assert_eq!(param_def_id.krate, item_def_id.krate); - - if let Some(param_node_id) = self.tcx().hir.as_local_node_id(param_def_id) { - // Parameter on an item defined within current crate: - // variance not yet inferred, so return a symbolic - // variance. - if let Some(&InferredIndex(index)) = self.opt_inferred_index(param_node_id) { - self.terms_cx.inferred_infos[index].term - } else { - // If there is no inferred entry for a type parameter, - // it must be declared on a (locally defiend) trait -- they don't - // get inferreds because they are always invariant. - if cfg!(debug_assertions) { - let item_node_id = self.tcx().hir.as_local_node_id(item_def_id).unwrap(); - let item = self.tcx().hir.expect_item(item_node_id); - let success = match item.node { - hir::ItemTrait(..) => true, - _ => false, - }; - if !success { - bug!("parameter {:?} has no inferred, but declared on non-trait: {:?}", - item_def_id, - item); - } - } - self.invariant + _ => { + span_bug!(tcx.def_span(def_id), + "`build_constraints_for_item` unsupported for this item"); } - } else { - // Parameter on an item defined within another crate: - // variance already inferred, just look it up. - let variances = self.tcx().variances_of(item_def_id); - self.constant_term(variances[index]) } } fn add_constraint(&mut self, - InferredIndex(index): InferredIndex, + current: &CurrentItem, + index: u32, variance: VarianceTermPtr<'a>) { debug!("add_constraint(index={}, variance={:?})", index, variance); self.constraints.push(Constraint { - inferred: InferredIndex(index), + inferred: InferredIndex(current.inferred_start.0 + index as usize), variance: variance, }); } @@ -354,15 +254,26 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { debug!("add_constraints_from_trait_ref: trait_ref={:?} variance={:?}", trait_ref, variance); + self.add_constraints_from_invariant_substs(current, trait_ref.substs, variance); + } - let trait_generics = self.tcx().generics_of(trait_ref.def_id); + fn add_constraints_from_invariant_substs(&mut self, + current: &CurrentItem, + substs: &Substs<'tcx>, + variance: VarianceTermPtr<'a>) { + debug!("add_constraints_from_invariant_substs: substs={:?} variance={:?}", + substs, + variance); - self.add_constraints_from_substs(current, - trait_ref.def_id, - &trait_generics.types, - &trait_generics.regions, - trait_ref.substs, - variance); + // Trait are always invariant so we can take advantage of that. + let variance_i = self.invariant(variance); + for ty in substs.types() { + self.add_constraints_from_ty(current, ty, variance_i); + } + + for region in substs.regions() { + self.add_constraints_from_region(current, region, variance_i); + } } /// Adds constraints appropriate for an instance of `ty` appearing @@ -383,8 +294,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { } ty::TyFnDef(..) | - ty::TyClosure(..) | - ty::TyAnon(..) => { + ty::TyClosure(..) => { bug!("Unexpected closure type in variance computation"); } @@ -410,26 +320,15 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { } ty::TyAdt(def, substs) => { - let adt_generics = self.read_generics(current, def.did); - - self.add_constraints_from_substs(current, - def.did, - &adt_generics.types, - &adt_generics.regions, - substs, - variance); + self.add_constraints_from_substs(current, def.did, substs, variance); } ty::TyProjection(ref data) => { - let trait_ref = &data.trait_ref; - let trait_generics = self.tcx().generics_of(trait_ref.def_id); + self.add_constraints_from_trait_ref(current, data.trait_ref, variance); + } - self.add_constraints_from_substs(current, - trait_ref.def_id, - &trait_generics.types, - &trait_generics.regions, - trait_ref.substs, - variance); + ty::TyAnon(_, substs) => { + self.add_constraints_from_invariant_substs(current, substs, variance); } ty::TyDynamic(ref data, r) => { @@ -448,23 +347,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { } ty::TyParam(ref data) => { - assert_eq!(current.generics.parent, None); - let mut i = data.idx as usize; - if !current.generics.has_self || i > 0 { - i -= current.generics.regions.len(); - } - let def_id = current.generics.types[i].def_id; - let node_id = self.tcx().hir.as_local_node_id(def_id).unwrap(); - match self.terms_cx.inferred_map.get(&node_id) { - Some(&index) => { - self.add_constraint(index, variance); - } - None => { - // We do not infer variance for type parameters - // declared on methods. They will not be present - // in the inferred_map. - } - } + self.add_constraint(current, data.idx, variance); } ty::TyFnPtr(sig) => { @@ -489,8 +372,6 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { fn add_constraints_from_substs(&mut self, current: &CurrentItem, def_id: DefId, - type_param_defs: &[ty::TypeParameterDef], - region_param_defs: &[ty::RegionParameterDef], substs: &Substs<'tcx>, variance: VarianceTermPtr<'a>) { debug!("add_constraints_from_substs(def_id={:?}, substs={:?}, variance={:?})", @@ -498,21 +379,45 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { substs, variance); - for p in type_param_defs { - let variance_decl = self.declared_variance(p.def_id, def_id, p.index as usize); + // We don't record `inferred_starts` entries for empty generics. + if substs.is_empty() { + return; + } + + // Add a corresponding relation into the dependencies to + // indicate that the variance for `current` relies on `def_id`. + if self.tcx().dep_graph.is_fully_enabled() { + self.dependencies.add(current.def_id, def_id); + } + + let (local, remote) = if let Some(id) = self.tcx().hir.as_local_node_id(def_id) { + (Some(self.terms_cx.inferred_starts[&id]), None) + } else { + (None, Some(self.tcx().variances_of(def_id))) + }; + + for (i, k) in substs.iter().enumerate() { + let variance_decl = if let Some(InferredIndex(start)) = local { + // Parameter on an item defined within current crate: + // variance not yet inferred, so return a symbolic + // variance. + self.terms_cx.inferred_terms[start + i] + } else { + // Parameter on an item defined within another crate: + // variance already inferred, just look it up. + self.constant_term(remote.as_ref().unwrap()[i]) + }; let variance_i = self.xform(variance, variance_decl); - let substs_ty = substs.type_for_def(p); debug!("add_constraints_from_substs: variance_decl={:?} variance_i={:?}", variance_decl, variance_i); - self.add_constraints_from_ty(current, substs_ty, variance_i); - } - - for p in region_param_defs { - let variance_decl = self.declared_variance(p.def_id, def_id, p.index as usize); - let variance_i = self.xform(variance, variance_decl); - let substs_r = substs.region_for_def(p); - self.add_constraints_from_region(current, substs_r, variance_i); + if let Some(ty) = k.as_type() { + self.add_constraints_from_ty(current, ty, variance_i); + } else if let Some(r) = k.as_region() { + self.add_constraints_from_region(current, r, variance_i); + } else { + bug!(); + } } } @@ -537,21 +442,14 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { variance: VarianceTermPtr<'a>) { match *region { ty::ReEarlyBound(ref data) => { - assert_eq!(current.generics.parent, None); - let i = data.index as usize - current.generics.has_self as usize; - let def_id = current.generics.regions[i].def_id; - let node_id = self.tcx().hir.as_local_node_id(def_id).unwrap(); - if self.is_to_be_inferred(node_id) { - let &index = self.opt_inferred_index(node_id).unwrap(); - self.add_constraint(index, variance); - } + self.add_constraint(current, data.index, variance); } ty::ReStatic => {} ty::ReLateBound(..) => { - // We do not infer variance for region parameters on - // methods or in fn types. + // Late-bound regions do not get substituted the same + // way early-bound regions do, so we skip them here. } ty::ReFree(..) | diff --git a/src/librustc_typeck/variance/mod.rs b/src/librustc_typeck/variance/mod.rs index 8f9f40ca40b..7a9f35545e2 100644 --- a/src/librustc_typeck/variance/mod.rs +++ b/src/librustc_typeck/variance/mod.rs @@ -54,45 +54,63 @@ fn crate_variances<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) fn variances_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_def_id: DefId) -> Rc> { - let item_id = tcx.hir.as_local_node_id(item_def_id).expect("expected local def-id"); - let item = tcx.hir.expect_item(item_id); - match item.node { - hir::ItemTrait(..) => { - // Traits are always invariant. - let generics = tcx.generics_of(item_def_id); - assert!(generics.parent.is_none()); - Rc::new(vec![ty::Variance::Invariant; generics.count()]) - } + let id = tcx.hir.as_local_node_id(item_def_id).expect("expected local def-id"); + let unsupported = || { + // Variance not relevant. + span_bug!(tcx.hir.span(id), "asked to compute variance for wrong kind of item") + }; + match tcx.hir.get(id) { + hir::map::NodeItem(item) => match item.node { + hir::ItemEnum(..) | + hir::ItemStruct(..) | + hir::ItemUnion(..) | + hir::ItemFn(..) => {} - hir::ItemEnum(..) | - hir::ItemStruct(..) | - hir::ItemUnion(..) => { - // Everything else must be inferred. + _ => unsupported() + }, - // Lacking red/green, we read the variances for all items here - // but ignore the dependencies, then re-synthesize the ones we need. - let crate_map = tcx.dep_graph.with_ignore(|| tcx.crate_variances(LOCAL_CRATE)); - let dep_node = item_def_id.to_dep_node(tcx, DepKind::ItemVarianceConstraints); + hir::map::NodeTraitItem(item) => match item.node { + hir::TraitItemKind::Method(..) => {} + + _ => unsupported() + }, + + hir::map::NodeImplItem(item) => match item.node { + hir::ImplItemKind::Method(..) => {} + + _ => unsupported() + }, + + hir::map::NodeForeignItem(item) => match item.node { + hir::ForeignItemFn(..) => {} + + _ => unsupported() + }, + + hir::map::NodeVariant(_) | hir::map::NodeStructCtor(_) => {} + + _ => unsupported() + } + + // Everything else must be inferred. + + // Lacking red/green, we read the variances for all items here + // but ignore the dependencies, then re-synthesize the ones we need. + let crate_map = tcx.dep_graph.with_ignore(|| tcx.crate_variances(LOCAL_CRATE)); + let dep_node = item_def_id.to_dep_node(tcx, DepKind::ItemVarianceConstraints); + tcx.dep_graph.read(dep_node); + for &dep_def_id in crate_map.dependencies.less_than(&item_def_id) { + if dep_def_id.is_local() { + let dep_node = dep_def_id.to_dep_node(tcx, DepKind::ItemVarianceConstraints); + tcx.dep_graph.read(dep_node); + } else { + let dep_node = dep_def_id.to_dep_node(tcx, DepKind::ItemVariances); tcx.dep_graph.read(dep_node); - for &dep_def_id in crate_map.dependencies.less_than(&item_def_id) { - if dep_def_id.is_local() { - let dep_node = dep_def_id.to_dep_node(tcx, DepKind::ItemVarianceConstraints); - tcx.dep_graph.read(dep_node); - } else { - let dep_node = dep_def_id.to_dep_node(tcx, DepKind::ItemVariances); - tcx.dep_graph.read(dep_node); - } - } - - crate_map.variances.get(&item_def_id) - .unwrap_or(&crate_map.empty_variance) - .clone() - } - - _ => { - // Variance not relevant. - span_bug!(item.span, "asked to compute variance for wrong kind of item") } } + + crate_map.variances.get(&item_def_id) + .unwrap_or(&crate_map.empty_variance) + .clone() } diff --git a/src/librustc_typeck/variance/solve.rs b/src/librustc_typeck/variance/solve.rs index af8ad491ec0..495eb95419a 100644 --- a/src/librustc_typeck/variance/solve.rs +++ b/src/librustc_typeck/variance/solve.rs @@ -36,15 +36,18 @@ struct SolveContext<'a, 'tcx: 'a> { pub fn solve_constraints(constraints_cx: ConstraintContext) -> ty::CrateVariancesMap { let ConstraintContext { terms_cx, dependencies, constraints, .. } = constraints_cx; - let solutions = terms_cx.inferred_infos - .iter() - .map(|ii| ii.initial_variance) - .collect(); + let mut solutions = vec![ty::Bivariant; terms_cx.inferred_terms.len()]; + for &(id, ref variances) in &terms_cx.lang_items { + let InferredIndex(start) = terms_cx.inferred_starts[&id]; + for (i, &variance) in variances.iter().enumerate() { + solutions[start + i] = variance; + } + } let mut solutions_cx = SolveContext { - terms_cx: terms_cx, - constraints: constraints, - solutions: solutions, + terms_cx, + constraints, + solutions, }; solutions_cx.solve(); let variances = solutions_cx.create_map(); @@ -71,12 +74,9 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> { let old_value = self.solutions[inferred]; let new_value = glb(variance, old_value); if old_value != new_value { - debug!("Updating inferred {} (node {}) \ + debug!("Updating inferred {} \ from {:?} to {:?} due to {:?}", inferred, - self.terms_cx - .inferred_infos[inferred] - .param_id, old_value, new_value, term); @@ -89,49 +89,28 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> { } fn create_map(&self) -> FxHashMap>> { - // Collect all the variances for a particular item and stick - // them into the variance map. We rely on the fact that we - // generate all the inferreds for a particular item - // consecutively (that is, we collect solutions for an item - // until we see a new item id, and we assume (1) the solutions - // are in the same order as the type parameters were declared - // and (2) all solutions or a given item appear before a new - // item id). - let tcx = self.terms_cx.tcx; - let mut map = FxHashMap(); - let solutions = &self.solutions; - let inferred_infos = &self.terms_cx.inferred_infos; - let mut index = 0; - let num_inferred = self.terms_cx.num_inferred(); - while index < num_inferred { - let item_id = inferred_infos[index].item_id; + self.terms_cx.inferred_starts.iter().map(|(&id, &InferredIndex(start))| { + let def_id = tcx.hir.local_def_id(id); + let generics = tcx.generics_of(def_id); - let mut item_variances = vec![]; + let mut variances = solutions[start..start+generics.count()].to_vec(); - while index < num_inferred && inferred_infos[index].item_id == item_id { - let info = &inferred_infos[index]; - let variance = solutions[index]; - debug!("Index {} Info {} Variance {:?}", - index, - info.index, - variance); + debug!("id={} variances={:?}", id, variances); - assert_eq!(item_variances.len(), info.index); - item_variances.push(variance); - index += 1; + // Functions can have unused type parameters: make those invariant. + if let ty::TyFnDef(..) = tcx.type_of(def_id).sty { + for variance in &mut variances { + if *variance == ty::Bivariant { + *variance = ty::Invariant; + } + } } - debug!("item_id={} item_variances={:?}", item_id, item_variances); - - let item_def_id = tcx.hir.local_def_id(item_id); - - map.insert(item_def_id, Rc::new(item_variances)); - } - - map + (def_id, Rc::new(variances)) + }).collect() } fn evaluate(&self, term: VarianceTermPtr<'a>) -> ty::Variance { diff --git a/src/librustc_typeck/variance/terms.rs b/src/librustc_typeck/variance/terms.rs index ad787c57e76..38457146a97 100644 --- a/src/librustc_typeck/variance/terms.rs +++ b/src/librustc_typeck/variance/terms.rs @@ -22,7 +22,6 @@ use arena::TypedArena; use rustc::ty::{self, TyCtxt}; use std::fmt; -use std::rc::Rc; use syntax::ast; use rustc::hir; use rustc::hir::itemlikevisit::ItemLikeVisitor; @@ -63,31 +62,17 @@ pub struct TermsContext<'a, 'tcx: 'a> { pub tcx: TyCtxt<'a, 'tcx, 'tcx>, pub arena: &'a TypedArena>, - pub empty_variances: Rc>, - // For marker types, UnsafeCell, and other lang items where // variance is hardcoded, records the item-id and the hardcoded // variance. pub lang_items: Vec<(ast::NodeId, Vec)>, - // Maps from the node id of a type/generic parameter to the - // corresponding inferred index. - pub inferred_map: NodeMap, + // Maps from the node id of an item to the first inferred index + // used for its type & region parameters. + pub inferred_starts: NodeMap, - // Maps from an InferredIndex to the info for that variable. - pub inferred_infos: Vec>, -} - -pub struct InferredInfo<'a> { - pub item_id: ast::NodeId, - pub index: usize, - pub param_id: ast::NodeId, - pub term: VarianceTermPtr<'a>, - - // Initial value to use for this parameter when inferring - // variance. For most parameters, this is Bivariant. But for lang - // items and input type parameters on traits, it is different. - pub initial_variance: ty::Variance, + // Maps from an InferredIndex to the term for that variable. + pub inferred_terms: Vec>, } pub fn determine_parameters_to_be_inferred<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -96,14 +81,10 @@ pub fn determine_parameters_to_be_inferred<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx> let mut terms_cx = TermsContext { tcx: tcx, arena: arena, - inferred_map: NodeMap(), - inferred_infos: Vec::new(), + inferred_starts: NodeMap(), + inferred_terms: vec![], lang_items: lang_items(tcx), - - // cache and share the variance struct used for items with - // no type/region parameters - empty_variances: Rc::new(vec![]), }; // See README.md for a discussion on dep-graph management. @@ -135,67 +116,28 @@ fn lang_items(tcx: TyCtxt) -> Vec<(ast::NodeId, Vec)> { } impl<'a, 'tcx> TermsContext<'a, 'tcx> { - fn add_inferreds_for_item(&mut self, - item_id: ast::NodeId, - generics: &hir::Generics) { - //! Add "inferreds" for the generic parameters declared on this - //! item. This has a lot of annoying parameters because we are - //! trying to drive this from the AST, rather than the - //! ty::Generics, so that we can get span info -- but this - //! means we must accommodate syntactic distinctions. - //! + fn add_inferreds_for_item(&mut self, id: ast::NodeId) { + let tcx = self.tcx; + let def_id = tcx.hir.local_def_id(id); + let count = tcx.generics_of(def_id).count(); + + if count == 0 { + return; + } + + // Record the start of this item's inferreds. + let start = self.inferred_terms.len(); + let newly_added = self.inferred_starts.insert(id, InferredIndex(start)).is_none(); + assert!(newly_added); // NB: In the code below for writing the results back into the // `CrateVariancesMap`, we rely on the fact that all inferreds // for a particular item are assigned continuous indices. - for (p, i) in generics.lifetimes.iter().zip(0..) { - let id = p.lifetime.id; - self.add_inferred(item_id, i, id); - } - - for (p, i) in generics.ty_params.iter().zip(generics.lifetimes.len()..) { - self.add_inferred(item_id, i, p.id); - } - } - - fn add_inferred(&mut self, item_id: ast::NodeId, index: usize, param_id: ast::NodeId) { - let inf_index = InferredIndex(self.inferred_infos.len()); - let term = self.arena.alloc(InferredTerm(inf_index)); - let initial_variance = self.pick_initial_variance(item_id, index); - self.inferred_infos.push(InferredInfo { - item_id: item_id, - index: index, - param_id: param_id, - term: term, - initial_variance: initial_variance, - }); - let newly_added = self.inferred_map.insert(param_id, inf_index).is_none(); - assert!(newly_added); - - debug!("add_inferred(item_path={}, \ - item_id={}, \ - index={}, \ - param_id={}, \ - inf_index={:?}, \ - initial_variance={:?})", - self.tcx.item_path_str(self.tcx.hir.local_def_id(item_id)), - item_id, - index, - param_id, - inf_index, - initial_variance); - } - - fn pick_initial_variance(&self, item_id: ast::NodeId, index: usize) -> ty::Variance { - match self.lang_items.iter().find(|&&(n, _)| n == item_id) { - Some(&(_, ref variances)) => variances[index], - None => ty::Bivariant, - } - } - - pub fn num_inferred(&self) -> usize { - self.inferred_infos.len() + let arena = self.arena; + self.inferred_terms.extend((start..start+count).map(|i| { + &*arena.alloc(InferredTerm(InferredIndex(i))) + })); } } @@ -205,30 +147,50 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for TermsContext<'a, 'tcx> { self.tcx.hir.node_to_string(item.id)); match item.node { - hir::ItemEnum(_, ref generics) | - hir::ItemStruct(_, ref generics) | - hir::ItemUnion(_, ref generics) => { - self.add_inferreds_for_item(item.id, generics); + hir::ItemStruct(ref struct_def, _) | + hir::ItemUnion(ref struct_def, _) => { + self.add_inferreds_for_item(item.id); + + if let hir::VariantData::Tuple(..) = *struct_def { + self.add_inferreds_for_item(struct_def.id()); + } } - hir::ItemTrait(..) | - hir::ItemExternCrate(_) | - hir::ItemUse(..) | - hir::ItemDefaultImpl(..) | - hir::ItemImpl(..) | - hir::ItemStatic(..) | - hir::ItemConst(..) | - hir::ItemFn(..) | - hir::ItemMod(..) | - hir::ItemForeignMod(..) | - hir::ItemGlobalAsm(..) | - hir::ItemTy(..) => {} + hir::ItemEnum(ref enum_def, _) => { + self.add_inferreds_for_item(item.id); + + for variant in &enum_def.variants { + if let hir::VariantData::Tuple(..) = variant.node.data { + self.add_inferreds_for_item(variant.node.data.id()); + } + } + } + + hir::ItemFn(..) => { + self.add_inferreds_for_item(item.id); + } + + hir::ItemForeignMod(ref foreign_mod) => { + for foreign_item in &foreign_mod.items { + if let hir::ForeignItemFn(..) = foreign_item.node { + self.add_inferreds_for_item(foreign_item.id); + } + } + } + + _ => {} } } - fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) { + fn visit_trait_item(&mut self, trait_item: &hir::TraitItem) { + if let hir::TraitItemKind::Method(..) = trait_item.node { + self.add_inferreds_for_item(trait_item.id); + } } - fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { + fn visit_impl_item(&mut self, impl_item: &hir::ImplItem) { + if let hir::ImplItemKind::Method(..) = impl_item.node { + self.add_inferreds_for_item(impl_item.id); + } } } diff --git a/src/test/compile-fail/variance-region-bounds.rs b/src/test/compile-fail/variance-region-bounds.rs deleted file mode 100644 index 41d204a541b..00000000000 --- a/src/test/compile-fail/variance-region-bounds.rs +++ /dev/null @@ -1,25 +0,0 @@ -// 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. - -// Check that `T:'a` is contravariant in T. - -#![feature(rustc_attrs)] - -#[rustc_variance] -trait Foo: 'static { //~ ERROR [o] -} - -#[rustc_variance] -trait Bar { //~ ERROR [o, o] - fn do_it(&self) - where T: 'static; -} - -fn main() { } diff --git a/src/test/compile-fail/variance-trait-bounds.rs b/src/test/compile-fail/variance-trait-bounds.rs index 58fb785c48c..9b88e38e085 100644 --- a/src/test/compile-fail/variance-trait-bounds.rs +++ b/src/test/compile-fail/variance-trait-bounds.rs @@ -14,13 +14,11 @@ // Check that bounds on type parameters (other than `Self`) do not // influence variance. -#[rustc_variance] -trait Getter { //~ ERROR [o, o] +trait Getter { fn get(&self) -> T; } -#[rustc_variance] -trait Setter { //~ ERROR [o, o] +trait Setter { fn get(&self, T); } @@ -34,20 +32,6 @@ enum TestEnum> { //~ ERROR [*, +] Foo(T) } -#[rustc_variance] -trait TestTrait> { //~ ERROR [o, o, o] - fn getter(&self, u: U) -> T; -} - -#[rustc_variance] -trait TestTrait2 : Getter { //~ ERROR [o, o] -} - -#[rustc_variance] -trait TestTrait3 { //~ ERROR [o, o] - fn getter>(&self); -} - #[rustc_variance] struct TestContraStruct> { //~ ERROR [*, +] t: T diff --git a/src/test/compile-fail/variance-types-bounds.rs b/src/test/compile-fail/variance-types-bounds.rs index 2df94cc907a..5075dd2ceed 100644 --- a/src/test/compile-fail/variance-types-bounds.rs +++ b/src/test/compile-fail/variance-types-bounds.rs @@ -36,37 +36,14 @@ struct TestIndirect2 { //~ ERROR [o, o] m: TestMut } -#[rustc_variance] -trait Getter { //~ ERROR [o, o] +trait Getter { fn get(&self) -> A; } -#[rustc_variance] -trait Setter { //~ ERROR [o, o] +trait Setter { fn set(&mut self, a: A); } -#[rustc_variance] -trait GetterSetter { //~ ERROR [o, o] - fn get(&self) -> A; - fn set(&mut self, a: A); -} - -#[rustc_variance] -trait GetterInTypeBound { //~ ERROR [o, o] - // Here, the use of `A` in the method bound *does* affect - // variance. Think of it as if the method requested a dictionary - // for `T:Getter`. Since this dictionary is an input, it is - // contravariant, and the Getter is covariant w/r/t A, yielding an - // overall contravariant result. - fn do_it>(&self); -} - -#[rustc_variance] -trait SetterInTypeBound { //~ ERROR [o, o] - fn do_it>(&self); -} - #[rustc_variance] struct TestObject { //~ ERROR [o, o] n: Box+Send>, From 69076f3a786e0412510af925f38a2a7f78b8e6ef Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 2 Jun 2017 22:12:01 +0300 Subject: [PATCH 056/162] tests: work around fallout from normalizing signatures separately. --- src/test/compile-fail/associated-types-path-2.rs | 2 ++ src/test/compile-fail/on-unimplemented/multiple-impls.rs | 6 ++++++ src/test/compile-fail/on-unimplemented/on-impl.rs | 2 ++ 3 files changed, 10 insertions(+) diff --git a/src/test/compile-fail/associated-types-path-2.rs b/src/test/compile-fail/associated-types-path-2.rs index cdb7dff692c..d62f6b0f1a3 100644 --- a/src/test/compile-fail/associated-types-path-2.rs +++ b/src/test/compile-fail/associated-types-path-2.rs @@ -38,11 +38,13 @@ pub fn f1_int_uint() { pub fn f1_uint_uint() { f1(2u32, 4u32); //~^ ERROR `u32: Foo` is not satisfied + //~| ERROR `u32: Foo` is not satisfied } pub fn f1_uint_int() { f1(2u32, 4i32); //~^ ERROR `u32: Foo` is not satisfied + //~| ERROR `u32: Foo` is not satisfied } pub fn f2_int() { diff --git a/src/test/compile-fail/on-unimplemented/multiple-impls.rs b/src/test/compile-fail/on-unimplemented/multiple-impls.rs index 0df8c41ffe1..15375936b89 100644 --- a/src/test/compile-fail/on-unimplemented/multiple-impls.rs +++ b/src/test/compile-fail/on-unimplemented/multiple-impls.rs @@ -44,12 +44,18 @@ fn main() { //~^ ERROR E0277 //~| NOTE trait message //~| NOTE required by + //~| ERROR E0277 + //~| NOTE trait message Index::index(&[] as &[i32], Foo(2u32)); //~^ ERROR E0277 //~| NOTE on impl for Foo //~| NOTE required by + //~| ERROR E0277 + //~| NOTE on impl for Foo Index::index(&[] as &[i32], Bar(2u32)); //~^ ERROR E0277 //~| NOTE on impl for Bar //~| NOTE required by + //~| ERROR E0277 + //~| NOTE on impl for Bar } diff --git a/src/test/compile-fail/on-unimplemented/on-impl.rs b/src/test/compile-fail/on-unimplemented/on-impl.rs index 79021cd03cc..66d612baab4 100644 --- a/src/test/compile-fail/on-unimplemented/on-impl.rs +++ b/src/test/compile-fail/on-unimplemented/on-impl.rs @@ -33,4 +33,6 @@ fn main() { //~^ ERROR E0277 //~| NOTE a usize is required //~| NOTE required by + //~| ERROR E0277 + //~| NOTE a usize is required } From 0e6eecb4e5bd2a9c308617f5e0c3cdf43124a601 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Tue, 27 Jun 2017 18:09:52 +0300 Subject: [PATCH 057/162] Rebase LLVM on top of LLVM 4.0.1 Fixes #42893. --- src/llvm | 2 +- src/rustllvm/llvm-rebuild-trigger | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/llvm b/src/llvm index d8c9dfcc4f5..8e1b4fedfa4 160000 --- a/src/llvm +++ b/src/llvm @@ -1 +1 @@ -Subproject commit d8c9dfcc4f5289c09bab5736966feee2a0e69594 +Subproject commit 8e1b4fedfa4542e65f82fe124bd6433f3bd0aec5 diff --git a/src/rustllvm/llvm-rebuild-trigger b/src/rustllvm/llvm-rebuild-trigger index e547659d19a..37ba3264452 100644 --- a/src/rustllvm/llvm-rebuild-trigger +++ b/src/rustllvm/llvm-rebuild-trigger @@ -1,4 +1,4 @@ # If this file is modified, then llvm will be (optionally) cleaned and then rebuilt. # The actual contents of this file do not matter, but to trigger a change on the # build bots then the contents should be changed so git updates the mtime. -2017-06-19 +2017-06-27 From 0dfd9c30f2c61458343e0816c66f448019e826d1 Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Sat, 24 Jun 2017 18:26:04 +0000 Subject: [PATCH 058/162] syntax: allow negative integer literal expression to be interpolated as pattern --- src/librustc_lint/builtin.rs | 10 ++---- src/librustc_passes/ast_validation.rs | 26 ++++++++++++++ src/libsyntax/parse/parser.rs | 4 ++- .../compile-fail/patkind-litrange-no-expr.rs | 36 +++++++++++++++++++ src/test/run-pass/macro-pat-neg-lit.rs | 35 ++++++++++++++++++ 5 files changed, 103 insertions(+), 8 deletions(-) create mode 100644 src/test/compile-fail/patkind-litrange-no-expr.rs create mode 100644 src/test/run-pass/macro-pat-neg-lit.rs diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 9800012917c..57843047f51 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -684,13 +684,9 @@ fn fl_lit_check_expr(cx: &EarlyContext, expr: &ast::Expr) { // These may occur in patterns // and can maybe contain float literals ExprKind::Unary(_, ref f) => fl_lit_check_expr(cx, f), - // These may occur in patterns - // and can't contain float literals - ExprKind::Path(..) => (), - // If something unhandled is encountered, we need to expand the - // search or ignore more ExprKinds. - _ => span_bug!(expr.span, "Unhandled expression {:?} in float lit pattern lint", - expr.node), + // Other kinds of exprs can't occur in patterns so we don't have to check them + // (ast_validation will emit an error if they occur) + _ => (), } } diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 7c443a4ac75..6ad03186dc7 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -93,6 +93,17 @@ impl<'a> AstValidator<'a> { } } } + + /// matches '-' lit | lit (cf. parser::Parser::parse_pat_literal_maybe_minus) + fn check_expr_within_pat(&self, expr: &Expr) { + match expr.node { + ExprKind::Lit(..) | ExprKind::Path(..) => {} + ExprKind::Unary(UnOp::Neg, ref inner) + if match inner.node { ExprKind::Lit(_) => true, _ => false } => {} + _ => self.err_handler().span_err(expr.span, "arbitrary expressions aren't allowed \ + in patterns") + } + } } impl<'a> Visitor<'a> for AstValidator<'a> { @@ -308,6 +319,21 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } visit::walk_generics(self, g) } + + fn visit_pat(&mut self, pat: &'a Pat) { + match pat.node { + PatKind::Lit(ref expr) => { + self.check_expr_within_pat(expr); + } + PatKind::Range(ref start, ref end, _) => { + self.check_expr_within_pat(start); + self.check_expr_within_pat(end); + } + _ => {} + } + + visit::walk_pat(self, pat) + } } pub fn check_crate(session: &Session, krate: &Crate) { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 851a638e148..5b0031b2f17 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1659,8 +1659,10 @@ impl<'a> Parser<'a> { Ok(codemap::Spanned { node: lit, span: lo.to(self.prev_span) }) } - /// matches '-' lit | lit + /// matches '-' lit | lit (cf. ast_validation::AstValidator::check_expr_within_pat) pub fn parse_pat_literal_maybe_minus(&mut self) -> PResult<'a, P> { + maybe_whole_expr!(self); + let minus_lo = self.span; let minus_present = self.eat(&token::BinOp(token::Minus)); let lo = self.span; diff --git a/src/test/compile-fail/patkind-litrange-no-expr.rs b/src/test/compile-fail/patkind-litrange-no-expr.rs new file mode 100644 index 00000000000..afb2cbb7db3 --- /dev/null +++ b/src/test/compile-fail/patkind-litrange-no-expr.rs @@ -0,0 +1,36 @@ +// Copyright 2017 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. + +macro_rules! enum_number { + ($name:ident { $($variant:ident = $value:expr, )* }) => { + enum $name { + $($variant = $value,)* + } + + fn foo(value: i32) -> Option<$name> { + match value { + $( $value => Some($name::$variant), )* // PatKind::Lit + $( $value ... 42 => Some($name::$variant), )* // PatKind::Range + _ => None + } + } + } +} + +enum_number!(Change { + Pos = 1, + Neg = -1, + Arith = 1 + 1, //~ ERROR arbitrary expressions aren't allowed in patterns + //~^ ERROR arbitrary expressions aren't allowed in patterns + //~^^ ERROR only char and numeric types are allowed in range patterns +}); + +fn main() {} + diff --git a/src/test/run-pass/macro-pat-neg-lit.rs b/src/test/run-pass/macro-pat-neg-lit.rs new file mode 100644 index 00000000000..43ac697edce --- /dev/null +++ b/src/test/run-pass/macro-pat-neg-lit.rs @@ -0,0 +1,35 @@ +// Copyright 2017 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. + +macro_rules! enum_number { + ($name:ident { $($variant:ident = $value:expr, )* }) => { + enum $name { + $($variant = $value,)* + } + + fn foo(value: i32) -> Option<$name> { + match value { + $( $value => Some($name::$variant), )* + _ => None + } + } + } +} + +enum_number!(Change { + Down = -1, + None = 0, + Up = 1, +}); + +fn main() { + if let Some(Change::Down) = foo(-1) {} else { panic!() } +} + From 3dad1977a54574ae48958e17e7273075785c08c6 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 27 Jun 2017 01:43:09 +1200 Subject: [PATCH 059/162] Update RLS submodule --- src/Cargo.lock | 60 +++++++++++++++++--------------------------------- src/tools/rls | 2 +- 2 files changed, 21 insertions(+), 41 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 386450f4a65..7b486212bc4 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -157,7 +157,7 @@ dependencies = [ [[package]] name = "cargo" version = "0.21.0" -source = "git+https://github.com/rust-lang/cargo#abf01e1eddb3145c83f71b469ea7bee37141e5e1" +source = "git+https://github.com/rust-lang/cargo#854bc167bbf74053f821f65cb86d506033f3d3a7" replace = "cargo 0.21.0" [[package]] @@ -319,7 +319,7 @@ name = "curl" version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "curl-sys 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", + "curl-sys 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)", @@ -329,7 +329,7 @@ dependencies = [ [[package]] name = "curl-sys" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", @@ -576,7 +576,7 @@ dependencies = [ [[package]] name = "languageserver-types" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -610,7 +610,7 @@ version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", - "curl-sys 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", + "curl-sys 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", "libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -994,7 +994,7 @@ dependencies = [ "aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1023,11 +1023,11 @@ dependencies = [ "cargo 0.21.0 (git+https://github.com/rust-lang/cargo)", "derive-new 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "languageserver-types 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "languageserver-types 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "racer 2.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-analysis 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-data 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rls-analysis 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rls-data 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rls-vfs 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "rustfmt-nightly 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1041,21 +1041,12 @@ dependencies = [ [[package]] name = "rls-analysis" -version = "0.3.2" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "derive-new 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-data 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rls-data" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ + "rls-data 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1813,15 +1804,6 @@ dependencies = [ "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "thread-id" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "thread_local" version = "0.2.7" @@ -1832,11 +1814,11 @@ dependencies = [ [[package]] name = "thread_local" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "thread-id 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1915,7 +1897,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "unreachable" -version = "0.1.1" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2050,7 +2032,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b8ebbb35d3dc9cd09497168f33de1acb79b265d350ab0ac34133b98f8509af1f" "checksum crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0c5ea215664ca264da8a9d9c3be80d2eaf30923c259d03e870388eb927508f97" "checksum curl 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6689276ab61f97c660669a5ecc117c36875dfc1ba301c986b16c653415bdf9d7" -"checksum curl-sys 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "cbd8b8d593de3bbf49252b92f398ef47f0c6c1ebdfd0f9282b9b9348aad8d71c" +"checksum curl-sys 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d5481162dc4f424d088581db2f979fa7d4c238fe9794595de61d8d7522e277de" "checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850" "checksum derive-new 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "41be6ca3b99e0c0483fb2389685448f650459c3ecbe4e18d7705d8010ec4ab8e" "checksum diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0a515461b6c8c08419850ced27bc29e86166dcdcde8fbe76f8b1f0589bb49472" @@ -2076,7 +2058,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c" "checksum jobserver 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4e28adc987f6d0521ef66ad60b055968107b164b3bb3cf3dc8474e0a380474a6" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum languageserver-types 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97c2985bfcbbcb0189cfa25e1c10c1ac7111df2b6214b652c690127aefdf4e5b" +"checksum languageserver-types 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c178b944c3187527293fb9f8a0b0db3c5fb62eb127cacd65296f651a2440f5b1" "checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf" "checksum libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)" = "38f5c2b18a287cf78b4097db62e20f43cace381dc76ae5c0a3073067f78b7ddc" "checksum libgit2-sys 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "df18a822100352d9863b302faf6f8f25c0e77f0e60feb40e5dbe1238b7f13b1d" @@ -2119,8 +2101,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b" "checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957" "checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db" -"checksum rls-analysis 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8d77d58e8933752142b5b92e3f8ba6d6f1630be6da5627c492268a43f79ffbda" -"checksum rls-data 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "374a8fad31cc0681a7bfd8a04079dd4afd0e981d34e18a171b1a467445bdf51e" +"checksum rls-analysis 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "78a05b130793ebc781c2d933299d7214a10d014fdebe5184eb652c81ba8d3184" "checksum rls-data 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e502ac679bc35e023e982506c32d0278ef89e29af1e4ad21cb70c44b525b87a9" "checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a" "checksum rls-vfs 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1f19246a0fda45f2fb6eb34addef2a692c044cbf1c90ec7695583450fb5f23e7" @@ -2155,9 +2136,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2b6b55df3198cc93372e85dd2ed817f0e38ce8cc0f22eb32391bfad9c4bf209" "checksum termcolor 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9a5193a56b8d82014662c4b933dea6bec851daf018a2b01722e007daaf5f9dca" "checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03" -"checksum thread-id 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8df7875b676fddfadffd96deea3b1124e5ede707d4884248931077518cf1f773" "checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5" -"checksum thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c85048c6260d17cf486ceae3282d9fb6b90be220bf5b28c400f5485ffc29f0c7" +"checksum thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1697c4b57aeeb7a536b647165a2825faddffb1d3bad386d507709bd51a90bb14" "checksum toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)" = "0590d72182e50e879c4da3b11c6488dae18fccb1ae0c7a3eda18e16795844796" "checksum toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "736b60249cb25337bc196faa43ee12c705e426f3d55c214d73a4e7be06f92cb4" "checksum toml 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bd86ad9ebee246fdedd610e0f6d0587b754a3d81438db930a244d0480ed7878f" @@ -2169,7 +2149,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f" "checksum unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "36dff09cafb4ec7c8cf0023eb0b686cb6ce65499116a12201c9e11840ca01beb" "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" -"checksum unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91" +"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" "checksum url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eeb819346883532a271eb626deb43c4a1bb4c4dd47c519bd78137c3e72a4fe27" "checksum url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "74e7d099f1ee52f823d4bdd60c93c3602043c728f5db3b97bdb548467f7bddea" "checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f" diff --git a/src/tools/rls b/src/tools/rls index d26fd6f089a..4c0a8b63d61 160000 --- a/src/tools/rls +++ b/src/tools/rls @@ -1 +1 @@ -Subproject commit d26fd6f089a4e7f1216a03a6d604bee33b2301dc +Subproject commit 4c0a8b63d61942349c18727409b2a600446e02d6 From 7dad2958be59801881fb3db7544de423420dabd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 27 Jun 2017 13:34:56 -0700 Subject: [PATCH 060/162] Review comments - Fix typo - Add docstring - Remove spurious test output file --- src/librustc/hir/map/mod.rs | 22 +++++++++++++++++++ src/librustc_typeck/check/mod.rs | 4 ++-- .../expected-return-on-unit.stderr | 4 ---- 3 files changed, 24 insertions(+), 6 deletions(-) delete mode 100644 src/test/ui/block-result/expected-return-on-unit.stderr diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index ddcc2c08850..02a36a372d9 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -632,6 +632,28 @@ impl<'hir> Map<'hir> { } } + /// Retrieve the NodeId for `id`'s enclosing method, unless there's a + /// `while` or `loop` before reacing it, as block tail returns are not + /// available in them. + /// + /// ``` + /// fn foo(x: usize) -> bool { + /// if x == 1 { + /// true // `get_return_block` gets passed the `id` corresponding + /// } else { // to this, it will return `foo`'s `NodeId`. + /// false + /// } + /// } + /// ``` + /// + /// ``` + /// fn foo(x: usize) -> bool { + /// loop { + /// true // `get_return_block` gets passed the `id` corresponding + /// } // to this, it will return `None`. + /// false + /// } + /// ``` pub fn get_return_block(&self, id: NodeId) -> Option { let match_fn = |node: &Node| { match *node { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 7c4b6a858d9..cba930d312f 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4214,7 +4214,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ty } - /// Given a `NodeId`, return the `FnDecl` of the method it is enclosed by and wether it is + /// Given a `NodeId`, return the `FnDecl` of the method it is enclosed by and whether it is /// `fn main` if it is a method, `None` otherwise. pub fn get_fn_decl(&self, blk_id: ast::NodeId) -> Option<(hir::FnDecl, bool)> { // Get enclosing Fn, if it is a function or a trait method, unless there's a `loop` or @@ -4227,7 +4227,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }) = parent { decl.clone().and_then(|decl| { // This is less than ideal, it will not present the return type span on any - // method called `main`, regardless of wether it is actually the entry point. + // method called `main`, regardless of whether it is actually the entry point. Some((decl, name == Symbol::intern("main"))) }) } else if let Node::NodeTraitItem(&hir::TraitItem { diff --git a/src/test/ui/block-result/expected-return-on-unit.stderr b/src/test/ui/block-result/expected-return-on-unit.stderr deleted file mode 100644 index 8a0d7a335d6..00000000000 --- a/src/test/ui/block-result/expected-return-on-unit.stderr +++ /dev/null @@ -1,4 +0,0 @@ -error[E0601]: main function not found - -error: aborting due to previous error(s) - From e72ee6e4ad0511aaf533a492382b84dfa712393f Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 27 Jun 2017 16:31:31 -0700 Subject: [PATCH 061/162] Use a little more compelling example of `for_each` --- src/libcore/iter/iterator.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index d38864f3edd..26660cb3331 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -500,16 +500,17 @@ pub trait Iterator { /// ``` /// #![feature(iterator_for_each)] /// - /// let mut v = vec![]; - /// (0..5).for_each(|x| v.push(x * 100)); + /// use std::sync::mpsc::channel; /// - /// let mut v2 = vec![]; - /// for x in 0..5 { v2.push(x * 100); } + /// let (tx, rx) = channel(); + /// (0..5).map(|x| x * 2 + 1) + /// .for_each(move |x| tx.send(x).unwrap()); /// - /// assert_eq!(v, v2); + /// let v: Vec<_> = rx.iter().collect(); + /// assert_eq!(v, vec![1, 3, 5, 7, 9]); /// ``` /// - /// For such a small example, the `for` loop is cleaner, but `for_each` + /// For such a small example, a `for` loop may be cleaner, but `for_each` /// might be preferable to keep a functional style with longer iterators: /// /// ``` From 71abfa7b913d79c7ff5a3cc32e2988d1aac86480 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Tue, 27 Jun 2017 18:34:07 +0300 Subject: [PATCH 062/162] re-add the call to `super_statement` in EraseRegions The move gathering code is sensitive to type-equality - that is rather un-robust and I plan to fix it eventually, but that's a more invasive change. And we want to fix the visitor anyway. Fixes #42903. --- src/librustc_mir/transform/erase_regions.rs | 5 +++-- src/test/run-pass/dynamic-drop.rs | 15 +++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs index e809695c180..eb283df869f 100644 --- a/src/librustc_mir/transform/erase_regions.rs +++ b/src/librustc_mir/transform/erase_regions.rs @@ -67,12 +67,13 @@ impl<'a, 'tcx> MutVisitor<'tcx> for EraseRegionsVisitor<'a, 'tcx> { } fn visit_statement(&mut self, - _block: BasicBlock, + block: BasicBlock, statement: &mut Statement<'tcx>, - _location: Location) { + location: Location) { if let StatementKind::EndRegion(_) = statement.kind { statement.kind = StatementKind::Nop; } + self.super_statement(block, statement, location); } } diff --git a/src/test/run-pass/dynamic-drop.rs b/src/test/run-pass/dynamic-drop.rs index 6725a0c547f..bdcd3eecc69 100644 --- a/src/test/run-pass/dynamic-drop.rs +++ b/src/test/run-pass/dynamic-drop.rs @@ -106,6 +106,18 @@ fn struct_dynamic_drop(a: &Allocator, c0: bool, c1: bool, c: bool) { } } +fn field_assignment(a: &Allocator, c0: bool) { + let mut x = (TwoPtrs(a.alloc(), a.alloc()), a.alloc()); + + x.1 = a.alloc(); + x.1 = a.alloc(); + + let f = (x.0).0; + if c0 { + (x.0).0 = f; + } +} + fn assignment2(a: &Allocator, c0: bool, c1: bool) { let mut _v = a.alloc(); let mut _w = a.alloc(); @@ -207,5 +219,8 @@ fn main() { run_test(|a| struct_dynamic_drop(a, true, true, false)); run_test(|a| struct_dynamic_drop(a, true, true, true)); + run_test(|a| field_assignment(a, false)); + run_test(|a| field_assignment(a, true)); + run_test_nopanic(|a| union1(a)); } From 4fb67dcf8f51e0a875ec7f00a3ef2649758b9b9a Mon Sep 17 00:00:00 2001 From: Andreas Sommer Date: Wed, 28 Jun 2017 10:55:57 +0200 Subject: [PATCH 063/162] Fix link reference --- src/doc/unstable-book/src/language-features/compile-error.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/unstable-book/src/language-features/compile-error.md b/src/doc/unstable-book/src/language-features/compile-error.md index 1b25eeda3f6..4b24c0a6a0d 100644 --- a/src/doc/unstable-book/src/language-features/compile-error.md +++ b/src/doc/unstable-book/src/language-features/compile-error.md @@ -2,7 +2,7 @@ The tracking issue for this feature is: [#40872] -[#29599]: https://github.com/rust-lang/rust/issues/40872 +[#40872]: https://github.com/rust-lang/rust/issues/40872 ------------------------ From 2783d0f7dac17f764c6580a04877e6813be574d2 Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Wed, 28 Jun 2017 13:43:56 +0200 Subject: [PATCH 064/162] Add links to the `ErrorKind` variants in errors of `open` --- src/libstd/fs.rs | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index f1ec4d2dff0..88994b284c9 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -654,25 +654,25 @@ impl OpenOptions { /// /// This function will return an error under a number of different /// circumstances. Some of these error conditions are listed here, together - /// with their [`ErrorKind`]. The mapping to `ErrorKind`s is not part of + /// with their [`ErrorKind`]. The mapping to [`ErrorKind`]s is not part of /// the compatiblity contract of the function, especially the `Other` kind /// might change to more specific kinds in the future. /// - /// * `NotFound`: The specified file does not exist and neither `create` or - /// `create_new` is set, - /// * `NotFound`: One of the directory components of the file path does not - /// exist. - /// * `PermissionDenied`: The user lacks permission to get the specified + /// * [`NotFound`]: The specified file does not exist and neither `create` + /// or `create_new` is set. + /// * [`NotFound`]: One of the directory components of the file path does + /// not exist. + /// * [`PermissionDenied`]: The user lacks permission to get the specified /// access rights for the file. - /// * `PermissionDenied`: The user lacks permission to open one of the + /// * [`PermissionDenied`]: The user lacks permission to open one of the /// directory components of the specified path. - /// * `AlreadyExists`: `create_new` was specified and the file already + /// * [`AlreadyExists`]: `create_new` was specified and the file already /// exists. - /// * `InvalidInput`: Invalid combinations of open options (truncate + /// * [`InvalidInput`]: Invalid combinations of open options (truncate /// without write access, no access mode set, etc.). - /// * `Other`: One of the directory components of the specified file path + /// * [`Other`]: One of the directory components of the specified file path /// was not, in fact, a directory. - /// * `Other`: Filesystem-level errors: full disk, write permission + /// * [`Other`]: Filesystem-level errors: full disk, write permission /// requested on a read-only file system, exceeded disk quota, too many /// open files, too long filename, too many symbolic links in the /// specified path (Unix-like systems only), etc. @@ -686,6 +686,11 @@ impl OpenOptions { /// ``` /// /// [`ErrorKind`]: ../io/enum.ErrorKind.html + /// [`AlreadyExists`]: ../io/enum.ErrorKind.html#variant.AlreadyExists + /// [`InvalidInput`]: ../io/enum.ErrorKind.html#variant.InvalidInput + /// [`NotFound`]: ../io/enum.ErrorKind.html#variant.NotFound + /// [`Other`]: ../io/enum.ErrorKind.html#variant.Other + /// [`PermissionDenied`]: ../io/enum.ErrorKind.html#variant.PermissionDenied #[stable(feature = "rust1", since = "1.0.0")] pub fn open>(&self, path: P) -> io::Result { self._open(path.as_ref()) From 13cd022060316146474915664a9e019906a2c79a Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Mon, 26 Jun 2017 14:57:26 +0200 Subject: [PATCH 065/162] Shift mir-dataflow from `rustc_borrowck` to `rustc_mir` crate. Turn `elaborate_drops` and `rustc_peek` implementations into MIR passes that also live in `rustc_mir` crate. Rewire things so `rustc_driver` uses the `ElaborateDrops` from `rustc_mir` crate. --- src/librustc_borrowck/borrowck/mod.rs | 27 ++-- src/librustc_borrowck/lib.rs | 3 +- src/librustc_driver/driver.rs | 3 +- .../dataflow/drop_flag_effects.rs} | 148 +++--------------- .../mir => librustc_mir}/dataflow/graphviz.rs | 13 +- .../dataflow/impls/mod.rs} | 29 ++-- .../mir => librustc_mir}/dataflow/mod.rs | 36 +++-- .../dataflow/move_paths}/abs_domain.rs | 0 .../dataflow/move_paths/mod.rs} | 12 +- src/librustc_mir/lib.rs | 3 + .../transform}/elaborate_drops.rs | 43 ++--- src/librustc_mir/transform/mod.rs | 2 + .../transform/rustc_peek.rs} | 65 +++++++- 13 files changed, 178 insertions(+), 206 deletions(-) rename src/{librustc_borrowck/borrowck/mir/mod.rs => librustc_mir/dataflow/drop_flag_effects.rs} (67%) rename src/{librustc_borrowck/borrowck/mir => librustc_mir}/dataflow/graphviz.rs (97%) rename src/{librustc_borrowck/borrowck/mir/dataflow/impls.rs => librustc_mir/dataflow/impls/mod.rs} (96%) rename src/{librustc_borrowck/borrowck/mir => librustc_mir}/dataflow/mod.rs (95%) rename src/{librustc_borrowck/borrowck/mir => librustc_mir/dataflow/move_paths}/abs_domain.rs (100%) rename src/{librustc_borrowck/borrowck/mir/gather_moves.rs => librustc_mir/dataflow/move_paths/mod.rs} (98%) rename src/{librustc_borrowck/borrowck/mir => librustc_mir/transform}/elaborate_drops.rs (94%) rename src/{librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs => librustc_mir/transform/rustc_peek.rs} (73%) diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index c72bdd04011..3be7c43cab9 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -18,8 +18,6 @@ pub use self::bckerr_code::*; pub use self::AliasableViolationKind::*; pub use self::MovedValueUseKind::*; -pub use self::mir::elaborate_drops::ElaborateDrops; - use self::InteriorKind::*; use rustc::hir::map as hir_map; @@ -55,8 +53,6 @@ pub mod gather_loans; pub mod move_data; -mod mir; - #[derive(Clone, Copy)] pub struct LoanDataFlowOperator; @@ -100,26 +96,21 @@ fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId) { } let body_id = tcx.hir.body_owned_by(owner_id); - let attributes = tcx.get_attrs(owner_def_id); let tables = tcx.typeck_tables_of(owner_def_id); let region_maps = tcx.region_maps(owner_def_id); let mut bccx = &mut BorrowckCtxt { tcx, tables, region_maps, owner_def_id }; let body = bccx.tcx.hir.body(body_id); - if bccx.tcx.has_attr(owner_def_id, "rustc_mir_borrowck") { - mir::borrowck_mir(bccx, owner_id, &attributes); - } else { - // Eventually, borrowck will always read the MIR, but at the - // moment we do not. So, for now, we always force MIR to be - // constructed for a given fn, since this may result in errors - // being reported and we want that to happen. - // - // Note that `mir_validated` is a "stealable" result; the - // thief, `optimized_mir()`, forces borrowck, so we know that - // is not yet stolen. - tcx.mir_validated(owner_def_id).borrow(); - } + // Eventually, borrowck will always read the MIR, but at the + // moment we do not. So, for now, we always force MIR to be + // constructed for a given fn, since this may result in errors + // being reported and we want that to happen. + // + // Note that `mir_validated` is a "stealable" result; the + // thief, `optimized_mir()`, forces borrowck, so we know that + // is not yet stolen. + tcx.mir_validated(owner_def_id).borrow(); let cfg = cfg::CFG::new(bccx.tcx, &body); let AnalysisData { all_loans, diff --git a/src/librustc_borrowck/lib.rs b/src/librustc_borrowck/lib.rs index 9c980ddf08a..a2b1e3c2663 100644 --- a/src/librustc_borrowck/lib.rs +++ b/src/librustc_borrowck/lib.rs @@ -21,7 +21,6 @@ #![feature(quote)] #![feature(rustc_diagnostic_macros)] #![feature(associated_consts)] -#![feature(nonzero)] #[macro_use] extern crate log; #[macro_use] extern crate syntax; @@ -39,7 +38,7 @@ extern crate core; // for NonZero pub use borrowck::check_crate; pub use borrowck::build_borrowck_dataflow_data_for_fn; -pub use borrowck::{AnalysisData, BorrowckCtxt, ElaborateDrops}; +pub use borrowck::{AnalysisData, BorrowckCtxt}; // NB: This module needs to be declared first so diagnostics are // registered before they are used. diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 159fee6aa4c..98278949d51 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -920,6 +920,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, // What we need to do constant evaluation. passes.push_pass(MIR_CONST, mir::transform::simplify::SimplifyCfg::new("initial")); passes.push_pass(MIR_CONST, mir::transform::type_check::TypeckMir); + passes.push_pass(MIR_CONST, mir::transform::rustc_peek::SanityCheck); // What we need to run borrowck etc. passes.push_pass(MIR_VALIDATED, mir::transform::qualify_consts::QualifyAndPromoteConstants); @@ -934,7 +935,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, // From here on out, regions are gone. passes.push_pass(MIR_OPTIMIZED, mir::transform::erase_regions::EraseRegions); passes.push_pass(MIR_OPTIMIZED, mir::transform::add_call_guards::AddCallGuards); - passes.push_pass(MIR_OPTIMIZED, borrowck::ElaborateDrops); + passes.push_pass(MIR_OPTIMIZED, mir::transform::elaborate_drops::ElaborateDrops); passes.push_pass(MIR_OPTIMIZED, mir::transform::no_landing_pads::NoLandingPads); passes.push_pass(MIR_OPTIMIZED, mir::transform::simplify::SimplifyCfg::new("elaborate-drops")); diff --git a/src/librustc_borrowck/borrowck/mir/mod.rs b/src/librustc_mir/dataflow/drop_flag_effects.rs similarity index 67% rename from src/librustc_borrowck/borrowck/mir/mod.rs rename to src/librustc_mir/dataflow/drop_flag_effects.rs index e3b99b9d4bd..daafbecc5df 100644 --- a/src/librustc_borrowck/borrowck/mir/mod.rs +++ b/src/librustc_mir/dataflow/drop_flag_effects.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2017 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,33 +8,24 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use borrowck::BorrowckCtxt; - use syntax::ast::{self, MetaItem}; use syntax_pos::DUMMY_SP; -use rustc::mir::{self, BasicBlock, BasicBlockData, Mir, Statement, Terminator, Location}; + +use rustc::mir::{self, Mir, BasicBlock, Location}; use rustc::session::Session; use rustc::ty::{self, TyCtxt}; -use rustc_mir::util::elaborate_drops::DropFlagState; -use rustc_data_structures::indexed_set::{IdxSet, IdxSetBuf}; - -mod abs_domain; -pub mod elaborate_drops; -mod dataflow; -mod gather_moves; -// mod graphviz; - -use self::dataflow::{BitDenotation}; -use self::dataflow::{DataflowOperator}; -use self::dataflow::{Dataflow, DataflowAnalysis, DataflowResults}; -use self::dataflow::{MaybeInitializedLvals, MaybeUninitializedLvals}; -use self::dataflow::{DefinitelyInitializedLvals}; -use self::gather_moves::{HasMoveData, MoveData, MovePathIndex, LookupResult}; +use util::elaborate_drops::DropFlagState; +use rustc_data_structures::indexed_set::{IdxSet}; use std::fmt; -fn has_rustc_mir_with(attrs: &[ast::Attribute], name: &str) -> Option { +use super::{Dataflow, DataflowBuilder, DataflowAnalysis}; +use super::{BitDenotation, DataflowOperator, DataflowResults}; +use super::indexes::MovePathIndex; +use super::move_paths::{MoveData, LookupResult}; + +pub(crate) fn has_rustc_mir_with(attrs: &[ast::Attribute], name: &str) -> Option { for attr in attrs { if attr.check_name("rustc_mir") { let items = attr.meta_item_list(); @@ -50,69 +41,11 @@ fn has_rustc_mir_with(attrs: &[ast::Attribute], name: &str) -> Option } pub struct MoveDataParamEnv<'tcx> { - move_data: MoveData<'tcx>, - param_env: ty::ParamEnv<'tcx>, + pub(crate) move_data: MoveData<'tcx>, + pub(crate) param_env: ty::ParamEnv<'tcx>, } -pub fn borrowck_mir(bcx: &mut BorrowckCtxt, - id: ast::NodeId, - attributes: &[ast::Attribute]) { - let tcx = bcx.tcx; - let def_id = tcx.hir.local_def_id(id); - debug!("borrowck_mir({:?}) UNIMPLEMENTED", def_id); - - // It is safe for us to borrow `mir_validated()`: `optimized_mir` - // steals it, but it forces the `borrowck` query. - let mir = &tcx.mir_validated(def_id).borrow(); - - let param_env = tcx.param_env(def_id); - let move_data = MoveData::gather_moves(mir, tcx, param_env); - let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env }; - let dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len()); - let flow_inits = - do_dataflow(tcx, mir, id, attributes, &dead_unwinds, - MaybeInitializedLvals::new(tcx, mir, &mdpe), - |bd, i| &bd.move_data().move_paths[i]); - let flow_uninits = - do_dataflow(tcx, mir, id, attributes, &dead_unwinds, - MaybeUninitializedLvals::new(tcx, mir, &mdpe), - |bd, i| &bd.move_data().move_paths[i]); - let flow_def_inits = - do_dataflow(tcx, mir, id, attributes, &dead_unwinds, - DefinitelyInitializedLvals::new(tcx, mir, &mdpe), - |bd, i| &bd.move_data().move_paths[i]); - - if has_rustc_mir_with(attributes, "rustc_peek_maybe_init").is_some() { - dataflow::sanity_check_via_rustc_peek(bcx.tcx, mir, id, attributes, &flow_inits); - } - if has_rustc_mir_with(attributes, "rustc_peek_maybe_uninit").is_some() { - dataflow::sanity_check_via_rustc_peek(bcx.tcx, mir, id, attributes, &flow_uninits); - } - if has_rustc_mir_with(attributes, "rustc_peek_definite_init").is_some() { - dataflow::sanity_check_via_rustc_peek(bcx.tcx, mir, id, attributes, &flow_def_inits); - } - - if has_rustc_mir_with(attributes, "stop_after_dataflow").is_some() { - bcx.tcx.sess.fatal("stop_after_dataflow ended compilation"); - } - - let mut mbcx = MirBorrowckCtxt { - bcx: bcx, - mir: mir, - node_id: id, - move_data: &mdpe.move_data, - flow_inits: flow_inits, - flow_uninits: flow_uninits, - }; - - for bb in mir.basic_blocks().indices() { - mbcx.process_basic_block(bb); - } - - debug!("borrowck_mir done"); -} - -fn do_dataflow<'a, 'tcx, BD, P>(tcx: TyCtxt<'a, 'tcx, 'tcx>, +pub(crate) fn do_dataflow<'a, 'tcx, BD, P>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &Mir<'tcx>, node_id: ast::NodeId, attributes: &[ast::Attribute], @@ -142,7 +75,7 @@ fn do_dataflow<'a, 'tcx, BD, P>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let print_postflow_to = name_found(tcx.sess, attributes, "borrowck_graphviz_postflow"); - let mut mbcx = MirBorrowckCtxtPreDataflow { + let mut mbcx = DataflowBuilder { node_id: node_id, print_preflow_to: print_preflow_to, print_postflow_to: print_postflow_to, @@ -153,46 +86,7 @@ fn do_dataflow<'a, 'tcx, BD, P>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mbcx.flow_state.results() } - -pub struct MirBorrowckCtxtPreDataflow<'a, 'tcx: 'a, BD> where BD: BitDenotation -{ - node_id: ast::NodeId, - flow_state: DataflowAnalysis<'a, 'tcx, BD>, - print_preflow_to: Option, - print_postflow_to: Option, -} - -#[allow(dead_code)] -pub struct MirBorrowckCtxt<'b, 'a: 'b, 'tcx: 'a> { - bcx: &'b mut BorrowckCtxt<'a, 'tcx>, - mir: &'b Mir<'tcx>, - node_id: ast::NodeId, - move_data: &'b MoveData<'tcx>, - flow_inits: DataflowResults>, - flow_uninits: DataflowResults> -} - -impl<'b, 'a: 'b, 'tcx: 'a> MirBorrowckCtxt<'b, 'a, 'tcx> { - fn process_basic_block(&mut self, bb: BasicBlock) { - let BasicBlockData { ref statements, ref terminator, is_cleanup: _ } = - self.mir[bb]; - for stmt in statements { - self.process_statement(bb, stmt); - } - - self.process_terminator(bb, terminator); - } - - fn process_statement(&mut self, bb: BasicBlock, stmt: &Statement<'tcx>) { - debug!("MirBorrowckCtxt::process_statement({:?}, {:?}", bb, stmt); - } - - fn process_terminator(&mut self, bb: BasicBlock, term: &Option>) { - debug!("MirBorrowckCtxt::process_terminator({:?}, {:?})", bb, term); - } -} - -fn move_path_children_matching<'tcx, F>(move_data: &MoveData<'tcx>, +pub fn move_path_children_matching<'tcx, F>(move_data: &MoveData<'tcx>, path: MovePathIndex, mut cond: F) -> Option @@ -253,7 +147,7 @@ fn lvalue_contents_drop_state_cannot_differ<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx } } -fn on_lookup_result_bits<'a, 'tcx, F>( +pub(crate) fn on_lookup_result_bits<'a, 'tcx, F>( tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &Mir<'tcx>, move_data: &MoveData<'tcx>, @@ -271,7 +165,7 @@ fn on_lookup_result_bits<'a, 'tcx, F>( } } -fn on_all_children_bits<'a, 'tcx, F>( +pub(crate) fn on_all_children_bits<'a, 'tcx, F>( tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &Mir<'tcx>, move_data: &MoveData<'tcx>, @@ -312,7 +206,7 @@ fn on_all_children_bits<'a, 'tcx, F>( on_all_children_bits(tcx, mir, move_data, move_path_index, &mut each_child); } -fn on_all_drop_children_bits<'a, 'tcx, F>( +pub(crate) fn on_all_drop_children_bits<'a, 'tcx, F>( tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &Mir<'tcx>, ctxt: &MoveDataParamEnv<'tcx>, @@ -333,7 +227,7 @@ fn on_all_drop_children_bits<'a, 'tcx, F>( }) } -fn drop_flag_effects_for_function_entry<'a, 'tcx, F>( +pub(crate) fn drop_flag_effects_for_function_entry<'a, 'tcx, F>( tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &Mir<'tcx>, ctxt: &MoveDataParamEnv<'tcx>, @@ -350,7 +244,7 @@ fn drop_flag_effects_for_function_entry<'a, 'tcx, F>( } } -fn drop_flag_effects_for_location<'a, 'tcx, F>( +pub(crate) fn drop_flag_effects_for_location<'a, 'tcx, F>( tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &Mir<'tcx>, ctxt: &MoveDataParamEnv<'tcx>, diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs b/src/librustc_mir/dataflow/graphviz.rs similarity index 97% rename from src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs rename to src/librustc_mir/dataflow/graphviz.rs index 7f95f07f48d..e6d77aa2686 100644 --- a/src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs +++ b/src/librustc_mir/dataflow/graphviz.rs @@ -15,7 +15,6 @@ use rustc::mir::{BasicBlock, Mir}; use rustc_data_structures::bitslice::bits_to_string; use rustc_data_structures::indexed_set::{IdxSet}; use rustc_data_structures::indexed_vec::Idx; -use rustc_mir::util as mir_util; use dot; use dot::IntoCow; @@ -28,8 +27,10 @@ use std::marker::PhantomData; use std::mem; use std::path::Path; -use super::super::MirBorrowckCtxtPreDataflow; +use util; + use super::{BitDenotation, DataflowState}; +use super::DataflowBuilder; impl DataflowState { fn each_bit(&self, words: &IdxSet, mut f: F) @@ -86,7 +87,7 @@ pub trait MirWithFlowState<'tcx> { fn flow_state(&self) -> &DataflowState; } -impl<'a, 'tcx: 'a, BD> MirWithFlowState<'tcx> for MirBorrowckCtxtPreDataflow<'a, 'tcx, BD> +impl<'a, 'tcx: 'a, BD> MirWithFlowState<'tcx> for DataflowBuilder<'a, 'tcx, BD> where 'tcx: 'a, BD: BitDenotation { type BD = BD; @@ -103,8 +104,8 @@ struct Graph<'a, 'tcx, MWF:'a, P> where render_idx: P, } -pub fn print_borrowck_graph_to<'a, 'tcx, BD, P>( - mbcx: &MirBorrowckCtxtPreDataflow<'a, 'tcx, BD>, +pub(crate) fn print_borrowck_graph_to<'a, 'tcx, BD, P>( + mbcx: &DataflowBuilder<'a, 'tcx, BD>, path: &Path, render_idx: P) -> io::Result<()> @@ -220,7 +221,7 @@ impl<'a, 'tcx, MWF, P> dot::Labeller<'a> for Graph<'a, 'tcx, MWF, P> } Ok(()) } - mir_util::write_graphviz_node_label( + util::write_graphviz_node_label( *n, self.mbcx.mir(), &mut v, 4, |w| { let flow = self.mbcx.flow_state(); diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs b/src/librustc_mir/dataflow/impls/mod.rs similarity index 96% rename from src/librustc_borrowck/borrowck/mir/dataflow/impls.rs rename to src/librustc_mir/dataflow/impls/mod.rs index 1a1ac7f9c74..97c996dea68 100644 --- a/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs +++ b/src/librustc_mir/dataflow/impls/mod.rs @@ -8,25 +8,26 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +//! Dataflow analyses are built upon some interpretation of the +//! bitvectors attached to each basic block, represented via a +//! zero-sized structure. + use rustc::ty::TyCtxt; use rustc::mir::{self, Mir, Location}; use rustc_data_structures::bitslice::BitSlice; // adds set_bit/get_bit to &[usize] bitvector rep. use rustc_data_structures::bitslice::{BitwiseOperator}; use rustc_data_structures::indexed_set::{IdxSet}; use rustc_data_structures::indexed_vec::Idx; -use rustc_mir::util::elaborate_drops::DropFlagState; -use super::super::gather_moves::{HasMoveData, MoveData, MoveOutIndex, MovePathIndex}; -use super::super::MoveDataParamEnv; -use super::super::drop_flag_effects_for_function_entry; -use super::super::drop_flag_effects_for_location; -use super::super::on_lookup_result_bits; +use super::MoveDataParamEnv; +use util::elaborate_drops::DropFlagState; +use super::move_paths::{HasMoveData, MoveData, MoveOutIndex, MovePathIndex}; use super::{BitDenotation, BlockSets, DataflowOperator}; -// Dataflow analyses are built upon some interpretation of the -// bitvectors attached to each basic block, represented via a -// zero-sized structure. +use super::drop_flag_effects_for_function_entry; +use super::drop_flag_effects_for_location; +use super::on_lookup_result_bits; /// `MaybeInitializedLvals` tracks all l-values that might be /// initialized upon reaching a particular point in the control flow @@ -219,6 +220,16 @@ pub struct MovingOutStatements<'a, 'tcx: 'a> { mdpe: &'a MoveDataParamEnv<'tcx>, } +impl<'a, 'tcx: 'a> MovingOutStatements<'a, 'tcx> { + pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, + mir: &'a Mir<'tcx>, + mdpe: &'a MoveDataParamEnv<'tcx>) + -> Self + { + MovingOutStatements { tcx: tcx, mir: mir, mdpe: mdpe } + } +} + impl<'a, 'tcx> HasMoveData<'tcx> for MovingOutStatements<'a, 'tcx> { fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data } } diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs similarity index 95% rename from src/librustc_borrowck/borrowck/mir/dataflow/mod.rs rename to src/librustc_mir/dataflow/mod.rs index f0f082a2561..d7ad9f9c09a 100644 --- a/src/librustc_borrowck/borrowck/mir/dataflow/mod.rs +++ b/src/librustc_mir/dataflow/mod.rs @@ -8,11 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use syntax::ast; + use rustc_data_structures::indexed_set::{IdxSet, IdxSetBuf}; use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::bitslice::{bitwise, BitwiseOperator}; -use rustc::ty::TyCtxt; +use rustc::ty::{TyCtxt}; use rustc::mir::{self, Mir}; use std::fmt::Debug; @@ -21,21 +23,31 @@ use std::mem; use std::path::PathBuf; use std::usize; -use super::MirBorrowckCtxtPreDataflow; - -pub use self::sanity_check::sanity_check_via_rustc_peek; pub use self::impls::{MaybeInitializedLvals, MaybeUninitializedLvals}; pub use self::impls::{DefinitelyInitializedLvals, MovingOutStatements}; +pub(crate) use self::drop_flag_effects::*; + +mod drop_flag_effects; mod graphviz; -mod sanity_check; mod impls; +pub mod move_paths; + +pub(crate) use self::move_paths::indexes; + +pub(crate) struct DataflowBuilder<'a, 'tcx: 'a, BD> where BD: BitDenotation +{ + node_id: ast::NodeId, + flow_state: DataflowAnalysis<'a, 'tcx, BD>, + print_preflow_to: Option, + print_postflow_to: Option, +} pub trait Dataflow { fn dataflow

(&mut self, p: P) where P: Fn(&BD, BD::Idx) -> &Debug; } -impl<'a, 'tcx: 'a, BD> Dataflow for MirBorrowckCtxtPreDataflow<'a, 'tcx, BD> +impl<'a, 'tcx: 'a, BD> Dataflow for DataflowBuilder<'a, 'tcx, BD> where BD: BitDenotation + DataflowOperator { fn dataflow

(&mut self, p: P) where P: Fn(&BD, BD::Idx) -> &Debug { @@ -135,7 +147,7 @@ fn dataflow_path(context: &str, prepost: &str, path: &str) -> PathBuf { path } -impl<'a, 'tcx: 'a, BD> MirBorrowckCtxtPreDataflow<'a, 'tcx, BD> +impl<'a, 'tcx: 'a, BD> DataflowBuilder<'a, 'tcx, BD> where BD: BitDenotation { fn pre_dataflow_instrumentation

(&self, p: P) -> io::Result<()> @@ -195,7 +207,7 @@ impl<'a, 'tcx: 'a, O> DataflowAnalysis<'a, 'tcx, O> pub fn mir(&self) -> &'a Mir<'tcx> { self.mir } } -pub struct DataflowResults(DataflowState) where O: BitDenotation; +pub struct DataflowResults(pub(crate) DataflowState) where O: BitDenotation; impl DataflowResults { pub fn sets(&self) -> &AllSets { @@ -213,7 +225,7 @@ pub struct DataflowState pub sets: AllSets, /// operator used to initialize, combine, and interpret bits. - operator: O, + pub(crate) operator: O, } #[derive(Debug)] @@ -240,9 +252,9 @@ pub struct AllSets { } pub struct BlockSets<'a, E: Idx> { - on_entry: &'a mut IdxSet, - gen_set: &'a mut IdxSet, - kill_set: &'a mut IdxSet, + pub(crate) on_entry: &'a mut IdxSet, + pub(crate) gen_set: &'a mut IdxSet, + pub(crate) kill_set: &'a mut IdxSet, } impl<'a, E:Idx> BlockSets<'a, E> { diff --git a/src/librustc_borrowck/borrowck/mir/abs_domain.rs b/src/librustc_mir/dataflow/move_paths/abs_domain.rs similarity index 100% rename from src/librustc_borrowck/borrowck/mir/abs_domain.rs rename to src/librustc_mir/dataflow/move_paths/abs_domain.rs diff --git a/src/librustc_borrowck/borrowck/mir/gather_moves.rs b/src/librustc_mir/dataflow/move_paths/mod.rs similarity index 98% rename from src/librustc_borrowck/borrowck/mir/gather_moves.rs rename to src/librustc_mir/dataflow/move_paths/mod.rs index a0ecdcc8e2f..d7ed0938e88 100644 --- a/src/librustc_borrowck/borrowck/mir/gather_moves.rs +++ b/src/librustc_mir/dataflow/move_paths/mod.rs @@ -21,14 +21,16 @@ use std::fmt; use std::mem; use std::ops::{Index, IndexMut}; -use super::abs_domain::{AbstractElem, Lift}; +use self::abs_domain::{AbstractElem, Lift}; + +mod abs_domain; // This submodule holds some newtype'd Index wrappers that are using // NonZero to ensure that Option occupies only a single word. // They are in a submodule to impose privacy restrictions; namely, to // ensure that other code does not accidentally access `index.0` // (which is likely to yield a subtle off-by-one error). -mod indexes { +pub(crate) mod indexes { use std::fmt; use core::nonzero::NonZero; use rustc_data_structures::indexed_vec::Idx; @@ -65,7 +67,7 @@ mod indexes { pub use self::indexes::MovePathIndex; pub use self::indexes::MoveOutIndex; -impl self::indexes::MoveOutIndex { +impl MoveOutIndex { pub fn move_path_index(&self, move_data: &MoveData) -> MovePathIndex { move_data.moves[*self].path } @@ -128,7 +130,7 @@ pub trait HasMoveData<'tcx> { pub struct LocationMap { /// Location-indexed (BasicBlock for outer index, index within BB /// for inner index) map. - map: IndexVec>, + pub(crate) map: IndexVec>, } impl Index for LocationMap { @@ -188,7 +190,7 @@ pub struct MovePathLookup<'tcx> { projections: FxHashMap<(MovePathIndex, AbstractElem<'tcx>), MovePathIndex> } -struct MoveDataBuilder<'a, 'tcx: 'a> { +pub(super) struct MoveDataBuilder<'a, 'tcx: 'a> { mir: &'a Mir<'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>, param_env: ty::ParamEnv<'tcx>, diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index bfa31c052e4..71855d3805e 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -26,6 +26,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment! #![feature(rustc_diagnostic_macros)] #![feature(placement_in_syntax)] #![feature(collection_placement)] +#![feature(nonzero)] #[macro_use] extern crate log; extern crate graphviz as dot; @@ -40,10 +41,12 @@ extern crate syntax; extern crate syntax_pos; extern crate rustc_const_math; extern crate rustc_const_eval; +extern crate core; // for NonZero pub mod diagnostics; mod build; +pub mod dataflow; mod hair; mod shim; pub mod transform; diff --git a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs similarity index 94% rename from src/librustc_borrowck/borrowck/mir/elaborate_drops.rs rename to src/librustc_mir/transform/elaborate_drops.rs index 83369772608..b158cb43ce7 100644 --- a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs +++ b/src/librustc_mir/transform/elaborate_drops.rs @@ -8,12 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use super::gather_moves::{HasMoveData, MoveData, MovePathIndex, LookupResult}; -use super::dataflow::{MaybeInitializedLvals, MaybeUninitializedLvals}; -use super::dataflow::{DataflowResults}; -use super::{on_all_children_bits, on_all_drop_children_bits}; -use super::{drop_flag_effects_for_location, on_lookup_result_bits}; -use super::MoveDataParamEnv; +use dataflow::move_paths::{HasMoveData, MoveData, MovePathIndex, LookupResult}; +use dataflow::{MaybeInitializedLvals, MaybeUninitializedLvals}; +use dataflow::{DataflowResults}; +use dataflow::{on_all_children_bits, on_all_drop_children_bits}; +use dataflow::{drop_flag_effects_for_location, on_lookup_result_bits}; +use dataflow::MoveDataParamEnv; +use dataflow; use rustc::ty::{self, TyCtxt}; use rustc::mir::*; use rustc::mir::transform::{MirPass, MirSource}; @@ -21,9 +22,9 @@ use rustc::middle::const_val::ConstVal; use rustc::util::nodemap::FxHashMap; use rustc_data_structures::indexed_set::IdxSetBuf; use rustc_data_structures::indexed_vec::Idx; -use rustc_mir::util::patch::MirPatch; -use rustc_mir::util::elaborate_drops::{DropFlagState, Unwind, elaborate_drop}; -use rustc_mir::util::elaborate_drops::{DropElaborator, DropStyle, DropFlagMode}; +use util::patch::MirPatch; +use util::elaborate_drops::{DropFlagState, Unwind, elaborate_drop}; +use util::elaborate_drops::{DropElaborator, DropStyle, DropFlagMode}; use syntax::ast; use syntax_pos::Span; @@ -54,13 +55,13 @@ impl MirPass for ElaborateDrops { }; let dead_unwinds = find_dead_unwinds(tcx, mir, id, &env); let flow_inits = - super::do_dataflow(tcx, mir, id, &[], &dead_unwinds, - MaybeInitializedLvals::new(tcx, mir, &env), - |bd, p| &bd.move_data().move_paths[p]); + dataflow::do_dataflow(tcx, mir, id, &[], &dead_unwinds, + MaybeInitializedLvals::new(tcx, mir, &env), + |bd, p| &bd.move_data().move_paths[p]); let flow_uninits = - super::do_dataflow(tcx, mir, id, &[], &dead_unwinds, - MaybeUninitializedLvals::new(tcx, mir, &env), - |bd, p| &bd.move_data().move_paths[p]); + dataflow::do_dataflow(tcx, mir, id, &[], &dead_unwinds, + MaybeUninitializedLvals::new(tcx, mir, &env), + |bd, p| &bd.move_data().move_paths[p]); ElaborateDropsCtxt { tcx: tcx, @@ -91,7 +92,7 @@ fn find_dead_unwinds<'a, 'tcx>( // reach cleanup blocks, which can't have unwind edges themselves. let mut dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len()); let flow_inits = - super::do_dataflow(tcx, mir, id, &[], &dead_unwinds, + dataflow::do_dataflow(tcx, mir, id, &[], &dead_unwinds, MaybeInitializedLvals::new(tcx, mir, &env), |bd, p| &bd.move_data().move_paths[p]); for (bb, bb_data) in mir.basic_blocks().iter_enumerated() { @@ -242,7 +243,7 @@ impl<'a, 'b, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, 'b, 'tcx> { } fn field_subpath(&self, path: Self::Path, field: Field) -> Option { - super::move_path_children_matching(self.ctxt.move_data(), path, |p| { + dataflow::move_path_children_matching(self.ctxt.move_data(), path, |p| { match p { &Projection { elem: ProjectionElem::Field(idx, _), .. @@ -253,7 +254,7 @@ impl<'a, 'b, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, 'b, 'tcx> { } fn deref_subpath(&self, path: Self::Path) -> Option { - super::move_path_children_matching(self.ctxt.move_data(), path, |p| { + dataflow::move_path_children_matching(self.ctxt.move_data(), path, |p| { match p { &Projection { elem: ProjectionElem::Deref, .. } => true, _ => false @@ -262,7 +263,7 @@ impl<'a, 'b, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, 'b, 'tcx> { } fn downcast_subpath(&self, path: Self::Path, variant: usize) -> Option { - super::move_path_children_matching(self.ctxt.move_data(), path, |p| { + dataflow::move_path_children_matching(self.ctxt.move_data(), path, |p| { match p { &Projection { elem: ProjectionElem::Downcast(_, idx), .. @@ -560,7 +561,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { fn drop_flags_for_args(&mut self) { let loc = Location { block: START_BLOCK, statement_index: 0 }; - super::drop_flag_effects_for_function_entry( + dataflow::drop_flag_effects_for_function_entry( self.tcx, self.mir, self.env, |path, ds| { self.set_drop_flag(loc, path, ds); } @@ -605,7 +606,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { } } let loc = Location { block: bb, statement_index: i }; - super::drop_flag_effects_for_location( + dataflow::drop_flag_effects_for_location( self.tcx, self.mir, self.env, loc, |path, ds| { if ds == DropFlagState::Absent || allow_initializations { self.set_drop_flag(loc, path, ds) diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index 4594c611d59..1530ea8e0df 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -30,6 +30,8 @@ pub mod simplify; pub mod erase_regions; pub mod no_landing_pads; pub mod type_check; +pub mod rustc_peek; +pub mod elaborate_drops; pub mod add_call_guards; pub mod promote_consts; pub mod qualify_consts; diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs b/src/librustc_mir/transform/rustc_peek.rs similarity index 73% rename from src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs rename to src/librustc_mir/transform/rustc_peek.rs index 4bef191b113..5918de0c688 100644 --- a/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs +++ b/src/librustc_mir/transform/rustc_peek.rs @@ -14,12 +14,67 @@ use syntax_pos::Span; use rustc::ty::{self, TyCtxt}; use rustc::mir::{self, Mir}; +use rustc::mir::transform::{MirPass, MirSource}; +use rustc_data_structures::indexed_set::IdxSetBuf; use rustc_data_structures::indexed_vec::Idx; -use super::super::gather_moves::{MovePathIndex, LookupResult}; -use super::BitDenotation; -use super::DataflowResults; -use super::super::gather_moves::HasMoveData; +use dataflow::do_dataflow; +use dataflow::MoveDataParamEnv; +use dataflow::BitDenotation; +use dataflow::DataflowResults; +use dataflow::{DefinitelyInitializedLvals, MaybeInitializedLvals, MaybeUninitializedLvals}; +use dataflow::move_paths::{MovePathIndex, LookupResult}; +use dataflow::move_paths::{HasMoveData, MoveData}; +use dataflow; + +use dataflow::has_rustc_mir_with; + +pub struct SanityCheck; + +impl MirPass for SanityCheck { + fn run_pass<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, + src: MirSource, mir: &mut Mir<'tcx>) { + let id = src.item_id(); + let def_id = tcx.hir.local_def_id(id); + if !tcx.has_attr(def_id, "rustc_mir_borrowck") { + debug!("skipping rustc_peek::SanityCheck on {}", tcx.item_path_str(def_id)); + return; + } else { + debug!("running rustc_peek::SanityCheck on {}", tcx.item_path_str(def_id)); + } + + let attributes = tcx.get_attrs(def_id); + let param_env = tcx.param_env(def_id); + let move_data = MoveData::gather_moves(mir, tcx, param_env); + let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env }; + let dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len()); + let flow_inits = + do_dataflow(tcx, mir, id, &attributes, &dead_unwinds, + MaybeInitializedLvals::new(tcx, mir, &mdpe), + |bd, i| &bd.move_data().move_paths[i]); + let flow_uninits = + do_dataflow(tcx, mir, id, &attributes, &dead_unwinds, + MaybeUninitializedLvals::new(tcx, mir, &mdpe), + |bd, i| &bd.move_data().move_paths[i]); + let flow_def_inits = + do_dataflow(tcx, mir, id, &attributes, &dead_unwinds, + DefinitelyInitializedLvals::new(tcx, mir, &mdpe), + |bd, i| &bd.move_data().move_paths[i]); + + if has_rustc_mir_with(&attributes, "rustc_peek_maybe_init").is_some() { + sanity_check_via_rustc_peek(tcx, mir, id, &attributes, &flow_inits); + } + if has_rustc_mir_with(&attributes, "rustc_peek_maybe_uninit").is_some() { + sanity_check_via_rustc_peek(tcx, mir, id, &attributes, &flow_uninits); + } + if has_rustc_mir_with(&attributes, "rustc_peek_definite_init").is_some() { + sanity_check_via_rustc_peek(tcx, mir, id, &attributes, &flow_def_inits); + } + if has_rustc_mir_with(&attributes, "stop_after_dataflow").is_some() { + tcx.sess.fatal("stop_after_dataflow ended compilation"); + } + } +} /// This function scans `mir` for all calls to the intrinsic /// `rustc_peek` that have the expression form `rustc_peek(&expr)`. @@ -92,7 +147,7 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // of the argument at time immediate preceding Call to // `rustc_peek`). - let mut sets = super::BlockSets { on_entry: &mut entry, + let mut sets = dataflow::BlockSets { on_entry: &mut entry, gen_set: &mut gen, kill_set: &mut kill }; From 6db48380ce437bcb21da450db1696ede0fcba158 Mon Sep 17 00:00:00 2001 From: Venkata Giri Reddy Date: Tue, 13 Jun 2017 20:14:23 +0000 Subject: [PATCH 066/162] rustc_typeck: remove old-style WF obligation --- src/librustc_typeck/check/mod.rs | 34 -------------------------------- 1 file changed, 34 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 701de029b2b..c08eeb740ec 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -992,14 +992,6 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, // Add formal parameters. for (arg_ty, arg) in fn_sig.inputs().iter().zip(&body.arguments) { - // The type of the argument must be well-formed. - // - // NB -- this is now checked in wfcheck, but that - // currently only results in warnings, so we issue an - // old-style WF obligation here so that we still get the - // errors that we used to get. - fcx.register_old_wf_obligation(arg_ty, arg.pat.span, traits::MiscObligation); - // Check the pattern. fcx.check_pat_arg(&arg.pat, arg_ty, true); fcx.write_ty(arg.id, arg_ty); @@ -1977,17 +1969,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } - /// Registers an obligation for checking later, during regionck, that the type `ty` must - /// outlive the region `r`. - pub fn register_region_obligation(&self, - ty: Ty<'tcx>, - region: ty::Region<'tcx>, - cause: traits::ObligationCause<'tcx>) - { - let mut fulfillment_cx = self.fulfillment_cx.borrow_mut(); - fulfillment_cx.register_region_obligation(ty, region, cause); - } - /// Registers an obligation for checking later, during regionck, that the type `ty` must /// outlive the region `r`. pub fn register_wf_obligation(&self, @@ -2002,21 +1983,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ty::Predicate::WellFormed(ty))); } - pub fn register_old_wf_obligation(&self, - ty: Ty<'tcx>, - span: Span, - code: traits::ObligationCauseCode<'tcx>) - { - // Registers an "old-style" WF obligation that uses the - // implicator code. This is basically a buggy version of - // `register_wf_obligation` that is being kept around - // temporarily just to help with phasing in the newer rules. - // - // FIXME(#27579) all uses of this should be migrated to register_wf_obligation eventually - let cause = traits::ObligationCause::new(span, self.body_id, code); - self.register_region_obligation(ty, self.tcx.types.re_empty, cause); - } - /// Registers obligations that all types appearing in `substs` are well-formed. pub fn add_wf_bounds(&self, substs: &Substs<'tcx>, expr: &hir::Expr) { From 74cb315a109f9b7a4a73cc6bf3ac481e92ec926d Mon Sep 17 00:00:00 2001 From: Venkata Giri Reddy Date: Tue, 13 Jun 2017 20:22:28 +0000 Subject: [PATCH 067/162] rustc_typeck: enforce argument type is sized --- src/librustc_typeck/check/mod.rs | 9 ++++++++ src/test/compile-fail/issue-38954.rs | 6 ++---- src/test/compile-fail/issue-42312.rs | 21 +++++++++++++++++++ .../run-pass/associated-types-sugar-path.rs | 2 -- 4 files changed, 32 insertions(+), 6 deletions(-) create mode 100644 src/test/compile-fail/issue-42312.rs diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index c08eeb740ec..a0afd58e586 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -994,6 +994,15 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, for (arg_ty, arg) in fn_sig.inputs().iter().zip(&body.arguments) { // Check the pattern. fcx.check_pat_arg(&arg.pat, arg_ty, true); + + // Check that argument is Sized. + // The check for a non-trivial pattern is a hack to avoid duplicate warnings + // for simple cases like `fn foo(x: Trait)`, + // where we would error once on the parameter as a whole, and once on the binding `x`. + if arg.pat.simple_name().is_none() { + fcx.require_type_is_sized(arg_ty, decl.output.span(), traits::MiscObligation); + } + fcx.write_ty(arg.id, arg_ty); } diff --git a/src/test/compile-fail/issue-38954.rs b/src/test/compile-fail/issue-38954.rs index 65b17a3db0b..896728b6da0 100644 --- a/src/test/compile-fail/issue-38954.rs +++ b/src/test/compile-fail/issue-38954.rs @@ -8,9 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(rustc_attrs)] - fn _test(ref _p: str) {} +//~^ ERROR the trait bound `str: std::marker::Sized` is not satisfied [E0277] -#[rustc_error] -fn main() { } //~ ERROR compilation successful +fn main() { } diff --git a/src/test/compile-fail/issue-42312.rs b/src/test/compile-fail/issue-42312.rs new file mode 100644 index 00000000000..06573b42b59 --- /dev/null +++ b/src/test/compile-fail/issue-42312.rs @@ -0,0 +1,21 @@ +// Copyright 2017 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 std::ops::Deref; + +pub trait Foo { + fn baz(_: Self::Target) where Self: Deref {} + //~^ ERROR `::Target: std::marker::Sized` is not satisfied +} + +pub fn f(_: ToString) {} +//~^ ERROR the trait bound `std::string::ToString + 'static: std::marker::Sized` is not satisfied + +fn main() { } diff --git a/src/test/run-pass/associated-types-sugar-path.rs b/src/test/run-pass/associated-types-sugar-path.rs index 587fb3f80d6..d8d42f2cba2 100644 --- a/src/test/run-pass/associated-types-sugar-path.rs +++ b/src/test/run-pass/associated-types-sugar-path.rs @@ -15,8 +15,6 @@ use std::ops::Deref; pub trait Foo { type A; fn boo(&self) -> Self::A; - - fn baz(_: Self::Target) where Self: Deref {} } impl Foo for isize { From 40dec0984ed2040532ac763f104b3bbbc13f514a Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 28 Jun 2017 23:14:06 +0300 Subject: [PATCH 068/162] Document that `/` works as separator on Windows --- src/libstd/path.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 42a54ed6d75..472ce6bc4fe 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -276,7 +276,7 @@ impl<'a> Prefix<'a> { /// ``` /// use std::path; /// -/// assert!(path::is_separator('/')); +/// assert!(path::is_separator('/')); // '/' works for both Unix and Windows /// assert!(!path::is_separator('❤')); /// ``` #[stable(feature = "rust1", since = "1.0.0")] @@ -1499,9 +1499,9 @@ impl AsRef for PathBuf { /// A slice of a path (akin to [`str`]). /// /// This type supports a number of operations for inspecting a path, including -/// breaking the path into its components (separated by `/` or `\`, depending on -/// the platform), extracting the file name, determining whether the path is -/// absolute, and so on. +/// breaking the path into its components (separated by `/` on Unix and by either +/// `/` or `\` on Windows), extracting the file name, determining whether the path +/// is absolute, and so on. /// /// This is an *unsized* type, meaning that it must always be used behind a /// pointer like `&` or [`Box`]. For an owned version of this type, @@ -1520,10 +1520,11 @@ impl AsRef for PathBuf { /// use std::path::Path; /// use std::ffi::OsStr; /// -/// let path = Path::new("/tmp/foo/bar.txt"); +/// // Note: this example does work on Windows +/// let path = Path::new("./foo/bar.txt"); /// /// let parent = path.parent(); -/// assert_eq!(parent, Some(Path::new("/tmp/foo"))); +/// assert_eq!(parent, Some(Path::new("./foo"))); /// /// let file_stem = path.file_stem(); /// assert_eq!(file_stem, Some(OsStr::new("bar"))); From 5ed21f5d47c28e0e1541c037683becb90adabe65 Mon Sep 17 00:00:00 2001 From: Venkata Giri Reddy Date: Wed, 28 Jun 2017 16:26:36 +0000 Subject: [PATCH 069/162] rustc_typeck: use body-id of type-checking item in need_type_info --- .../infer/error_reporting/need_type_info.rs | 12 +++++------- src/librustc/traits/error_reporting.rs | 16 +++++++++------- src/librustc/traits/mod.rs | 2 +- src/librustc_mir/transform/qualify_consts.rs | 2 +- src/librustc_typeck/check/compare_method.rs | 4 ++-- src/librustc_typeck/check/dropck.rs | 2 +- src/librustc_typeck/check/mod.rs | 7 +++++-- src/librustc_typeck/check/writeback.rs | 2 +- src/librustc_typeck/coherence/builtin.rs | 2 +- src/librustc_typeck/lib.rs | 2 +- src/test/compile-fail/issue-23046.rs | 4 ++-- 11 files changed, 29 insertions(+), 26 deletions(-) diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs index 7361d66428f..a684881c091 100644 --- a/src/librustc/infer/error_reporting/need_type_info.rs +++ b/src/librustc/infer/error_reporting/need_type_info.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use hir::{self, map, Local, Pat, Body}; +use hir::{self, Local, Pat, Body}; use hir::intravisit::{self, Visitor, NestedVisitorMap}; use infer::InferCtxt; use infer::type_variable::TypeVariableOrigin; @@ -88,7 +88,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } } - pub fn need_type_info(&self, body_id: hir::BodyId, span: Span, ty: Ty<'tcx>) { + pub fn need_type_info(&self, body_id: Option, span: Span, ty: Ty<'tcx>) { let ty = self.resolve_type_vars_if_possible(&ty); let name = self.extract_type_name(&ty); @@ -103,11 +103,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { found_arg_pattern: None, }; - // #40294: cause.body_id can also be a fn declaration. - // Currently, if it's anything other than NodeExpr, we just ignore it - match self.tcx.hir.find(body_id.node_id) { - Some(map::NodeExpr(expr)) => local_visitor.visit_expr(expr), - _ => () + if let Some(body_id) = body_id { + let expr = self.tcx.hir.expect_expr(body_id.node_id); + local_visitor.visit_expr(expr); } if let Some(pattern) = local_visitor.found_arg_pattern { diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 247fb079fe7..64a6a0522cd 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -45,7 +45,8 @@ use syntax_pos::{DUMMY_SP, Span}; impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { pub fn report_fulfillment_errors(&self, - errors: &Vec>) { + errors: &Vec>, + body_id: Option) { #[derive(Debug)] struct ErrorDescriptor<'tcx> { predicate: ty::Predicate<'tcx>, @@ -105,7 +106,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { for (error, suppressed) in errors.iter().zip(is_suppressed) { if !suppressed { - self.report_fulfillment_error(error); + self.report_fulfillment_error(error, body_id); } } } @@ -148,7 +149,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { false } - fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>) { + fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>, + body_id: Option) { debug!("report_fulfillment_errors({:?})", error); match error.code { FulfillmentErrorCode::CodeSelectionError(ref e) => { @@ -158,7 +160,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { self.report_projection_error(&error.obligation, e); } FulfillmentErrorCode::CodeAmbiguity => { - self.maybe_report_ambiguity(&error.obligation); + self.maybe_report_ambiguity(&error.obligation, body_id); } FulfillmentErrorCode::CodeSubtypeError(ref expected_found, ref err) => { self.report_mismatched_types(&error.obligation.cause, @@ -869,14 +871,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { - fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>) { + fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>, + body_id: Option) { // Unable to successfully determine, probably means // insufficient type information, but could mean // ambiguous impls. The latter *ought* to be a // coherence violation, so we don't report it here. let predicate = self.resolve_type_vars_if_possible(&obligation.predicate); - let body_id = hir::BodyId { node_id: obligation.cause.body_id }; let span = obligation.cause.span; debug!("maybe_report_ambiguity(predicate={:?}, obligation={:?})", @@ -953,7 +955,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let &SubtypePredicate { a_is_expected: _, a, b } = data.skip_binder(); // both must be type variables, or the other would've been instantiated assert!(a.is_ty_var() && b.is_ty_var()); - self.need_type_info(hir::BodyId { node_id: obligation.cause.body_id }, + self.need_type_info(body_id, obligation.cause.span, a); } diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index e9196cd1243..056aad74600 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -498,7 +498,7 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ) { Ok(predicates) => predicates, Err(errors) => { - infcx.report_fulfillment_errors(&errors); + infcx.report_fulfillment_errors(&errors, None); // An unnormalized env is better than nothing. return elaborated_env; } diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 91d6ce60b39..68b687a2e61 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -996,7 +996,7 @@ impl MirPass for QualifyAndPromoteConstants { tcx.require_lang_item(lang_items::SyncTraitLangItem), cause); if let Err(err) = fulfillment_cx.select_all_or_error(&infcx) { - infcx.report_fulfillment_errors(&err); + infcx.report_fulfillment_errors(&err, None); } }); } diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index fd5147d76e8..bf134f9547d 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -328,7 +328,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Check that all obligations are satisfied by the implementation's // version. if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) { - infcx.report_fulfillment_errors(errors); + infcx.report_fulfillment_errors(errors, None); return Err(ErrorReported); } @@ -793,7 +793,7 @@ pub fn compare_const_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Check that all obligations are satisfied by the implementation's // version. if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) { - infcx.report_fulfillment_errors(errors); + infcx.report_fulfillment_errors(errors, None); return; } diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index 93057f91997..ed22cd1333e 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -110,7 +110,7 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>( if let Err(ref errors) = fulfillment_cx.select_all_or_error(&infcx) { // this could be reached when we get lazy normalization - infcx.report_fulfillment_errors(errors); + infcx.report_fulfillment_errors(errors, None); return Err(ErrorReported); } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index a0afd58e586..dadf00944c6 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -216,6 +216,8 @@ pub struct Inherited<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { /// environment is for an item or something where the "callee" is /// not clear. implicit_region_bound: Option>, + + body_id: Option, } impl<'a, 'gcx, 'tcx> Deref for Inherited<'a, 'gcx, 'tcx> { @@ -604,6 +606,7 @@ impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> { deferred_cast_checks: RefCell::new(Vec::new()), anon_types: RefCell::new(NodeMap()), implicit_region_bound, + body_id, } } @@ -2119,7 +2122,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { match fulfillment_cx.select_all_or_error(self) { Ok(()) => { } - Err(errors) => { self.report_fulfillment_errors(&errors); } + Err(errors) => { self.report_fulfillment_errors(&errors, self.inh.body_id); } } } @@ -2127,7 +2130,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn select_obligations_where_possible(&self) { match self.fulfillment_cx.borrow_mut().select_where_possible(self) { Ok(()) => { } - Err(errors) => { self.report_fulfillment_errors(&errors); } + Err(errors) => { self.report_fulfillment_errors(&errors, self.inh.body_id); } } } diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 4af262bcb78..81e5dae5477 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -377,7 +377,7 @@ impl<'cx, 'gcx, 'tcx> Resolver<'cx, 'gcx, 'tcx> { fn report_error(&self, t: Ty<'tcx>) { if !self.tcx.sess.has_errors() { - self.infcx.need_type_info(self.body.id(), self.span.to_span(&self.tcx), t); + self.infcx.need_type_info(Some(self.body.id()), self.span.to_span(&self.tcx), t); } } } diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs index ccbc0299041..9305eff1436 100644 --- a/src/librustc_typeck/coherence/builtin.rs +++ b/src/librustc_typeck/coherence/builtin.rs @@ -386,7 +386,7 @@ pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Check that all transitive obligations are satisfied. if let Err(errors) = fulfill_cx.select_all_or_error(&infcx) { - infcx.report_fulfillment_errors(&errors); + infcx.report_fulfillment_errors(&errors, None); } // Finally, resolve all regions. diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 519e1ca6e5a..2857b5fb5e0 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -166,7 +166,7 @@ fn require_same_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, match fulfill_cx.select_all_or_error(infcx) { Ok(()) => true, Err(errors) => { - infcx.report_fulfillment_errors(&errors); + infcx.report_fulfillment_errors(&errors, None); false } } diff --git a/src/test/compile-fail/issue-23046.rs b/src/test/compile-fail/issue-23046.rs index 28109747b75..129f7c8b1ea 100644 --- a/src/test/compile-fail/issue-23046.rs +++ b/src/test/compile-fail/issue-23046.rs @@ -24,7 +24,7 @@ pub fn let_<'var, VAR, F: for<'v: 'var> Fn(Expr<'v, VAR>) -> Expr<'v, VAR>> } fn main() { - let ex = |x| { - let_(add(x,x), |y| { //~ ERROR type annotations needed + let ex = |x| { //~ ERROR type annotations needed + let_(add(x,x), |y| { let_(add(x, x), |x|x)})}; } From a6ca302097ff30c0eb7746c5ef642fa4af4b6285 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Wed, 28 Jun 2017 23:50:24 +0300 Subject: [PATCH 070/162] add comments --- src/librustc_trans/collector.rs | 4 ++++ src/librustc_trans/trans_item.rs | 23 +++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index 3536dcf16e5..55a2c281403 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -304,7 +304,11 @@ fn collect_roots<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, scx.tcx().hir.krate().visit_all_item_likes(&mut visitor); } + // We can only translate items that are instantiable - items all of + // whose predicates hold. Luckily, items that aren't instantiable + // can't actually be used, so we can just skip translating them. roots.retain(|root| root.is_instantiable(scx.tcx())); + roots } diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs index 6e8b2e0a2a6..192e23a66a1 100644 --- a/src/librustc_trans/trans_item.rs +++ b/src/librustc_trans/trans_item.rs @@ -253,6 +253,29 @@ impl<'a, 'tcx> TransItem<'tcx> { /// Returns whether this instance is instantiable - whether it has no unsatisfied /// predicates. + /// + /// In order to translate an item, all of its predicates must hold, because + /// otherwise the item does not make sense. Type-checking ensures that + /// the predicates of every item that is *used by* a valid item *do* + /// hold, so we can rely on that. + /// + /// However, we translate collector roots (reachable items) and functions + /// in vtables when they are seen, even if they are not used, and so they + /// might not be instantiable. For example, a programmer can define this + /// public function: + /// + /// pub fn foo<'a>(s: &'a mut ()) where &'a mut (): Clone { + /// <&mut () as Clone>::clone(&s); + /// } + /// + /// That function can't be translated, because the method `<&mut () as Clone>::clone` + /// does not exist. Luckily for us, that function can't ever be used, + /// because that would require for `&'a mut (): Clone` to hold, so we + /// can just not emit any code, or even a linker reference for it. + /// + /// Similarly, if a vtable method has such a signature, and therefore can't + /// be used, we can just not emit it and have a placeholder (a null pointer, + /// which will never be accessed) in its place. pub fn is_instantiable(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> bool { debug!("is_instantiable({:?})", self); let (def_id, substs) = match *self { From b689e46c628ea8f71f45709c969b19c220baa49c Mon Sep 17 00:00:00 2001 From: Aidan Hobson Sayers Date: Wed, 28 Jun 2017 22:54:05 +0100 Subject: [PATCH 071/162] Stamp the whole build script --- .travis.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index b95196da356..96163c75c9d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -171,16 +171,16 @@ before_script: if [[ "$SKIP_BUILD" == true ]]; then export RUN_SCRIPT="echo 'skipping, not a full build'"; else - RUN_SCRIPT="stamp src/ci/init_repo.sh . $HOME/rustsrc"; + RUN_SCRIPT="src/ci/init_repo.sh . $HOME/rustsrc"; if [ "$TRAVIS_OS_NAME" = "osx" ]; then - export RUN_SCRIPT="$RUN_SCRIPT && stamp src/ci/run.sh"; + export RUN_SCRIPT="$RUN_SCRIPT && src/ci/run.sh"; else - export RUN_SCRIPT="$RUN_SCRIPT && stamp src/ci/docker/run.sh $IMAGE"; + export RUN_SCRIPT="$RUN_SCRIPT && src/ci/docker/run.sh $IMAGE"; fi fi script: - - sh -x -c "$RUN_SCRIPT" + - stamp sh -x -c "$RUN_SCRIPT" after_success: - > From 5ed38946beaaad4ece7ad43bc3d03db7e8972401 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 28 Jun 2017 11:09:00 -0700 Subject: [PATCH 072/162] Move type parameter shadowing test to `ui` --- .../shadowed-type-parameter.rs | 0 src/test/ui/shadowed-type-parameter.stderr | 28 +++++++++++++++++++ 2 files changed, 28 insertions(+) rename src/test/{compile-fail => ui}/shadowed-type-parameter.rs (100%) create mode 100644 src/test/ui/shadowed-type-parameter.stderr diff --git a/src/test/compile-fail/shadowed-type-parameter.rs b/src/test/ui/shadowed-type-parameter.rs similarity index 100% rename from src/test/compile-fail/shadowed-type-parameter.rs rename to src/test/ui/shadowed-type-parameter.rs diff --git a/src/test/ui/shadowed-type-parameter.stderr b/src/test/ui/shadowed-type-parameter.stderr new file mode 100644 index 00000000000..d77523299bc --- /dev/null +++ b/src/test/ui/shadowed-type-parameter.stderr @@ -0,0 +1,28 @@ +error[E0194]: type parameter `T` shadows another type parameter of the same name + --> $DIR/shadowed-type-parameter.rs:30:27 + | +27 | trait Bar { + | - first `T` declared here +... +30 | fn shadow_in_required(&self); + | ^ shadows another type parameter + +error[E0194]: type parameter `T` shadows another type parameter of the same name + --> $DIR/shadowed-type-parameter.rs:33:27 + | +27 | trait Bar { + | - first `T` declared here +... +33 | fn shadow_in_provided(&self) {} + | ^ shadows another type parameter + +error[E0194]: type parameter `T` shadows another type parameter of the same name + --> $DIR/shadowed-type-parameter.rs:18:25 + | +17 | impl Foo { + | - first `T` declared here +18 | fn shadow_in_method(&self) {} + | ^ shadows another type parameter + +error: aborting due to previous error(s) + From 984e76468b34c6874220cc2fbce9dc2f98c6eecc Mon Sep 17 00:00:00 2001 From: Aidan Hobson Sayers Date: Wed, 28 Jun 2017 23:05:29 +0100 Subject: [PATCH 073/162] Record some details to help with possible bad clocks --- .travis.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.travis.yml b/.travis.yml index 96163c75c9d..21877ecb43e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -179,8 +179,14 @@ before_script: fi fi +# Log time information from this machine and an external machine for insight into possible +# clock drift. Timezones don't matter since relative deltas give all the necessary info. script: + - > + date && curl -s --head https://google.com | grep ^Date: | sed 's/Date: //g' - stamp sh -x -c "$RUN_SCRIPT" + - > + date && curl -s --head https://google.com | grep ^Date: | sed 's/Date: //g' after_success: - > From 09f42fb9ccb4dfd728e323cbe5d25ed04a8262ad Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 24 Jun 2017 22:26:45 +0200 Subject: [PATCH 074/162] Add E0619 --- src/librustc_typeck/check/mod.rs | 6 +++--- src/librustc_typeck/diagnostics.rs | 27 +++++++++++++++++++++++++++ src/test/compile-fail/E0619.rs | 18 ++++++++++++++++++ 3 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 src/test/compile-fail/E0619.rs diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 34cf1d7f96b..a8d0be2bd04 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4716,9 +4716,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // If not, error. if alternative.is_ty_var() || alternative.references_error() { if !self.is_tainted_by_errors() { - self.type_error_message(sp, |_actual| { - "the type of this value must be known in this context".to_string() - }, ty); + type_error_struct!(self.tcx.sess, sp, ty, E0619, + "the type of this value must be known in this context") + .emit(); } self.demand_suptype(sp, self.tcx.types.err, ty); ty = self.tcx.types.err; diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index bf5adc8644d..09c3445672a 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -4665,6 +4665,33 @@ i_am_a_function(); ``` "##, +E0619: r##" +A not (yet) known type was used. + +Erroneous code example: + +```compile_fail,E0619 +let x; + +match x { + (..) => {} // error: the type of this value must be known in this context + _ => {} +} +``` + +To fix this error, just specify the type of the variable. Example: + +``` +let x: i32 = 0; // Here, we say that `x` is an `i32` (and give it a value to + // avoid another compiler error). + +match x { + 0 => {} // ok! + _ => {} +} +``` +"##, + } register_diagnostics! { diff --git a/src/test/compile-fail/E0619.rs b/src/test/compile-fail/E0619.rs new file mode 100644 index 00000000000..8ef90d89931 --- /dev/null +++ b/src/test/compile-fail/E0619.rs @@ -0,0 +1,18 @@ +// Copyright 2017 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 x; + + match x { + (..) => {} //~ ERROR E0619 + _ => {} + } +} From 05ac25affa2f9dda6c6e9e8c5005736e98391c44 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 24 Jun 2017 23:23:47 +0200 Subject: [PATCH 075/162] Add E0620 --- src/librustc_typeck/check/cast.rs | 10 ++++------ src/librustc_typeck/diagnostics.rs | 19 +++++++++++++++++++ src/test/compile-fail/E0620.rs | 13 +++++++++++++ 3 files changed, 36 insertions(+), 6 deletions(-) create mode 100644 src/test/compile-fail/E0620.rs diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 46d304976dc..7bd24c939ca 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -239,12 +239,10 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { } let tstr = fcx.ty_to_string(self.cast_ty); - let mut err = - fcx.type_error_struct(self.span, - |actual| { - format!("cast to unsized type: `{}` as `{}`", actual, tstr) - }, - self.expr_ty); + let mut err = type_error_struct!(fcx.tcx.sess, self.span, self.expr_ty, E0620, + "cast to unsized type: `{}` as `{}`", + fcx.resolve_type_vars_if_possible(&self.expr_ty), + tstr); match self.expr_ty.sty { ty::TyRef(_, ty::TypeAndMut { mutbl: mt, .. }) => { let mtstr = match mt { diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 09c3445672a..112249463f6 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -4692,6 +4692,25 @@ match x { ``` "##, +E0620: r##" +A cast to an unsized type was attempted. + +Erroneous code example: + +```compile_fail,E0620 +let x = &[1_usize, 2] as [usize]; // error: cast to unsized type: `&[usize; 2]` + // as `[usize]` +``` + +In Rust, some types don't have a size at compile-time (like slices and traits +for example). Therefore, you can't cast into them directly. Try casting to a +reference instead: + +``` +let x = &[1_usize, 2] as &[usize]; // ok! +``` +"##, + } register_diagnostics! { diff --git a/src/test/compile-fail/E0620.rs b/src/test/compile-fail/E0620.rs new file mode 100644 index 00000000000..5e945dfa5c8 --- /dev/null +++ b/src/test/compile-fail/E0620.rs @@ -0,0 +1,13 @@ +// Copyright 2017 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 _foo = &[1_usize, 2] as [usize]; //~ ERROR E0620 +} From ff0fb9d906444aa054c6203506350cf752e5bea3 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 24 Jun 2017 23:24:07 +0200 Subject: [PATCH 076/162] Remove unused methods --- src/librustc/infer/mod.rs | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index d5020b12ee0..9500e4a3604 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -1191,28 +1191,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // types using one of these methods, and should not call span_err directly for such // errors. - pub fn type_error_message(&self, - sp: Span, - mk_msg: M, - actual_ty: Ty<'tcx>) - where M: FnOnce(String) -> String, - { - self.type_error_struct(sp, mk_msg, actual_ty).emit(); - } - - // FIXME: this results in errors without an error code. Deprecate? - pub fn type_error_struct(&self, - sp: Span, - mk_msg: M, - actual_ty: Ty<'tcx>) - -> DiagnosticBuilder<'tcx> - where M: FnOnce(String) -> String, - { - self.type_error_struct_with_diag(sp, |actual_ty| { - self.tcx.sess.struct_span_err(sp, &mk_msg(actual_ty)) - }, actual_ty) - } - pub fn type_error_struct_with_diag(&self, sp: Span, mk_diag: M, From 5acc1deaf8ddcf540a7d58a50046f02a1a728a8f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 27 Jun 2017 23:07:56 +0200 Subject: [PATCH 077/162] Improve long error explanations for E0620 and E0621 --- src/librustc_typeck/diagnostics.rs | 46 +++++++++++++++++++----------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 112249463f6..1b17faccc87 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -4666,28 +4666,41 @@ i_am_a_function(); "##, E0619: r##" -A not (yet) known type was used. +The type-checker needed to know the type of an expression, but that type had not +yet been inferred. Erroneous code example: ```compile_fail,E0619 -let x; - -match x { - (..) => {} // error: the type of this value must be known in this context - _ => {} +let mut x = vec![]; +match x.pop() { + Some(v) => { + // Here, the type of `v` is not (yet) known, so we + // cannot resolve this method call: + v.to_uppercase(); // error: the type of this value must be known in + // this context + } + None => {} } ``` +Type inference typically proceeds from the top of the function to the bottom, +figuring out types as it goes. In some cases -- notably method calls and +overloadable operators like `*` -- the type checker may not have enough +information *yet* to make progress. This can be true even if the rest of the +function provides enough context (because the type-checker hasn't looked that +far ahead yet). In this case, type annotations can be used to help it along. + To fix this error, just specify the type of the variable. Example: ``` -let x: i32 = 0; // Here, we say that `x` is an `i32` (and give it a value to - // avoid another compiler error). - -match x { - 0 => {} // ok! - _ => {} +let mut x: Vec = vec![]; // We precise the type of the vec elements. +match x.pop() { + Some(v) => { + v.to_uppercase(); // Since rustc now knows the type of the vec elements, + // we can use `v`'s methods. + } + None => {} } ``` "##, @@ -4702,9 +4715,11 @@ let x = &[1_usize, 2] as [usize]; // error: cast to unsized type: `&[usize; 2]` // as `[usize]` ``` -In Rust, some types don't have a size at compile-time (like slices and traits -for example). Therefore, you can't cast into them directly. Try casting to a -reference instead: +In Rust, some types don't have a known size at compile-time. For example, in a +slice type like `[u32]`, the number of elements is not known at compile-time and +hence the overall size cannot be computed. As a result, such types can only be +manipulated through a reference (e.g., `&T` or `&mut T`) or other pointer-type +(e.g., `Box` or `Rc`). Try casting to a reference instead: ``` let x = &[1_usize, 2] as &[usize]; // ok! @@ -4782,5 +4797,4 @@ register_diagnostics! { E0568, // auto-traits can not have predicates, E0588, // packed struct cannot transitively contain a `[repr(align)]` struct E0592, // duplicate definitions with name `{}` - E0619, // intrinsic must be a function } From e03948ef3e19ff90066ca366bf76c390d7a42bc5 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 25 Jun 2017 20:34:49 +0300 Subject: [PATCH 078/162] Make `$crate` a keyword --- src/librustc/hir/print.rs | 6 +- src/librustc_resolve/build_reduced_graph.rs | 5 +- src/librustc_resolve/lib.rs | 5 +- src/librustc_resolve/macros.rs | 2 +- src/libsyntax/ast.rs | 5 +- src/libsyntax/ext/tt/quoted.rs | 4 +- src/libsyntax/parse/token.rs | 3 +- src/libsyntax/print/pprust.rs | 4 +- src/libsyntax_pos/symbol.rs | 103 +++++++++--------- .../compile-fail/dollar-crate-is-keyword-2.rs | 23 ++++ .../compile-fail/dollar-crate-is-keyword.rs | 24 ++++ src/test/compile-fail/use-self-type.rs | 21 ++++ 12 files changed, 139 insertions(+), 66 deletions(-) create mode 100644 src/test/compile-fail/dollar-crate-is-keyword-2.rs create mode 100644 src/test/compile-fail/dollar-crate-is-keyword.rs create mode 100644 src/test/compile-fail/use-self-type.rs diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index a78d5ce1c16..c6f4cd585d7 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -1527,7 +1527,8 @@ impl<'a> State<'a> { if i > 0 { word(&mut self.s, "::")? } - if segment.name != keywords::CrateRoot.name() && segment.name != "$crate" { + if segment.name != keywords::CrateRoot.name() && + segment.name != keywords::DollarCrate.name() { self.print_name(segment.name)?; self.print_path_parameters(&segment.parameters, colons_before_params)?; } @@ -1554,7 +1555,8 @@ impl<'a> State<'a> { if i > 0 { word(&mut self.s, "::")? } - if segment.name != keywords::CrateRoot.name() && segment.name != "$crate" { + if segment.name != keywords::CrateRoot.name() && + segment.name != keywords::DollarCrate.name() { self.print_name(segment.name)?; self.print_path_parameters(&segment.parameters, colons_before_params)?; } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index b97c08b5bde..4b6b754dca6 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -149,14 +149,15 @@ impl<'a> Resolver<'a> { resolve_error(self, view_path.span, ResolutionError::SelfImportsOnlyAllowedWithin); - } else if source_name == "$crate" && full_path.segments.len() == 1 { + } else if source_name == keywords::DollarCrate.name() && + full_path.segments.len() == 1 { let crate_root = self.resolve_crate_root(source.ctxt); let crate_name = match crate_root.kind { ModuleKind::Def(_, name) => name, ModuleKind::Block(..) => unreachable!(), }; source.name = crate_name; - if binding.name == "$crate" { + if binding.name == keywords::DollarCrate.name() { binding.name = crate_name; } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 8c11aa7def8..4bfe4d25ded 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -2665,7 +2665,8 @@ impl<'a> Resolver<'a> { }; if path.len() > 1 && !global_by_default && result.base_def() != Def::Err && - path[0].name != keywords::CrateRoot.name() && path[0].name != "$crate" { + path[0].name != keywords::CrateRoot.name() && + path[0].name != keywords::DollarCrate.name() { let unqualified_result = { match self.resolve_path(&[*path.last().unwrap()], Some(ns), false, span) { PathResult::NonModule(path_res) => path_res.base_def(), @@ -2718,7 +2719,7 @@ impl<'a> Resolver<'a> { if i == 0 && ns == TypeNS && ident.name == keywords::CrateRoot.name() { module = Some(self.resolve_crate_root(ident.ctxt.modern())); continue - } else if i == 0 && ns == TypeNS && ident.name == "$crate" { + } else if i == 0 && ns == TypeNS && ident.name == keywords::DollarCrate.name() { module = Some(self.resolve_crate_root(ident.ctxt)); continue } diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 60c07eda4d5..0fbc596f2e1 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -128,7 +128,7 @@ impl<'a> base::Resolver for Resolver<'a> { impl<'a, 'b> Folder for EliminateCrateVar<'a, 'b> { fn fold_path(&mut self, mut path: ast::Path) -> ast::Path { let ident = path.segments[0].identifier; - if ident.name == "$crate" { + if ident.name == keywords::DollarCrate.name() { path.segments[0].identifier.name = keywords::CrateRoot.name(); let module = self.0.resolve_crate_root(ident.ctxt); if !module.is_local() { diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 8bd58ec7a52..ecab801d408 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -97,9 +97,8 @@ impl Path { } pub fn default_to_global(mut self) -> Path { - let name = self.segments[0].identifier.name; - if !self.is_global() && name != "$crate" && - name != keywords::SelfValue.name() && name != keywords::Super.name() { + if !self.is_global() && + !::parse::token::Ident(self.segments[0].identifier).is_path_segment_keyword() { self.segments.insert(0, PathSegment::crate_root()); } self diff --git a/src/libsyntax/ext/tt/quoted.rs b/src/libsyntax/ext/tt/quoted.rs index fa65e9501c2..c094a23cefc 100644 --- a/src/libsyntax/ext/tt/quoted.rs +++ b/src/libsyntax/ext/tt/quoted.rs @@ -12,7 +12,7 @@ use ast; use ext::tt::macro_parser; use parse::{ParseSess, token}; use print::pprust; -use symbol::{keywords, Symbol}; +use symbol::keywords; use syntax_pos::{DUMMY_SP, Span, BytePos}; use tokenstream; @@ -196,7 +196,7 @@ fn parse_tree(tree: tokenstream::TokenTree, Some(tokenstream::TokenTree::Token(ident_span, token::Ident(ident))) => { let span = Span { lo: span.lo, ..ident_span }; if ident.name == keywords::Crate.name() { - let ident = ast::Ident { name: Symbol::intern("$crate"), ..ident }; + let ident = ast::Ident { name: keywords::DollarCrate.name(), ..ident }; TokenTree::Token(span, token::Ident(ident)) } else { TokenTree::Token(span, token::SubstNt(ident)) diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 77db604c56e..d6a4dc2ee96 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -327,7 +327,8 @@ impl Token { match self.ident() { Some(id) => id.name == keywords::Super.name() || id.name == keywords::SelfValue.name() || - id.name == keywords::SelfType.name(), + id.name == keywords::SelfType.name() || + id.name == keywords::DollarCrate.name(), None => false, } } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 34cda433d52..6c00e0b9efd 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -761,7 +761,7 @@ pub trait PrintState<'a> { word(self.writer(), "::")? } if segment.identifier.name != keywords::CrateRoot.name() && - segment.identifier.name != "$crate" { + segment.identifier.name != keywords::DollarCrate.name() { word(self.writer(), &segment.identifier.name.as_str())?; } } @@ -2375,7 +2375,7 @@ impl<'a> State<'a> { -> io::Result<()> { if segment.identifier.name != keywords::CrateRoot.name() && - segment.identifier.name != "$crate" { + segment.identifier.name != keywords::DollarCrate.name() { self.print_ident(segment.identifier)?; if let Some(ref parameters) = segment.parameters { self.print_path_parameters(parameters, colons_before_params)?; diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 6b5caff27e8..5e2e448f741 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -250,63 +250,64 @@ declare_keywords! { (4, Const, "const") (5, Continue, "continue") (6, Crate, "crate") - (7, Else, "else") - (8, Enum, "enum") - (9, Extern, "extern") - (10, False, "false") - (11, Fn, "fn") - (12, For, "for") - (13, If, "if") - (14, Impl, "impl") - (15, In, "in") - (16, Let, "let") - (17, Loop, "loop") - (18, Match, "match") - (19, Mod, "mod") - (20, Move, "move") - (21, Mut, "mut") - (22, Pub, "pub") - (23, Ref, "ref") - (24, Return, "return") - (25, SelfValue, "self") - (26, SelfType, "Self") - (27, Static, "static") - (28, Struct, "struct") - (29, Super, "super") - (30, Trait, "trait") - (31, True, "true") - (32, Type, "type") - (33, Unsafe, "unsafe") - (34, Use, "use") - (35, Where, "where") - (36, While, "while") + (7, DollarCrate, "$crate") + (8, Else, "else") + (9, Enum, "enum") + (10, Extern, "extern") + (11, False, "false") + (12, Fn, "fn") + (13, For, "for") + (14, If, "if") + (15, Impl, "impl") + (16, In, "in") + (17, Let, "let") + (18, Loop, "loop") + (19, Match, "match") + (20, Mod, "mod") + (21, Move, "move") + (22, Mut, "mut") + (23, Pub, "pub") + (24, Ref, "ref") + (25, Return, "return") + (26, SelfValue, "self") + (27, SelfType, "Self") + (28, Static, "static") + (29, Struct, "struct") + (30, Super, "super") + (31, Trait, "trait") + (32, True, "true") + (33, Type, "type") + (34, Unsafe, "unsafe") + (35, Use, "use") + (36, Where, "where") + (37, While, "while") // Keywords reserved for future use. - (37, Abstract, "abstract") - (38, Alignof, "alignof") - (39, Become, "become") - (40, Do, "do") - (41, Final, "final") - (42, Macro, "macro") - (43, Offsetof, "offsetof") - (44, Override, "override") - (45, Priv, "priv") - (46, Proc, "proc") - (47, Pure, "pure") - (48, Sizeof, "sizeof") - (49, Typeof, "typeof") - (50, Unsized, "unsized") - (51, Virtual, "virtual") - (52, Yield, "yield") + (38, Abstract, "abstract") + (39, Alignof, "alignof") + (40, Become, "become") + (41, Do, "do") + (42, Final, "final") + (43, Macro, "macro") + (44, Offsetof, "offsetof") + (45, Override, "override") + (46, Priv, "priv") + (47, Proc, "proc") + (48, Pure, "pure") + (49, Sizeof, "sizeof") + (50, Typeof, "typeof") + (51, Unsized, "unsized") + (52, Virtual, "virtual") + (53, Yield, "yield") // Weak keywords, have special meaning only in specific contexts. - (53, Default, "default") - (54, StaticLifetime, "'static") - (55, Union, "union") - (56, Catch, "catch") + (54, Default, "default") + (55, StaticLifetime, "'static") + (56, Union, "union") + (57, Catch, "catch") // A virtual keyword that resolves to the crate root when used in a lexical scope. - (57, CrateRoot, "{{root}}") + (58, CrateRoot, "{{root}}") } // If an interner exists in TLS, return it. Otherwise, prepare a fresh one. diff --git a/src/test/compile-fail/dollar-crate-is-keyword-2.rs b/src/test/compile-fail/dollar-crate-is-keyword-2.rs new file mode 100644 index 00000000000..e221fc6e9e0 --- /dev/null +++ b/src/test/compile-fail/dollar-crate-is-keyword-2.rs @@ -0,0 +1,23 @@ +// Copyright 2017 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. + +mod a {} + +macro_rules! m { + () => { + use a::$crate; //~ ERROR unresolved import `a::$crate` + use a::$crate::b; //~ ERROR unresolved import `a::$crate::b` + type A = a::$crate; //~ ERROR cannot find type `$crate` in module `a` + } +} + +m!(); + +fn main() {} diff --git a/src/test/compile-fail/dollar-crate-is-keyword.rs b/src/test/compile-fail/dollar-crate-is-keyword.rs new file mode 100644 index 00000000000..0bd47a0e11a --- /dev/null +++ b/src/test/compile-fail/dollar-crate-is-keyword.rs @@ -0,0 +1,24 @@ +// Copyright 2017 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. + +macro_rules! m { + () => { + struct $crate {} //~ ERROR expected identifier, found keyword `$crate` + + use $crate; // OK + //~^ WARN `$crate` may not be imported + use $crate as $crate; //~ ERROR expected identifier, found keyword `$crate` + //~^ WARN `$crate` may not be imported + } +} + +m!(); + +fn main() {} diff --git a/src/test/compile-fail/use-self-type.rs b/src/test/compile-fail/use-self-type.rs new file mode 100644 index 00000000000..6b5286bf0a7 --- /dev/null +++ b/src/test/compile-fail/use-self-type.rs @@ -0,0 +1,21 @@ +// Copyright 2017 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 S; + +impl S { + fn f() {} + fn g() { + use Self::f; //~ ERROR unresolved import + pub(in Self::f) struct Z; //~ ERROR Use of undeclared type or module `Self` + } +} + +fn main() {} From b33fd6d75966411c3934cd6bde07bb1a653b2d83 Mon Sep 17 00:00:00 2001 From: petrochenkov Date: Thu, 29 Jun 2017 13:16:35 +0300 Subject: [PATCH 079/162] Change some terminology around keywords and reserved identifiers --- src/librustdoc/html/highlight.rs | 2 +- src/libsyntax/parse/lexer/mod.rs | 2 +- src/libsyntax/parse/parser.rs | 46 ++----- src/libsyntax/parse/token.rs | 27 ++-- src/libsyntax_pos/symbol.rs | 125 +++++++++--------- .../compile-fail/dollar-crate-is-keyword.rs | 4 +- src/test/parse-fail/macro-keyword.rs | 2 +- 7 files changed, 99 insertions(+), 109 deletions(-) diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index a40d1e6bdc9..de8749c43d9 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -300,7 +300,7 @@ impl<'a> Classifier<'a> { "Some" | "None" | "Ok" | "Err" => Class::PreludeVal, "$crate" => Class::KeyWord, - _ if tas.tok.is_any_keyword() => Class::KeyWord, + _ if tas.tok.is_reserved_ident() => Class::KeyWord, _ => { if self.in_macro_nonterminal { diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index e2656bea483..a35b278a4b0 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -1283,7 +1283,7 @@ impl<'a> StringReader<'a> { }); let keyword_checking_token = &token::Ident(keyword_checking_ident); let last_bpos = self.pos; - if keyword_checking_token.is_any_keyword() && + if keyword_checking_token.is_reserved_ident() && !keyword_checking_token.is_keyword(keywords::Static) { self.err_span_(start, last_bpos, "lifetimes cannot use keyword names"); } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 5b0031b2f17..64506c4af46 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -511,14 +511,13 @@ impl<'a> Parser<'a> { } pub fn this_token_descr(&self) -> String { - let s = self.this_token_to_string(); - if self.token.is_strict_keyword() { - format!("keyword `{}`", s) - } else if self.token.is_reserved_keyword() { - format!("reserved keyword `{}`", s) - } else { - format!("`{}`", s) - } + let prefix = match &self.token { + t if t.is_special_ident() => "reserved identifier ", + t if t.is_used_keyword() => "keyword ", + t if t.is_unused_keyword() => "reserved keyword ", + _ => "", + }; + format!("{}`{}`", prefix, self.this_token_to_string()) } pub fn unexpected_last(&self, t: &token::Token) -> PResult<'a, T> { @@ -637,10 +636,12 @@ impl<'a> Parser<'a> { } pub fn parse_ident(&mut self) -> PResult<'a, ast::Ident> { - self.check_strict_keywords(); - self.check_reserved_keywords(); match self.token { token::Ident(i) => { + if self.token.is_reserved_ident() { + self.span_err(self.span, &format!("expected identifier, found {}", + self.this_token_descr())); + } self.bump(); Ok(i) } @@ -713,25 +714,6 @@ impl<'a> Parser<'a> { } } - /// Signal an error if the given string is a strict keyword - pub fn check_strict_keywords(&mut self) { - if self.token.is_strict_keyword() { - let token_str = self.this_token_to_string(); - let span = self.span; - self.span_err(span, - &format!("expected identifier, found keyword `{}`", - token_str)); - } - } - - /// Signal an error if the current token is a reserved keyword - pub fn check_reserved_keywords(&mut self) { - if self.token.is_reserved_keyword() { - let token_str = self.this_token_to_string(); - self.fatal(&format!("`{}` is a reserved keyword", token_str)).emit() - } - } - fn check_ident(&mut self) -> bool { if self.token.is_ident() { true @@ -2301,7 +2283,7 @@ impl<'a> Parser<'a> { ex = ExprKind::Break(lt, e); hi = self.prev_span; } else if self.token.is_keyword(keywords::Let) { - // Catch this syntax error here, instead of in `check_strict_keywords`, so + // Catch this syntax error here, instead of in `parse_ident`, so // that we can explicitly mention that let is not to be used as an expression let mut db = self.fatal("expected expression, found statement (`let`)"); db.note("variable declaration using `let` is a statement"); @@ -3540,7 +3522,7 @@ impl<'a> Parser<'a> { // Parse box pat let subpat = self.parse_pat()?; pat = PatKind::Box(subpat); - } else if self.token.is_ident() && !self.token.is_any_keyword() && + } else if self.token.is_ident() && !self.token.is_reserved_ident() && self.parse_as_ident() { // Parse ident @ pat // This can give false positives and parse nullary enums, @@ -3815,7 +3797,7 @@ impl<'a> Parser<'a> { fn is_union_item(&self) -> bool { self.token.is_keyword(keywords::Union) && - self.look_ahead(1, |t| t.is_ident() && !t.is_any_keyword()) + self.look_ahead(1, |t| t.is_ident() && !t.is_reserved_ident()) } fn is_defaultness(&self) -> bool { diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index d6a4dc2ee96..75969cf2eb8 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -87,7 +87,7 @@ impl Lit { fn ident_can_begin_expr(ident: ast::Ident) -> bool { let ident_token: Token = Ident(ident); - !ident_token.is_any_keyword() || + !ident_token.is_reserved_ident() || ident_token.is_path_segment_keyword() || [ keywords::Do.name(), @@ -110,7 +110,7 @@ fn ident_can_begin_expr(ident: ast::Ident) -> bool { fn ident_can_begin_type(ident: ast::Ident) -> bool { let ident_token: Token = Ident(ident); - !ident_token.is_any_keyword() || + !ident_token.is_reserved_ident() || ident_token.is_path_segment_keyword() || [ keywords::For.name(), @@ -315,7 +315,7 @@ impl Token { pub fn is_path_start(&self) -> bool { self == &ModSep || self.is_qpath_start() || self.is_path() || - self.is_path_segment_keyword() || self.is_ident() && !self.is_any_keyword() + self.is_path_segment_keyword() || self.is_ident() && !self.is_reserved_ident() } /// Returns `true` if the token is a given keyword, `kw`. @@ -333,13 +333,17 @@ impl Token { } } - /// Returns `true` if the token is either a strict or reserved keyword. - pub fn is_any_keyword(&self) -> bool { - self.is_strict_keyword() || self.is_reserved_keyword() + // Returns true for reserved identifiers used internally for elided lifetimes, + // unnamed method parameters, crate root module, error recovery etc. + pub fn is_special_ident(&self) -> bool { + match self.ident() { + Some(id) => id.name <= keywords::DollarCrate.name(), + _ => false, + } } - /// Returns `true` if the token is a strict keyword. - pub fn is_strict_keyword(&self) -> bool { + /// Returns `true` if the token is a keyword used in the language. + pub fn is_used_keyword(&self) -> bool { match self.ident() { Some(id) => id.name >= keywords::As.name() && id.name <= keywords::While.name(), _ => false, @@ -347,12 +351,17 @@ impl Token { } /// Returns `true` if the token is a keyword reserved for possible future use. - pub fn is_reserved_keyword(&self) -> bool { + pub fn is_unused_keyword(&self) -> bool { match self.ident() { Some(id) => id.name >= keywords::Abstract.name() && id.name <= keywords::Yield.name(), _ => false, } } + + /// Returns `true` if the token is either a special identifier or a keyword. + pub fn is_reserved_ident(&self) -> bool { + self.is_special_ident() || self.is_used_keyword() || self.is_unused_keyword() + } } #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash)] diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 5e2e448f741..debac70545a 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -237,77 +237,76 @@ macro_rules! declare_keywords {( // NB: leaving holes in the ident table is bad! a different ident will get // interned with the id from the hole, but it will be between the min and max // of the reserved words, and thus tagged as "reserved". -// After modifying this list adjust `is_strict_keyword`/`is_reserved_keyword`, +// After modifying this list adjust `is_special_ident`, `is_used_keyword`/`is_unused_keyword`, // this should be rarely necessary though if the keywords are kept in alphabetic order. declare_keywords! { - // Invalid identifier + // Special reserved identifiers used internally for elided lifetimes, + // unnamed method parameters, crate root module, error recovery etc. (0, Invalid, "") + (1, CrateRoot, "{{root}}") + (2, DollarCrate, "$crate") - // Strict keywords used in the language. - (1, As, "as") - (2, Box, "box") - (3, Break, "break") - (4, Const, "const") - (5, Continue, "continue") - (6, Crate, "crate") - (7, DollarCrate, "$crate") - (8, Else, "else") - (9, Enum, "enum") - (10, Extern, "extern") - (11, False, "false") - (12, Fn, "fn") - (13, For, "for") - (14, If, "if") - (15, Impl, "impl") - (16, In, "in") - (17, Let, "let") - (18, Loop, "loop") - (19, Match, "match") - (20, Mod, "mod") - (21, Move, "move") - (22, Mut, "mut") - (23, Pub, "pub") - (24, Ref, "ref") - (25, Return, "return") - (26, SelfValue, "self") - (27, SelfType, "Self") - (28, Static, "static") - (29, Struct, "struct") - (30, Super, "super") - (31, Trait, "trait") - (32, True, "true") - (33, Type, "type") - (34, Unsafe, "unsafe") - (35, Use, "use") - (36, Where, "where") - (37, While, "while") + // Keywords used in the language. + (3, As, "as") + (4, Box, "box") + (5, Break, "break") + (6, Const, "const") + (7, Continue, "continue") + (8, Crate, "crate") + (9, Else, "else") + (10, Enum, "enum") + (11, Extern, "extern") + (12, False, "false") + (13, Fn, "fn") + (14, For, "for") + (15, If, "if") + (16, Impl, "impl") + (17, In, "in") + (18, Let, "let") + (19, Loop, "loop") + (20, Match, "match") + (21, Mod, "mod") + (22, Move, "move") + (23, Mut, "mut") + (24, Pub, "pub") + (25, Ref, "ref") + (26, Return, "return") + (27, SelfValue, "self") + (28, SelfType, "Self") + (29, Static, "static") + (30, Struct, "struct") + (31, Super, "super") + (32, Trait, "trait") + (33, True, "true") + (34, Type, "type") + (35, Unsafe, "unsafe") + (36, Use, "use") + (37, Where, "where") + (38, While, "while") // Keywords reserved for future use. - (38, Abstract, "abstract") - (39, Alignof, "alignof") - (40, Become, "become") - (41, Do, "do") - (42, Final, "final") - (43, Macro, "macro") - (44, Offsetof, "offsetof") - (45, Override, "override") - (46, Priv, "priv") - (47, Proc, "proc") - (48, Pure, "pure") - (49, Sizeof, "sizeof") - (50, Typeof, "typeof") - (51, Unsized, "unsized") - (52, Virtual, "virtual") - (53, Yield, "yield") + (39, Abstract, "abstract") + (40, Alignof, "alignof") + (41, Become, "become") + (42, Do, "do") + (43, Final, "final") + (44, Macro, "macro") + (45, Offsetof, "offsetof") + (46, Override, "override") + (47, Priv, "priv") + (48, Proc, "proc") + (49, Pure, "pure") + (50, Sizeof, "sizeof") + (51, Typeof, "typeof") + (52, Unsized, "unsized") + (53, Virtual, "virtual") + (54, Yield, "yield") // Weak keywords, have special meaning only in specific contexts. - (54, Default, "default") - (55, StaticLifetime, "'static") - (56, Union, "union") - (57, Catch, "catch") - - // A virtual keyword that resolves to the crate root when used in a lexical scope. - (58, CrateRoot, "{{root}}") + (55, Default, "default") + (56, StaticLifetime, "'static") + (57, Union, "union") + (58, Catch, "catch") } // If an interner exists in TLS, return it. Otherwise, prepare a fresh one. diff --git a/src/test/compile-fail/dollar-crate-is-keyword.rs b/src/test/compile-fail/dollar-crate-is-keyword.rs index 0bd47a0e11a..70597a230a8 100644 --- a/src/test/compile-fail/dollar-crate-is-keyword.rs +++ b/src/test/compile-fail/dollar-crate-is-keyword.rs @@ -10,11 +10,11 @@ macro_rules! m { () => { - struct $crate {} //~ ERROR expected identifier, found keyword `$crate` + struct $crate {} //~ ERROR expected identifier, found reserved identifier `$crate` use $crate; // OK //~^ WARN `$crate` may not be imported - use $crate as $crate; //~ ERROR expected identifier, found keyword `$crate` + use $crate as $crate; //~ ERROR expected identifier, found reserved identifier `$crate` //~^ WARN `$crate` may not be imported } } diff --git a/src/test/parse-fail/macro-keyword.rs b/src/test/parse-fail/macro-keyword.rs index 6a7ccff1554..c7dcaf4137e 100644 --- a/src/test/parse-fail/macro-keyword.rs +++ b/src/test/parse-fail/macro-keyword.rs @@ -10,7 +10,7 @@ // compile-flags: -Z parse-only -fn macro() { //~ ERROR `macro` is a reserved keyword +fn macro() { //~ ERROR expected identifier, found reserved keyword `macro` } pub fn main() { From 17fca8b4604bc4cf89ac06292f6475614984edc9 Mon Sep 17 00:00:00 2001 From: Masaki Hara Date: Thu, 8 Jun 2017 14:46:46 +0900 Subject: [PATCH 080/162] Check explicitly that tuple initializer is Sized. --- src/librustc/traits/error_reporting.rs | 3 +++ src/librustc/traits/mod.rs | 2 ++ src/librustc/traits/structural_impls.rs | 3 +++ src/librustc_typeck/check/mod.rs | 1 + src/test/compile-fail/unsized3.rs | 1 + 5 files changed, 10 insertions(+) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index e2e3d520d47..35de536223a 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -1097,6 +1097,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ObligationCauseCode::AssignmentLhsSized => { err.note("the left-hand-side of an assignment must have a statically known size"); } + ObligationCauseCode::TupleInitializerSized => { + err.note("tuples must have a statically known size to be initialized"); + } ObligationCauseCode::StructInitializerSized => { err.note("structs must have a statically known size to be initialized"); } diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index c128438aea0..16c41c816b4 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -121,6 +121,8 @@ pub enum ObligationCauseCode<'tcx> { // Various cases where expressions must be sized/copy/etc: /// L = X implies that L is Sized AssignmentLhsSized, + /// (x1, .., xn) must be Sized + TupleInitializerSized, /// S { ... } must be Sized StructInitializerSized, /// Type of each variable must be Sized diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index 0d6df78c2ac..c4479e69032 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -189,6 +189,7 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> { tcx.lift(&ty).map(super::ObjectCastObligation) } super::AssignmentLhsSized => Some(super::AssignmentLhsSized), + super::TupleInitializerSized => Some(super::TupleInitializerSized), super::StructInitializerSized => Some(super::StructInitializerSized), super::VariableType(id) => Some(super::VariableType(id)), super::ReturnType(id) => Some(super::ReturnType(id)), @@ -476,6 +477,7 @@ impl<'tcx> TypeFoldable<'tcx> for traits::ObligationCauseCode<'tcx> { super::TupleElem | super::ItemObligation(_) | super::AssignmentLhsSized | + super::TupleInitializerSized | super::StructInitializerSized | super::VariableType(_) | super::ReturnType(_) | @@ -523,6 +525,7 @@ impl<'tcx> TypeFoldable<'tcx> for traits::ObligationCauseCode<'tcx> { super::TupleElem | super::ItemObligation(_) | super::AssignmentLhsSized | + super::TupleInitializerSized | super::StructInitializerSized | super::VariableType(_) | super::ReturnType(_) | diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 34cf1d7f96b..631158df474 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3854,6 +3854,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if tuple.references_error() { tcx.types.err } else { + self.require_type_is_sized(tuple, expr.span, traits::TupleInitializerSized); tuple } } diff --git a/src/test/compile-fail/unsized3.rs b/src/test/compile-fail/unsized3.rs index 9b6ccf22c8d..e96e0ea3aec 100644 --- a/src/test/compile-fail/unsized3.rs +++ b/src/test/compile-fail/unsized3.rs @@ -54,6 +54,7 @@ fn f9(x1: Box>) { fn f10(x1: Box>) { f5(&(32, *x1)); //~^ ERROR `X: std::marker::Sized` is not satisfied + //~| ERROR `X: std::marker::Sized` is not satisfied } pub fn main() { From 23d1521684380a0a3099cb7439270cd650de36fb Mon Sep 17 00:00:00 2001 From: Masaki Hara Date: Thu, 8 Jun 2017 14:49:54 +0900 Subject: [PATCH 081/162] Add unsized tuple coercions. --- src/librustc/traits/error_reporting.rs | 2 +- src/librustc/traits/select.rs | 36 ++++++ src/librustc/ty/layout.rs | 10 +- src/librustc/ty/util.rs | 29 +++-- src/librustc_trans/glue.rs | 12 +- src/test/compile-fail/dst-bad-assign-3.rs | 48 ++++++++ src/test/compile-fail/dst-bad-coerce1.rs | 12 ++ src/test/compile-fail/dst-bad-coerce2.rs | 10 ++ src/test/compile-fail/dst-bad-coerce3.rs | 10 ++ src/test/compile-fail/dst-bad-coerce4.rs | 8 ++ src/test/compile-fail/dst-bad-deep-2.rs | 21 ++++ src/test/run-pass-valgrind/dst-dtor-1.rs | 3 +- src/test/run-pass-valgrind/dst-dtor-2.rs | 3 +- src/test/run-pass/dst-irrefutable-bind.rs | 10 ++ src/test/run-pass/dst-raw.rs | 32 ++++++ src/test/run-pass/dst-trait-tuple.rs | 110 +++++++++++++++++++ src/test/run-pass/dst-tuple-sole.rs | 83 ++++++++++++++ src/test/run-pass/dst-tuple.rs | 128 ++++++++++++++++++++++ 18 files changed, 549 insertions(+), 18 deletions(-) create mode 100644 src/test/compile-fail/dst-bad-assign-3.rs create mode 100644 src/test/compile-fail/dst-bad-deep-2.rs create mode 100644 src/test/run-pass/dst-trait-tuple.rs create mode 100644 src/test/run-pass/dst-tuple-sole.rs create mode 100644 src/test/run-pass/dst-tuple.rs diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 35de536223a..0bf0e21baaf 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -1060,7 +1060,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { err.note("slice and array elements must have `Sized` type"); } ObligationCauseCode::TupleElem => { - err.note("tuple elements must have `Sized` type"); + err.note("only the last element of a tuple may have a dynamically sized type"); } ObligationCauseCode::ProjectionWf(data) => { err.note(&format!("required so that the projection `{}` is well-formed", diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index a66b6b86354..11169eefdaf 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -1651,6 +1651,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { def_id_a == def_id_b } + // (.., T) -> (.., U). + (&ty::TyTuple(tys_a, _), &ty::TyTuple(tys_b, _)) => { + tys_a.len() == tys_b.len() + } + _ => false }; @@ -2617,6 +2622,37 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { &[inner_target])); } + // (.., T) -> (.., U). + (&ty::TyTuple(tys_a, _), &ty::TyTuple(tys_b, _)) => { + assert_eq!(tys_a.len(), tys_b.len()); + + // The last field of the tuple has to exist. + let (a_last, a_mid) = if let Some(x) = tys_a.split_last() { + x + } else { + return Err(Unimplemented); + }; + let b_last = tys_b.last().unwrap(); + + // Check that the source tuple with the target's + // last element is a subtype of the target. + let new_tuple = tcx.mk_tup(a_mid.iter().chain(Some(b_last)), false); + let InferOk { obligations, .. } = + self.infcx.at(&obligation.cause, obligation.param_env) + .eq(target, new_tuple) + .map_err(|_| Unimplemented)?; + self.inferred_obligations.extend(obligations); + + // Construct the nested T: Unsize predicate. + nested.push(tcx.predicate_for_trait_def( + obligation.param_env, + obligation.cause.clone(), + obligation.predicate.def_id(), + obligation.recursion_depth + 1, + a_last, + &[b_last])); + } + _ => bug!() }; diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 12af56d5c3d..e1aa89078a3 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -1220,12 +1220,16 @@ impl<'a, 'tcx> Layout { } ty::TyTuple(tys, _) => { - // FIXME(camlorn): if we ever allow unsized tuples, this needs to be checked. - // See the univariant case below to learn how. + let kind = if tys.len() == 0 { + StructKind::AlwaysSizedUnivariant + } else { + StructKind::MaybeUnsizedUnivariant + }; + let st = Struct::new(dl, &tys.iter().map(|ty| ty.layout(tcx, param_env)) .collect::, _>>()?, - &ReprOptions::default(), StructKind::AlwaysSizedUnivariant, ty)?; + &ReprOptions::default(), kind, ty)?; Univariant { variant: st, non_zero: false } } diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 98ef7918fef..df4bbad3859 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -317,15 +317,26 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { target: Ty<'tcx>) -> (Ty<'tcx>, Ty<'tcx>) { let (mut a, mut b) = (source, target); - while let (&TyAdt(a_def, a_substs), &TyAdt(b_def, b_substs)) = (&a.sty, &b.sty) { - if a_def != b_def || !a_def.is_struct() { - break; - } - match a_def.struct_variant().fields.last() { - Some(f) => { - a = f.ty(self, a_substs); - b = f.ty(self, b_substs); - } + loop { + match (&a.sty, &b.sty) { + (&TyAdt(a_def, a_substs), &TyAdt(b_def, b_substs)) + if a_def == b_def && a_def.is_struct() => { + if let Some(f) = a_def.struct_variant().fields.last() { + a = f.ty(self, a_substs); + b = f.ty(self, b_substs); + } else { + break; + } + }, + (&TyTuple(a_tys, _), &TyTuple(b_tys, _)) + if a_tys.len() == b_tys.len() => { + if let Some(a_last) = a_tys.last() { + a = a_last; + b = b_tys.last().unwrap(); + } else { + break; + } + }, _ => break, } } diff --git a/src/librustc_trans/glue.rs b/src/librustc_trans/glue.rs index 367f0398fa8..c2f44c089a2 100644 --- a/src/librustc_trans/glue.rs +++ b/src/librustc_trans/glue.rs @@ -76,7 +76,7 @@ pub fn size_and_align_of_dst<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, t: Ty<'tcx>, inf } assert!(!info.is_null()); match t.sty { - ty::TyAdt(def, substs) => { + ty::TyAdt(..) | ty::TyTuple(..) => { let ccx = bcx.ccx; // First get the size of all statically known fields. // Don't use size_of because it also rounds up to alignment, which we @@ -101,8 +101,14 @@ pub fn size_and_align_of_dst<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, t: Ty<'tcx>, inf // Recurse to get the size of the dynamically sized field (must be // the last field). - let last_field = def.struct_variant().fields.last().unwrap(); - let field_ty = monomorphize::field_ty(bcx.tcx(), substs, last_field); + let field_ty = match t.sty { + ty::TyAdt(def, substs) => { + let last_field = def.struct_variant().fields.last().unwrap(); + monomorphize::field_ty(bcx.tcx(), substs, last_field) + }, + ty::TyTuple(tys, _) => tys.last().unwrap(), + _ => unreachable!(), + }; let (unsized_size, unsized_align) = size_and_align_of_dst(bcx, field_ty, info); // FIXME (#26403, #27023): We should be adding padding diff --git a/src/test/compile-fail/dst-bad-assign-3.rs b/src/test/compile-fail/dst-bad-assign-3.rs new file mode 100644 index 00000000000..3c089edf001 --- /dev/null +++ b/src/test/compile-fail/dst-bad-assign-3.rs @@ -0,0 +1,48 @@ +// 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. + +// Forbid assignment into a dynamically sized type. + +type Fat = (isize, &'static str, T); +//~^ WARNING trait bounds are not (yet) enforced + +#[derive(PartialEq,Eq)] +struct Bar; + +#[derive(PartialEq,Eq)] +struct Bar1 { + f: isize +} + +trait ToBar { + fn to_bar(&self) -> Bar; + fn to_val(&self) -> isize; +} + +impl ToBar for Bar1 { + fn to_bar(&self) -> Bar { + Bar + } + fn to_val(&self) -> isize { + self.f + } +} + +pub fn main() { + // Assignment. + let f5: &mut Fat = &mut (5, "some str", Bar1 {f :42}); + let z: Box = Box::new(Bar1 {f: 36}); + f5.2 = Bar1 {f: 36}; + //~^ ERROR mismatched types + //~| expected type `ToBar` + //~| found type `Bar1` + //~| expected trait ToBar, found struct `Bar1` + //~| ERROR `ToBar: std::marker::Sized` is not satisfied +} diff --git a/src/test/compile-fail/dst-bad-coerce1.rs b/src/test/compile-fail/dst-bad-coerce1.rs index 9a3ea54a3a4..722ff8f25d6 100644 --- a/src/test/compile-fail/dst-bad-coerce1.rs +++ b/src/test/compile-fail/dst-bad-coerce1.rs @@ -29,4 +29,16 @@ pub fn main() { let f2: &Fat = &f1; let f3: &Fat = f2; //~^ ERROR `Foo: Bar` is not satisfied + + // Tuple with a vec of isize. + let f1 = ([1, 2, 3],); + let f2: &([isize; 3],) = &f1; + let f3: &([usize],) = f2; + //~^ ERROR mismatched types + + // Tuple with a trait. + let f1 = (Foo,); + let f2: &(Foo,) = &f1; + let f3: &(Bar,) = f2; + //~^ ERROR `Foo: Bar` is not satisfied } diff --git a/src/test/compile-fail/dst-bad-coerce2.rs b/src/test/compile-fail/dst-bad-coerce2.rs index 160197368d6..9e92f649b2d 100644 --- a/src/test/compile-fail/dst-bad-coerce2.rs +++ b/src/test/compile-fail/dst-bad-coerce2.rs @@ -28,4 +28,14 @@ pub fn main() { let f1 = Fat { ptr: Foo }; let f2: &Fat = &f1; let f3: &mut Fat = f2; //~ ERROR mismatched types + + // Tuple with a vec of ints. + let f1 = ([1, 2, 3],); + let f2: &([isize; 3],) = &f1; + let f3: &mut ([isize],) = f2; //~ ERROR mismatched types + + // Tuple with a trait. + let f1 = (Foo,); + let f2: &(Foo,) = &f1; + let f3: &mut (Bar,) = f2; //~ ERROR mismatched types } diff --git a/src/test/compile-fail/dst-bad-coerce3.rs b/src/test/compile-fail/dst-bad-coerce3.rs index 7bad3bd69d3..4dedae9331b 100644 --- a/src/test/compile-fail/dst-bad-coerce3.rs +++ b/src/test/compile-fail/dst-bad-coerce3.rs @@ -28,6 +28,16 @@ fn baz<'a>() { let f1 = Fat { ptr: Foo }; let f2: &Fat = &f1; //~ ERROR `f1` does not live long enough let f3: &'a Fat = f2; + + // Tuple with a vec of ints. + let f1 = ([1, 2, 3],); + let f2: &([isize; 3],) = &f1; //~ ERROR `f1` does not live long enough + let f3: &'a ([isize],) = f2; + + // Tuple with a trait. + let f1 = (Foo,); + let f2: &(Foo,) = &f1; //~ ERROR `f1` does not live long enough + let f3: &'a (Bar,) = f2; } pub fn main() { diff --git a/src/test/compile-fail/dst-bad-coerce4.rs b/src/test/compile-fail/dst-bad-coerce4.rs index 9d4d56cf791..2e78108a8de 100644 --- a/src/test/compile-fail/dst-bad-coerce4.rs +++ b/src/test/compile-fail/dst-bad-coerce4.rs @@ -22,4 +22,12 @@ pub fn main() { //~| expected type `&Fat<[isize; 3]>` //~| found type `&Fat<[isize]>` //~| expected array of 3 elements, found slice + + // Tuple with a vec of isizes. + let f1: &([isize],) = &([1, 2, 3],); + let f2: &([isize; 3],) = f1; + //~^ ERROR mismatched types + //~| expected type `&([isize; 3],)` + //~| found type `&([isize],)` + //~| expected array of 3 elements, found slice } diff --git a/src/test/compile-fail/dst-bad-deep-2.rs b/src/test/compile-fail/dst-bad-deep-2.rs new file mode 100644 index 00000000000..831afd27153 --- /dev/null +++ b/src/test/compile-fail/dst-bad-deep-2.rs @@ -0,0 +1,21 @@ +// 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. + +// Try to initialise a DST struct where the lost information is deeply nested. +// This is an error because it requires an unsized rvalue. This is a problem +// because it would require stack allocation of an unsized temporary (*g in the +// test). + +pub fn main() { + let f: ([isize; 3],) = ([5, 6, 7],); + let g: &([isize],) = &f; + let h: &(([isize],),) = &(*g,); + //~^ ERROR `[isize]: std::marker::Sized` is not satisfied +} diff --git a/src/test/run-pass-valgrind/dst-dtor-1.rs b/src/test/run-pass-valgrind/dst-dtor-1.rs index 4af642a106c..00bfebb3f1e 100644 --- a/src/test/run-pass-valgrind/dst-dtor-1.rs +++ b/src/test/run-pass-valgrind/dst-dtor-1.rs @@ -28,7 +28,8 @@ struct Fat { pub fn main() { { - let _x: Box> = Box::>::new(Fat { f: Foo }); + let _x: Box<(i32, Fat)> = + Box::<(i32, Fat)>::new((42, Fat { f: Foo })); } unsafe { assert!(DROP_RAN); diff --git a/src/test/run-pass-valgrind/dst-dtor-2.rs b/src/test/run-pass-valgrind/dst-dtor-2.rs index 283b8202b35..fa0c6c03225 100644 --- a/src/test/run-pass-valgrind/dst-dtor-2.rs +++ b/src/test/run-pass-valgrind/dst-dtor-2.rs @@ -25,7 +25,8 @@ struct Fat { pub fn main() { { - let _x: Box> = Box::>::new(Fat { f: [Foo, Foo, Foo] }); + let _x: Box<(Fat<[Foo]>,)> = + Box::<(Fat<[Foo; 3]>,)>::new((Fat { f: [Foo, Foo, Foo] },)); } unsafe { assert_eq!(DROP_RAN, 3); diff --git a/src/test/run-pass/dst-irrefutable-bind.rs b/src/test/run-pass/dst-irrefutable-bind.rs index 9f8067f372a..bd6ad9207ad 100644 --- a/src/test/run-pass/dst-irrefutable-bind.rs +++ b/src/test/run-pass/dst-irrefutable-bind.rs @@ -21,4 +21,14 @@ fn main() { let slice = &[1,2,3]; let x = Test(&slice); let Test(&_slice) = x; + + + let x = (10, [1,2,3]); + let x : &(i32, [i32]) = &x; + + let & ref _y = x; + + let slice = &[1,2,3]; + let x = (10, &slice); + let (_, &_slice) = x; } diff --git a/src/test/run-pass/dst-raw.rs b/src/test/run-pass/dst-raw.rs index 3a74626b029..c82cbd75044 100644 --- a/src/test/run-pass/dst-raw.rs +++ b/src/test/run-pass/dst-raw.rs @@ -45,6 +45,14 @@ pub fn main() { }; assert_eq!(r, 42); + // raw DST tuple + let p = (A { f: 42 },); + let o: *const (Trait,) = &p; + let r = unsafe { + (&*o).0.foo() + }; + assert_eq!(r, 42); + // raw slice let a: *const [_] = &[1, 2, 3]; unsafe { @@ -72,6 +80,15 @@ pub fn main() { assert_eq!(len, 3); } + // raw DST tuple with slice + let c: *const ([_],) = &([1, 2, 3],); + unsafe { + let b = (&*c).0[0]; + assert_eq!(b, 1); + let len = (&*c).0.len(); + assert_eq!(len, 3); + } + // all of the above with *mut let mut x = A { f: 42 }; let z: *mut Trait = &mut x; @@ -87,6 +104,13 @@ pub fn main() { }; assert_eq!(r, 42); + let mut p = (A { f: 42 },); + let o: *mut (Trait,) = &mut p; + let r = unsafe { + (&*o).0.foo() + }; + assert_eq!(r, 42); + let a: *mut [_] = &mut [1, 2, 3]; unsafe { let b = (*a)[2]; @@ -110,4 +134,12 @@ pub fn main() { let len = (&*c).f.len(); assert_eq!(len, 3); } + + let c: *mut ([_],) = &mut ([1, 2, 3],); + unsafe { + let b = (&*c).0[0]; + assert_eq!(b, 1); + let len = (&*c).0.len(); + assert_eq!(len, 3); + } } diff --git a/src/test/run-pass/dst-trait-tuple.rs b/src/test/run-pass/dst-trait-tuple.rs new file mode 100644 index 00000000000..ab60e95c74e --- /dev/null +++ b/src/test/run-pass/dst-trait-tuple.rs @@ -0,0 +1,110 @@ +// 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. + + +#![allow(unused_features)] +#![feature(box_syntax)] + +type Fat = (isize, &'static str, T); + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +struct Bar; + +#[derive(Copy, Clone, PartialEq, Eq)] +struct Bar1 { + f: isize +} + +trait ToBar { + fn to_bar(&self) -> Bar; + fn to_val(&self) -> isize; +} + +impl ToBar for Bar { + fn to_bar(&self) -> Bar { + *self + } + fn to_val(&self) -> isize { + 0 + } +} +impl ToBar for Bar1 { + fn to_bar(&self) -> Bar { + Bar + } + fn to_val(&self) -> isize { + self.f + } +} + +// x is a fat pointer +fn foo(x: &Fat) { + assert_eq!(x.0, 5); + assert_eq!(x.1, "some str"); + assert_eq!(x.2.to_bar(), Bar); + assert_eq!(x.2.to_val(), 42); + + let y = &x.2; + assert_eq!(y.to_bar(), Bar); + assert_eq!(y.to_val(), 42); +} + +fn bar(x: &ToBar) { + assert_eq!(x.to_bar(), Bar); + assert_eq!(x.to_val(), 42); +} + +fn baz(x: &Fat>) { + assert_eq!(x.0, 5); + assert_eq!(x.1, "some str"); + assert_eq!((x.2).0, 8); + assert_eq!((x.2).1, "deep str"); + assert_eq!((x.2).2.to_bar(), Bar); + assert_eq!((x.2).2.to_val(), 42); + + let y = &(x.2).2; + assert_eq!(y.to_bar(), Bar); + assert_eq!(y.to_val(), 42); + +} + +pub fn main() { + let f1 = (5, "some str", Bar1 {f :42}); + foo(&f1); + let f2 = &f1; + foo(f2); + let f3: &Fat = f2; + foo(f3); + let f4: &Fat = &f1; + foo(f4); + let f5: &Fat = &(5, "some str", Bar1 {f :42}); + foo(f5); + + // Zero size object. + let f6: &Fat = &(5, "some str", Bar); + assert_eq!(f6.2.to_bar(), Bar); + + // &* + // + let f7: Box = Box::new(Bar1 {f :42}); + bar(&*f7); + + // Deep nesting + let f1 = (5, "some str", (8, "deep str", Bar1 {f :42})); + baz(&f1); + let f2 = &f1; + baz(f2); + let f3: &Fat> = f2; + baz(f3); + let f4: &Fat> = &f1; + baz(f4); + let f5: &Fat> = &(5, "some str", (8, "deep str", Bar1 {f :42})); + baz(f5); +} diff --git a/src/test/run-pass/dst-tuple-sole.rs b/src/test/run-pass/dst-tuple-sole.rs new file mode 100644 index 00000000000..d3901a7555f --- /dev/null +++ b/src/test/run-pass/dst-tuple-sole.rs @@ -0,0 +1,83 @@ +// 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. + +// As dst-tuple.rs, but the unsized field is the only field in the tuple. + + +type Fat = (T,); + +// x is a fat pointer +fn foo(x: &Fat<[isize]>) { + let y = &x.0; + assert_eq!(x.0.len(), 3); + assert_eq!(y[0], 1); + assert_eq!(x.0[1], 2); +} + +fn foo2(x: &Fat<[T]>) { + let y = &x.0; + let bar = Bar; + assert_eq!(x.0.len(), 3); + assert_eq!(y[0].to_bar(), bar); + assert_eq!(x.0[1].to_bar(), bar); +} + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +struct Bar; + +trait ToBar { + fn to_bar(&self) -> Bar; +} + +impl ToBar for Bar { + fn to_bar(&self) -> Bar { + *self + } +} + +pub fn main() { + // With a vec of ints. + let f1 = ([1, 2, 3],); + foo(&f1); + let f2 = &f1; + foo(f2); + let f3: &Fat<[isize]> = f2; + foo(f3); + let f4: &Fat<[isize]> = &f1; + foo(f4); + let f5: &Fat<[isize]> = &([1, 2, 3],); + foo(f5); + + // With a vec of Bars. + let bar = Bar; + let f1 = ([bar, bar, bar],); + foo2(&f1); + let f2 = &f1; + foo2(f2); + let f3: &Fat<[Bar]> = f2; + foo2(f3); + let f4: &Fat<[Bar]> = &f1; + foo2(f4); + let f5: &Fat<[Bar]> = &([bar, bar, bar],); + foo2(f5); + + // Assignment. + let f5: &mut Fat<[isize]> = &mut ([1, 2, 3],); + f5.0[1] = 34; + assert_eq!(f5.0[0], 1); + assert_eq!(f5.0[1], 34); + assert_eq!(f5.0[2], 3); + + // Zero size vec. + let f5: &Fat<[isize]> = &([],); + assert!(f5.0.is_empty()); + let f5: &Fat<[Bar]> = &([],); + assert!(f5.0.is_empty()); +} diff --git a/src/test/run-pass/dst-tuple.rs b/src/test/run-pass/dst-tuple.rs new file mode 100644 index 00000000000..130294feb6c --- /dev/null +++ b/src/test/run-pass/dst-tuple.rs @@ -0,0 +1,128 @@ +// 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. + + +#![allow(unknown_features)] +#![feature(box_syntax)] + +type Fat = (isize, &'static str, T); + +// x is a fat pointer +fn foo(x: &Fat<[isize]>) { + let y = &x.2; + assert_eq!(x.2.len(), 3); + assert_eq!(y[0], 1); + assert_eq!(x.2[1], 2); + assert_eq!(x.0, 5); + assert_eq!(x.1, "some str"); +} + +fn foo2(x: &Fat<[T]>) { + let y = &x.2; + let bar = Bar; + assert_eq!(x.2.len(), 3); + assert_eq!(y[0].to_bar(), bar); + assert_eq!(x.2[1].to_bar(), bar); + assert_eq!(x.0, 5); + assert_eq!(x.1, "some str"); +} + +fn foo3(x: &Fat>) { + let y = &(x.2).2; + assert_eq!(x.0, 5); + assert_eq!(x.1, "some str"); + assert_eq!((x.2).0, 8); + assert_eq!((x.2).1, "deep str"); + assert_eq!((x.2).2.len(), 3); + assert_eq!(y[0], 1); + assert_eq!((x.2).2[1], 2); +} + + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +struct Bar; + +trait ToBar { + fn to_bar(&self) -> Bar; +} + +impl ToBar for Bar { + fn to_bar(&self) -> Bar { + *self + } +} + +pub fn main() { + // With a vec of ints. + let f1 = (5, "some str", [1, 2, 3]); + foo(&f1); + let f2 = &f1; + foo(f2); + let f3: &Fat<[isize]> = f2; + foo(f3); + let f4: &Fat<[isize]> = &f1; + foo(f4); + let f5: &Fat<[isize]> = &(5, "some str", [1, 2, 3]); + foo(f5); + + // With a vec of Bars. + let bar = Bar; + let f1 = (5, "some str", [bar, bar, bar]); + foo2(&f1); + let f2 = &f1; + foo2(f2); + let f3: &Fat<[Bar]> = f2; + foo2(f3); + let f4: &Fat<[Bar]> = &f1; + foo2(f4); + let f5: &Fat<[Bar]> = &(5, "some str", [bar, bar, bar]); + foo2(f5); + + // Assignment. + let f5: &mut Fat<[isize]> = &mut (5, "some str", [1, 2, 3]); + f5.2[1] = 34; + assert_eq!(f5.2[0], 1); + assert_eq!(f5.2[1], 34); + assert_eq!(f5.2[2], 3); + + // Zero size vec. + let f5: &Fat<[isize]> = &(5, "some str", []); + assert!(f5.2.is_empty()); + let f5: &Fat<[Bar]> = &(5, "some str", []); + assert!(f5.2.is_empty()); + + // Deeply nested. + let f1 = (5, "some str", (8, "deep str", [1, 2, 3])); + foo3(&f1); + let f2 = &f1; + foo3(f2); + let f3: &Fat> = f2; + foo3(f3); + let f4: &Fat> = &f1; + foo3(f4); + let f5: &Fat> = &(5, "some str", (8, "deep str", [1, 2, 3])); + foo3(f5); + + // Box. + let f1 = Box::new([1, 2, 3]); + assert_eq!((*f1)[1], 2); + let f2: Box<[isize]> = f1; + assert_eq!((*f2)[1], 2); + + // Nested Box. + let f1 : Box> = box (5, "some str", [1, 2, 3]); + foo(&*f1); + let f2 : Box> = f1; + foo(&*f2); + + let f3 : Box> = + Box::>::new((5, "some str", [1, 2, 3])); + foo(&*f3); +} From b0bf1b46820d74c30a725a7ea332305098bf3def Mon Sep 17 00:00:00 2001 From: Masaki Hara Date: Wed, 14 Jun 2017 12:27:51 +0900 Subject: [PATCH 082/162] Split dst-dtor-{1,2} tests into four. --- src/test/run-pass-valgrind/dst-dtor-1.rs | 3 +-- src/test/run-pass-valgrind/dst-dtor-2.rs | 3 +-- src/test/run-pass-valgrind/dst-dtor-3.rs | 32 ++++++++++++++++++++++++ src/test/run-pass-valgrind/dst-dtor-4.rs | 29 +++++++++++++++++++++ 4 files changed, 63 insertions(+), 4 deletions(-) create mode 100644 src/test/run-pass-valgrind/dst-dtor-3.rs create mode 100644 src/test/run-pass-valgrind/dst-dtor-4.rs diff --git a/src/test/run-pass-valgrind/dst-dtor-1.rs b/src/test/run-pass-valgrind/dst-dtor-1.rs index 00bfebb3f1e..4af642a106c 100644 --- a/src/test/run-pass-valgrind/dst-dtor-1.rs +++ b/src/test/run-pass-valgrind/dst-dtor-1.rs @@ -28,8 +28,7 @@ struct Fat { pub fn main() { { - let _x: Box<(i32, Fat)> = - Box::<(i32, Fat)>::new((42, Fat { f: Foo })); + let _x: Box> = Box::>::new(Fat { f: Foo }); } unsafe { assert!(DROP_RAN); diff --git a/src/test/run-pass-valgrind/dst-dtor-2.rs b/src/test/run-pass-valgrind/dst-dtor-2.rs index fa0c6c03225..283b8202b35 100644 --- a/src/test/run-pass-valgrind/dst-dtor-2.rs +++ b/src/test/run-pass-valgrind/dst-dtor-2.rs @@ -25,8 +25,7 @@ struct Fat { pub fn main() { { - let _x: Box<(Fat<[Foo]>,)> = - Box::<(Fat<[Foo; 3]>,)>::new((Fat { f: [Foo, Foo, Foo] },)); + let _x: Box> = Box::>::new(Fat { f: [Foo, Foo, Foo] }); } unsafe { assert_eq!(DROP_RAN, 3); diff --git a/src/test/run-pass-valgrind/dst-dtor-3.rs b/src/test/run-pass-valgrind/dst-dtor-3.rs new file mode 100644 index 00000000000..b21f6434b54 --- /dev/null +++ b/src/test/run-pass-valgrind/dst-dtor-3.rs @@ -0,0 +1,32 @@ +// 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. + +// no-prefer-dynamic + +static mut DROP_RAN: bool = false; + +struct Foo; +impl Drop for Foo { + fn drop(&mut self) { + unsafe { DROP_RAN = true; } + } +} + +trait Trait { fn dummy(&self) { } } +impl Trait for Foo {} + +pub fn main() { + { + let _x: Box<(i32, Trait)> = Box::<(i32, Foo)>::new((42, Foo)); + } + unsafe { + assert!(DROP_RAN); + } +} diff --git a/src/test/run-pass-valgrind/dst-dtor-4.rs b/src/test/run-pass-valgrind/dst-dtor-4.rs new file mode 100644 index 00000000000..810589de770 --- /dev/null +++ b/src/test/run-pass-valgrind/dst-dtor-4.rs @@ -0,0 +1,29 @@ +// 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. + +// no-prefer-dynamic + +static mut DROP_RAN: isize = 0; + +struct Foo; +impl Drop for Foo { + fn drop(&mut self) { + unsafe { DROP_RAN += 1; } + } +} + +pub fn main() { + { + let _x: Box<(i32, [Foo])> = Box::<(i32, [Foo; 3])>::new((42, [Foo, Foo, Foo])); + } + unsafe { + assert_eq!(DROP_RAN, 3); + } +} From 03660b647690c3dea12a20468f9f798bacd14d82 Mon Sep 17 00:00:00 2001 From: Masaki Hara Date: Sat, 24 Jun 2017 16:20:27 +0900 Subject: [PATCH 083/162] Move unsized_tuple_coercion behind a feature gate. --- .../unsized-tuple-coercion.md | 27 +++++++++++++++++++ src/librustc_typeck/check/coercion.rs | 21 ++++++++++++++- src/libsyntax/feature_gate.rs | 6 +++++ src/test/compile-fail/dst-bad-assign-3.rs | 2 ++ src/test/compile-fail/dst-bad-coerce1.rs | 2 ++ src/test/compile-fail/dst-bad-coerce3.rs | 2 ++ src/test/compile-fail/dst-bad-coerce4.rs | 2 ++ src/test/compile-fail/dst-bad-deep-2.rs | 2 ++ .../feature-gate-unsized_tuple_coercion.rs | 14 ++++++++++ src/test/run-pass-valgrind/dst-dtor-3.rs | 2 ++ src/test/run-pass-valgrind/dst-dtor-4.rs | 2 ++ src/test/run-pass/dst-irrefutable-bind.rs | 2 ++ src/test/run-pass/dst-raw.rs | 2 ++ src/test/run-pass/dst-trait-tuple.rs | 1 + src/test/run-pass/dst-tuple-sole.rs | 2 ++ src/test/run-pass/dst-tuple.rs | 1 + 16 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 src/doc/unstable-book/src/language-features/unsized-tuple-coercion.md create mode 100644 src/test/compile-fail/feature-gate-unsized_tuple_coercion.rs diff --git a/src/doc/unstable-book/src/language-features/unsized-tuple-coercion.md b/src/doc/unstable-book/src/language-features/unsized-tuple-coercion.md new file mode 100644 index 00000000000..c243737e1be --- /dev/null +++ b/src/doc/unstable-book/src/language-features/unsized-tuple-coercion.md @@ -0,0 +1,27 @@ +# `unsized_tuple_coercion` + +The tracking issue for this feature is: [#XXXXX] + +[#XXXXX]: https://github.com/rust-lang/rust/issues/XXXXX + +------------------------ + +This is a part of [RFC0401]. According to the RFC, there should be an implementation like this: + +```rust +impl<..., T, U: ?Sized> Unsized<(..., U)> for (..., T) where T: Unsized {} +``` + +This implementation is currently gated behind `#[feature(unsized_tuple_coercion)]` to avoid insta-stability. Therefore you can use it like this: + +```rust +#![feature(unsized_tuple_coercion)] + +fn main() { + let x : ([i32; 3], [i32; 3]) = ([1, 2, 3], [4, 5, 6]); + let y : &([i32; 3], [i32]) = &x; + assert_eq!(y.1[0], 4); +} +``` + +[RFC0401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index 81aa59e956a..968e893b9a0 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -76,6 +76,7 @@ use rustc::ty::relate::RelateResult; use rustc::ty::subst::Subst; use errors::DiagnosticBuilder; use syntax::abi; +use syntax::feature_gate; use syntax::ptr::P; use syntax_pos; @@ -520,6 +521,8 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { coerce_source, &[coerce_target])); + let mut has_unsized_tuple_coercion = false; + // Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid // emitting a coercion in cases like `Foo<$1>` -> `Foo<$2>`, where // inference might unify those two inner type variables later. @@ -527,7 +530,15 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { while let Some(obligation) = queue.pop_front() { debug!("coerce_unsized resolve step: {:?}", obligation); let trait_ref = match obligation.predicate { - ty::Predicate::Trait(ref tr) if traits.contains(&tr.def_id()) => tr.clone(), + ty::Predicate::Trait(ref tr) if traits.contains(&tr.def_id()) => { + if unsize_did == tr.def_id() { + if let ty::TyTuple(..) = tr.0.input_types().nth(1).unwrap().sty { + debug!("coerce_unsized: found unsized tuple coercion"); + has_unsized_tuple_coercion = true; + } + } + tr.clone() + } _ => { coercion.obligations.push(obligation); continue; @@ -557,6 +568,14 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { } } + if has_unsized_tuple_coercion && !self.tcx.sess.features.borrow().unsized_tuple_coercion { + feature_gate::emit_feature_err(&self.tcx.sess.parse_sess, + "unsized_tuple_coercion", + self.cause.span, + feature_gate::GateIssue::Language, + feature_gate::EXPLAIN_UNSIZED_TUPLE_COERCION); + } + Ok(coercion) } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 74bf19b841e..5de9062de74 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -357,6 +357,9 @@ declare_features! ( // Allows a test to fail without failing the whole suite (active, allow_fail, "1.19.0", Some(42219)), + + // Allows unsized tuple coercion. + (active, unsized_tuple_coercion, "1.20.0", None), ); declare_features! ( @@ -1041,6 +1044,9 @@ pub const EXPLAIN_VIS_MATCHER: &'static str = pub const EXPLAIN_PLACEMENT_IN: &'static str = "placement-in expression syntax is experimental and subject to change."; +pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &'static str = + "Unsized tuple coercion is not stable enough for use and is subject to change"; + struct PostExpansionVisitor<'a> { context: &'a Context<'a>, } diff --git a/src/test/compile-fail/dst-bad-assign-3.rs b/src/test/compile-fail/dst-bad-assign-3.rs index 3c089edf001..1c3bad5ba56 100644 --- a/src/test/compile-fail/dst-bad-assign-3.rs +++ b/src/test/compile-fail/dst-bad-assign-3.rs @@ -10,6 +10,8 @@ // Forbid assignment into a dynamically sized type. +#![feature(unsized_tuple_coercion)] + type Fat = (isize, &'static str, T); //~^ WARNING trait bounds are not (yet) enforced diff --git a/src/test/compile-fail/dst-bad-coerce1.rs b/src/test/compile-fail/dst-bad-coerce1.rs index 722ff8f25d6..b0de84a5300 100644 --- a/src/test/compile-fail/dst-bad-coerce1.rs +++ b/src/test/compile-fail/dst-bad-coerce1.rs @@ -10,6 +10,8 @@ // Attempt to change the type as well as unsizing. +#![feature(unsized_tuple_coercion)] + 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 4dedae9331b..35a147c15bb 100644 --- a/src/test/compile-fail/dst-bad-coerce3.rs +++ b/src/test/compile-fail/dst-bad-coerce3.rs @@ -10,6 +10,8 @@ // Attempt to extend the lifetime as well as unsizing. +#![feature(unsized_tuple_coercion)] + 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 2e78108a8de..874b7588ff9 100644 --- a/src/test/compile-fail/dst-bad-coerce4.rs +++ b/src/test/compile-fail/dst-bad-coerce4.rs @@ -10,6 +10,8 @@ // Attempt to coerce from unsized to sized. +#![feature(unsized_tuple_coercion)] + struct Fat { ptr: T } diff --git a/src/test/compile-fail/dst-bad-deep-2.rs b/src/test/compile-fail/dst-bad-deep-2.rs index 831afd27153..0c812b1d815 100644 --- a/src/test/compile-fail/dst-bad-deep-2.rs +++ b/src/test/compile-fail/dst-bad-deep-2.rs @@ -13,6 +13,8 @@ // because it would require stack allocation of an unsized temporary (*g in the // test). +#![feature(unsized_tuple_coercion)] + pub fn main() { let f: ([isize; 3],) = ([5, 6, 7],); let g: &([isize],) = &f; diff --git a/src/test/compile-fail/feature-gate-unsized_tuple_coercion.rs b/src/test/compile-fail/feature-gate-unsized_tuple_coercion.rs new file mode 100644 index 00000000000..4ddde011263 --- /dev/null +++ b/src/test/compile-fail/feature-gate-unsized_tuple_coercion.rs @@ -0,0 +1,14 @@ +// Copyright 2017 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 _ : &(Send,) = &((),); + //~^ ERROR Unsized tuple coercion is not stable enough +} diff --git a/src/test/run-pass-valgrind/dst-dtor-3.rs b/src/test/run-pass-valgrind/dst-dtor-3.rs index b21f6434b54..1ae66a28a84 100644 --- a/src/test/run-pass-valgrind/dst-dtor-3.rs +++ b/src/test/run-pass-valgrind/dst-dtor-3.rs @@ -10,6 +10,8 @@ // no-prefer-dynamic +#![feature(unsized_tuple_coercion)] + static mut DROP_RAN: bool = false; struct Foo; diff --git a/src/test/run-pass-valgrind/dst-dtor-4.rs b/src/test/run-pass-valgrind/dst-dtor-4.rs index 810589de770..e416f25bc03 100644 --- a/src/test/run-pass-valgrind/dst-dtor-4.rs +++ b/src/test/run-pass-valgrind/dst-dtor-4.rs @@ -10,6 +10,8 @@ // no-prefer-dynamic +#![feature(unsized_tuple_coercion)] + static mut DROP_RAN: isize = 0; struct Foo; diff --git a/src/test/run-pass/dst-irrefutable-bind.rs b/src/test/run-pass/dst-irrefutable-bind.rs index bd6ad9207ad..b1d6c732e7f 100644 --- a/src/test/run-pass/dst-irrefutable-bind.rs +++ b/src/test/run-pass/dst-irrefutable-bind.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(unsized_tuple_coercion)] + struct Test(T); fn main() { diff --git a/src/test/run-pass/dst-raw.rs b/src/test/run-pass/dst-raw.rs index c82cbd75044..9ebfbee8a33 100644 --- a/src/test/run-pass/dst-raw.rs +++ b/src/test/run-pass/dst-raw.rs @@ -11,6 +11,8 @@ // Test DST raw pointers +#![feature(unsized_tuple_coercion)] + trait Trait { fn foo(&self) -> isize; } diff --git a/src/test/run-pass/dst-trait-tuple.rs b/src/test/run-pass/dst-trait-tuple.rs index ab60e95c74e..9803e26f5f8 100644 --- a/src/test/run-pass/dst-trait-tuple.rs +++ b/src/test/run-pass/dst-trait-tuple.rs @@ -11,6 +11,7 @@ #![allow(unused_features)] #![feature(box_syntax)] +#![feature(unsized_tuple_coercion)] type Fat = (isize, &'static str, T); diff --git a/src/test/run-pass/dst-tuple-sole.rs b/src/test/run-pass/dst-tuple-sole.rs index d3901a7555f..a788e25218e 100644 --- a/src/test/run-pass/dst-tuple-sole.rs +++ b/src/test/run-pass/dst-tuple-sole.rs @@ -11,6 +11,8 @@ // As dst-tuple.rs, but the unsized field is the only field in the tuple. +#![feature(unsized_tuple_coercion)] + type Fat = (T,); // x is a fat pointer diff --git a/src/test/run-pass/dst-tuple.rs b/src/test/run-pass/dst-tuple.rs index 130294feb6c..2f5b28495b8 100644 --- a/src/test/run-pass/dst-tuple.rs +++ b/src/test/run-pass/dst-tuple.rs @@ -11,6 +11,7 @@ #![allow(unknown_features)] #![feature(box_syntax)] +#![feature(unsized_tuple_coercion)] type Fat = (isize, &'static str, T); From 141265dfe8eb345d3218c771db957a93d6c7f000 Mon Sep 17 00:00:00 2001 From: Masaki Hara Date: Sun, 25 Jun 2017 07:32:00 +0900 Subject: [PATCH 084/162] Give a tracking-issue number for unsized tuple coercion. --- .../src/language-features/unsized-tuple-coercion.md | 4 ++-- src/libsyntax/feature_gate.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/doc/unstable-book/src/language-features/unsized-tuple-coercion.md b/src/doc/unstable-book/src/language-features/unsized-tuple-coercion.md index c243737e1be..200a9c19462 100644 --- a/src/doc/unstable-book/src/language-features/unsized-tuple-coercion.md +++ b/src/doc/unstable-book/src/language-features/unsized-tuple-coercion.md @@ -1,8 +1,8 @@ # `unsized_tuple_coercion` -The tracking issue for this feature is: [#XXXXX] +The tracking issue for this feature is: [#42877] -[#XXXXX]: https://github.com/rust-lang/rust/issues/XXXXX +[#42877]: https://github.com/rust-lang/rust/issues/42877 ------------------------ diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 5de9062de74..df8ee189d21 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -359,7 +359,7 @@ declare_features! ( (active, allow_fail, "1.19.0", Some(42219)), // Allows unsized tuple coercion. - (active, unsized_tuple_coercion, "1.20.0", None), + (active, unsized_tuple_coercion, "1.20.0", Some(42877)), ); declare_features! ( From 94862c601be15a8edd93539244177f5a9145374d Mon Sep 17 00:00:00 2001 From: Masaki Hara Date: Thu, 29 Jun 2017 20:00:31 +0900 Subject: [PATCH 085/162] Correct comments about unsizing regarding #40319. --- src/librustc/traits/select.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 11169eefdaf..856fea7c2c4 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -2596,8 +2596,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let inner_source = field.subst(tcx, substs_a); let inner_target = field.subst(tcx, substs_b); - // Check that the source structure with the target's - // type parameters is a subtype of the target. + // Check that the source struct with the target's + // unsized parameters is equal to the target. let params = substs_a.iter().enumerate().map(|(i, &k)| { if ty_params.contains(i) { Kind::from(substs_b.type_at(i)) @@ -2635,7 +2635,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let b_last = tys_b.last().unwrap(); // Check that the source tuple with the target's - // last element is a subtype of the target. + // last element is equal to the target. let new_tuple = tcx.mk_tup(a_mid.iter().chain(Some(b_last)), false); let InferOk { obligations, .. } = self.infcx.at(&obligation.cause, obligation.param_env) From 176225c4ddd0dd6f469826b40b0cdae399b4a9c3 Mon Sep 17 00:00:00 2001 From: gaurikholkar Date: Mon, 12 Jun 2017 11:45:19 -0700 Subject: [PATCH 086/162] Adding diagnostic code 0611 for lifetime errors with one named, one anonymous lifetime parameter --- src/librustc/diagnostics.rs | 25 ++++ src/librustc/infer/error_reporting/mod.rs | 41 ++++--- .../error_reporting/named_anon_conflict.rs | 115 ++++++++++++++++++ src/librustc/infer/error_reporting/util.rs | 56 +++++++++ src/librustc/infer/mod.rs | 2 +- .../ex1-return-one-existing-name-if-else-2.rs | 15 +++ ...-return-one-existing-name-if-else-2.stderr | 10 ++ .../ex1-return-one-existing-name-if-else-3.rs | 15 +++ ...-return-one-existing-name-if-else-3.stderr | 10 ++ ...one-existing-name-if-else-using-closure.rs | 24 ++++ ...existing-name-if-else-using-closure.stderr | 29 +++++ ...x1-return-one-existing-name-if-else.stderr | 23 +--- .../ex2a-push-one-existing-name-2.rs | 19 +++ .../ex2a-push-one-existing-name-2.stderr | 10 ++ .../ex2a-push-one-existing-name.stderr | 25 +--- 15 files changed, 365 insertions(+), 54 deletions(-) create mode 100644 src/librustc/infer/error_reporting/named_anon_conflict.rs create mode 100644 src/librustc/infer/error_reporting/util.rs create mode 100644 src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.rs create mode 100644 src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.stderr create mode 100644 src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.rs create mode 100644 src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.stderr create mode 100644 src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-closure.rs create mode 100644 src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-closure.stderr create mode 100644 src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.rs create mode 100644 src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.stderr diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 5e36bd8ec27..1e7f3f9aeb8 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -1946,6 +1946,31 @@ Maybe you just misspelled the lint name or the lint doesn't exist anymore. Either way, try to update/remove it in order to fix the error. "##, +E0611: r##" +Lifetime parameter is missing in one of the function argument. Erroneous +code example: + +```compile_fail,E0611 +fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 { // explicit lifetime required + // in the type of `y` + if x > y { x } else { y } +} + +fn main () { } +``` + +Please add the missing lifetime parameter to remove this error. Example: + +``` +fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 { + if x > y { x } else { y } +} + +fn main() { +} +``` +"##, + } diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 11bac21bc42..1bc01ab858c 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -67,14 +67,17 @@ use hir::def_id::DefId; use middle::region; use traits::{ObligationCause, ObligationCauseCode}; use ty::{self, TyCtxt, TypeFoldable}; -use ty::{Region, Issue32330}; +use ty::{Region, Issue32330 }; use ty::error::TypeError; use syntax::ast::DUMMY_NODE_ID; use syntax_pos::{Pos, Span}; use errors::{DiagnosticBuilder, DiagnosticStyledString}; - mod note; + mod need_type_info; +mod named_anon_conflict; +mod util; + impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn note_and_explain_region(self, @@ -255,34 +258,42 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { - pub fn report_region_errors(&self, - errors: &Vec>) { + + pub fn report_region_errors(&self, errors: &Vec>) { debug!("report_region_errors(): {} errors to start", errors.len()); // try to pre-process the errors, which will group some of them // together into a `ProcessedErrors` group: let errors = self.process_errors(errors); - debug!("report_region_errors: {} errors after preprocessing", errors.len()); + debug!("report_region_errors: {} errors after preprocessing", + errors.len()); for error in errors { + debug!("report_region_errors: error = {:?}", error); - match error.clone() { - ConcreteFailure(origin, sub, sup) => { - self.report_concrete_failure(origin, sub, sup).emit(); - } + // If ConcreteFailure does not have an anonymous region + if !self.report_named_anon_conflict(&error){ - GenericBoundFailure(kind, param_ty, sub) => { - self.report_generic_bound_failure(kind, param_ty, sub); - } + match error.clone() { - SubSupConflict(var_origin, + ConcreteFailure(origin, sub, sup) => { + + self.report_concrete_failure(origin, sub, sup).emit(); + } + + GenericBoundFailure(kind, param_ty, sub) => { + self.report_generic_bound_failure(kind, param_ty, sub); + } + + SubSupConflict(var_origin, sub_origin, sub_r, sup_origin, sup_r) => { - self.report_sub_sup_conflict(var_origin, + self.report_sub_sup_conflict(var_origin, sub_origin, sub_r, sup_origin, sup_r); - } + } + } } } } diff --git a/src/librustc/infer/error_reporting/named_anon_conflict.rs b/src/librustc/infer/error_reporting/named_anon_conflict.rs new file mode 100644 index 00000000000..d48cb398ec2 --- /dev/null +++ b/src/librustc/infer/error_reporting/named_anon_conflict.rs @@ -0,0 +1,115 @@ +// 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. +// +// 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. + +//! Error Reporting for Anonymous Region Lifetime Errors. +use hir; +use infer::InferCtxt; +use ty::{self, Region}; +use infer::region_inference::RegionResolutionError::*; +use infer::region_inference::RegionResolutionError; + +impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { + // This method walks the Type of the function body arguments using + // `fold_regions()` function and returns the + // &hir::Arg of the function argument corresponding to the anonymous + // region and the Ty corresponding to the named region. + // Currently only the case where the function declaration consists of + // one named region and one anonymous region is handled. + // Consider the example `fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32` + // Here, the `y` and the `Ty` of `y` is returned after being substituted + // by that of the named region. + pub fn find_arg_with_anonymous_region(&self, + anon_region: Region<'tcx>, + named_region: Region<'tcx>) + -> Option<(&hir::Arg, ty::Ty<'tcx>)> { + + match *anon_region { + ty::ReFree(ref free_region) => { + + let id = free_region.scope; + let node_id = self.tcx.hir.as_local_node_id(id).unwrap(); + let body_id = self.tcx.hir.maybe_body_owned_by(node_id).unwrap(); + + let body = self.tcx.hir.body(body_id); + body.arguments + .iter() + .filter_map(|arg| if let Some(tables) = self.in_progress_tables { + let ty = tables.borrow().node_id_to_type(arg.id); + let mut found_anon_region = false; + let new_arg_ty = self.tcx + .fold_regions(&ty, + &mut false, + |r, _| if *r == *anon_region { + found_anon_region = true; + named_region + } else { + r + }); + if found_anon_region { + return Some((arg, new_arg_ty)); + } else { + None + } + } else { + None + }) + .next() + } + _ => None, + } + + } + + // This method generates the error message for the case when + // the function arguments consist of a named region and an anonymous + // region and corresponds to `ConcreteFailure(..)` + pub fn report_named_anon_conflict(&self, error: &RegionResolutionError<'tcx>) -> bool { + + let (span, sub, sup) = match *error { + ConcreteFailure(ref origin, sub, sup) => (origin.span(), sub, sup), + _ => return false, // inapplicable + }; + + let (named, (var, new_ty)) = + if self.is_named_region(sub) && self.is_anonymous_region(sup) { + (sub, self.find_arg_with_anonymous_region(sup, sub).unwrap()) + } else if self.is_named_region(sup) && self.is_anonymous_region(sub) { + (sup, self.find_arg_with_anonymous_region(sub, sup).unwrap()) + } else { + return false; // inapplicable + }; + + if let Some(simple_name) = var.pat.simple_name() { + struct_span_err!(self.tcx.sess, + var.pat.span, + E0611, + "explicit lifetime required in the type of `{}`", + simple_name) + .span_label(var.pat.span, + format!("consider changing the type of `{}` to `{}`", + simple_name, + new_ty)) + .span_label(span, format!("lifetime `{}` required", named)) + .emit(); + + } else { + struct_span_err!(self.tcx.sess, + var.pat.span, + E0611, + "explicit lifetime required in parameter type") + .span_label(var.pat.span, + format!("consider changing type to `{}`", new_ty)) + .span_label(span, format!("lifetime `{}` required", named)) + .emit(); + } + return true; + + } +} diff --git a/src/librustc/infer/error_reporting/util.rs b/src/librustc/infer/error_reporting/util.rs new file mode 100644 index 00000000000..ea0c706d8aa --- /dev/null +++ b/src/librustc/infer/error_reporting/util.rs @@ -0,0 +1,56 @@ +// 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. +// +// 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. + +//! Helper for error reporting code for named_anon_conflict + +use ty::{self, Region}; +use infer::InferCtxt; +use hir::map as hir_map; + +impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { + // This method returns whether the given Region is Named + pub fn is_named_region(&self, region: Region<'tcx>) -> bool { + + match *region { + ty::ReFree(ref free_region) => { + match free_region.bound_region { + ty::BrNamed(..) => true, + _ => false, + } + } + _ => false, + } + } + + // This method returns whether the given Region is Anonymous + pub fn is_anonymous_region(&self, region: Region<'tcx>) -> bool { + + match *region { + ty::ReFree(ref free_region) => { + match free_region.bound_region { + ty::BrAnon(..) => { + let id = free_region.scope; + let node_id = self.tcx.hir.as_local_node_id(id).unwrap(); + match self.tcx.hir.find(node_id) { + Some(hir_map::NodeItem(..)) | + Some(hir_map::NodeImplItem(..)) | + Some(hir_map::NodeTraitItem(..)) => { /* proceed ahead */ } + _ => return false, // inapplicable + // we target only top-level functions + } + return true; + } + _ => false, + } + } + _ => false, + } + } +} diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index d5020b12ee0..07de44c9294 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -38,7 +38,6 @@ use errors::DiagnosticBuilder; use syntax_pos::{self, Span, DUMMY_SP}; use util::nodemap::FxHashMap; use arena::DroplessArena; - use self::combine::CombineFields; use self::higher_ranked::HrMatchResult; use self::region_inference::{RegionVarBindings, RegionSnapshot}; @@ -1077,6 +1076,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { region_map, free_regions); let errors = self.region_vars.resolve_regions(®ion_rels); + if !self.is_tainted_by_errors() { // As a heuristic, just skip reporting region errors // altogether if other errors have been reported while diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.rs b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.rs new file mode 100644 index 00000000000..a1716c4e797 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.rs @@ -0,0 +1,15 @@ +// Copyright 2016 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 foo<'a>(x: &i32, y: &'a i32) -> &'a i32 { + if x > y { x } else { y } +} + +fn main() { } diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.stderr new file mode 100644 index 00000000000..a04a9461eb4 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.stderr @@ -0,0 +1,10 @@ +error[E0611]: explicit lifetime required in the type of `x` + --> $DIR/ex1-return-one-existing-name-if-else-2.rs:11:12 + | +11 | fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 { + | ^ consider changing the type of `x` to `&'a i32` +12 | if x > y { x } else { y } + | - lifetime `'a` required + +error: aborting due to previous error(s) + diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.rs b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.rs new file mode 100644 index 00000000000..7bd32d87617 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.rs @@ -0,0 +1,15 @@ +// Copyright 2016 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 foo<'a>((x, y): (&'a i32, &i32)) -> &'a i32 { + if x > y { x } else { y } +} + +fn main () { } diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.stderr new file mode 100644 index 00000000000..143021cbbdd --- /dev/null +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.stderr @@ -0,0 +1,10 @@ +error[E0611]: explicit lifetime required in parameter type + --> $DIR/ex1-return-one-existing-name-if-else-3.rs:11:12 + | +11 | fn foo<'a>((x, y): (&'a i32, &i32)) -> &'a i32 { + | ^^^^^^ consider changing type to `(&'a i32, &'a i32)` +12 | if x > y { x } else { y } + | - lifetime `'a` required + +error: aborting due to previous error(s) + diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-closure.rs b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-closure.rs new file mode 100644 index 00000000000..faf4fe547bf --- /dev/null +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-closure.rs @@ -0,0 +1,24 @@ +// Copyright 2016 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 invoke<'a, F>(x: &'a i32, f: F) -> &'a i32 +where F: FnOnce(&'a i32, &i32) -> &'a i32 +{ + let y = 22; + f(x, &y) +} + +fn foo<'a>(x: &'a i32) { + invoke(&x, |a, b| if a > b { a } else { b }); +} + +fn main() { +} + diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-closure.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-closure.stderr new file mode 100644 index 00000000000..c96ff9bc114 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-closure.stderr @@ -0,0 +1,29 @@ +error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements + --> $DIR/ex1-return-one-existing-name-if-else-using-closure.rs:19:5 + | +19 | invoke(&x, |a, b| if a > b { a } else { b }); + | ^^^^^^ + | +note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 19:16... + --> $DIR/ex1-return-one-existing-name-if-else-using-closure.rs:19:16 + | +19 | invoke(&x, |a, b| if a > b { a } else { b }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...so that reference does not outlive borrowed content + --> $DIR/ex1-return-one-existing-name-if-else-using-closure.rs:19:45 + | +19 | invoke(&x, |a, b| if a > b { a } else { b }); + | ^ +note: but, the lifetime must be valid for the call at 19:5... + --> $DIR/ex1-return-one-existing-name-if-else-using-closure.rs:19:5 + | +19 | invoke(&x, |a, b| if a > b { a } else { b }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...so that argument is valid for the call + --> $DIR/ex1-return-one-existing-name-if-else-using-closure.rs:19:12 + | +19 | invoke(&x, |a, b| if a > b { a } else { b }); + | ^^ + +error: aborting due to previous error(s) + diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.stderr index 0ab24b0b3e6..84f166dfa30 100644 --- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.stderr +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.stderr @@ -1,23 +1,10 @@ -error[E0312]: lifetime of reference outlives lifetime of borrowed content... - --> $DIR/ex1-return-one-existing-name-if-else.rs:12:27 +error[E0611]: explicit lifetime required in the type of `y` + --> $DIR/ex1-return-one-existing-name-if-else.rs:11:24 | +11 | fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 { + | ^ consider changing the type of `y` to `&'a i32` 12 | if x > y { x } else { y } - | ^ - | -note: ...the reference is valid for the lifetime 'a as defined on the function body at 11:1... - --> $DIR/ex1-return-one-existing-name-if-else.rs:11:1 - | -11 | / fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 { -12 | | if x > y { x } else { y } -13 | | } - | |_^ -note: ...but the borrowed content is only valid for the anonymous lifetime #1 defined on the function body at 11:1 - --> $DIR/ex1-return-one-existing-name-if-else.rs:11:1 - | -11 | / fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 { -12 | | if x > y { x } else { y } -13 | | } - | |_^ + | - lifetime `'a` required error: aborting due to previous error(s) diff --git a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.rs b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.rs new file mode 100644 index 00000000000..dd34e1aa6d9 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.rs @@ -0,0 +1,19 @@ +// Copyright 2016 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 Ref<'a, T: 'a> { + data: &'a T +} + +fn foo<'a>(x: Ref, y: &mut Vec>) { + y.push(x); +} + +fn main() { } diff --git a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.stderr b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.stderr new file mode 100644 index 00000000000..61e97dc2bcd --- /dev/null +++ b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.stderr @@ -0,0 +1,10 @@ +error[E0611]: explicit lifetime required in the type of `x` + --> $DIR/ex2a-push-one-existing-name-2.rs:15:12 + | +15 | fn foo<'a>(x: Ref, y: &mut Vec>) { + | ^ consider changing the type of `x` to `Ref<'a, i32>` +16 | y.push(x); + | - lifetime `'a` required + +error: aborting due to previous error(s) + diff --git a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr index 7d0947b364e..51d86a1f964 100644 --- a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr +++ b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr @@ -1,25 +1,10 @@ -error[E0308]: mismatched types - --> $DIR/ex2a-push-one-existing-name.rs:16:12 +error[E0611]: explicit lifetime required in the type of `y` + --> $DIR/ex2a-push-one-existing-name.rs:15:39 | +15 | fn foo<'a>(x: &mut Vec>, y: Ref) { + | ^ consider changing the type of `y` to `Ref<'a, i32>` 16 | x.push(y); - | ^ lifetime mismatch - | - = note: expected type `Ref<'a, _>` - found type `Ref<'_, _>` -note: the anonymous lifetime #2 defined on the function body at 15:1... - --> $DIR/ex2a-push-one-existing-name.rs:15:1 - | -15 | / fn foo<'a>(x: &mut Vec>, y: Ref) { -16 | | x.push(y); -17 | | } - | |_^ -note: ...does not necessarily outlive the lifetime 'a as defined on the function body at 15:1 - --> $DIR/ex2a-push-one-existing-name.rs:15:1 - | -15 | / fn foo<'a>(x: &mut Vec>, y: Ref) { -16 | | x.push(y); -17 | | } - | |_^ + | - lifetime `'a` required error: aborting due to previous error(s) From 5df7a2c86334e89abf813b786bd03375bf62e770 Mon Sep 17 00:00:00 2001 From: gaurikholkar Date: Thu, 15 Jun 2017 03:50:02 -0700 Subject: [PATCH 087/162] Adding new ui test for trait impl --- src/librustc/infer/error_reporting/util.rs | 1 - ...rn-one-existing-name-if-else-using-impl.rs | 27 +++++++++++++++++++ ...ne-existing-name-if-else-using-impl.stderr | 27 +++++++++++++++++++ 3 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.rs create mode 100644 src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.stderr diff --git a/src/librustc/infer/error_reporting/util.rs b/src/librustc/infer/error_reporting/util.rs index ea0c706d8aa..38bb3e93d00 100644 --- a/src/librustc/infer/error_reporting/util.rs +++ b/src/librustc/infer/error_reporting/util.rs @@ -40,7 +40,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let node_id = self.tcx.hir.as_local_node_id(id).unwrap(); match self.tcx.hir.find(node_id) { Some(hir_map::NodeItem(..)) | - Some(hir_map::NodeImplItem(..)) | Some(hir_map::NodeTraitItem(..)) => { /* proceed ahead */ } _ => return false, // inapplicable // we target only top-level functions diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.rs b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.rs new file mode 100644 index 00000000000..36d956a3996 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.rs @@ -0,0 +1,27 @@ +// Copyright 2016 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 Foo { + + fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32; + +} + +impl Foo for () { + + fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 { + + if x > y { x } else { y } + + } + +} + +fn main() {} diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.stderr new file mode 100644 index 00000000000..15ecca61805 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.stderr @@ -0,0 +1,27 @@ +error[E0312]: lifetime of reference outlives lifetime of borrowed content... + --> $DIR/ex1-return-one-existing-name-if-else-using-impl.rs:21:20 + | +21 | if x > y { x } else { y } + | ^ + | +note: ...the reference is valid for the lifetime 'a as defined on the method body at 19:5... + --> $DIR/ex1-return-one-existing-name-if-else-using-impl.rs:19:5 + | +19 | / fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 { +20 | | +21 | | if x > y { x } else { y } +22 | | +23 | | } + | |_____^ +note: ...but the borrowed content is only valid for the anonymous lifetime #1 defined on the method body at 19:5 + --> $DIR/ex1-return-one-existing-name-if-else-using-impl.rs:19:5 + | +19 | / fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 { +20 | | +21 | | if x > y { x } else { y } +22 | | +23 | | } + | |_____^ + +error: aborting due to previous error(s) + From 4bed5f0094b632ec2a10d73074fcd02e289e20cc Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 15 Jun 2017 15:01:44 -0400 Subject: [PATCH 088/162] update reference for test --- ...turn-one-existing-name-if-else-using-closure.stderr | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-closure.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-closure.stderr index c96ff9bc114..20104afae51 100644 --- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-closure.stderr +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-closure.stderr @@ -14,16 +14,16 @@ note: ...so that reference does not outlive borrowed content | 19 | invoke(&x, |a, b| if a > b { a } else { b }); | ^ -note: but, the lifetime must be valid for the call at 19:5... +note: but, the lifetime must be valid for the expression at 19:5... --> $DIR/ex1-return-one-existing-name-if-else-using-closure.rs:19:5 | 19 | invoke(&x, |a, b| if a > b { a } else { b }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...so that argument is valid for the call - --> $DIR/ex1-return-one-existing-name-if-else-using-closure.rs:19:12 + | ^^^^^^ +note: ...so that a type/lifetime parameter is in scope here + --> $DIR/ex1-return-one-existing-name-if-else-using-closure.rs:19:5 | 19 | invoke(&x, |a, b| if a > b { a } else { b }); - | ^^ + | ^^^^^^ error: aborting due to previous error(s) From ae92bd095c16c3aa14b986b089a1ded8df4c8369 Mon Sep 17 00:00:00 2001 From: gaurikholkar Date: Thu, 15 Jun 2017 13:53:49 -0700 Subject: [PATCH 089/162] Interchange ^ and - --- src/librustc/infer/error_reporting/named_anon_conflict.rs | 4 ++-- .../ex1-return-one-existing-name-if-else-2.stderr | 6 +++--- .../ex1-return-one-existing-name-if-else-3.stderr | 6 +++--- .../ex1-return-one-existing-name-if-else.stderr | 6 +++--- .../ui/lifetime-errors/ex2a-push-one-existing-name-2.stderr | 6 +++--- .../ui/lifetime-errors/ex2a-push-one-existing-name.stderr | 6 +++--- 6 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/librustc/infer/error_reporting/named_anon_conflict.rs b/src/librustc/infer/error_reporting/named_anon_conflict.rs index d48cb398ec2..77af2216910 100644 --- a/src/librustc/infer/error_reporting/named_anon_conflict.rs +++ b/src/librustc/infer/error_reporting/named_anon_conflict.rs @@ -88,7 +88,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { if let Some(simple_name) = var.pat.simple_name() { struct_span_err!(self.tcx.sess, - var.pat.span, + span, E0611, "explicit lifetime required in the type of `{}`", simple_name) @@ -101,7 +101,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } else { struct_span_err!(self.tcx.sess, - var.pat.span, + span, E0611, "explicit lifetime required in parameter type") .span_label(var.pat.span, diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.stderr index a04a9461eb4..ada7af8c1e4 100644 --- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.stderr +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.stderr @@ -1,10 +1,10 @@ error[E0611]: explicit lifetime required in the type of `x` - --> $DIR/ex1-return-one-existing-name-if-else-2.rs:11:12 + --> $DIR/ex1-return-one-existing-name-if-else-2.rs:12:16 | 11 | fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 { - | ^ consider changing the type of `x` to `&'a i32` + | - consider changing the type of `x` to `&'a i32` 12 | if x > y { x } else { y } - | - lifetime `'a` required + | ^ lifetime `'a` required error: aborting due to previous error(s) diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.stderr index 143021cbbdd..58aab711394 100644 --- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.stderr +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.stderr @@ -1,10 +1,10 @@ error[E0611]: explicit lifetime required in parameter type - --> $DIR/ex1-return-one-existing-name-if-else-3.rs:11:12 + --> $DIR/ex1-return-one-existing-name-if-else-3.rs:12:27 | 11 | fn foo<'a>((x, y): (&'a i32, &i32)) -> &'a i32 { - | ^^^^^^ consider changing type to `(&'a i32, &'a i32)` + | ------ consider changing type to `(&'a i32, &'a i32)` 12 | if x > y { x } else { y } - | - lifetime `'a` required + | ^ lifetime `'a` required error: aborting due to previous error(s) diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.stderr index 84f166dfa30..837fa141bf1 100644 --- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.stderr +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.stderr @@ -1,10 +1,10 @@ error[E0611]: explicit lifetime required in the type of `y` - --> $DIR/ex1-return-one-existing-name-if-else.rs:11:24 + --> $DIR/ex1-return-one-existing-name-if-else.rs:12:27 | 11 | fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 { - | ^ consider changing the type of `y` to `&'a i32` + | - consider changing the type of `y` to `&'a i32` 12 | if x > y { x } else { y } - | - lifetime `'a` required + | ^ lifetime `'a` required error: aborting due to previous error(s) diff --git a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.stderr b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.stderr index 61e97dc2bcd..a16dac672ae 100644 --- a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.stderr +++ b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.stderr @@ -1,10 +1,10 @@ error[E0611]: explicit lifetime required in the type of `x` - --> $DIR/ex2a-push-one-existing-name-2.rs:15:12 + --> $DIR/ex2a-push-one-existing-name-2.rs:16:12 | 15 | fn foo<'a>(x: Ref, y: &mut Vec>) { - | ^ consider changing the type of `x` to `Ref<'a, i32>` + | - consider changing the type of `x` to `Ref<'a, i32>` 16 | y.push(x); - | - lifetime `'a` required + | ^ lifetime `'a` required error: aborting due to previous error(s) diff --git a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr index 51d86a1f964..537090aa67d 100644 --- a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr +++ b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr @@ -1,10 +1,10 @@ error[E0611]: explicit lifetime required in the type of `y` - --> $DIR/ex2a-push-one-existing-name.rs:15:39 + --> $DIR/ex2a-push-one-existing-name.rs:16:12 | 15 | fn foo<'a>(x: &mut Vec>, y: Ref) { - | ^ consider changing the type of `y` to `Ref<'a, i32>` + | - consider changing the type of `y` to `Ref<'a, i32>` 16 | x.push(y); - | - lifetime `'a` required + | ^ lifetime `'a` required error: aborting due to previous error(s) From 8fb6f74e57f6c75113074b56f48b16992c5ce1e1 Mon Sep 17 00:00:00 2001 From: gaurikholkar Date: Sat, 17 Jun 2017 16:27:07 -0700 Subject: [PATCH 090/162] Enabling E0611 for inherent functions --- src/librustc/infer/error_reporting/mod.rs | 14 +++- .../error_reporting/named_anon_conflict.rs | 77 +++++++++++++++---- src/librustc/infer/error_reporting/util.rs | 25 ------ ...-one-existing-name-if-else-using-impl-2.rs | 18 +++++ ...-existing-name-if-else-using-impl-2.stderr | 10 +++ ...-one-existing-name-if-else-using-impl-3.rs | 24 ++++++ ...-existing-name-if-else-using-impl-3.stderr | 11 +++ 7 files changed, 137 insertions(+), 42 deletions(-) create mode 100644 src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.rs create mode 100644 src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.stderr create mode 100644 src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.rs create mode 100644 src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 1bc01ab858c..b3f7f2d3764 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -67,7 +67,7 @@ use hir::def_id::DefId; use middle::region; use traits::{ObligationCause, ObligationCauseCode}; use ty::{self, TyCtxt, TypeFoldable}; -use ty::{Region, Issue32330 }; +use ty::{Region, Issue32330}; use ty::error::TypeError; use syntax::ast::DUMMY_NODE_ID; use syntax_pos::{Pos, Span}; @@ -272,11 +272,17 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { for error in errors { debug!("report_region_errors: error = {:?}", error); - // If ConcreteFailure does not have an anonymous region - if !self.report_named_anon_conflict(&error){ + + if !self.try_report_named_anon_conflict(&error){ match error.clone() { - + // These errors could indicate all manner of different + // problems with many different solutions. Rather + // than generate a "one size fits all" error, what we + // attempt to do is go through a number of specific + // scenarios and try to find the best way to present + // the error. If all of these fails, we fall back to a rather + // general bit of code that displays the error information ConcreteFailure(origin, sub, sup) => { self.report_concrete_failure(origin, sub, sup).emit(); diff --git a/src/librustc/infer/error_reporting/named_anon_conflict.rs b/src/librustc/infer/error_reporting/named_anon_conflict.rs index 77af2216910..8af9381107b 100644 --- a/src/librustc/infer/error_reporting/named_anon_conflict.rs +++ b/src/librustc/infer/error_reporting/named_anon_conflict.rs @@ -14,6 +14,7 @@ use infer::InferCtxt; use ty::{self, Region}; use infer::region_inference::RegionResolutionError::*; use infer::region_inference::RegionResolutionError; +use hir::map as hir_map; impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // This method walks the Type of the function body arguments using @@ -23,12 +24,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // Currently only the case where the function declaration consists of // one named region and one anonymous region is handled. // Consider the example `fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32` - // Here, the `y` and the `Ty` of `y` is returned after being substituted - // by that of the named region. - pub fn find_arg_with_anonymous_region(&self, - anon_region: Region<'tcx>, - named_region: Region<'tcx>) - -> Option<(&hir::Arg, ty::Ty<'tcx>)> { + // Here, we would return the hir::Arg for y, and we return the type &'a + // i32, which is the type of y but with the anonymous region replaced + // with 'a. + fn find_arg_with_anonymous_region(&self, + anon_region: Region<'tcx>, + named_region: Region<'tcx>) + -> Option<(&hir::Arg, ty::Ty<'tcx>)> { match *anon_region { ty::ReFree(ref free_region) => { @@ -70,29 +72,35 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // This method generates the error message for the case when // the function arguments consist of a named region and an anonymous // region and corresponds to `ConcreteFailure(..)` - pub fn report_named_anon_conflict(&self, error: &RegionResolutionError<'tcx>) -> bool { + pub fn try_report_named_anon_conflict(&self, error: &RegionResolutionError<'tcx>) -> bool { let (span, sub, sup) = match *error { ConcreteFailure(ref origin, sub, sup) => (origin.span(), sub, sup), _ => return false, // inapplicable }; - let (named, (var, new_ty)) = - if self.is_named_region(sub) && self.is_anonymous_region(sup) { + // Determine whether the sub and sup consist of one named region ('a) + // and one anonymous (elided) region. If so, find the parameter arg + // where the anonymous region appears (there must always be one; we + // only introduced anonymous regions in parameters) as well as a + // version new_ty of its type where the anonymous region is replaced + // with the named one. + let (named, (arg, new_ty)) = + if self.is_named_region(sub) && self.is_suitable_anonymous_region(sup) { (sub, self.find_arg_with_anonymous_region(sup, sub).unwrap()) - } else if self.is_named_region(sup) && self.is_anonymous_region(sub) { + } else if self.is_named_region(sup) && self.is_suitable_anonymous_region(sub) { (sup, self.find_arg_with_anonymous_region(sub, sup).unwrap()) } else { return false; // inapplicable }; - if let Some(simple_name) = var.pat.simple_name() { + if let Some(simple_name) = arg.pat.simple_name() { struct_span_err!(self.tcx.sess, span, E0611, "explicit lifetime required in the type of `{}`", simple_name) - .span_label(var.pat.span, + .span_label(arg.pat.span, format!("consider changing the type of `{}` to `{}`", simple_name, new_ty)) @@ -104,7 +112,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { span, E0611, "explicit lifetime required in parameter type") - .span_label(var.pat.span, + .span_label(arg.pat.span, format!("consider changing type to `{}`", new_ty)) .span_label(span, format!("lifetime `{}` required", named)) .emit(); @@ -112,4 +120,47 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { return true; } + + // This method returns whether the given Region is Anonymous + pub fn is_suitable_anonymous_region(&self, region: Region<'tcx>) -> bool { + + match *region { + ty::ReFree(ref free_region) => { + match free_region.bound_region { + ty::BrAnon(..) => { + let anonymous_region_binding_scope = free_region.scope; + let node_id = self.tcx + .hir + .as_local_node_id(anonymous_region_binding_scope) + .unwrap(); + match self.tcx.hir.find(node_id) { + Some(hir_map::NodeItem(..)) | + Some(hir_map::NodeTraitItem(..)) => { + // proceed ahead // + } + Some(hir_map::NodeImplItem(..)) => { + if self.tcx.impl_trait_ref(self.tcx. +associated_item(anonymous_region_binding_scope).container.id()).is_some() { + // For now, we do not try to target impls of traits. This is + // because this message is going to suggest that the user + // change the fn signature, but they may not be free to do so, + // since the signature must match the trait. + // + // FIXME(#42706) -- in some cases, we could do better here. + return false;//None; + } + else{ } + + } + _ => return false, // inapplicable + // we target only top-level functions + } + return true; + } + _ => false, + } + } + _ => false, + } + } } diff --git a/src/librustc/infer/error_reporting/util.rs b/src/librustc/infer/error_reporting/util.rs index 38bb3e93d00..66c351b49ac 100644 --- a/src/librustc/infer/error_reporting/util.rs +++ b/src/librustc/infer/error_reporting/util.rs @@ -12,7 +12,6 @@ use ty::{self, Region}; use infer::InferCtxt; -use hir::map as hir_map; impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // This method returns whether the given Region is Named @@ -28,28 +27,4 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { _ => false, } } - - // This method returns whether the given Region is Anonymous - pub fn is_anonymous_region(&self, region: Region<'tcx>) -> bool { - - match *region { - ty::ReFree(ref free_region) => { - match free_region.bound_region { - ty::BrAnon(..) => { - let id = free_region.scope; - let node_id = self.tcx.hir.as_local_node_id(id).unwrap(); - match self.tcx.hir.find(node_id) { - Some(hir_map::NodeItem(..)) | - Some(hir_map::NodeTraitItem(..)) => { /* proceed ahead */ } - _ => return false, // inapplicable - // we target only top-level functions - } - return true; - } - _ => false, - } - } - _ => false, - } - } } diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.rs b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.rs new file mode 100644 index 00000000000..8849f7084b3 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.rs @@ -0,0 +1,18 @@ +// Copyright 2016 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 Foo { + +fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 { + if x > y { x } else { y } + } +} + +fn main() { } diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.stderr new file mode 100644 index 00000000000..ec787eb749c --- /dev/null +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.stderr @@ -0,0 +1,10 @@ +error[E0611]: explicit lifetime required in the type of `x` + --> $DIR/ex1-return-one-existing-name-if-else-using-impl-2.rs:14:15 + | +13 | fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 { + | - consider changing the type of `x` to `&'a i32` +14 | if x > y { x } else { y } + | ^ lifetime `'a` required + +error: aborting due to previous error(s) + diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.rs b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.rs new file mode 100644 index 00000000000..60f794279a5 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.rs @@ -0,0 +1,24 @@ +// Copyright 2016 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 Foo { + field: i32 +} + +impl Foo { + fn foo<'a>(&'a self, x: &i32) -> &i32 { + + if true { &self.field } else { x } + + } + +} + +fn main() { } diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr new file mode 100644 index 00000000000..cedceb559d5 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr @@ -0,0 +1,11 @@ +error[E0611]: explicit lifetime required in the type of `x` + --> $DIR/ex1-return-one-existing-name-if-else-using-impl-3.rs:18:36 + | +16 | fn foo<'a>(&'a self, x: &i32) -> &i32 { + | - consider changing the type of `x` to `&'a i32` +17 | +18 | if true { &self.field } else { x } + | ^ lifetime `'a` required + +error: aborting due to previous error(s) + From 2d99ffd11b28357ed989a9641ed94ea384659d51 Mon Sep 17 00:00:00 2001 From: gaurikholkar Date: Tue, 20 Jun 2017 06:42:11 -0700 Subject: [PATCH 091/162] track anonymous regions in return types, fix tidy errors --- src/librustc/infer/error_reporting/mod.rs | 2 +- .../error_reporting/named_anon_conflict.rs | 53 +++++++++++++------ ...-one-existing-name-if-else-using-impl-3.rs | 2 +- ...n-one-existing-name-return-type-is-anon.rs | 24 +++++++++ ...e-existing-name-return-type-is-anon.stderr | 27 ++++++++++ 5 files changed, 91 insertions(+), 17 deletions(-) create mode 100644 src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.rs create mode 100644 src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index b3f7f2d3764..9e2d922b932 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -272,7 +272,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { for error in errors { debug!("report_region_errors: error = {:?}", error); - + if !self.try_report_named_anon_conflict(&error){ match error.clone() { diff --git a/src/librustc/infer/error_reporting/named_anon_conflict.rs b/src/librustc/infer/error_reporting/named_anon_conflict.rs index 8af9381107b..edb7887b504 100644 --- a/src/librustc/infer/error_reporting/named_anon_conflict.rs +++ b/src/librustc/infer/error_reporting/named_anon_conflict.rs @@ -15,6 +15,7 @@ use ty::{self, Region}; use infer::region_inference::RegionResolutionError::*; use infer::region_inference::RegionResolutionError; use hir::map as hir_map; +use hir::def_id::DefId; impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // This method walks the Type of the function body arguments using @@ -24,13 +25,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // Currently only the case where the function declaration consists of // one named region and one anonymous region is handled. // Consider the example `fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32` - // Here, we would return the hir::Arg for y, and we return the type &'a + // Here, we would return the hir::Arg for y, we return the type &'a // i32, which is the type of y but with the anonymous region replaced - // with 'a. + // with 'a and also the corresponding bound region. fn find_arg_with_anonymous_region(&self, anon_region: Region<'tcx>, named_region: Region<'tcx>) - -> Option<(&hir::Arg, ty::Ty<'tcx>)> { + -> Option<(&hir::Arg, ty::Ty<'tcx>, ty::BoundRegion)> { match *anon_region { ty::ReFree(ref free_region) => { @@ -55,7 +56,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { r }); if found_anon_region { - return Some((arg, new_arg_ty)); + return Some((arg, new_arg_ty, free_region.bound_region)); } else { None } @@ -85,15 +86,36 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // only introduced anonymous regions in parameters) as well as a // version new_ty of its type where the anonymous region is replaced // with the named one. - let (named, (arg, new_ty)) = - if self.is_named_region(sub) && self.is_suitable_anonymous_region(sup) { - (sub, self.find_arg_with_anonymous_region(sup, sub).unwrap()) - } else if self.is_named_region(sup) && self.is_suitable_anonymous_region(sub) { - (sup, self.find_arg_with_anonymous_region(sub, sup).unwrap()) + let (named, (arg, new_ty, br), scope_def_id) = + if self.is_named_region(sub) && self.is_suitable_anonymous_region(sup).is_some() { + (sub, + self.find_arg_with_anonymous_region(sup, sub).unwrap(), + self.is_suitable_anonymous_region(sup).unwrap()) + } else if self.is_named_region(sup) && + self.is_suitable_anonymous_region(sub).is_some() { + (sup, + self.find_arg_with_anonymous_region(sub, sup).unwrap(), + self.is_suitable_anonymous_region(sub).unwrap()) } else { return false; // inapplicable }; + // Here, we check for the case where the anonymous region + // is in the return type. + // FIXME(#42703) - Need to handle certain cases here. + let ret_ty = self.tcx.type_of(scope_def_id); + match ret_ty.sty { + ty::TyFnDef(_, _, sig) => { + let late_bound_regions = self.tcx + .collect_referenced_late_bound_regions(&sig.output()); + if late_bound_regions.iter().any(|r| *r == br) { + return false; + } else { + } + } + _ => {} + } + if let Some(simple_name) = arg.pat.simple_name() { struct_span_err!(self.tcx.sess, span, @@ -122,7 +144,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } // This method returns whether the given Region is Anonymous - pub fn is_suitable_anonymous_region(&self, region: Region<'tcx>) -> bool { + // and returns the DefId corresponding to the region. + pub fn is_suitable_anonymous_region(&self, region: Region<'tcx>) -> Option { match *region { ty::ReFree(ref free_region) => { @@ -147,20 +170,20 @@ associated_item(anonymous_region_binding_scope).container.id()).is_some() { // since the signature must match the trait. // // FIXME(#42706) -- in some cases, we could do better here. - return false;//None; + return None; } else{ } } - _ => return false, // inapplicable + _ => return None, // inapplicable // we target only top-level functions } - return true; + return Some(anonymous_region_binding_scope); } - _ => false, + _ => None, } } - _ => false, + _ => None, } } } diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.rs b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.rs index 60f794279a5..362290ff3fa 100644 --- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.rs +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.rs @@ -14,7 +14,7 @@ struct Foo { impl Foo { fn foo<'a>(&'a self, x: &i32) -> &i32 { - + if true { &self.field } else { x } } diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.rs b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.rs new file mode 100644 index 00000000000..96b733be9b4 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.rs @@ -0,0 +1,24 @@ +// Copyright 2016 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 Foo { + field: i32 +} + +impl Foo { + fn foo<'a>(&self, x: &'a i32) -> &i32 { + + x + + } + +} + +fn main() { } diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr new file mode 100644 index 00000000000..e32de589d28 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr @@ -0,0 +1,27 @@ +error[E0312]: lifetime of reference outlives lifetime of borrowed content... + --> $DIR/ex1-return-one-existing-name-return-type-is-anon.rs:18:5 + | +18 | x + | ^ + | +note: ...the reference is valid for the anonymous lifetime #1 defined on the method body at 16:3... + --> $DIR/ex1-return-one-existing-name-return-type-is-anon.rs:16:3 + | +16 | / fn foo<'a>(&self, x: &'a i32) -> &i32 { +17 | | +18 | | x +19 | | +20 | | } + | |___^ +note: ...but the borrowed content is only valid for the lifetime 'a as defined on the method body at 16:3 + --> $DIR/ex1-return-one-existing-name-return-type-is-anon.rs:16:3 + | +16 | / fn foo<'a>(&self, x: &'a i32) -> &i32 { +17 | | +18 | | x +19 | | +20 | | } + | |___^ + +error: aborting due to previous error(s) + From a851e1e543c944b38472751d251593f3c593cc3a Mon Sep 17 00:00:00 2001 From: gaurikholkar Date: Wed, 21 Jun 2017 07:01:35 -0700 Subject: [PATCH 092/162] Adding changes to track anonymous region in self --- .../error_reporting/named_anon_conflict.rs | 60 ++++++++++++------- ...-existing-name-if-else-using-impl-3.stderr | 2 +- ...e-existing-name-return-type-is-anon.stderr | 4 +- ...1-return-one-existing-name-self-is-anon.rs | 23 +++++++ ...turn-one-existing-name-self-is-anon.stderr | 27 +++++++++ 5 files changed, 93 insertions(+), 23 deletions(-) create mode 100644 src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.rs create mode 100644 src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.stderr diff --git a/src/librustc/infer/error_reporting/named_anon_conflict.rs b/src/librustc/infer/error_reporting/named_anon_conflict.rs index edb7887b504..a63ae186f61 100644 --- a/src/librustc/infer/error_reporting/named_anon_conflict.rs +++ b/src/librustc/infer/error_reporting/named_anon_conflict.rs @@ -27,11 +27,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // Consider the example `fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32` // Here, we would return the hir::Arg for y, we return the type &'a // i32, which is the type of y but with the anonymous region replaced - // with 'a and also the corresponding bound region. - fn find_arg_with_anonymous_region(&self, - anon_region: Region<'tcx>, - named_region: Region<'tcx>) - -> Option<(&hir::Arg, ty::Ty<'tcx>, ty::BoundRegion)> { + // with 'a, the corresponding bound region and is_first which is true if + // the hir::Arg is the first argument in the function declaration. + fn find_arg_with_anonymous_region + (&self, + anon_region: Region<'tcx>, + named_region: Region<'tcx>) + -> Option<(&hir::Arg, ty::Ty<'tcx>, ty::BoundRegion, bool)> { match *anon_region { ty::ReFree(ref free_region) => { @@ -39,7 +41,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let id = free_region.scope; let node_id = self.tcx.hir.as_local_node_id(id).unwrap(); let body_id = self.tcx.hir.maybe_body_owned_by(node_id).unwrap(); - + let mut is_first = false; let body = self.tcx.hir.body(body_id); body.arguments .iter() @@ -56,7 +58,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { r }); if found_anon_region { - return Some((arg, new_arg_ty, free_region.bound_region)); + if body.arguments.iter().nth(0) == Some(&arg) { + is_first = true; + } + return Some((arg, + new_arg_ty, + free_region.bound_region, + is_first)); } else { None } @@ -86,19 +94,19 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // only introduced anonymous regions in parameters) as well as a // version new_ty of its type where the anonymous region is replaced // with the named one. - let (named, (arg, new_ty, br), scope_def_id) = - if self.is_named_region(sub) && self.is_suitable_anonymous_region(sup).is_some() { - (sub, - self.find_arg_with_anonymous_region(sup, sub).unwrap(), - self.is_suitable_anonymous_region(sup).unwrap()) - } else if self.is_named_region(sup) && - self.is_suitable_anonymous_region(sub).is_some() { - (sup, - self.find_arg_with_anonymous_region(sub, sup).unwrap(), - self.is_suitable_anonymous_region(sub).unwrap()) - } else { - return false; // inapplicable - }; + let (named, (arg, new_ty, br, is_first), scope_def_id) = if + self.is_named_region(sub) && self.is_suitable_anonymous_region(sup).is_some() { + (sub, + self.find_arg_with_anonymous_region(sup, sub).unwrap(), + self.is_suitable_anonymous_region(sup).unwrap()) + } else if + self.is_named_region(sup) && self.is_suitable_anonymous_region(sub).is_some() { + (sup, + self.find_arg_with_anonymous_region(sub, sup).unwrap(), + self.is_suitable_anonymous_region(sub).unwrap()) + } else { + return false; // inapplicable + }; // Here, we check for the case where the anonymous region // is in the return type. @@ -116,6 +124,18 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { _ => {} } + // Here we check for the case where anonymous region + // corresponds to self and if yes, we display E0312. + // FIXME(#42700) - Need to format self properly to + // enable E0611 for it. + if is_first && + self.tcx + .opt_associated_item(scope_def_id) + .map(|i| i.method_has_self_argument) + .unwrap_or(false) { + return false; + } + if let Some(simple_name) = arg.pat.simple_name() { struct_span_err!(self.tcx.sess, span, diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr index cedceb559d5..502871022ff 100644 --- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr @@ -3,7 +3,7 @@ error[E0611]: explicit lifetime required in the type of `x` | 16 | fn foo<'a>(&'a self, x: &i32) -> &i32 { | - consider changing the type of `x` to `&'a i32` -17 | +17 | 18 | if true { &self.field } else { x } | ^ lifetime `'a` required diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr index e32de589d28..471b3401827 100644 --- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr @@ -8,7 +8,7 @@ note: ...the reference is valid for the anonymous lifetime #1 defined on the met --> $DIR/ex1-return-one-existing-name-return-type-is-anon.rs:16:3 | 16 | / fn foo<'a>(&self, x: &'a i32) -> &i32 { -17 | | +17 | | 18 | | x 19 | | 20 | | } @@ -17,7 +17,7 @@ note: ...but the borrowed content is only valid for the lifetime 'a as defined o --> $DIR/ex1-return-one-existing-name-return-type-is-anon.rs:16:3 | 16 | / fn foo<'a>(&self, x: &'a i32) -> &i32 { -17 | | +17 | | 18 | | x 19 | | 20 | | } diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.rs b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.rs new file mode 100644 index 00000000000..a8ce60c47b6 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.rs @@ -0,0 +1,23 @@ +// Copyright 2016 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 Foo { + field: i32, +} + +impl Foo { + fn foo<'a>(&self, x: &'a Foo) -> &'a Foo { + + if true { x } else { self } + + } +} + +fn main() {} diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.stderr new file mode 100644 index 00000000000..46fc43eaf57 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.stderr @@ -0,0 +1,27 @@ +error[E0312]: lifetime of reference outlives lifetime of borrowed content... + --> $DIR/ex1-return-one-existing-name-self-is-anon.rs:18:30 + | +18 | if true { x } else { self } + | ^^^^ + | +note: ...the reference is valid for the lifetime 'a as defined on the method body at 16:5... + --> $DIR/ex1-return-one-existing-name-self-is-anon.rs:16:5 + | +16 | / fn foo<'a>(&self, x: &'a Foo) -> &'a Foo { +17 | | +18 | | if true { x } else { self } +19 | | +20 | | } + | |_____^ +note: ...but the borrowed content is only valid for the anonymous lifetime #1 defined on the method body at 16:5 + --> $DIR/ex1-return-one-existing-name-self-is-anon.rs:16:5 + | +16 | / fn foo<'a>(&self, x: &'a Foo) -> &'a Foo { +17 | | +18 | | if true { x } else { self } +19 | | +20 | | } + | |_____^ + +error: aborting due to previous error(s) + From 82f25b32ae568986de275d87fe355ec63307d8cb Mon Sep 17 00:00:00 2001 From: gaurikholkar Date: Thu, 22 Jun 2017 10:56:05 -0700 Subject: [PATCH 093/162] code review fixes --- .../error_reporting/named_anon_conflict.rs | 55 +++++++++---------- 1 file changed, 26 insertions(+), 29 deletions(-) diff --git a/src/librustc/infer/error_reporting/named_anon_conflict.rs b/src/librustc/infer/error_reporting/named_anon_conflict.rs index a63ae186f61..4a1f4b418ae 100644 --- a/src/librustc/infer/error_reporting/named_anon_conflict.rs +++ b/src/librustc/infer/error_reporting/named_anon_conflict.rs @@ -43,39 +43,36 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let body_id = self.tcx.hir.maybe_body_owned_by(node_id).unwrap(); let mut is_first = false; let body = self.tcx.hir.body(body_id); - body.arguments - .iter() - .filter_map(|arg| if let Some(tables) = self.in_progress_tables { - let ty = tables.borrow().node_id_to_type(arg.id); - let mut found_anon_region = false; - let new_arg_ty = self.tcx - .fold_regions(&ty, - &mut false, - |r, _| if *r == *anon_region { - found_anon_region = true; - named_region - } else { - r - }); - if found_anon_region { - if body.arguments.iter().nth(0) == Some(&arg) { - is_first = true; - } - return Some((arg, - new_arg_ty, - free_region.bound_region, - is_first)); - } else { - None - } + if let Some(tables) = self.in_progress_tables { + body.arguments + .iter() + .filter_map(|arg| { + let ty = tables.borrow().node_id_to_type(arg.id); + let mut found_anon_region = false; + let new_arg_ty = self.tcx + .fold_regions(&ty, &mut false, |r, _| if *r == *anon_region { + found_anon_region = true; + named_region } else { - None - }) - .next() + r + }); + if found_anon_region { + if body.arguments.iter().nth(0) == Some(&arg) { + is_first = true; + } + Some((arg, new_arg_ty, free_region.bound_region, is_first)) + } else { + None + } + }) + .next() + } else { + None + } } _ => None, - } + } } // This method generates the error message for the case when From aebc4e007493c623aaf69ef04d1a649b74fd5bfb Mon Sep 17 00:00:00 2001 From: gaurikholkar Date: Mon, 26 Jun 2017 11:26:01 -0700 Subject: [PATCH 094/162] Changing the error code to E0621 --- src/librustc/diagnostics.rs | 29 +++++++++++++++---- .../error_reporting/named_anon_conflict.rs | 6 ++-- ...-return-one-existing-name-if-else-2.stderr | 2 +- ...-return-one-existing-name-if-else-3.stderr | 2 +- ...-existing-name-if-else-using-impl-2.stderr | 2 +- ...-existing-name-if-else-using-impl-3.stderr | 2 +- ...x1-return-one-existing-name-if-else.stderr | 2 +- .../ex2a-push-one-existing-name-2.stderr | 2 +- .../ex2a-push-one-existing-name.stderr | 2 +- 9 files changed, 33 insertions(+), 16 deletions(-) diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 1e7f3f9aeb8..aa62cab7c3d 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -1946,11 +1946,19 @@ Maybe you just misspelled the lint name or the lint doesn't exist anymore. Either way, try to update/remove it in order to fix the error. "##, -E0611: r##" -Lifetime parameter is missing in one of the function argument. Erroneous -code example: +E0621: r##" +This error code indicates a mismatch between the function signature (i.e., +the parameter types and the return type) and the function body. Most of +the time, this indicates that the function signature needs to be changed to +match the body, but it may be that the body needs to be changed to match +the signature. -```compile_fail,E0611 +Specifically, one or more of the parameters contain borrowed data that +needs to have a named lifetime in order for the body to type-check. Most of +the time, this is because the borrowed data is being returned from the +function, as in this example: + +```compile_fail,E0621 fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 { // explicit lifetime required // in the type of `y` if x > y { x } else { y } @@ -1959,15 +1967,24 @@ fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 { // explicit lifetime required fn main () { } ``` -Please add the missing lifetime parameter to remove this error. Example: +Here, the function is returning data borrowed from either x or y, but the +'a annotation indicates that it is returning data only from x. We can make +the signature match the body by changing the type of y to &'a i32, like so: ``` fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 { if x > y { x } else { y } } -fn main() { +fn main () { } +``` +Alternatively, you could change the body not to return data from y: +``` +fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 { + x } + +fn main () { } ``` "##, diff --git a/src/librustc/infer/error_reporting/named_anon_conflict.rs b/src/librustc/infer/error_reporting/named_anon_conflict.rs index 4a1f4b418ae..fb0bd901db4 100644 --- a/src/librustc/infer/error_reporting/named_anon_conflict.rs +++ b/src/librustc/infer/error_reporting/named_anon_conflict.rs @@ -124,7 +124,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // Here we check for the case where anonymous region // corresponds to self and if yes, we display E0312. // FIXME(#42700) - Need to format self properly to - // enable E0611 for it. + // enable E0621 for it. if is_first && self.tcx .opt_associated_item(scope_def_id) @@ -136,7 +136,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { if let Some(simple_name) = arg.pat.simple_name() { struct_span_err!(self.tcx.sess, span, - E0611, + E0621, "explicit lifetime required in the type of `{}`", simple_name) .span_label(arg.pat.span, @@ -149,7 +149,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } else { struct_span_err!(self.tcx.sess, span, - E0611, + E0621, "explicit lifetime required in parameter type") .span_label(arg.pat.span, format!("consider changing type to `{}`", new_ty)) diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.stderr index ada7af8c1e4..4d8c5e039af 100644 --- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.stderr +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.stderr @@ -1,4 +1,4 @@ -error[E0611]: explicit lifetime required in the type of `x` +error[E0621]: explicit lifetime required in the type of `x` --> $DIR/ex1-return-one-existing-name-if-else-2.rs:12:16 | 11 | fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 { diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.stderr index 58aab711394..07b276601f4 100644 --- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.stderr +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.stderr @@ -1,4 +1,4 @@ -error[E0611]: explicit lifetime required in parameter type +error[E0621]: explicit lifetime required in parameter type --> $DIR/ex1-return-one-existing-name-if-else-3.rs:12:27 | 11 | fn foo<'a>((x, y): (&'a i32, &i32)) -> &'a i32 { diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.stderr index ec787eb749c..2adf0cd762c 100644 --- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.stderr +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.stderr @@ -1,4 +1,4 @@ -error[E0611]: explicit lifetime required in the type of `x` +error[E0621]: explicit lifetime required in the type of `x` --> $DIR/ex1-return-one-existing-name-if-else-using-impl-2.rs:14:15 | 13 | fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 { diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr index 502871022ff..15825017d15 100644 --- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr @@ -1,4 +1,4 @@ -error[E0611]: explicit lifetime required in the type of `x` +error[E0621]: explicit lifetime required in the type of `x` --> $DIR/ex1-return-one-existing-name-if-else-using-impl-3.rs:18:36 | 16 | fn foo<'a>(&'a self, x: &i32) -> &i32 { diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.stderr index 837fa141bf1..892a6dcd1e9 100644 --- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.stderr +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.stderr @@ -1,4 +1,4 @@ -error[E0611]: explicit lifetime required in the type of `y` +error[E0621]: explicit lifetime required in the type of `y` --> $DIR/ex1-return-one-existing-name-if-else.rs:12:27 | 11 | fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 { diff --git a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.stderr b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.stderr index a16dac672ae..ea696c51d62 100644 --- a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.stderr +++ b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.stderr @@ -1,4 +1,4 @@ -error[E0611]: explicit lifetime required in the type of `x` +error[E0621]: explicit lifetime required in the type of `x` --> $DIR/ex2a-push-one-existing-name-2.rs:16:12 | 15 | fn foo<'a>(x: Ref, y: &mut Vec>) { diff --git a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr index 537090aa67d..1630ae32ba6 100644 --- a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr +++ b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr @@ -1,4 +1,4 @@ -error[E0611]: explicit lifetime required in the type of `y` +error[E0621]: explicit lifetime required in the type of `y` --> $DIR/ex2a-push-one-existing-name.rs:16:12 | 15 | fn foo<'a>(x: &mut Vec>, y: Ref) { From 95409016f8e84a47715526a89929cd22a2f25c16 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 27 Jun 2017 13:16:47 -0400 Subject: [PATCH 095/162] remove `fn main() { }` from extended errors --- src/librustc/diagnostics.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index aa62cab7c3d..035640b9710 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -1963,8 +1963,6 @@ fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 { // explicit lifetime required // in the type of `y` if x > y { x } else { y } } - -fn main () { } ``` Here, the function is returning data borrowed from either x or y, but the @@ -1975,16 +1973,14 @@ the signature match the body by changing the type of y to &'a i32, like so: fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 { if x > y { x } else { y } } - -fn main () { } ``` + Alternatively, you could change the body not to return data from y: + ``` fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 { x } - -fn main () { } ``` "##, From e8b8f30373941f1d606d21c741bb136d81c3d082 Mon Sep 17 00:00:00 2001 From: gaurikholkar Date: Tue, 27 Jun 2017 12:54:15 -0700 Subject: [PATCH 096/162] Code review fixes --- src/librustc/infer/error_reporting/mod.rs | 1 - .../error_reporting/named_anon_conflict.rs | 42 +++++++++---------- src/librustc/infer/error_reporting/util.rs | 30 ------------- src/librustc/ty/sty.rs | 14 +++++++ 4 files changed, 34 insertions(+), 53 deletions(-) delete mode 100644 src/librustc/infer/error_reporting/util.rs diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 9e2d922b932..82bbb4a1bf5 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -76,7 +76,6 @@ mod note; mod need_type_info; mod named_anon_conflict; -mod util; impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { diff --git a/src/librustc/infer/error_reporting/named_anon_conflict.rs b/src/librustc/infer/error_reporting/named_anon_conflict.rs index fb0bd901db4..cdfb57c86f9 100644 --- a/src/librustc/infer/error_reporting/named_anon_conflict.rs +++ b/src/librustc/infer/error_reporting/named_anon_conflict.rs @@ -41,12 +41,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let id = free_region.scope; let node_id = self.tcx.hir.as_local_node_id(id).unwrap(); let body_id = self.tcx.hir.maybe_body_owned_by(node_id).unwrap(); - let mut is_first = false; let body = self.tcx.hir.body(body_id); if let Some(tables) = self.in_progress_tables { body.arguments .iter() - .filter_map(|arg| { + .enumerate() + .filter_map(|(index, arg)| { let ty = tables.borrow().node_id_to_type(arg.id); let mut found_anon_region = false; let new_arg_ty = self.tcx @@ -57,9 +57,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { r }); if found_anon_region { - if body.arguments.iter().nth(0) == Some(&arg) { - is_first = true; - } + let is_first = index == 0; Some((arg, new_arg_ty, free_region.bound_region, is_first)) } else { None @@ -91,19 +89,18 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // only introduced anonymous regions in parameters) as well as a // version new_ty of its type where the anonymous region is replaced // with the named one. - let (named, (arg, new_ty, br, is_first), scope_def_id) = if - self.is_named_region(sub) && self.is_suitable_anonymous_region(sup).is_some() { - (sub, - self.find_arg_with_anonymous_region(sup, sub).unwrap(), - self.is_suitable_anonymous_region(sup).unwrap()) - } else if - self.is_named_region(sup) && self.is_suitable_anonymous_region(sub).is_some() { - (sup, - self.find_arg_with_anonymous_region(sub, sup).unwrap(), - self.is_suitable_anonymous_region(sub).unwrap()) - } else { - return false; // inapplicable - }; + let (named, (arg, new_ty, br, is_first), scope_def_id) = + if sub.is_named_region() && self.is_suitable_anonymous_region(sup).is_some() { + (sub, + self.find_arg_with_anonymous_region(sup, sub).unwrap(), + self.is_suitable_anonymous_region(sup).unwrap()) + } else if sup.is_named_region() && self.is_suitable_anonymous_region(sub).is_some() { + (sup, + self.find_arg_with_anonymous_region(sub, sup).unwrap(), + self.is_suitable_anonymous_region(sub).unwrap()) + } else { + return false; // inapplicable + }; // Here, we check for the case where the anonymous region // is in the return type. @@ -179,8 +176,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // proceed ahead // } Some(hir_map::NodeImplItem(..)) => { - if self.tcx.impl_trait_ref(self.tcx. -associated_item(anonymous_region_binding_scope).container.id()).is_some() { + let container_id = self.tcx + .associated_item(anonymous_region_binding_scope) + .container + .id(); + if self.tcx.impl_trait_ref(container_id).is_some() { // For now, we do not try to target impls of traits. This is // because this message is going to suggest that the user // change the fn signature, but they may not be free to do so, @@ -189,8 +189,6 @@ associated_item(anonymous_region_binding_scope).container.id()).is_some() { // FIXME(#42706) -- in some cases, we could do better here. return None; } - else{ } - } _ => return None, // inapplicable // we target only top-level functions diff --git a/src/librustc/infer/error_reporting/util.rs b/src/librustc/infer/error_reporting/util.rs deleted file mode 100644 index 66c351b49ac..00000000000 --- a/src/librustc/infer/error_reporting/util.rs +++ /dev/null @@ -1,30 +0,0 @@ -// 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. -// -// 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. - -//! Helper for error reporting code for named_anon_conflict - -use ty::{self, Region}; -use infer::InferCtxt; - -impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { - // This method returns whether the given Region is Named - pub fn is_named_region(&self, region: Region<'tcx>) -> bool { - - match *region { - ty::ReFree(ref free_region) => { - match free_region.bound_region { - ty::BrNamed(..) => true, - _ => false, - } - } - _ => false, - } - } -} diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index ed3312d88a3..452775e9e13 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -990,6 +990,20 @@ impl RegionKind { flags } + + // This method returns whether the given Region is Named + pub fn is_named_region(&self) -> bool { + + match *self { + ty::ReFree(ref free_region) => { + match free_region.bound_region { + ty::BrNamed(..) => true, + _ => false, + } + } + _ => false, + } + } } /// Type utilities From 5841021f071f7e6393e3ee510c4e02f44cb0fbee Mon Sep 17 00:00:00 2001 From: gaurikholkar Date: Wed, 28 Jun 2017 12:18:21 -0700 Subject: [PATCH 097/162] conflict fixes --- src/librustc/infer/error_reporting/named_anon_conflict.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustc/infer/error_reporting/named_anon_conflict.rs b/src/librustc/infer/error_reporting/named_anon_conflict.rs index cdfb57c86f9..21f8a04be0a 100644 --- a/src/librustc/infer/error_reporting/named_anon_conflict.rs +++ b/src/librustc/infer/error_reporting/named_anon_conflict.rs @@ -107,7 +107,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // FIXME(#42703) - Need to handle certain cases here. let ret_ty = self.tcx.type_of(scope_def_id); match ret_ty.sty { - ty::TyFnDef(_, _, sig) => { + ty::TyFnDef(_, _) => { + let sig = ret_ty.fn_sig(self.tcx); let late_bound_regions = self.tcx .collect_referenced_late_bound_regions(&sig.output()); if late_bound_regions.iter().any(|r| *r == br) { From 5be4fa864af439cb18fe9bff4297e229f2879c73 Mon Sep 17 00:00:00 2001 From: gaurikholkar Date: Thu, 29 Jun 2017 06:35:09 -0700 Subject: [PATCH 098/162] code fixes for error code use warning --- .../error_reporting/named_anon_conflict.rs | 38 ++++++++----------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/src/librustc/infer/error_reporting/named_anon_conflict.rs b/src/librustc/infer/error_reporting/named_anon_conflict.rs index 21f8a04be0a..ccbc5cdb862 100644 --- a/src/librustc/infer/error_reporting/named_anon_conflict.rs +++ b/src/librustc/infer/error_reporting/named_anon_conflict.rs @@ -131,29 +131,23 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { return false; } - if let Some(simple_name) = arg.pat.simple_name() { - struct_span_err!(self.tcx.sess, - span, - E0621, - "explicit lifetime required in the type of `{}`", - simple_name) - .span_label(arg.pat.span, - format!("consider changing the type of `{}` to `{}`", - simple_name, - new_ty)) - .span_label(span, format!("lifetime `{}` required", named)) - .emit(); - + let (error_var, span_label_var) = if let Some(simple_name) = arg.pat.simple_name() { + (format!("the type of `{}`", simple_name), format!("the type of `{}`", simple_name)) } else { - struct_span_err!(self.tcx.sess, - span, - E0621, - "explicit lifetime required in parameter type") - .span_label(arg.pat.span, - format!("consider changing type to `{}`", new_ty)) - .span_label(span, format!("lifetime `{}` required", named)) - .emit(); - } + (format!("parameter type"), format!("type")) + }; + + + struct_span_err!(self.tcx.sess, + span, + E0621, + "explicit lifetime required in {}", + error_var) + .span_label(arg.pat.span, + format!("consider changing {} to `{}`", span_label_var, new_ty)) + .span_label(span, format!("lifetime `{}` required", named)) + .emit(); + return true; } From 1ea6813a61960dc89ceea95fe1cf7d3129aa8687 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Thu, 29 Jun 2017 19:47:12 +0300 Subject: [PATCH 099/162] mem_categorization: handle type-based paths in variant patterns These can't be used in correct programs, but must be handled in order to prevent ICEs. Fixes #42880. --- src/librustc/middle/expr_use_visitor.rs | 9 +-- src/librustc/middle/mem_categorization.rs | 92 +++++++++++------------ src/test/compile-fail/issue-42880.rs | 18 +++++ 3 files changed, 64 insertions(+), 55 deletions(-) create mode 100644 src/test/compile-fail/issue-42880.rs diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 58e77f40d98..259bd4f0999 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -816,7 +816,6 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { fn walk_pat(&mut self, cmt_discr: mc::cmt<'tcx>, pat: &hir::Pat, match_mode: MatchMode) { debug!("walk_pat cmt_discr={:?} pat={:?}", cmt_discr, pat); - let tcx = self.tcx(); let ExprUseVisitor { ref mc, ref mut delegate, param_env } = *self; return_if_err!(mc.cat_pattern(cmt_discr.clone(), pat, |cmt_pat, pat| { if let PatKind::Binding(bmode, def_id, ..) = pat.node { @@ -864,13 +863,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { match def { Def::Variant(variant_did) | Def::VariantCtor(variant_did, ..) => { - let enum_did = tcx.parent_def_id(variant_did).unwrap(); - let downcast_cmt = if tcx.adt_def(enum_did).is_univariant() { - cmt_pat - } else { - let cmt_pat_ty = cmt_pat.ty; - mc.cat_downcast(pat, cmt_pat, cmt_pat_ty, variant_did) - }; + let downcast_cmt = mc.cat_downcast_if_needed(pat, cmt_pat, variant_did); debug!("variant downcast_cmt={:?} pat={:?}", downcast_cmt, pat); delegate.matched_pat(pat, downcast_cmt, match_mode); diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 259079cf160..5c741eccf83 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -1032,22 +1032,29 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { ret } - pub fn cat_downcast(&self, - node: &N, - base_cmt: cmt<'tcx>, - downcast_ty: Ty<'tcx>, - variant_did: DefId) - -> cmt<'tcx> { - let ret = Rc::new(cmt_ { - id: node.id(), - span: node.span(), - mutbl: base_cmt.mutbl.inherit(), - cat: Categorization::Downcast(base_cmt, variant_did), - ty: downcast_ty, - note: NoteNone - }); - debug!("cat_downcast ret={:?}", ret); - ret + pub fn cat_downcast_if_needed(&self, + node: &N, + base_cmt: cmt<'tcx>, + variant_did: DefId) + -> cmt<'tcx> { + // univariant enums do not need downcasts + let base_did = self.tcx.parent_def_id(variant_did).unwrap(); + if !self.tcx.adt_def(base_did).is_univariant() { + let base_ty = base_cmt.ty; + let ret = Rc::new(cmt_ { + id: node.id(), + span: node.span(), + mutbl: base_cmt.mutbl.inherit(), + cat: Categorization::Downcast(base_cmt, variant_did), + ty: base_ty, + note: NoteNone + }); + debug!("cat_downcast ret={:?}", ret); + ret + } else { + debug!("cat_downcast univariant={:?}", base_cmt); + base_cmt + } } pub fn cat_pattern(&self, cmt: cmt<'tcx>, pat: &hir::Pat, mut op: F) -> McResult<()> @@ -1109,45 +1116,23 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { op(cmt.clone(), pat); - // Note: This goes up here (rather than within the PatKind::TupleStruct arm - // alone) because PatKind::Struct can also refer to variants. - let cmt = match pat.node { - PatKind::Path(hir::QPath::Resolved(_, ref path)) | - PatKind::TupleStruct(hir::QPath::Resolved(_, ref path), ..) | - PatKind::Struct(hir::QPath::Resolved(_, ref path), ..) => { - match path.def { - Def::Err => { - debug!("access to unresolvable pattern {:?}", pat); - return Err(()) - } - Def::Variant(variant_did) | - Def::VariantCtor(variant_did, ..) => { - // univariant enums do not need downcasts - let enum_did = self.tcx.parent_def_id(variant_did).unwrap(); - if !self.tcx.adt_def(enum_did).is_univariant() { - self.cat_downcast(pat, cmt.clone(), cmt.ty, variant_did) - } else { - cmt - } - } - _ => cmt - } - } - _ => cmt - }; - match pat.node { PatKind::TupleStruct(ref qpath, ref subpats, ddpos) => { let def = self.tables.qpath_def(qpath, pat.id); - let expected_len = match def { + let (cmt, expected_len) = match def { + Def::Err => { + debug!("access to unresolvable pattern {:?}", pat); + return Err(()) + } Def::VariantCtor(def_id, CtorKind::Fn) => { let enum_def = self.tcx.parent_def_id(def_id).unwrap(); - self.tcx.adt_def(enum_def).variant_with_id(def_id).fields.len() + (self.cat_downcast_if_needed(pat, cmt, def_id), + self.tcx.adt_def(enum_def).variant_with_id(def_id).fields.len()) } Def::StructCtor(_, CtorKind::Fn) => { match self.pat_ty(&pat)?.sty { ty::TyAdt(adt_def, _) => { - adt_def.struct_variant().fields.len() + (cmt, adt_def.struct_variant().fields.len()) } ref ty => { span_bug!(pat.span, "tuple struct pattern unexpected type {:?}", ty); @@ -1168,8 +1153,21 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { } } - PatKind::Struct(_, ref field_pats, _) => { + PatKind::Struct(ref qpath, ref field_pats, _) => { // {f1: p1, ..., fN: pN} + let def = self.tables.qpath_def(qpath, pat.id); + let cmt = match def { + Def::Err => { + debug!("access to unresolvable pattern {:?}", pat); + return Err(()) + }, + Def::Variant(variant_did) | + Def::VariantCtor(variant_did, ..) => { + self.cat_downcast_if_needed(pat, cmt, variant_did) + }, + _ => cmt + }; + for fp in field_pats { let field_ty = self.pat_ty(&fp.node.pat)?; // see (*2) let cmt_field = self.cat_field(pat, cmt.clone(), fp.node.name, field_ty); diff --git a/src/test/compile-fail/issue-42880.rs b/src/test/compile-fail/issue-42880.rs new file mode 100644 index 00000000000..ebb1ec425d1 --- /dev/null +++ b/src/test/compile-fail/issue-42880.rs @@ -0,0 +1,18 @@ +// Copyright 2017 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. + +type Value = String; + +fn main() { + let f = |&Value::String(_)| (); //~ ERROR no associated item named + + let vec: Vec = Vec::new(); + vec.last().map(f); +} From 4abcf28d2baaf53afe810e75ddfbfa8eff72c863 Mon Sep 17 00:00:00 2001 From: gaurikholkar Date: Thu, 29 Jun 2017 14:13:53 -0700 Subject: [PATCH 100/162] adding compile-fail test --- .../E0495.rs} | 7 ++--- ...existing-name-if-else-using-closure.stderr | 29 ------------------- 2 files changed, 3 insertions(+), 33 deletions(-) rename src/test/{ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-closure.rs => compile-fail/E0495.rs} (84%) delete mode 100644 src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-closure.stderr diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-closure.rs b/src/test/compile-fail/E0495.rs similarity index 84% rename from src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-closure.rs rename to src/test/compile-fail/E0495.rs index faf4fe547bf..e47c4d7199c 100644 --- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-closure.rs +++ b/src/test/compile-fail/E0495.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// FIXME - This test gives different results on different machines. fn invoke<'a, F>(x: &'a i32, f: F) -> &'a i32 where F: FnOnce(&'a i32, &i32) -> &'a i32 { @@ -15,10 +16,8 @@ where F: FnOnce(&'a i32, &i32) -> &'a i32 f(x, &y) } -fn foo<'a>(x: &'a i32) { +fn foo<'a>(x: &'a i32) { //~ ERROR E0495 invoke(&x, |a, b| if a > b { a } else { b }); } -fn main() { -} - +fn main() {} diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-closure.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-closure.stderr deleted file mode 100644 index 20104afae51..00000000000 --- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-closure.stderr +++ /dev/null @@ -1,29 +0,0 @@ -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements - --> $DIR/ex1-return-one-existing-name-if-else-using-closure.rs:19:5 - | -19 | invoke(&x, |a, b| if a > b { a } else { b }); - | ^^^^^^ - | -note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 19:16... - --> $DIR/ex1-return-one-existing-name-if-else-using-closure.rs:19:16 - | -19 | invoke(&x, |a, b| if a > b { a } else { b }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...so that reference does not outlive borrowed content - --> $DIR/ex1-return-one-existing-name-if-else-using-closure.rs:19:45 - | -19 | invoke(&x, |a, b| if a > b { a } else { b }); - | ^ -note: but, the lifetime must be valid for the expression at 19:5... - --> $DIR/ex1-return-one-existing-name-if-else-using-closure.rs:19:5 - | -19 | invoke(&x, |a, b| if a > b { a } else { b }); - | ^^^^^^ -note: ...so that a type/lifetime parameter is in scope here - --> $DIR/ex1-return-one-existing-name-if-else-using-closure.rs:19:5 - | -19 | invoke(&x, |a, b| if a > b { a } else { b }); - | ^^^^^^ - -error: aborting due to previous error(s) - From 7be171db70685eb4f6465f2d9047f8bfe1651708 Mon Sep 17 00:00:00 2001 From: Andre Bogus Date: Thu, 29 Jun 2017 23:38:13 +0200 Subject: [PATCH 101/162] fix a stray semicolon --- src/tools/compiletest/src/header.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index c9e24492207..5ac60d8f2c8 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -549,7 +549,7 @@ impl Config { pub fn lldb_version_to_int(version_string: &str) -> isize { let error_string = format!("Encountered LLDB version string with unexpected format: {}", version_string); - version_string.parse().expect(&error_string); + version_string.parse().expect(&error_string) } fn expand_variables(mut value: String, config: &Config) -> String { From cb26a25d4b355e9836fc139bb71ad96d37e6c265 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 29 Jun 2017 18:02:31 -0400 Subject: [PATCH 102/162] tweak comments in E0495.rs --- src/test/compile-fail/E0495.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/test/compile-fail/E0495.rs b/src/test/compile-fail/E0495.rs index e47c4d7199c..55871a90f23 100644 --- a/src/test/compile-fail/E0495.rs +++ b/src/test/compile-fail/E0495.rs @@ -8,7 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// FIXME - This test gives different results on different machines. +// Test that we give the generic E0495 when one of the free regions is +// bound in a closure (rather than suggesting a change to the signature +// of the closure, which is not specified in `foo` but rather in `invoke`). + +// FIXME - This might be better as a UI test, but the finer details +// of the error seem to vary on different machines. fn invoke<'a, F>(x: &'a i32, f: F) -> &'a i32 where F: FnOnce(&'a i32, &i32) -> &'a i32 { From 8ee6bddf0b8b9b77ecd1e4b8105dc3fe161e6626 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Thu, 29 Jun 2017 17:22:36 -0700 Subject: [PATCH 103/162] redox: symlink and readlink --- src/libstd/sys/redox/fs.rs | 14 ++++++++++---- src/libstd/sys/redox/syscall/flag.rs | 2 ++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/libstd/sys/redox/fs.rs b/src/libstd/sys/redox/fs.rs index 48d9cdcb2c9..9a16fc1bf66 100644 --- a/src/libstd/sys/redox/fs.rs +++ b/src/libstd/sys/redox/fs.rs @@ -420,12 +420,18 @@ fn remove_dir_all_recursive(path: &Path) -> io::Result<()> { } pub fn readlink(p: &Path) -> io::Result { - canonicalize(p) + let fd = cvt(syscall::open(p.to_str().unwrap(), syscall::O_SYMLINK | syscall::O_RDONLY))?; + let mut buf: [u8; 4096] = [0; 4096]; + let count = cvt(syscall::read(fd, &mut buf))?; + cvt(syscall::close(fd))?; + Ok(PathBuf::from(unsafe { String::from_utf8_unchecked(Vec::from(&buf[..count])) })) } -pub fn symlink(_src: &Path, _dst: &Path) -> io::Result<()> { - ::sys_common::util::dumb_print(format_args!("Symlink\n")); - unimplemented!(); +pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> { + let fd = cvt(syscall::open(dst.to_str().unwrap(), syscall::O_SYMLINK | syscall::O_CREAT | syscall::O_WRONLY | 0o777))?; + cvt(syscall::write(fd, src.to_str().unwrap().as_bytes()))?; + cvt(syscall::close(fd))?; + Ok(()) } pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> { diff --git a/src/libstd/sys/redox/syscall/flag.rs b/src/libstd/sys/redox/syscall/flag.rs index 9f0d3e6f779..bd603cfe6ef 100644 --- a/src/libstd/sys/redox/syscall/flag.rs +++ b/src/libstd/sys/redox/syscall/flag.rs @@ -33,6 +33,7 @@ pub const MAP_WRITE_COMBINE: usize = 2; pub const MODE_TYPE: u16 = 0xF000; pub const MODE_DIR: u16 = 0x4000; pub const MODE_FILE: u16 = 0x8000; +pub const MODE_SYMLINK: u16 = 0xA000; pub const MODE_PERM: u16 = 0x0FFF; pub const MODE_SETUID: u16 = 0o4000; @@ -53,6 +54,7 @@ pub const O_TRUNC: usize = 0x0400_0000; pub const O_EXCL: usize = 0x0800_0000; pub const O_DIRECTORY: usize = 0x1000_0000; pub const O_STAT: usize = 0x2000_0000; +pub const O_SYMLINK: usize = 0x4000_0000; pub const O_ACCMODE: usize = O_RDONLY | O_WRONLY | O_RDWR; pub const SEEK_SET: usize = 0; From 8ed83f4aaf75821feff3236b1c4d8d6e5302efba Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Thu, 29 Jun 2017 18:18:32 -0700 Subject: [PATCH 104/162] Fix Redox build, apparently broken by #42687 --- src/libstd/sys/redox/fast_thread_local.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/libstd/sys/redox/fast_thread_local.rs b/src/libstd/sys/redox/fast_thread_local.rs index 7dc61ce6654..9f0eee024d5 100644 --- a/src/libstd/sys/redox/fast_thread_local.rs +++ b/src/libstd/sys/redox/fast_thread_local.rs @@ -57,7 +57,7 @@ impl Key { } } -unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) { +pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) { // The fallback implementation uses a vanilla OS-based TLS key to track // the list of destructors that need to be run for this thread. The key // then has its own destructor which runs all the other destructors. @@ -115,3 +115,7 @@ pub unsafe extern fn destroy_value(ptr: *mut u8) { ptr::drop_in_place((*ptr).inner.get()); } } + +pub fn requires_move_before_drop() -> bool { + false +} From d23a62ba71c826b792db19dbf41ff4b70591fd7a Mon Sep 17 00:00:00 2001 From: Marc-Antoine Perennou Date: Thu, 29 Jun 2017 10:03:56 +0200 Subject: [PATCH 105/162] rustbuild: set __CARGO_DEFAULT_LIB_METADATA to channel Signed-off-by: Marc-Antoine Perennou --- src/bootstrap/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index ce7cde8fc94..86180077b82 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -347,7 +347,7 @@ impl Build { // FIXME: Temporary fix for https://github.com/rust-lang/cargo/issues/3005 // Force cargo to output binaries with disambiguating hashes in the name - cargo.env("__CARGO_DEFAULT_LIB_METADATA", "1"); + cargo.env("__CARGO_DEFAULT_LIB_METADATA", &self.config.channel); let stage; if compiler.stage == 0 && self.local_rebuild { From 93528d90720c71892c24ea53d7a2467b8a335776 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Perennou Date: Fri, 30 Jun 2017 09:38:13 +0200 Subject: [PATCH 106/162] update cargo submodule This brings in several fixes and the new handling of __CARGO_DEFAULT_LIB_METADATA Signed-off-by: Marc-Antoine Perennou --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index abf01e1eddb..d2d6e675fcb 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit abf01e1eddb3145c83f71b469ea7bee37141e5e1 +Subproject commit d2d6e675fcb70cfb91c2cf2fad8cdd345c120316 From a43377773f3b38e4f521964a3b519f97f50fc3e4 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 30 Jun 2017 05:11:28 -0400 Subject: [PATCH 107/162] move ERROR line --- src/test/compile-fail/E0495.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/compile-fail/E0495.rs b/src/test/compile-fail/E0495.rs index 55871a90f23..980461bedae 100644 --- a/src/test/compile-fail/E0495.rs +++ b/src/test/compile-fail/E0495.rs @@ -21,8 +21,8 @@ where F: FnOnce(&'a i32, &i32) -> &'a i32 f(x, &y) } -fn foo<'a>(x: &'a i32) { //~ ERROR E0495 - invoke(&x, |a, b| if a > b { a } else { b }); +fn foo<'a>(x: &'a i32) { + invoke(&x, |a, b| if a > b { a } else { b }); //~ ERROR E0495 } fn main() {} From 37a88f478dd80404b7b8c3890db96f5850ecd7bf Mon Sep 17 00:00:00 2001 From: gaurikholkar Date: Fri, 30 Jun 2017 02:33:33 -0700 Subject: [PATCH 108/162] rename compile-fail test --- .../{E0495.rs => E0621-does-not-trigger-for-closures.rs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/test/compile-fail/{E0495.rs => E0621-does-not-trigger-for-closures.rs} (100%) diff --git a/src/test/compile-fail/E0495.rs b/src/test/compile-fail/E0621-does-not-trigger-for-closures.rs similarity index 100% rename from src/test/compile-fail/E0495.rs rename to src/test/compile-fail/E0621-does-not-trigger-for-closures.rs From 401614b75a1d653786fd527546d288e4cba3a58e Mon Sep 17 00:00:00 2001 From: Venkata Giri Reddy Date: Fri, 30 Jun 2017 16:55:32 +0000 Subject: [PATCH 109/162] rustc_llvm: re-run build script when env var LLVM_CONFIG changes --- src/bootstrap/compile.rs | 4 ---- src/librustc_llvm/build.rs | 6 +----- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index c8ab3a8fc1d..b2bd792e93b 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -276,10 +276,6 @@ pub fn rustc(build: &Build, target: &str, compiler: &Compiler) { if build.is_rust_llvm(target) { cargo.env("LLVM_RUSTLLVM", "1"); } - if let Some(ref cfg_file) = build.flags.config { - let cfg_path = t!(PathBuf::from(cfg_file).canonicalize()); - cargo.env("CFG_LLVM_TOML", cfg_path.into_os_string()); - } cargo.env("LLVM_CONFIG", build.llvm_config(target)); let target_config = build.config.target_config.get(target); if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) { diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs index 01b37a55f4f..3f0f5369607 100644 --- a/src/librustc_llvm/build.rs +++ b/src/librustc_llvm/build.rs @@ -60,11 +60,7 @@ fn main() { }); println!("cargo:rerun-if-changed={}", llvm_config.display()); - - if let Some(cfg_toml) = env::var_os("CFG_LLVM_TOML") { - let cfg_path = PathBuf::from(cfg_toml); - println!("cargo:rerun-if-changed={}", cfg_path.display()); - } + println!("cargo:rerun-if-env-changed=LLVM_CONFIG"); // Test whether we're cross-compiling LLVM. This is a pretty rare case // currently where we're producing an LLVM for a different platform than From 741dc2bad5a6804d024a5b2975859a23a50e1c85 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 30 Jun 2017 10:21:46 -0700 Subject: [PATCH 110/162] Track `iterator_for_each` in #42986 --- .../unstable-book/src/library-features/iterator-for-each.md | 4 ++-- src/libcore/iter/iterator.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/doc/unstable-book/src/library-features/iterator-for-each.md b/src/doc/unstable-book/src/library-features/iterator-for-each.md index 72fdac5e40d..ebeb5f6a1de 100644 --- a/src/doc/unstable-book/src/library-features/iterator-for-each.md +++ b/src/doc/unstable-book/src/library-features/iterator-for-each.md @@ -1,8 +1,8 @@ # `iterator_for_each` -The tracking issue for this feature is: [#TBD] +The tracking issue for this feature is: [#42986] -[#TBD]: https://github.com/rust-lang/rust/issues/TBD +[#42986]: https://github.com/rust-lang/rust/issues/42986 ------------------------ diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index 26660cb3331..d9887094fef 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -522,7 +522,7 @@ pub trait Iterator { /// .for_each(|(i, x)| println!("{}:{}", i, x)); /// ``` #[inline] - #[unstable(feature = "iterator_for_each", issue = "0")] + #[unstable(feature = "iterator_for_each", issue = "42986")] fn for_each(self, mut f: F) where Self: Sized, F: FnMut(Self::Item), { From 4f13da736220fc0d5f3218ac2763617f20b10b89 Mon Sep 17 00:00:00 2001 From: Venkata Giri Reddy Date: Fri, 30 Jun 2017 17:35:00 +0000 Subject: [PATCH 111/162] rustc_{a,l,m,t}san: re-run build script if env var LLVM_CONFIG changes --- src/librustc_asan/build.rs | 1 + src/librustc_lsan/build.rs | 1 + src/librustc_msan/build.rs | 1 + src/librustc_tsan/build.rs | 1 + 4 files changed, 4 insertions(+) diff --git a/src/librustc_asan/build.rs b/src/librustc_asan/build.rs index 3a80baa0485..cb7721affe7 100644 --- a/src/librustc_asan/build.rs +++ b/src/librustc_asan/build.rs @@ -32,4 +32,5 @@ fn main() { .build_target("asan") .build(); } + println!("cargo:rerun-if-env-changed=LLVM_CONFIG"); } diff --git a/src/librustc_lsan/build.rs b/src/librustc_lsan/build.rs index da53571a243..3d2ae480de6 100644 --- a/src/librustc_lsan/build.rs +++ b/src/librustc_lsan/build.rs @@ -32,4 +32,5 @@ fn main() { .build_target("lsan") .build(); } + println!("cargo:rerun-if-env-changed=LLVM_CONFIG"); } diff --git a/src/librustc_msan/build.rs b/src/librustc_msan/build.rs index dcadbe86966..7e2a82dd0ab 100644 --- a/src/librustc_msan/build.rs +++ b/src/librustc_msan/build.rs @@ -32,4 +32,5 @@ fn main() { .build_target("msan") .build(); } + println!("cargo:rerun-if-env-changed=LLVM_CONFIG"); } diff --git a/src/librustc_tsan/build.rs b/src/librustc_tsan/build.rs index 5ea52f17a0f..641d9c3647d 100644 --- a/src/librustc_tsan/build.rs +++ b/src/librustc_tsan/build.rs @@ -32,4 +32,5 @@ fn main() { .build_target("tsan") .build(); } + println!("cargo:rerun-if-env-changed=LLVM_CONFIG"); } From 0a9c13624d2fede5c6ce8e5aa7f486403098bde6 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Fri, 30 Jun 2017 08:34:53 -1000 Subject: [PATCH 112/162] Revert "Stabilize RangeArgument" This reverts commit 143206d54d7558c2326212df99efc98110904fdb. --- src/liballoc/btree/map.rs | 5 +- src/liballoc/btree/set.rs | 3 +- src/liballoc/lib.rs | 51 ++++- src/liballoc/range.rs | 138 +++++++++++++- src/liballoc/string.rs | 5 +- src/liballoc/vec.rs | 5 +- src/liballoc/vec_deque.rs | 5 +- src/libcollections/lib.rs | 1 - src/libcore/ops/mod.rs | 3 - src/libcore/ops/range.rs | 174 +----------------- .../accumulate_vec.rs | 3 +- src/librustc_data_structures/array_vec.rs | 5 +- src/librustc_data_structures/indexed_vec.rs | 3 +- src/librustc_data_structures/lib.rs | 1 + src/libstd/collections/mod.rs | 2 - 15 files changed, 217 insertions(+), 187 deletions(-) diff --git a/src/liballoc/btree/map.rs b/src/liballoc/btree/map.rs index 5243fb6ae0e..a51c70159db 100644 --- a/src/liballoc/btree/map.rs +++ b/src/liballoc/btree/map.rs @@ -13,11 +13,12 @@ use core::fmt::Debug; use core::hash::{Hash, Hasher}; use core::iter::{FromIterator, Peekable, FusedIterator}; use core::marker::PhantomData; -use core::ops::{Index, RangeArgument}; -use core::ops::Bound::{Excluded, Included, Unbounded}; +use core::ops::Index; use core::{fmt, intrinsics, mem, ptr}; use borrow::Borrow; +use Bound::{Excluded, Included, Unbounded}; +use range::RangeArgument; use super::node::{self, Handle, NodeRef, marker}; use super::search; diff --git a/src/liballoc/btree/set.rs b/src/liballoc/btree/set.rs index c755d2d8b85..d32460da939 100644 --- a/src/liballoc/btree/set.rs +++ b/src/liballoc/btree/set.rs @@ -16,11 +16,12 @@ use core::cmp::{min, max}; use core::fmt::Debug; use core::fmt; use core::iter::{Peekable, FromIterator, FusedIterator}; -use core::ops::{BitOr, BitAnd, BitXor, Sub, RangeArgument}; +use core::ops::{BitOr, BitAnd, BitXor, Sub}; use borrow::Borrow; use btree_map::{BTreeMap, Keys}; use super::Recover; +use range::RangeArgument; // FIXME(conventions): implement bounded iterators diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 6f4e300fd3c..ca52943ea97 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -203,7 +203,56 @@ mod std { pub use core::ops; // RangeFull } -pub use core::ops::Bound; +/// An endpoint of a range of keys. +/// +/// # Examples +/// +/// `Bound`s are range endpoints: +/// +/// ``` +/// #![feature(collections_range)] +/// +/// use std::collections::range::RangeArgument; +/// use std::collections::Bound::*; +/// +/// assert_eq!((..100).start(), Unbounded); +/// assert_eq!((1..12).start(), Included(&1)); +/// assert_eq!((1..12).end(), Excluded(&12)); +/// ``` +/// +/// Using a tuple of `Bound`s as an argument to [`BTreeMap::range`]. +/// Note that in most cases, it's better to use range syntax (`1..5`) instead. +/// +/// ``` +/// use std::collections::BTreeMap; +/// use std::collections::Bound::{Excluded, Included, Unbounded}; +/// +/// let mut map = BTreeMap::new(); +/// map.insert(3, "a"); +/// map.insert(5, "b"); +/// map.insert(8, "c"); +/// +/// for (key, value) in map.range((Excluded(3), Included(8))) { +/// println!("{}: {}", key, value); +/// } +/// +/// assert_eq!(Some((&3, &"a")), map.range((Unbounded, Included(5))).next()); +/// ``` +/// +/// [`BTreeMap::range`]: btree_map/struct.BTreeMap.html#method.range +#[stable(feature = "collections_bound", since = "1.17.0")] +#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] +pub enum Bound { + /// An inclusive bound. + #[stable(feature = "collections_bound", since = "1.17.0")] + Included(T), + /// An exclusive bound. + #[stable(feature = "collections_bound", since = "1.17.0")] + Excluded(T), + /// An infinite endpoint. Indicates that there is no bound in this direction. + #[stable(feature = "collections_bound", since = "1.17.0")] + Unbounded, +} /// An intermediate trait for specialization of `Extend`. #[doc(hidden)] diff --git a/src/liballoc/range.rs b/src/liballoc/range.rs index 0a058c47a50..f862da0d61e 100644 --- a/src/liballoc/range.rs +++ b/src/liballoc/range.rs @@ -11,8 +11,142 @@ #![unstable(feature = "collections_range", reason = "waiting for dust to settle on inclusive ranges", issue = "30877")] -#![rustc_deprecated(reason = "moved to core::ops", since = "1.19.0")] //! Range syntax. -pub use core::ops::RangeArgument; +use core::ops::{RangeFull, Range, RangeTo, RangeFrom, RangeInclusive, RangeToInclusive}; +use Bound::{self, Excluded, Included, Unbounded}; + +/// `RangeArgument` is implemented by Rust's built-in range types, produced +/// by range syntax like `..`, `a..`, `..b` or `c..d`. +pub trait RangeArgument { + /// Start index bound. + /// + /// Returns the start value as a `Bound`. + /// + /// # Examples + /// + /// ``` + /// #![feature(alloc)] + /// #![feature(collections_range)] + /// + /// extern crate alloc; + /// + /// # fn main() { + /// use alloc::range::RangeArgument; + /// use alloc::Bound::*; + /// + /// assert_eq!((..10).start(), Unbounded); + /// assert_eq!((3..10).start(), Included(&3)); + /// # } + /// ``` + fn start(&self) -> Bound<&T>; + + /// End index bound. + /// + /// Returns the end value as a `Bound`. + /// + /// # Examples + /// + /// ``` + /// #![feature(alloc)] + /// #![feature(collections_range)] + /// + /// extern crate alloc; + /// + /// # fn main() { + /// use alloc::range::RangeArgument; + /// use alloc::Bound::*; + /// + /// assert_eq!((3..).end(), Unbounded); + /// assert_eq!((3..10).end(), Excluded(&10)); + /// # } + /// ``` + fn end(&self) -> Bound<&T>; +} + +// FIXME add inclusive ranges to RangeArgument + +impl RangeArgument for RangeFull { + fn start(&self) -> Bound<&T> { + Unbounded + } + fn end(&self) -> Bound<&T> { + Unbounded + } +} + +impl RangeArgument for RangeFrom { + fn start(&self) -> Bound<&T> { + Included(&self.start) + } + fn end(&self) -> Bound<&T> { + Unbounded + } +} + +impl RangeArgument for RangeTo { + fn start(&self) -> Bound<&T> { + Unbounded + } + fn end(&self) -> Bound<&T> { + Excluded(&self.end) + } +} + +impl RangeArgument for Range { + fn start(&self) -> Bound<&T> { + Included(&self.start) + } + fn end(&self) -> Bound<&T> { + Excluded(&self.end) + } +} + +#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] +impl RangeArgument for RangeInclusive { + fn start(&self) -> Bound<&T> { + Included(&self.start) + } + fn end(&self) -> Bound<&T> { + Included(&self.end) + } +} + +#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] +impl RangeArgument for RangeToInclusive { + fn start(&self) -> Bound<&T> { + Unbounded + } + fn end(&self) -> Bound<&T> { + Included(&self.end) + } +} + +impl RangeArgument for (Bound, Bound) { + fn start(&self) -> Bound<&T> { + match *self { + (Included(ref start), _) => Included(start), + (Excluded(ref start), _) => Excluded(start), + (Unbounded, _) => Unbounded, + } + } + + fn end(&self) -> Bound<&T> { + match *self { + (_, Included(ref end)) => Included(end), + (_, Excluded(ref end)) => Excluded(end), + (_, Unbounded) => Unbounded, + } + } +} + +impl<'a, T: ?Sized + 'a> RangeArgument for (Bound<&'a T>, Bound<&'a T>) { + fn start(&self) -> Bound<&T> { + self.0 + } + + fn end(&self) -> Bound<&T> { + self.1 + } +} diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index 1f0894d39d4..79d1ccf637d 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -59,14 +59,15 @@ use core::fmt; use core::hash; use core::iter::{FromIterator, FusedIterator}; -use core::ops::{self, Add, AddAssign, Index, IndexMut, RangeArgument}; -use core::ops::Bound::{Excluded, Included, Unbounded}; +use core::ops::{self, Add, AddAssign, Index, IndexMut}; use core::ptr; use core::str::pattern::Pattern; use std_unicode::lossy; use std_unicode::char::{decode_utf16, REPLACEMENT_CHARACTER}; use borrow::{Cow, ToOwned}; +use range::RangeArgument; +use Bound::{Excluded, Included, Unbounded}; use str::{self, from_boxed_utf8_unchecked, FromStr, Utf8Error, Chars}; use vec::Vec; use boxed::Box; diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index e118d406ecf..5d1999a4262 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -74,8 +74,7 @@ use core::iter::{FromIterator, FusedIterator, TrustedLen}; use core::mem; #[cfg(not(test))] use core::num::Float; -use core::ops::{InPlace, Index, IndexMut, Place, Placer, RangeArgument}; -use core::ops::Bound::{Excluded, Included, Unbounded}; +use core::ops::{InPlace, Index, IndexMut, Place, Placer}; use core::ops; use core::ptr; use core::ptr::Shared; @@ -85,6 +84,8 @@ use borrow::ToOwned; use borrow::Cow; use boxed::Box; use raw_vec::RawVec; +use super::range::RangeArgument; +use Bound::{Excluded, Included, Unbounded}; /// A contiguous growable array type, written `Vec` but pronounced 'vector'. /// diff --git a/src/liballoc/vec_deque.rs b/src/liballoc/vec_deque.rs index d1d334267bc..18175a5d01b 100644 --- a/src/liballoc/vec_deque.rs +++ b/src/liballoc/vec_deque.rs @@ -21,8 +21,7 @@ use core::cmp::Ordering; use core::fmt; use core::iter::{repeat, FromIterator, FusedIterator}; use core::mem; -use core::ops::{Index, IndexMut, Place, Placer, InPlace, RangeArgument}; -use core::ops::Bound::{Excluded, Included, Unbounded}; +use core::ops::{Index, IndexMut, Place, Placer, InPlace}; use core::ptr; use core::ptr::Shared; use core::slice; @@ -32,6 +31,8 @@ use core::cmp; use raw_vec::RawVec; +use super::range::RangeArgument; +use Bound::{Excluded, Included, Unbounded}; use super::vec::Vec; const INITIAL_CAPACITY: usize = 7; // 2^3 - 1 diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index 0a939831622..de5d6df328c 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -46,7 +46,6 @@ pub use alloc::binary_heap; pub use alloc::borrow; pub use alloc::fmt; pub use alloc::linked_list; -#[allow(deprecated)] pub use alloc::range; pub use alloc::slice; pub use alloc::str; diff --git a/src/libcore/ops/mod.rs b/src/libcore/ops/mod.rs index 34f00850579..a78f4fe28a6 100644 --- a/src/libcore/ops/mod.rs +++ b/src/libcore/ops/mod.rs @@ -183,9 +183,6 @@ pub use self::index::{Index, IndexMut}; #[stable(feature = "rust1", since = "1.0.0")] pub use self::range::{Range, RangeFrom, RangeFull, RangeTo}; -#[stable(feature = "range_argument", since = "1.19.0")] -pub use self::range::{RangeArgument, Bound}; - #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] pub use self::range::{RangeInclusive, RangeToInclusive}; diff --git a/src/libcore/ops/range.rs b/src/libcore/ops/range.rs index 65e09da4fff..33258b7a875 100644 --- a/src/libcore/ops/range.rs +++ b/src/libcore/ops/range.rs @@ -9,7 +9,6 @@ // except according to those terms. use fmt; -use ops::Bound::{Included, Excluded, Unbounded}; /// An unbounded range. Use `..` (two dots) for its shorthand. /// @@ -72,8 +71,7 @@ impl fmt::Debug for RangeFull { /// assert_eq!(arr[1..3], [ 1,2 ]); // Range /// } /// ``` -#[derive(Clone, PartialEq, Eq, Hash)] -// not Copy -- see #27186 +#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 #[stable(feature = "rust1", since = "1.0.0")] pub struct Range { /// The lower bound of the range (inclusive). @@ -136,8 +134,7 @@ impl> Range { /// assert_eq!(arr[1..3], [ 1,2 ]); /// } /// ``` -#[derive(Clone, PartialEq, Eq, Hash)] -// not Copy -- see #27186 +#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 #[stable(feature = "rust1", since = "1.0.0")] pub struct RangeFrom { /// The lower bound of the range (inclusive). @@ -253,16 +250,17 @@ impl> RangeTo { /// assert_eq!(arr[1...2], [ 1,2 ]); // RangeInclusive /// } /// ``` -#[derive(Clone, PartialEq, Eq, Hash)] -// not Copy -- see #27186 +#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] pub struct RangeInclusive { /// The lower bound of the range (inclusive). - #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", + #[unstable(feature = "inclusive_range", + reason = "recently added, follows RFC", issue = "28237")] pub start: Idx, /// The upper bound of the range (inclusive). - #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", + #[unstable(feature = "inclusive_range", + reason = "recently added, follows RFC", issue = "28237")] pub end: Idx, } @@ -335,7 +333,8 @@ impl> RangeInclusive { #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] pub struct RangeToInclusive { /// The upper bound of the range (inclusive) - #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", + #[unstable(feature = "inclusive_range", + reason = "recently added, follows RFC", issue = "28237")] pub end: Idx, } @@ -366,158 +365,3 @@ impl> RangeToInclusive { // RangeToInclusive cannot impl From> // because underflow would be possible with (..0).into() - -/// `RangeArgument` is implemented by Rust's built-in range types, produced -/// by range syntax like `..`, `a..`, `..b` or `c..d`. -#[stable(feature = "range_argument", since = "1.19.0")] -pub trait RangeArgument { - /// Start index bound. - /// - /// Returns the start value as a `Bound`. - /// - /// # Examples - /// - /// ``` - /// use std::ops::RangeArgument; - /// use std::ops::Bound::*; - /// - /// assert_eq!((..10).start(), Unbounded); - /// assert_eq!((3..10).start(), Included(&3)); - /// ``` - #[stable(feature = "range_argument", since = "1.19.0")] - fn start(&self) -> Bound<&T>; - - /// End index bound. - /// - /// Returns the end value as a `Bound`. - /// - /// # Examples - /// - /// ``` - /// use std::ops::RangeArgument; - /// use std::ops::Bound::*; - /// - /// assert_eq!((3..).end(), Unbounded); - /// assert_eq!((3..10).end(), Excluded(&10)); - /// ``` - #[stable(feature = "range_argument", since = "1.19.0")] - fn end(&self) -> Bound<&T>; -} - -#[stable(feature = "range_argument", since = "1.19.0")] -impl RangeArgument for RangeFull { - fn start(&self) -> Bound<&T> { - Unbounded - } - fn end(&self) -> Bound<&T> { - Unbounded - } -} - -#[stable(feature = "range_argument", since = "1.19.0")] -impl RangeArgument for RangeFrom { - fn start(&self) -> Bound<&T> { - Included(&self.start) - } - fn end(&self) -> Bound<&T> { - Unbounded - } -} - -#[stable(feature = "range_argument", since = "1.19.0")] -impl RangeArgument for RangeTo { - fn start(&self) -> Bound<&T> { - Unbounded - } - fn end(&self) -> Bound<&T> { - Excluded(&self.end) - } -} - -#[stable(feature = "range_argument", since = "1.19.0")] -impl RangeArgument for Range { - fn start(&self) -> Bound<&T> { - Included(&self.start) - } - fn end(&self) -> Bound<&T> { - Excluded(&self.end) - } -} - -#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] -impl RangeArgument for RangeInclusive { - fn start(&self) -> Bound<&T> { - Included(&self.start) - } - fn end(&self) -> Bound<&T> { - Included(&self.end) - } -} - -#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] -impl RangeArgument for RangeToInclusive { - fn start(&self) -> Bound<&T> { - Unbounded - } - fn end(&self) -> Bound<&T> { - Included(&self.end) - } -} - -#[stable(feature = "range_argument", since = "1.19.0")] -impl RangeArgument for (Bound, Bound) { - fn start(&self) -> Bound<&T> { - match *self { - (Included(ref start), _) => Included(start), - (Excluded(ref start), _) => Excluded(start), - (Unbounded, _) => Unbounded, - } - } - - fn end(&self) -> Bound<&T> { - match *self { - (_, Included(ref end)) => Included(end), - (_, Excluded(ref end)) => Excluded(end), - (_, Unbounded) => Unbounded, - } - } -} - -#[stable(feature = "range_argument", since = "1.19.0")] -impl<'a, T: ?Sized + 'a> RangeArgument for (Bound<&'a T>, Bound<&'a T>) { - fn start(&self) -> Bound<&T> { - self.0 - } - - fn end(&self) -> Bound<&T> { - self.1 - } -} - -/// An endpoint of a range of keys. -/// -/// # Examples -/// -/// `Bound`s are range endpoints: -/// -/// ``` -/// use std::ops::RangeArgument; -/// use std::ops::Bound::*; -/// -/// assert_eq!((..100).start(), Unbounded); -/// assert_eq!((1..12).start(), Included(&1)); -/// assert_eq!((1..12).end(), Excluded(&12)); -/// ``` -#[stable(feature = "collections_bound", since = "1.17.0")] -#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] -pub enum Bound { - /// An inclusive bound. - #[stable(feature = "collections_bound", since = "1.17.0")] - Included(T), - /// An exclusive bound. - #[stable(feature = "collections_bound", since = "1.17.0")] - Excluded(T), - /// An infinite endpoint. Indicates that there is no bound in this direction. - #[stable(feature = "collections_bound", since = "1.17.0")] - Unbounded, -} diff --git a/src/librustc_data_structures/accumulate_vec.rs b/src/librustc_data_structures/accumulate_vec.rs index eacd394ad5e..c03c2890ba3 100644 --- a/src/librustc_data_structures/accumulate_vec.rs +++ b/src/librustc_data_structures/accumulate_vec.rs @@ -15,10 +15,11 @@ //! //! The N above is determined by Array's implementor, by way of an associatated constant. -use std::ops::{Deref, DerefMut, RangeArgument}; +use std::ops::{Deref, DerefMut}; use std::iter::{self, IntoIterator, FromIterator}; use std::slice; use std::vec; +use std::collections::range::RangeArgument; use rustc_serialize::{Encodable, Encoder, Decodable, Decoder}; diff --git a/src/librustc_data_structures/array_vec.rs b/src/librustc_data_structures/array_vec.rs index a9abdf1377e..078bb801751 100644 --- a/src/librustc_data_structures/array_vec.rs +++ b/src/librustc_data_structures/array_vec.rs @@ -13,12 +13,13 @@ use std::marker::Unsize; use std::iter::Extend; use std::ptr::{self, drop_in_place, Shared}; -use std::ops::{Deref, DerefMut, Range, RangeArgument}; -use std::ops::Bound::{Excluded, Included, Unbounded}; +use std::ops::{Deref, DerefMut, Range}; use std::hash::{Hash, Hasher}; use std::slice; use std::fmt; use std::mem; +use std::collections::range::RangeArgument; +use std::collections::Bound::{Excluded, Included, Unbounded}; use std::mem::ManuallyDrop; pub unsafe trait Array { diff --git a/src/librustc_data_structures/indexed_vec.rs b/src/librustc_data_structures/indexed_vec.rs index 3bf926fa8bf..29ac650aa70 100644 --- a/src/librustc_data_structures/indexed_vec.rs +++ b/src/librustc_data_structures/indexed_vec.rs @@ -8,11 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::collections::range::RangeArgument; use std::fmt::Debug; use std::iter::{self, FromIterator}; use std::slice; use std::marker::PhantomData; -use std::ops::{Index, IndexMut, Range, RangeArgument}; +use std::ops::{Index, IndexMut, Range}; use std::fmt; use std::vec; use std::u32; diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index 0bbda547761..d63b4c9c31b 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -25,6 +25,7 @@ #![deny(warnings)] #![feature(shared)] +#![feature(collections_range)] #![feature(nonzero)] #![feature(unboxed_closures)] #![feature(fn_traits)] diff --git a/src/libstd/collections/mod.rs b/src/libstd/collections/mod.rs index 2ed6724b07d..b8a6a66eaa6 100644 --- a/src/libstd/collections/mod.rs +++ b/src/libstd/collections/mod.rs @@ -436,8 +436,6 @@ pub use self::hash_map::HashMap; pub use self::hash_set::HashSet; #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_deprecated(reason = "moved to std::ops", since = "1.19.0")] -#[allow(deprecated)] pub use alloc::range; mod hash; From aff84eb3aa24119084079d5aa2d385bfaa5c8a2d Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Fri, 30 Jun 2017 23:13:40 +0300 Subject: [PATCH 113/162] Add .editorconfig to src/rustllvm ... which uses 2 space indent instead of common 4 spaces. --- src/rustllvm/.editorconfig | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 src/rustllvm/.editorconfig diff --git a/src/rustllvm/.editorconfig b/src/rustllvm/.editorconfig new file mode 100644 index 00000000000..865cd45f708 --- /dev/null +++ b/src/rustllvm/.editorconfig @@ -0,0 +1,6 @@ +[*.{h,cpp}] +end_of_line = lf +insert_final_newline = true +charset = utf-8 +indent_style = space +indent_size = 2 From affe6e148c9aee2977d4ba0679f0ff92c67a16da Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Fri, 30 Jun 2017 23:18:47 +0300 Subject: [PATCH 114/162] Ignore *.iml files ... which are IntelliJ IDEA module files. (`.idea` is IDEA project files.) --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index ff839c34df1..b54bab177d0 100644 --- a/.gitignore +++ b/.gitignore @@ -51,6 +51,7 @@ .hg/ .hgignore .idea +*.iml __pycache__/ *.py[cod] *$py.class From aa3fa254768f1cfe51fc013a24383153fa2b924a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 29 Jun 2017 00:02:21 +0200 Subject: [PATCH 115/162] Add E0619 error explanation --- src/librustc_typeck/diagnostics.rs | 21 +++++++++++++++++++++ src/test/compile-fail/E0619.rs | 14 ++++++-------- src/test/compile-fail/invalid-intrinsic.rs | 16 ---------------- 3 files changed, 27 insertions(+), 24 deletions(-) delete mode 100644 src/test/compile-fail/invalid-intrinsic.rs diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 1b17faccc87..8181dba1e96 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -4666,6 +4666,7 @@ i_am_a_function(); "##, E0619: r##" +<<<<<<< HEAD The type-checker needed to know the type of an expression, but that type had not yet been inferred. @@ -4726,6 +4727,26 @@ let x = &[1_usize, 2] as &[usize]; // ok! ``` "##, +E0621: r##" +An intrinsic was declared without being a function. + +Erroneous code example: + +```compile_fail,E0621 +#![feature(intrinsics)] +extern "rust-intrinsic" { + pub static breakpoint : unsafe extern "rust-intrinsic" fn(); + // error: intrinsic must be a function +} + +fn main() { unsafe { breakpoint(); } } +``` + +An intrinsic is a function available for use in a given programming language +whose implementation is handled specially by the compiler. In order to fix this +error, just declare a function. +"##, + } register_diagnostics! { diff --git a/src/test/compile-fail/E0619.rs b/src/test/compile-fail/E0619.rs index 8ef90d89931..7c61a61f0bd 100644 --- a/src/test/compile-fail/E0619.rs +++ b/src/test/compile-fail/E0619.rs @@ -1,4 +1,4 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -8,11 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn main() { - let x; - - match x { - (..) => {} //~ ERROR E0619 - _ => {} - } +#![feature(intrinsics)] +extern "rust-intrinsic" { + pub static breakpoint : unsafe extern "rust-intrinsic" fn(); + //~^ ERROR intrinsic must be a function [E0619] } +fn main() { unsafe { breakpoint(); } } diff --git a/src/test/compile-fail/invalid-intrinsic.rs b/src/test/compile-fail/invalid-intrinsic.rs deleted file mode 100644 index c42d78c323e..00000000000 --- a/src/test/compile-fail/invalid-intrinsic.rs +++ /dev/null @@ -1,16 +0,0 @@ -// 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. - -#![feature(intrinsics)] -extern "rust-intrinsic" { - pub static breakpoint : unsafe extern "rust-intrinsic" fn(); - //~^ ERROR intrinsic must be a function -} -fn main() { unsafe { breakpoint(); } } From 3456608aaed5db6ec3a520a295983e97c4f031fd Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Fri, 30 Jun 2017 13:37:05 -0700 Subject: [PATCH 116/162] Fix long line --- src/libstd/sys/redox/fs.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libstd/sys/redox/fs.rs b/src/libstd/sys/redox/fs.rs index 9a16fc1bf66..c5a19e8debe 100644 --- a/src/libstd/sys/redox/fs.rs +++ b/src/libstd/sys/redox/fs.rs @@ -428,7 +428,8 @@ pub fn readlink(p: &Path) -> io::Result { } pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> { - let fd = cvt(syscall::open(dst.to_str().unwrap(), syscall::O_SYMLINK | syscall::O_CREAT | syscall::O_WRONLY | 0o777))?; + let fd = cvt(syscall::open(dst.to_str().unwrap(), + syscall::O_SYMLINK | syscall::O_CREAT | syscall::O_WRONLY | 0o777))?; cvt(syscall::write(fd, src.to_str().unwrap().as_bytes()))?; cvt(syscall::close(fd))?; Ok(()) From 162b5a347590a7dbc77d3281595b1bfaba98e3b1 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 29 Jun 2017 21:03:19 +0200 Subject: [PATCH 117/162] Fix error codes mixup --- src/librustc_typeck/check/intrinsic.rs | 2 +- src/librustc_typeck/diagnostics.rs | 5 ++--- src/test/compile-fail/E0619.rs | 15 +++++++++------ src/test/compile-fail/E0622.rs | 16 ++++++++++++++++ 4 files changed, 28 insertions(+), 10 deletions(-) create mode 100644 src/test/compile-fail/E0622.rs diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index 3acfbd1d844..96643ae72ab 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -37,7 +37,7 @@ fn equate_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, match it.node { hir::ForeignItemFn(..) => {} _ => { - struct_span_err!(tcx.sess, it.span, E0619, + struct_span_err!(tcx.sess, it.span, E0622, "intrinsic must be a function") .span_label(it.span, "expected a function") .emit(); diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 8181dba1e96..37f6f3753d7 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -4666,7 +4666,6 @@ i_am_a_function(); "##, E0619: r##" -<<<<<<< HEAD The type-checker needed to know the type of an expression, but that type had not yet been inferred. @@ -4727,12 +4726,12 @@ let x = &[1_usize, 2] as &[usize]; // ok! ``` "##, -E0621: r##" +E0622: r##" An intrinsic was declared without being a function. Erroneous code example: -```compile_fail,E0621 +```compile_fail,E0622 #![feature(intrinsics)] extern "rust-intrinsic" { pub static breakpoint : unsafe extern "rust-intrinsic" fn(); diff --git a/src/test/compile-fail/E0619.rs b/src/test/compile-fail/E0619.rs index 7c61a61f0bd..a5a5ff7218d 100644 --- a/src/test/compile-fail/E0619.rs +++ b/src/test/compile-fail/E0619.rs @@ -1,4 +1,4 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,9 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(intrinsics)] -extern "rust-intrinsic" { - pub static breakpoint : unsafe extern "rust-intrinsic" fn(); - //~^ ERROR intrinsic must be a function [E0619] +fn main() { + let x; + + match x { + (..) => {} //~ ERROR E0619 + _ => {} + } } -fn main() { unsafe { breakpoint(); } } + diff --git a/src/test/compile-fail/E0622.rs b/src/test/compile-fail/E0622.rs new file mode 100644 index 00000000000..f2bde5b0364 --- /dev/null +++ b/src/test/compile-fail/E0622.rs @@ -0,0 +1,16 @@ +// 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. + +#![feature(intrinsics)] +extern "rust-intrinsic" { + pub static breakpoint : unsafe extern "rust-intrinsic" fn(); + //~^ ERROR intrinsic must be a function [E0622] +} +fn main() { unsafe { breakpoint(); } } From a6994d7f3aed68f6a200fa6c48484924c4109c0b Mon Sep 17 00:00:00 2001 From: Behnam Esfahbod Date: Fri, 30 Jun 2017 17:25:28 -0600 Subject: [PATCH 118/162] [libstd_unicode] Upgrade to Unicode 10.0.0 --- src/libstd_unicode/tables.rs | 323 ++++++++++++++++++----------------- 1 file changed, 168 insertions(+), 155 deletions(-) diff --git a/src/libstd_unicode/tables.rs b/src/libstd_unicode/tables.rs index 7173040350e..0938738b52c 100644 --- a/src/libstd_unicode/tables.rs +++ b/src/libstd_unicode/tables.rs @@ -14,7 +14,7 @@ /// The version of [Unicode](http://www.unicode.org/) /// that the unicode parts of `CharExt` and `UnicodeStrPrelude` traits are based on. -pub const UNICODE_VERSION: (u64, u64, u64) = (9, 0, 0); +pub const UNICODE_VERSION: (u64, u64, u64) = (10, 0, 0); // BoolTrie is a trie for representing a set of Unicode codepoints. It is @@ -167,7 +167,7 @@ pub mod general_category { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 6, 7, 0, 0, 8, 0, 0, 0, 6, 0, 0, 0, 0, 0, 8, 0, 8, 0, 0, 0, 0, 0, 8, 0, 9, 6, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, + 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -236,7 +236,7 @@ pub mod derived_property { 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 95, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 96, 97, 36, 36, 36, 36, 98, 99, 36, 100, 101, 36, 102, - 103, 104, 105, 36, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 36, 117, 36, + 103, 104, 105, 36, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 36, 95, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, @@ -244,23 +244,23 @@ pub mod derived_property { 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 118, 119, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 117, 118, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, - 36, 36, 36, 36, 36, 120, 36, 121, 122, 123, 124, 125, 36, 36, 36, 36, 126, 127, 128, - 129, 31, 130, 36, 131, 132, 133, 113, 134 + 36, 36, 36, 36, 36, 119, 36, 120, 121, 122, 123, 124, 36, 36, 36, 36, 125, 126, 127, + 128, 31, 129, 36, 130, 131, 132, 113, 133 ], r3: &[ - 0x00001ffffcffffff, 0x0000000001ffffff, 0x3fdfffff00000000, 0xffff03f8fff00000, - 0xefffffffffffffff, 0xfffe000fffe1dfff, 0xe3c5fdfffff99fef, 0x0003000fb080599f, - 0xc36dfdfffff987ee, 0x003f00005e021987, 0xe3edfdfffffbbfee, 0x0200000f00011bbf, + 0x00001ffffcffffff, 0x000007ff01ffffff, 0x3fdfffff00000000, 0xffff03f8fff00000, + 0xefffffffffffffff, 0xfffe000fffe1dfff, 0xe3c5fdfffff99fef, 0x1003000fb080599f, + 0xc36dfdfffff987ee, 0x003f00005e021987, 0xe3edfdfffffbbfee, 0x1e00000f00011bbf, 0xe3edfdfffff99fee, 0x0002000fb0c0199f, 0xc3ffc718d63dc7ec, 0x0000000000811dc7, 0xe3fffdfffffddfef, 0x0000000f07601ddf, 0xe3effdfffffddfef, 0x0006000f40601ddf, - 0xe7fffffffffddfee, 0xfc00000f80f05ddf, 0x2ffbfffffc7fffec, 0x000c0000ff5f807f, + 0xe7fffffffffddfef, 0xfc00000f80f05ddf, 0x2ffbfffffc7fffec, 0x000c0000ff5f807f, 0x07fffffffffffffe, 0x000000000000207f, 0x3bffecaefef02596, 0x00000000f000205f, 0x0000000000000001, 0xfffe1ffffffffeff, 0x1ffffffffeffff03, 0x0000000000000000, 0xf97fffffffffffff, 0xffffc1e7ffff0000, 0xffffffff3000407f, 0xf7ffffffffff20bf, @@ -278,74 +278,76 @@ pub mod derived_property { 0x000003ffffffffff, 0xffff7fffffffffff, 0xffffffff7fffffff, 0x000c781fffffffff, 0xffff20bfffffffff, 0x000080ffffffffff, 0x7f7f7f7f007fffff, 0xffffffff7f7f7f7f, 0x0000800000000000, 0x1f3e03fe000000e0, 0xfffffffee07fffff, 0xf7ffffffffffffff, - 0xfffe3fffffffffe0, 0x07ffffff00007fff, 0xffff000000000000, 0x00000000003fffff, + 0xfffe7fffffffffe0, 0x07ffffff00007fff, 0xffff000000000000, 0x000007ffffffffff, 0x0000000000001fff, 0x3fffffffffff0000, 0x00000c00ffff1fff, 0x8ff07fffffffffff, 0x0000ffffffffffff, 0xfffffffcff800000, 0x00ff7ffffffff9ff, 0xff80000000000000, 0x000000fffffff7bb, 0x000fffffffffffff, 0x28fc00000000002f, 0xffff07fffffffc00, 0x1fffffff0007ffff, 0xfff7ffffffffffff, 0x7c00ffdf00008000, 0x007fffffffffffff, 0xc47fffff00003fff, 0x7fffffffffffffff, 0x003cffff38000005, 0xffff7f7f007e7e7e, - 0xffff003ff7ffffff, 0x000007ffffffffff, 0xffff000fffffffff, 0x0ffffffffffff87f, - 0xffff3fffffffffff, 0x0000000003ffffff, 0x5f7ffdffe0f8007f, 0xffffffffffffffdb, - 0x0003ffffffffffff, 0xfffffffffff80000, 0x3fffffffffffffff, 0xffffffffffff0000, - 0xfffffffffffcffff, 0x0fff0000000000ff, 0xffdf000000000000, 0x1fffffffffffffff, - 0x07fffffe00000000, 0xffffffc007fffffe, 0x000000001cfcfcfc + 0xffff003ff7ffffff, 0xffff000fffffffff, 0x0ffffffffffff87f, 0xffff3fffffffffff, + 0x0000000003ffffff, 0x5f7ffdffe0f8007f, 0xffffffffffffffdb, 0x0003ffffffffffff, + 0xfffffffffff80000, 0x3fffffffffffffff, 0xffffffffffff0000, 0xfffffffffffcffff, + 0x0fff0000000000ff, 0xffdf000000000000, 0x1fffffffffffffff, 0x07fffffe00000000, + 0xffffffc007fffffe, 0x000000001cfcfcfc ], r4: [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 5, 5, 9, 5, 10, 11, 12, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 13, 14, - 15, 5, 5, 16, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 15, 7, 16, 17, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 ], r5: &[ 0, 1, 2, 3, 4, 5, 4, 4, 4, 4, 6, 7, 8, 9, 10, 11, 2, 2, 12, 13, 14, 15, 4, 4, 2, 2, 2, 2, 16, 17, 4, 4, 18, 19, 20, 21, 22, 4, 23, 4, 24, 25, 26, 27, 28, 29, 30, 4, 2, 31, 32, 32, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 33, 34, 35, 32, 36, 2, 37, 38, 4, 39, 40, 41, 42, 4, 4, 2, 43, 2, 44, 4, 4, 45, 46, 47, 48, 28, 4, 49, 4, 4, 4, 4, 4, 50, 51, 4, 4, 4, - 4, 4, 4, 4, 52, 4, 4, 4, 4, 53, 54, 55, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 56, 4, 2, 57, 2, 2, 2, 58, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 52, 53, 54, 55, 4, 4, 4, 4, 56, 57, 58, 4, 59, 60, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 61, 4, 2, 62, 2, 2, 2, 63, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 57, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 62, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 59, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 64, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, - 2, 2, 2, 2, 52, 20, 4, 60, 16, 61, 62, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 63, 64, - 65, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, + 2, 2, 2, 2, 2, 2, 55, 20, 4, 65, 16, 66, 67, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, + 68, 69, 70, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 66, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 32, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 67, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 71, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 32, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 20, 72, 2, 2, 2, 2, 2, 73, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 2, 68, 69, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 2, 70, 71, 72, 73, 74, 2, 2, 2, 2, 75, 76, 77, 78, 79, 80, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 81, + 4, 4, 4, 4, 4, 4, 4, 2, 74, 75, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 76, 77, 78, 79, 80, 2, 2, 2, 2, 81, 82, 83, 84, 85, 86, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 2, 2, 2, 82, 2, 83, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 84, 85, - 86, 4, 4, 4, 4, 4, 4, 4, 4, 4, 87, 88, 89, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 87, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 2, 2, 2, 88, 2, 89, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 90, 91, 92, 4, 4, 4, 4, 4, 4, 4, 4, 4, 72, 93, 94, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 90, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 95, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 2, 2, 2, 10, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 2, 2, 2, 10, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 91, 4, 4, 4, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 96, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 97, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 92, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4 + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 98, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ], r6: &[ 0xb7ffff7fffffefff, 0x000000003fff3fff, 0xffffffffffffffff, 0x07ffffffffffffff, 0x0000000000000000, 0x001fffffffffffff, 0xffffffff1fffffff, 0x000000000001ffff, - 0xffff0000ffffffff, 0x07ffffffffff07ff, 0xffffffff3fffffff, 0x00000000003eff0f, + 0xffffe000ffffffff, 0x07ffffffffff07ff, 0xffffffff3fffffff, 0x00000000003eff0f, 0xffff00003fffffff, 0x0fffffffff0fffff, 0xffff00ffffffffff, 0x0000000fffffffff, 0x007fffffffffffff, 0x000000ff003fffff, 0x91bffffffffffd3f, 0x007fffff003fffff, 0x000000007fffffff, 0x0037ffff00000000, 0x03ffffff003fffff, 0xc0ffffffffffffff, @@ -356,17 +358,18 @@ pub mod derived_property { 0x000001ffffffffff, 0xe3edfdfffff99fef, 0x0000000fe081199f, 0x00000000000007bb, 0x00000000000000b3, 0x7f3fffffffffffff, 0x000000003f000000, 0x7fffffffffffffff, 0x0000000000000011, 0x000007ffe3ffffff, 0xffffffff00000000, 0x80000000ffffffff, - 0x01ffffffffffffff, 0x7f7ffffffffffdff, 0xfffc000000000001, 0x007ffefffffcffff, - 0x0000000003ffffff, 0x00007fffffffffff, 0x000000000000000f, 0x000000000000007f, - 0x00003fffffff0000, 0xe0fffff80000000f, 0x000000000000ffff, 0x7fffffffffff001f, - 0x00000000fff80000, 0x0000000100000000, 0x00001fffffffffff, 0x0000000000000003, - 0x1fff07ffffffffff, 0x0000000043ff01ff, 0xffffffffffdfffff, 0xebffde64dfffffff, - 0xffffffffffffffef, 0x7bffffffdfdfe7bf, 0xfffffffffffdfc5f, 0xffffff3fffffffff, - 0xf7fffffff7fffffd, 0xffdfffffffdfffff, 0xffff7fffffff7fff, 0xfffffdfffffffdff, - 0x0000000000000ff7, 0x000007dbf9ffff7f, 0x000000000000001f, 0x000000000000008f, - 0x0af7fe96ffffffef, 0x5ef7f796aa96ea84, 0x0ffffbee0ffffbff, 0xffff000000000000, - 0xffff03ffffff03ff, 0x00000000000003ff, 0x00000000007fffff, 0x00000003ffffffff, - 0x000000003fffffff + 0x7fe7ffffffffffff, 0xffffffffffff0000, 0x0000000000ffffcf, 0x01ffffffffffffff, + 0x7f7ffffffffffdff, 0xfffc000000000001, 0x007ffefffffcffff, 0xb47ffffffffffb7f, + 0x00000000000000cb, 0x0000000003ffffff, 0x00007fffffffffff, 0x000000000000000f, + 0x000000000000007f, 0x00003fffffff0000, 0xe0fffff80000000f, 0x000000000000ffff, + 0x7fffffffffff001f, 0x00000000fff80000, 0x0000000300000000, 0x00001fffffffffff, + 0xffff000000000000, 0x0fffffffffffffff, 0x1fff07ffffffffff, 0x0000000043ff01ff, + 0xffffffffffdfffff, 0xebffde64dfffffff, 0xffffffffffffffef, 0x7bffffffdfdfe7bf, + 0xfffffffffffdfc5f, 0xffffff3fffffffff, 0xf7fffffff7fffffd, 0xffdfffffffdfffff, + 0xffff7fffffff7fff, 0xfffffdfffffffdff, 0x0000000000000ff7, 0x000007dbf9ffff7f, + 0x000000000000001f, 0x000000000000008f, 0x0af7fe96ffffffef, 0x5ef7f796aa96ea84, + 0x0ffffbee0ffffbff, 0xffff03ffffff03ff, 0x00000000000003ff, 0x00000000007fffff, + 0xffff0003ffffffff, 0x00000001ffffffff, 0x000000003fffffff ], }; @@ -426,9 +429,9 @@ pub mod derived_property { r3: &[ 0x00003fffffc00000, 0x000000000e000000, 0x0000000000000000, 0xfffffffffff00000, 0x1400000000000007, 0x0002000c00fe21fe, 0x1000000000000002, 0x0000000c0000201e, - 0x1000000000000006, 0x0023000000023986, 0x0000000c000021be, 0x9000000000000002, + 0x1000000000000006, 0x0023000000023986, 0xfc00000c000021be, 0x9000000000000002, 0x0000000c0040201e, 0x0000000000000004, 0x0000000000002001, 0xc000000000000001, - 0x0000000c00603dc1, 0x0000000c00003040, 0x0000000000000002, 0x00000000005c0400, + 0x0000000c00603dc1, 0x0000000c00003040, 0x1800000000000003, 0x00000000005c0400, 0x07f2000000000000, 0x0000000000007fc0, 0x1bf2000000000000, 0x0000000000003f40, 0x02a0000003000000, 0x7ffe000000000000, 0x1ffffffffeffe0df, 0x0000000000000040, 0x66fde00000000000, 0x001e0001c3000000, 0x0000000020002064, 0x1000000000000000, @@ -437,7 +440,7 @@ pub mod derived_property { 0x0e04018700000000, 0x0000000009800000, 0x9ff81fe57f400000, 0x7fff008000000000, 0x17d000000000000f, 0x000ff80000000004, 0x00003b3c00000003, 0x0003a34000000000, 0x00cff00000000000, 0x3f00000000000000, 0x031021fdfff70000, 0xfffff00000000000, - 0x010007ffffffffff, 0xfffffffff8000000, 0xf83fffffffffffff, 0xa000000000000000, + 0x010007ffffffffff, 0xfffffffff8000000, 0xfbffffffffffffff, 0xa000000000000000, 0x6000e000e000e003, 0x00007c900300f800, 0x8002ffdf00000000, 0x000000001fff0000, 0x0001ffffffff0000, 0x3000000000000000, 0x0003800000000000, 0x8000800000000000, 0xffffffff00000000, 0x0000800000000000, 0x083e3c0000000020, 0x000000007e000000, @@ -465,24 +468,24 @@ pub mod derived_property { 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 8, 0, 9, 10, 11, 12, 13, 0, 0, 14, 15, 16, 0, 0, 17, 18, 19, 20, - 0, 0, 21, 22, 23, 24, 25, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 27, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 21, 22, 23, 24, 25, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 28, 29, 0, 0, 0, + 0, 0, 30, 0, 31, 0, 32, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, - 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 35, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 38, 39, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 42, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 35, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 37, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 41, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 44, 45, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 45, - 0, 0, 45, 45, 45, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0 + 50, 51, 0, 0, 51, 51, 51, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 ], r6: &[ 0x0000000000000000, 0x2000000000000000, 0x0000000100000000, 0x07c0000000000000, @@ -491,12 +494,14 @@ pub mod derived_property { 0x0000000000001c00, 0x40d3800000000000, 0x000007f880000000, 0x1000000000000003, 0x001f1fc000000001, 0xff00000000000000, 0x000000000000005c, 0x85f8000000000000, 0x000000000000000d, 0xb03c000000000000, 0x0000000030000001, 0xa7f8000000000000, - 0x0000000000000001, 0x00bf280000000000, 0x00000fbce0000000, 0xbf7f000000000000, - 0x006dfcfffffc0000, 0x001f000000000000, 0x007f000000000000, 0x000000000000000f, - 0x00000000ffff8000, 0x0000000f60000000, 0xfff8038000000000, 0x00003c0000000fe7, - 0x000000000000001c, 0xf87fffffffffffff, 0x00201fffffffffff, 0x0000fffef8000010, - 0x000007dbf9ffff7f, 0x00000000007f0000, 0x00000000000007f0, 0xf800000000000000, - 0xffffffff00000002, 0xffffffffffffffff, 0x0000ffffffffffff + 0x0000000000000001, 0x00bf280000000000, 0x00000fbce0000000, 0x79f800000000067e, + 0x000000000e7e0080, 0x00000000037ffc00, 0xbf7f000000000000, 0x006dfcfffffc0000, + 0xb47e000000000000, 0x00000000000000bf, 0x001f000000000000, 0x007f000000000000, + 0x000000000000000f, 0x00000000ffff8000, 0x0000000300000000, 0x0000000f60000000, + 0xfff8038000000000, 0x00003c0000000fe7, 0x000000000000001c, 0xf87fffffffffffff, + 0x00201fffffffffff, 0x0000fffef8000010, 0x000007dbf9ffff7f, 0x00000000007f0000, + 0x00000000000007f0, 0xf800000000000000, 0xffffffff00000002, 0xffffffffffffffff, + 0x0000ffffffffffff ], }; @@ -851,12 +856,12 @@ pub mod derived_property { 127 ], r3: &[ - 0x00003fffffffffff, 0x000000000fffffff, 0x3fdfffff00000000, 0xfffffffbfff00000, - 0xffffffffffffffff, 0xfffeffcfffffffff, 0xf3c5fdfffff99fef, 0x0003ffcfb080799f, - 0xd36dfdfffff987ee, 0x003fffc05e023987, 0xf3edfdfffffbbfee, 0x0200ffcf00013bbf, + 0x00003fffffffffff, 0x000007ff0fffffff, 0x3fdfffff00000000, 0xfffffffbfff00000, + 0xffffffffffffffff, 0xfffeffcfffffffff, 0xf3c5fdfffff99fef, 0x1003ffcfb080799f, + 0xd36dfdfffff987ee, 0x003fffc05e023987, 0xf3edfdfffffbbfee, 0xfe00ffcf00013bbf, 0xf3edfdfffff99fee, 0x0002ffcfb0c0399f, 0xc3ffc718d63dc7ec, 0x0000ffc000813dc7, 0xe3fffdfffffddfef, 0x0000ffcf07603ddf, 0xf3effdfffffddfef, 0x0006ffcf40603ddf, - 0xe7fffffffffddfee, 0xfc00ffcf80f07ddf, 0x2ffbfffffc7fffec, 0x000cffc0ff5f847f, + 0xfffffffffffddfef, 0xfc00ffcf80f07ddf, 0x2ffbfffffc7fffec, 0x000cffc0ff5f847f, 0x07fffffffffffffe, 0x0000000003ff7fff, 0x3bffecaefef02596, 0x00000000f3ff3f5f, 0xc2a003ff03000001, 0xfffe1ffffffffeff, 0x1ffffffffeffffdf, 0x0000000000000040, 0xffffffffffff03ff, 0xffffffff3fffffff, 0xf7ffffffffff20bf, 0xffffffff3d7f3dff, @@ -867,13 +872,13 @@ pub mod derived_property { 0x003fffffffffffff, 0x0fff0fff7fffffff, 0x001f3fffffffffc0, 0xffff0fffffffffff, 0x0000000007ff03ff, 0xffffffff0fffffff, 0x9fffffff7fffffff, 0x3fff008003ff03ff, 0x0000000000000000, 0x000ff80003ff0fff, 0x000fffffffffffff, 0x3fffffffffffe3ff, - 0x00000000000001ff, 0x037ffffffff70000, 0xf83fffffffffffff, 0xffffffff3f3fffff, + 0x00000000000001ff, 0x03fffffffff70000, 0xfbffffffffffffff, 0xffffffff3f3fffff, 0x3fffffffaaff3f3f, 0x5fdfffffffffffff, 0x1fdc1fff0fcf1fdc, 0x8000000000000000, 0x8002000000100001, 0x000000001fff0000, 0x0001ffe21fff0000, 0xf3fffd503f2ffc84, 0xffffffff000043e0, 0xffff7fffffffffff, 0xffffffff7fffffff, 0x000ff81fffffffff, 0xffff20bfffffffff, 0x800080ffffffffff, 0x7f7f7f7f007fffff, 0xffffffff7f7f7f7f, - 0x1f3efffe000000e0, 0xfffffffee67fffff, 0xf7ffffffffffffff, 0xfffe3fffffffffe0, - 0x07ffffff00007fff, 0xffff000000000000, 0x00000000003fffff, 0x0000000000001fff, + 0x1f3efffe000000e0, 0xfffffffee67fffff, 0xf7ffffffffffffff, 0xfffe7fffffffffe0, + 0x07ffffff00007fff, 0xffff000000000000, 0x000007ffffffffff, 0x0000000000001fff, 0x3fffffffffff0000, 0x00000fffffff1fff, 0xbff0ffffffffffff, 0x0003ffffffffffff, 0xfffffffcff800000, 0x00ff7ffffffff9ff, 0xff80000000000000, 0x000000ffffffffff, 0x28ffffff03ff003f, 0xffff3fffffffffff, 0x1fffffff000fffff, 0x7fffffff03ff8001, @@ -886,60 +891,62 @@ pub mod derived_property { ], r4: [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 5, 5, 9, 5, 10, 11, 5, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 13, - 14, 5, 5, 15, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 14, 7, 15, 16, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 16, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 + 5, 5, 5, 5, 5, 5, 5, 17, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 ], r5: &[ 0, 1, 2, 3, 4, 5, 4, 6, 4, 4, 7, 8, 9, 10, 11, 12, 2, 2, 13, 14, 15, 16, 4, 4, 2, 2, 2, 2, 17, 18, 4, 4, 19, 20, 21, 22, 23, 4, 24, 4, 25, 26, 27, 28, 29, 30, 31, 4, 2, 32, 33, 33, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 34, 3, 35, 36, 37, 2, 38, 39, 4, 40, 41, 42, 43, 4, 4, 2, 44, 2, 45, 4, 4, 46, 47, 2, 48, 49, 50, 51, 4, 4, 4, 4, 4, 52, 53, 4, 4, 4, - 4, 4, 4, 4, 54, 4, 4, 4, 4, 55, 56, 57, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 58, 4, 2, 59, 2, 2, 2, 60, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 54, 55, 56, 57, 4, 4, 4, 4, 58, 59, 60, 4, 61, 62, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 63, 4, 2, 64, 2, 2, 2, 65, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 59, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 64, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 61, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 66, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, - 2, 2, 2, 2, 54, 62, 4, 63, 17, 64, 65, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 66, 67, - 68, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, + 2, 2, 2, 2, 2, 2, 57, 67, 4, 68, 17, 69, 70, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, + 71, 72, 73, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 69, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 33, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 70, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 74, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 33, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 21, 75, 2, 2, 2, 2, 2, 76, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 2, 71, 72, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 73, 74, 4, 4, - 75, 4, 4, 4, 4, 4, 4, 2, 76, 77, 78, 79, 80, 2, 2, 2, 2, 81, 82, 83, 84, 85, 86, 4, 4, - 4, 4, 4, 4, 4, 4, 87, 88, 89, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 90, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 2, 2, 2, 91, 2, 44, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 92, 93, 94, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 95, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 4, 4, 4, 4, 4, 4, 4, 2, 77, 78, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 79, 80, 4, 4, 81, 4, 4, 4, 4, 4, 4, 2, 82, 83, 84, 85, 86, 2, 2, 2, 2, 87, 88, 89, 90, + 91, 92, 4, 4, 4, 4, 4, 4, 4, 4, 93, 94, 95, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 96, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 97, 2, 44, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 98, 99, 100, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 101, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 2, 2, 2, 11, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 2, 2, 2, 11, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 96, 4, 4, 4, 4, 4, 4, 4, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 102, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 103, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 2, 2, 2, 2, 2, 2, 2, 2, 97, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 98, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 104, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 105, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ], r6: &[ 0xb7ffff7fffffefff, 0x000000003fff3fff, 0xffffffffffffffff, 0x07ffffffffffffff, 0x0000000000000000, 0x001fffffffffffff, 0x2000000000000000, 0xffffffff1fffffff, - 0x000000010001ffff, 0xffff0000ffffffff, 0x07ffffffffff07ff, 0xffffffff3fffffff, + 0x000000010001ffff, 0xffffe000ffffffff, 0x07ffffffffff07ff, 0xffffffff3fffffff, 0x00000000003eff0f, 0xffff03ff3fffffff, 0x0fffffffff0fffff, 0xffff00ffffffffff, 0x0000000fffffffff, 0x007fffffffffffff, 0x000000ff003fffff, 0x91bffffffffffd3f, 0x007fffff003fffff, 0x000000007fffffff, 0x0037ffff00000000, 0x03ffffff003fffff, @@ -950,18 +957,20 @@ pub mod derived_property { 0xffff01ffbfffbd7f, 0x03ff07ffffffffff, 0xf3edfdfffff99fef, 0x001f1fcfe081399f, 0x0000000003ff07ff, 0x0000000003ff00bf, 0xff3fffffffffffff, 0x000000003f000001, 0x0000000003ff0011, 0x00ffffffffffffff, 0x00000000000003ff, 0x03ff0fffe3ffffff, - 0xffffffff00000000, 0x800003ffffffffff, 0x01ffffffffffffff, 0xff7ffffffffffdff, - 0xfffc000003ff0001, 0x007ffefffffcffff, 0x0000000003ffffff, 0x00007fffffffffff, - 0x000000000000000f, 0x000000000000007f, 0x000003ff7fffffff, 0x001f3fffffff0000, - 0xe0fffff803ff000f, 0x000000000000ffff, 0x7fffffffffff001f, 0x00000000ffff8000, - 0x0000000100000000, 0x00001fffffffffff, 0x0000000000000003, 0x1fff07ffffffffff, - 0x0000000063ff01ff, 0xf807e3e000000000, 0x00003c0000000fe7, 0x000000000000001c, - 0xffffffffffdfffff, 0xebffde64dfffffff, 0xffffffffffffffef, 0x7bffffffdfdfe7bf, - 0xfffffffffffdfc5f, 0xffffff3fffffffff, 0xf7fffffff7fffffd, 0xffdfffffffdfffff, - 0xffff7fffffff7fff, 0xfffffdfffffffdff, 0xffffffffffffcff7, 0xf87fffffffffffff, - 0x00201fffffffffff, 0x0000fffef8000010, 0x000007dbf9ffff7f, 0x00000000007f001f, - 0x0af7fe96ffffffef, 0x5ef7f796aa96ea84, 0x0ffffbee0ffffbff, 0x00000000007fffff, - 0x00000003ffffffff, 0x000000003fffffff, 0x0000ffffffffffff + 0xffffffff00000000, 0x800003ffffffffff, 0x7fffffffffffffff, 0xffffffffffff0080, + 0x0000000003ffffcf, 0x01ffffffffffffff, 0xff7ffffffffffdff, 0xfffc000003ff0001, + 0x007ffefffffcffff, 0xb47ffffffffffb7f, 0x0000000003ff00ff, 0x0000000003ffffff, + 0x00007fffffffffff, 0x000000000000000f, 0x000000000000007f, 0x000003ff7fffffff, + 0x001f3fffffff0000, 0xe0fffff803ff000f, 0x000000000000ffff, 0x7fffffffffff001f, + 0x00000000ffff8000, 0x0000000300000000, 0x00001fffffffffff, 0xffff000000000000, + 0x0fffffffffffffff, 0x1fff07ffffffffff, 0x0000000063ff01ff, 0xf807e3e000000000, + 0x00003c0000000fe7, 0x000000000000001c, 0xffffffffffdfffff, 0xebffde64dfffffff, + 0xffffffffffffffef, 0x7bffffffdfdfe7bf, 0xfffffffffffdfc5f, 0xffffff3fffffffff, + 0xf7fffffff7fffffd, 0xffdfffffffdfffff, 0xffff7fffffff7fff, 0xfffffdfffffffdff, + 0xffffffffffffcff7, 0xf87fffffffffffff, 0x00201fffffffffff, 0x0000fffef8000010, + 0x000007dbf9ffff7f, 0x00000000007f001f, 0x0af7fe96ffffffef, 0x5ef7f796aa96ea84, + 0x0ffffbee0ffffbff, 0x00000000007fffff, 0xffff0003ffffffff, 0x00000001ffffffff, + 0x000000003fffffff, 0x0000ffffffffffff ], }; @@ -1027,8 +1036,8 @@ pub mod derived_property { 129, 130, 131, 132 ], r3: &[ - 0x00000110043fffff, 0x0000000001ffffff, 0x3fdfffff00000000, 0x0000000000000000, - 0x23fffffffffffff0, 0xfffe0003ff010000, 0x23c5fdfffff99fe1, 0x00030003b0004000, + 0x00000110043fffff, 0x000007ff01ffffff, 0x3fdfffff00000000, 0x0000000000000000, + 0x23fffffffffffff0, 0xfffe0003ff010000, 0x23c5fdfffff99fe1, 0x10030003b0004000, 0x036dfdfffff987e0, 0x001c00005e000000, 0x23edfdfffffbbfe0, 0x0200000300010000, 0x23edfdfffff99fe0, 0x00020003b0000000, 0x03ffc718d63dc7e8, 0x0000000000010000, 0x23fffdfffffddfe0, 0x0000000307000000, 0x23effdfffffddfe1, 0x0006000340000000, @@ -1048,8 +1057,8 @@ pub mod derived_property { 0x1fdc1fff0fcf1fdc, 0x8002000000000000, 0x000000001fff0000, 0xf3fffd503f2ffc84, 0xffffffff000043e0, 0xffff7fffffffffff, 0xffffffff7fffffff, 0x000c781fffffffff, 0xffff20bfffffffff, 0x000080ffffffffff, 0x7f7f7f7f007fffff, 0x000000007f7f7f7f, - 0x1f3e03fe000000e0, 0xfffffffee07fffff, 0xf7ffffffffffffff, 0xfffe3fffffffffe0, - 0x07ffffff00007fff, 0xffff000000000000, 0x00000000003fffff, 0x0000000000001fff, + 0x1f3e03fe000000e0, 0xfffffffee07fffff, 0xf7ffffffffffffff, 0xfffe7fffffffffe0, + 0x07ffffff00007fff, 0xffff000000000000, 0x000007ffffffffff, 0x0000000000001fff, 0x3fffffffffff0000, 0x00000c00ffff1fff, 0x80007fffffffffff, 0xffffffff3fffffff, 0x0000ffffffffffff, 0xfffffffcff800000, 0x00ff7ffffffff9ff, 0xff80000000000000, 0x00000007fffff7bb, 0x000ffffffffffffc, 0x28fc000000000000, 0xffff003ffffffc00, @@ -1064,58 +1073,60 @@ pub mod derived_property { ], r4: [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 5, 5, 9, 5, 10, 11, 5, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 13, - 14, 5, 5, 15, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 14, 7, 15, 16, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 ], r5: &[ 0, 1, 2, 3, 4, 5, 4, 4, 4, 4, 6, 7, 8, 9, 10, 11, 2, 2, 12, 13, 14, 15, 4, 4, 2, 2, 2, 2, 16, 17, 4, 4, 18, 19, 20, 21, 22, 4, 23, 4, 24, 25, 26, 27, 28, 29, 30, 4, 2, 31, 32, 32, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 33, 4, 34, 35, 36, 37, 38, 39, 40, 4, 41, 20, 42, 43, 4, 4, 5, 44, 45, 46, 4, 4, 47, 48, 45, 49, 50, 4, 51, 4, 4, 4, 4, 4, 52, 53, 4, - 4, 4, 4, 4, 4, 4, 54, 4, 4, 4, 4, 55, 56, 57, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 51, 4, 2, 47, 2, 2, 2, 58, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 54, 55, 56, 57, 4, 4, 4, 4, 58, 59, 60, 4, 61, 62, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 51, 4, 2, 47, 2, 2, 2, 63, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 47, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 47, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 59, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 64, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, - 2, 2, 2, 2, 2, 2, 54, 20, 4, 60, 45, 61, 57, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, - 62, 63, 64, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 2, 2, 2, 2, 2, 2, 2, 2, 57, 20, 4, 65, 45, 66, 60, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 2, 67, 68, 69, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 65, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 32, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 66, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 70, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 32, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 20, 71, 2, 2, 2, 2, 2, + 72, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 2, 73, 74, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 75, 76, 77, 78, 79, 2, 2, 2, 2, 80, 81, 82, 83, 84, + 85, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 2, 67, 68, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 69, 70, 71, 72, 73, 2, 2, 2, 2, 74, 75, 76, 77, 78, 79, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 2, 2, 2, 80, 2, 58, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 81, 82, 83, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 84, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 86, 2, 63, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 87, 88, 89, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 90, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 2, 2, 2, 10, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 2, 2, 2, 10, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 85, 4, 4, 4, 4, 4, 4, 4, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 91, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 92, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 2, 2, 2, 2, 2, 2, 2, 2, 86, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4 + 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 93, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ], r6: &[ 0xb7ffff7fffffefff, 0x000000003fff3fff, 0xffffffffffffffff, 0x07ffffffffffffff, 0x0000000000000000, 0x001fffffffffffff, 0xffffffff1fffffff, 0x000000000001ffff, - 0xffff0000ffffffff, 0x003fffffffff07ff, 0xffffffff3fffffff, 0x00000000003eff0f, + 0xffffe000ffffffff, 0x003fffffffff07ff, 0xffffffff3fffffff, 0x00000000003eff0f, 0xffff00003fffffff, 0x0fffffffff0fffff, 0xffff00ffffffffff, 0x0000000fffffffff, 0x007fffffffffffff, 0x000000ff003fffff, 0x91bffffffffffd3f, 0x007fffff003fffff, 0x000000007fffffff, 0x0037ffff00000000, 0x03ffffff003fffff, 0xc0ffffffffffffff, @@ -1126,15 +1137,17 @@ pub mod derived_property { 0x00000ffffffbffff, 0xffff01ffbfffbd7f, 0x23edfdfffff99fe0, 0x00000003e0010000, 0x0000000000000780, 0x0000ffffffffffff, 0x00000000000000b0, 0x00007fffffffffff, 0x000000000f000000, 0x0000000000000010, 0x000007ffffffffff, 0x0000000003ffffff, - 0xffffffff00000000, 0x80000000ffffffff, 0x01ffffffffffffff, 0x00007ffffffffdff, - 0xfffc000000000001, 0x000000000000ffff, 0x000000000000000f, 0x000000000000007f, - 0x00003fffffff0000, 0xe0fffff80000000f, 0x000000000001001f, 0x00000000fff80000, - 0x0000000100000000, 0x00001fffffffffff, 0x0000000000000003, 0x1fff07ffffffffff, - 0x0000000003ff01ff, 0xffffffffffdfffff, 0xebffde64dfffffff, 0xffffffffffffffef, - 0x7bffffffdfdfe7bf, 0xfffffffffffdfc5f, 0xffffff3fffffffff, 0xf7fffffff7fffffd, - 0xffdfffffffdfffff, 0xffff7fffffff7fff, 0xfffffdfffffffdff, 0x0000000000000ff7, - 0x000000000000001f, 0x0af7fe96ffffffef, 0x5ef7f796aa96ea84, 0x0ffffbee0ffffbff, - 0x00000000007fffff, 0x00000003ffffffff, 0x000000003fffffff + 0xffffffff00000000, 0x80000000ffffffff, 0x0407fffffffff801, 0xfffffffff0010000, + 0x00000000000003cf, 0x01ffffffffffffff, 0x00007ffffffffdff, 0xfffc000000000001, + 0x000000000000ffff, 0x0001fffffffffb7f, 0x0000000000000040, 0x000000000000000f, + 0x000000000000007f, 0x00003fffffff0000, 0xe0fffff80000000f, 0x000000000001001f, + 0x00000000fff80000, 0x0000000300000000, 0x00001fffffffffff, 0xffff000000000000, + 0x0fffffffffffffff, 0x1fff07ffffffffff, 0x0000000003ff01ff, 0xffffffffffdfffff, + 0xebffde64dfffffff, 0xffffffffffffffef, 0x7bffffffdfdfe7bf, 0xfffffffffffdfc5f, + 0xffffff3fffffffff, 0xf7fffffff7fffffd, 0xffdfffffffdfffff, 0xffff7fffffff7fff, + 0xfffffdfffffffdff, 0x0000000000000ff7, 0x000000000000001f, 0x0af7fe96ffffffef, + 0x5ef7f796aa96ea84, 0x0ffffbee0ffffbff, 0x00000000007fffff, 0xffff0003ffffffff, + 0x00000001ffffffff, 0x000000003fffffff ], }; From b62bdaafe038b8933fac5df5fa0fa5ddbaf176b7 Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Thu, 29 Jun 2017 17:52:43 +0300 Subject: [PATCH 119/162] When writing LLVM IR output demangled fn name in comments `--emit=llvm-ir` looks like this now: ``` ; as core::ops::index::IndexMut>::index_mut ; Function Attrs: inlinehint uwtable define internal { i8*, i64 } @"_ZN106_$LT$alloc..vec..Vec$LT$T$GT$$u20$as$u20$core..ops..index..IndexMut$LT$core..ops..range..RangeFull$GT$$GT$9index_mut17h7f7b576609f30262E"(%"alloc::vec::Vec"* dereferenceable(24)) unnamed_addr #0 { start: ... ``` cc https://github.com/integer32llc/rust-playground/issues/15 --- src/Cargo.lock | 1 + src/librustc_llvm/ffi.rs | 8 +- src/librustc_trans/Cargo.toml | 1 + src/librustc_trans/back/write.rs | 39 +++++++++- src/librustc_trans/lib.rs | 1 + src/rustllvm/PassWrapper.cpp | 128 ++++++++++++++++++++++++++++++- 6 files changed, 173 insertions(+), 5 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 386450f4a65..50608ca2d04 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -1407,6 +1407,7 @@ dependencies = [ "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", + "rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_back 0.0.0", "rustc_bitflags 0.0.0", "rustc_const_math 0.0.0", diff --git a/src/librustc_llvm/ffi.rs b/src/librustc_llvm/ffi.rs index 312b5a38d6e..770d16e5c02 100644 --- a/src/librustc_llvm/ffi.rs +++ b/src/librustc_llvm/ffi.rs @@ -1597,7 +1597,13 @@ extern "C" { Output: *const c_char, FileType: FileType) -> LLVMRustResult; - pub fn LLVMRustPrintModule(PM: PassManagerRef, M: ModuleRef, Output: *const c_char); + pub fn LLVMRustPrintModule(PM: PassManagerRef, + M: ModuleRef, + Output: *const c_char, + Demangle: extern fn(*const c_char, + size_t, + *mut c_char, + size_t) -> size_t); pub fn LLVMRustSetLLVMOptions(Argc: c_int, Argv: *const *const c_char); pub fn LLVMRustPrintPasses(); pub fn LLVMRustSetNormalizedTarget(M: ModuleRef, triple: *const c_char); diff --git a/src/librustc_trans/Cargo.toml b/src/librustc_trans/Cargo.toml index 86590bff4ff..a512cf2f02a 100644 --- a/src/librustc_trans/Cargo.toml +++ b/src/librustc_trans/Cargo.toml @@ -15,6 +15,7 @@ flate2 = "0.2" jobserver = "0.1.5" log = "0.3" owning_ref = "0.3.3" +rustc-demangle = "0.1.4" rustc = { path = "../librustc" } rustc_back = { path = "../librustc_back" } rustc_bitflags = { path = "../librustc_bitflags" } diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index 7e99ea0ee19..562d7171156 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -29,15 +29,18 @@ use syntax_pos::MultiSpan; use context::{is_pie_binary, get_reloc_model}; use jobserver::{Client, Acquired}; use crossbeam::{scope, Scope}; +use rustc_demangle; use std::cmp; use std::ffi::CString; use std::fs; use std::io; +use std::io::Write; use std::path::{Path, PathBuf}; use std::str; use std::sync::mpsc::{channel, Sender}; -use libc::{c_uint, c_void}; +use std::slice; +use libc::{c_uint, c_void, c_char, size_t}; pub const RELOC_MODEL_ARGS : [(&'static str, llvm::RelocMode); 7] = [ ("pic", llvm::RelocMode::PIC), @@ -510,8 +513,40 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, if config.emit_ir { let out = output_names.temp_path(OutputType::LlvmAssembly, module_name); let out = path2cstr(&out); + + extern "C" fn demangle_callback(input_ptr: *const c_char, + input_len: size_t, + output_ptr: *mut c_char, + output_len: size_t) -> size_t { + let input = unsafe { + slice::from_raw_parts(input_ptr as *const u8, input_len as usize) + }; + + let input = match str::from_utf8(input) { + Ok(s) => s, + Err(_) => return 0, + }; + + let output = unsafe { + slice::from_raw_parts_mut(output_ptr as *mut u8, output_len as usize) + }; + let mut cursor = io::Cursor::new(output); + + let demangled = match rustc_demangle::try_demangle(input) { + Ok(d) => d, + Err(_) => return 0, + }; + + if let Err(_) = write!(cursor, "{:#}", demangled) { + // Possible only if provided buffer is not big enough + return 0; + } + + cursor.position() as size_t + } + with_codegen(tm, llmod, config.no_builtins, |cpm| { - llvm::LLVMRustPrintModule(cpm, llmod, out.as_ptr()); + llvm::LLVMRustPrintModule(cpm, llmod, out.as_ptr(), demangle_callback); llvm::LLVMDisposePassManager(cpm); }) } diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index d480f249b44..6acd10cb887 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -52,6 +52,7 @@ extern crate rustc_const_math; #[macro_use] #[no_link] extern crate rustc_bitflags; +extern crate rustc_demangle; extern crate jobserver; #[macro_use] extern crate log; diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index fdbe4e5f7ad..7fb1eafb30d 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -10,11 +10,14 @@ #include +#include + #include "rustllvm.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/IR/AutoUpgrade.h" +#include "llvm/IR/AssemblyAnnotationWriter.h" #include "llvm/Support/CBindingWrapping.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Host.h" @@ -503,8 +506,129 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR, return LLVMRustResult::Success; } + +// Callback to demangle function name +// Parameters: +// * name to be demangled +// * name len +// * output buffer +// * output buffer len +// Returns len of demangled string, or 0 if demangle failed. +typedef size_t (*DemangleFn)(const char*, size_t, char*, size_t); + + +namespace { + +class RustAssemblyAnnotationWriter : public AssemblyAnnotationWriter { + DemangleFn Demangle; + std::vector Buf; + +public: + RustAssemblyAnnotationWriter(DemangleFn Demangle) : Demangle(Demangle) {} + + // Return empty string if demangle failed + // or if name does not need to be demangled + StringRef CallDemangle(StringRef name) { + if (!Demangle) { + return StringRef(); + } + + if (Buf.size() < name.size() * 2) { + // Semangled name usually shorter than mangled, + // but allocate twice as much memory just in case + Buf.resize(name.size() * 2); + } + + auto R = Demangle(name.data(), name.size(), Buf.data(), Buf.size()); + if (!R) { + // Demangle failed. + return StringRef(); + } + + auto Demangled = StringRef(Buf.data(), R); + if (Demangled == name) { + // Do not print anything if demangled name is equal to mangled. + return StringRef(); + } + + return Demangled; + } + + void emitFunctionAnnot(const Function *F, + formatted_raw_ostream &OS) override { + StringRef Demangled = CallDemangle(F->getName()); + if (Demangled.empty()) { + return; + } + + OS << "; " << Demangled << "\n"; + } + + void emitInstructionAnnot(const Instruction *I, + formatted_raw_ostream &OS) override { + const char *Name; + const Value *Value; + if (const CallInst *CI = dyn_cast(I)) { + Name = "call"; + Value = CI->getCalledValue(); + } else if (const InvokeInst* II = dyn_cast(I)) { + Name = "invoke"; + Value = II->getCalledValue(); + } else { + // Could demangle more operations, e. g. + // `store %place, @function`. + return; + } + + if (!Value->hasName()) { + return; + } + + StringRef Demangled = CallDemangle(Value->getName()); + if (Demangled.empty()) { + return; + } + + OS << "; " << Name << " " << Demangled << "\n"; + } +}; + +class RustPrintModulePass : public ModulePass { + raw_ostream* OS; + DemangleFn Demangle; +public: + static char ID; + RustPrintModulePass() : ModulePass(ID), OS(nullptr), Demangle(nullptr) {} + RustPrintModulePass(raw_ostream &OS, DemangleFn Demangle) + : ModulePass(ID), OS(&OS), Demangle(Demangle) {} + + bool runOnModule(Module &M) override { + RustAssemblyAnnotationWriter AW(Demangle); + + M.print(*OS, &AW, false); + + return false; + } + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesAll(); + } + + static StringRef name() { return "RustPrintModulePass"; } +}; + +} // namespace + +namespace llvm { + void initializeRustPrintModulePassPass(PassRegistry&); +} + +char RustPrintModulePass::ID = 0; +INITIALIZE_PASS(RustPrintModulePass, "print-rust-module", + "Print rust module to stderr", false, false) + extern "C" void LLVMRustPrintModule(LLVMPassManagerRef PMR, LLVMModuleRef M, - const char *Path) { + const char *Path, DemangleFn Demangle) { llvm::legacy::PassManager *PM = unwrap(PMR); std::string ErrorInfo; @@ -515,7 +639,7 @@ extern "C" void LLVMRustPrintModule(LLVMPassManagerRef PMR, LLVMModuleRef M, formatted_raw_ostream FOS(OS); - PM->add(createPrintModulePass(FOS)); + PM->add(new RustPrintModulePass(FOS, Demangle)); PM->run(*unwrap(M)); } From d280b40b18532dfeb80b1a98109fa6218630b939 Mon Sep 17 00:00:00 2001 From: Sergio Benitez Date: Fri, 30 Jun 2017 18:05:04 -0700 Subject: [PATCH 120/162] Stabilize 'more_io_inner_methods' feature. --- .../library-features/more-io-inner-methods.md | 11 ---------- src/libstd/io/mod.rs | 20 +++++-------------- 2 files changed, 5 insertions(+), 26 deletions(-) delete mode 100644 src/doc/unstable-book/src/library-features/more-io-inner-methods.md diff --git a/src/doc/unstable-book/src/library-features/more-io-inner-methods.md b/src/doc/unstable-book/src/library-features/more-io-inner-methods.md deleted file mode 100644 index c84f40e7ee5..00000000000 --- a/src/doc/unstable-book/src/library-features/more-io-inner-methods.md +++ /dev/null @@ -1,11 +0,0 @@ -# `more_io_inner_methods` - -The tracking issue for this feature is: [#41519] - -[#41519]: https://github.com/rust-lang/rust/issues/41519 - ------------------------- - -This feature enables several internal accessor methods on structures in -`std::io` including `Take::{get_ref, get_mut}` and `Chain::{into_inner, get_ref, -get_mut}`. diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 680a5f32ae2..71c76008244 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -1589,8 +1589,6 @@ impl Chain { /// # Examples /// /// ``` - /// #![feature(more_io_inner_methods)] - /// /// # use std::io; /// use std::io::prelude::*; /// use std::fs::File; @@ -1604,7 +1602,7 @@ impl Chain { /// # Ok(()) /// # } /// ``` - #[unstable(feature = "more_io_inner_methods", issue="41519")] + #[stable(feature = "more_io_inner_methods", since = "1.20.0")] pub fn into_inner(self) -> (T, U) { (self.first, self.second) } @@ -1614,8 +1612,6 @@ impl Chain { /// # Examples /// /// ``` - /// #![feature(more_io_inner_methods)] - /// /// # use std::io; /// use std::io::prelude::*; /// use std::fs::File; @@ -1629,7 +1625,7 @@ impl Chain { /// # Ok(()) /// # } /// ``` - #[unstable(feature = "more_io_inner_methods", issue="41519")] + #[stable(feature = "more_io_inner_methods", since = "1.20.0")] pub fn get_ref(&self) -> (&T, &U) { (&self.first, &self.second) } @@ -1643,8 +1639,6 @@ impl Chain { /// # Examples /// /// ``` - /// #![feature(more_io_inner_methods)] - /// /// # use std::io; /// use std::io::prelude::*; /// use std::fs::File; @@ -1658,7 +1652,7 @@ impl Chain { /// # Ok(()) /// # } /// ``` - #[unstable(feature = "more_io_inner_methods", issue="41519")] + #[stable(feature = "more_io_inner_methods", since = "1.20.0")] pub fn get_mut(&mut self) -> (&mut T, &mut U) { (&mut self.first, &mut self.second) } @@ -1791,8 +1785,6 @@ impl Take { /// # Examples /// /// ``` - /// #![feature(more_io_inner_methods)] - /// /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; @@ -1808,7 +1800,7 @@ impl Take { /// # Ok(()) /// # } /// ``` - #[unstable(feature = "more_io_inner_methods", issue="41519")] + #[stable(feature = "more_io_inner_methods", since = "1.20.0")] pub fn get_ref(&self) -> &T { &self.inner } @@ -1822,8 +1814,6 @@ impl Take { /// # Examples /// /// ``` - /// #![feature(more_io_inner_methods)] - /// /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; @@ -1839,7 +1829,7 @@ impl Take { /// # Ok(()) /// # } /// ``` - #[unstable(feature = "more_io_inner_methods", issue="41519")] + #[stable(feature = "more_io_inner_methods", since = "1.20.0")] pub fn get_mut(&mut self) -> &mut T { &mut self.inner } From ebf24ad3e9e21ddf5b8b532f414026e6d511626c Mon Sep 17 00:00:00 2001 From: Milton Mazzarri Date: Fri, 30 Jun 2017 23:24:35 -0500 Subject: [PATCH 121/162] bootstrap: Fix some PEP8 issues This commit also adds a few missing docstrings --- src/bootstrap/bootstrap.py | 53 ++++++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 19 deletions(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 8dc2875ec42..49e073dcc13 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -25,10 +25,11 @@ from time import time def get(url, path, verbose=False): - sha_url = url + ".sha256" + suffix = '.sha256' + sha_url = url + suffix with tempfile.NamedTemporaryFile(delete=False) as temp_file: temp_path = temp_file.name - with tempfile.NamedTemporaryFile(suffix=".sha256", delete=False) as sha_file: + with tempfile.NamedTemporaryFile(suffix=suffix, delete=False) as sha_file: sha_path = sha_file.name try: @@ -55,6 +56,7 @@ def get(url, path, verbose=False): def delete_if_present(path, verbose): + """Remove the given file if present""" if os.path.isfile(path): if verbose: print("removing " + path) @@ -92,12 +94,13 @@ def _download(path, url, probably_big, verbose, exception): def verify(path, sha_path, verbose): + """Check if the sha256 sum of the given path is valid""" if verbose: print("verifying " + path) - with open(path, "rb") as f: - found = hashlib.sha256(f.read()).hexdigest() - with open(sha_path, "r") as f: - expected = f.readline().split()[0] + with open(path, "rb") as source: + found = hashlib.sha256(source.read()).hexdigest() + with open(sha_path, "r") as sha256sum: + expected = sha256sum.readline().split()[0] verified = found == expected if not verified: print("invalid checksum:\n" @@ -107,6 +110,7 @@ def verify(path, sha_path, verbose): def unpack(tarball, dst, verbose=False, match=None): + """Unpack the given tarball file""" print("extracting " + tarball) fname = os.path.basename(tarball).replace(".tar.gz", "") with contextlib.closing(tarfile.open(tarball)) as tar: @@ -128,6 +132,7 @@ def unpack(tarball, dst, verbose=False, match=None): shutil.move(tp, fp) shutil.rmtree(os.path.join(dst, fname)) + def run(args, verbose=False, exception=False, **kwargs): if verbose: print("running: " + ' '.join(args)) @@ -245,7 +250,8 @@ class RustBuild(object): return # At this point we're pretty sure the user is running NixOS - print("info: you seem to be running NixOS. Attempting to patch " + fname) + nix_os_msg = "info: you seem to be running NixOS. Attempting to patch" + print(" ".join([nix_os_msg, fname])) try: interpreter = subprocess.check_output( @@ -293,18 +299,22 @@ class RustBuild(object): return self._cargo_channel def rustc_stamp(self): + """Return the path for .rustc-stamp""" return os.path.join(self.bin_root(), '.rustc-stamp') def cargo_stamp(self): + """Return the path for .cargo-stamp""" return os.path.join(self.bin_root(), '.cargo-stamp') def rustc_out_of_date(self): + """Check if rustc is out of date""" if not os.path.exists(self.rustc_stamp()) or self.clean: return True with open(self.rustc_stamp(), 'r') as f: return self.stage0_date() != f.read() def cargo_out_of_date(self): + """Check if cargo is out of date""" if not os.path.exists(self.cargo_stamp()) or self.clean: return True with open(self.cargo_stamp(), 'r') as f: @@ -357,8 +367,7 @@ class RustBuild(object): def exe_suffix(self): if sys.platform == 'win32': return '.exe' - else: - return '' + return '' def print_what_it_means_to_bootstrap(self): if hasattr(self, 'printed'): @@ -366,7 +375,7 @@ class RustBuild(object): self.printed = True if os.path.exists(self.bootstrap_binary()): return - if not '--help' in sys.argv or len(sys.argv) == 1: + if '--help' not in sys.argv or len(sys.argv) == 1: return print('info: the build system for Rust is written in Rust, so this') @@ -461,8 +470,8 @@ class RustBuild(object): # always emit 'i386' on x86/amd64 systems). As such, isainfo -k # must be used instead. try: - cputype = subprocess.check_output(['isainfo', - '-k']).strip().decode(default_encoding) + cputype = subprocess.check_output( + ['isainfo', '-k']).strip().decode(default_encoding) except (subprocess.CalledProcessError, OSError): err = "isainfo not found" if self.verbose: @@ -562,21 +571,26 @@ class RustBuild(object): default_encoding = sys.getdefaultencoding() run(["git", "submodule", "-q", "sync"], cwd=self.rust_root) submodules = [s.split(' ', 1)[1] for s in subprocess.check_output( - ["git", "config", "--file", os.path.join(self.rust_root, ".gitmodules"), + ["git", "config", "--file", + os.path.join(self.rust_root, ".gitmodules"), "--get-regexp", "path"] ).decode(default_encoding).splitlines()] submodules = [module for module in submodules if not ((module.endswith("llvm") and - (self.get_toml('llvm-config') or self.get_mk('CFG_LLVM_ROOT'))) or + (self.get_toml('llvm-config') or + self.get_mk('CFG_LLVM_ROOT'))) or (module.endswith("jemalloc") and - (self.get_toml('jemalloc') or self.get_mk('CFG_JEMALLOC_ROOT')))) - ] + (self.get_toml('jemalloc') or + self.get_mk('CFG_JEMALLOC_ROOT'))))] run(["git", "submodule", "update", - "--init"] + submodules, cwd=self.rust_root, verbose=self.verbose) + "--init"] + submodules, + cwd=self.rust_root, verbose=self.verbose) run(["git", "submodule", "-q", "foreach", "git", - "reset", "-q", "--hard"], cwd=self.rust_root, verbose=self.verbose) + "reset", "-q", "--hard"], + cwd=self.rust_root, verbose=self.verbose) run(["git", "submodule", "-q", "foreach", "git", - "clean", "-qdfx"], cwd=self.rust_root, verbose=self.verbose) + "clean", "-qdfx"], + cwd=self.rust_root, verbose=self.verbose) def bootstrap(): @@ -692,5 +706,6 @@ def main(): format_build_time(time() - start_time)) sys.exit(exit_code) + if __name__ == '__main__': main() From 44c6781cefa71e06fbbedce782496426782246fc Mon Sep 17 00:00:00 2001 From: Milton Mazzarri Date: Sat, 1 Jul 2017 07:16:57 -0500 Subject: [PATCH 122/162] Simplify print arguments --- src/bootstrap/bootstrap.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 49e073dcc13..eaf2a40f2fa 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -251,7 +251,7 @@ class RustBuild(object): # At this point we're pretty sure the user is running NixOS nix_os_msg = "info: you seem to be running NixOS. Attempting to patch" - print(" ".join([nix_os_msg, fname])) + print(nix_os_msg, fname) try: interpreter = subprocess.check_output( From 5350e22366e059f2099af91d23350be1073ee165 Mon Sep 17 00:00:00 2001 From: Stjepan Glavina Date: Sun, 2 Jul 2017 02:09:21 +0200 Subject: [PATCH 123/162] Stabilize feature sort_unstable --- .../src/library-features/sort-unstable.md | 40 ------------------- src/liballoc/slice.rs | 27 +++++++------ src/libcore/slice/sort.rs | 4 +- 3 files changed, 17 insertions(+), 54 deletions(-) delete mode 100644 src/doc/unstable-book/src/library-features/sort-unstable.md diff --git a/src/doc/unstable-book/src/library-features/sort-unstable.md b/src/doc/unstable-book/src/library-features/sort-unstable.md deleted file mode 100644 index 9effcfc774c..00000000000 --- a/src/doc/unstable-book/src/library-features/sort-unstable.md +++ /dev/null @@ -1,40 +0,0 @@ -# `sort_unstable` - -The tracking issue for this feature is: [#40585] - -[#40585]: https://github.com/rust-lang/rust/issues/40585 - ------------------------- - -The default `sort` method on slices is stable. In other words, it guarantees -that the original order of equal elements is preserved after sorting. The -method has several undesirable characteristics: - -1. It allocates a sizable chunk of memory. -2. If you don't need stability, it is not as performant as it could be. - -An alternative is the new `sort_unstable` feature, which includes these -methods for sorting slices: - -1. `sort_unstable` -2. `sort_unstable_by` -3. `sort_unstable_by_key` - -Unstable sorting is generally faster and makes no allocations. The majority -of real-world sorting needs doesn't require stability, so these methods can -very often come in handy. - -Another important difference is that `sort` lives in `libstd` and -`sort_unstable` lives in `libcore`. The reason is that the former makes -allocations and the latter doesn't. - -A simple example: - -```rust -#![feature(sort_unstable)] - -let mut v = [-5, 4, 1, -3, 2]; - -v.sort_unstable(); -assert!(v == [-5, -3, 1, 2, 4]); -``` diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index 88876999d76..b0e872aeb69 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -1144,6 +1144,10 @@ impl [T] { /// /// This sort is stable (i.e. does not reorder equal elements) and `O(n log n)` worst-case. /// + /// When applicable, unstable sorting is preferred because it is generally faster than stable + /// sorting and it doesn't allocate auxiliary memory. + /// See [`sort_unstable`](#method.sort_unstable). + /// /// # Current implementation /// /// The current algorithm is an adaptive, iterative merge sort inspired by @@ -1174,6 +1178,10 @@ impl [T] { /// /// This sort is stable (i.e. does not reorder equal elements) and `O(n log n)` worst-case. /// + /// When applicable, unstable sorting is preferred because it is generally faster than stable + /// sorting and it doesn't allocate auxiliary memory. + /// See [`sort_unstable_by`](#method.sort_unstable_by). + /// /// # Current implementation /// /// The current algorithm is an adaptive, iterative merge sort inspired by @@ -1207,6 +1215,10 @@ impl [T] { /// /// This sort is stable (i.e. does not reorder equal elements) and `O(n log n)` worst-case. /// + /// When applicable, unstable sorting is preferred because it is generally faster than stable + /// sorting and it doesn't allocate auxiliary memory. + /// See [`sort_unstable_by_key`](#method.sort_unstable_by_key). + /// /// # Current implementation /// /// The current algorithm is an adaptive, iterative merge sort inspired by @@ -1251,8 +1263,6 @@ impl [T] { /// # Examples /// /// ``` - /// #![feature(sort_unstable)] - /// /// let mut v = [-5, 4, 1, -3, 2]; /// /// v.sort_unstable(); @@ -1260,8 +1270,7 @@ impl [T] { /// ``` /// /// [pdqsort]: https://github.com/orlp/pdqsort - // FIXME #40585: Mention `sort_unstable` in the documentation for `sort`. - #[unstable(feature = "sort_unstable", issue = "40585")] + #[stable(feature = "sort_unstable", since = "1.20.0")] #[inline] pub fn sort_unstable(&mut self) where T: Ord @@ -1288,8 +1297,6 @@ impl [T] { /// # Examples /// /// ``` - /// #![feature(sort_unstable)] - /// /// let mut v = [5, 4, 1, 3, 2]; /// v.sort_unstable_by(|a, b| a.cmp(b)); /// assert!(v == [1, 2, 3, 4, 5]); @@ -1300,8 +1307,7 @@ impl [T] { /// ``` /// /// [pdqsort]: https://github.com/orlp/pdqsort - // FIXME #40585: Mention `sort_unstable_by` in the documentation for `sort_by`. - #[unstable(feature = "sort_unstable", issue = "40585")] + #[stable(feature = "sort_unstable", since = "1.20.0")] #[inline] pub fn sort_unstable_by(&mut self, compare: F) where F: FnMut(&T, &T) -> Ordering @@ -1328,8 +1334,6 @@ impl [T] { /// # Examples /// /// ``` - /// #![feature(sort_unstable)] - /// /// let mut v = [-5i32, 4, 1, -3, 2]; /// /// v.sort_unstable_by_key(|k| k.abs()); @@ -1337,8 +1341,7 @@ impl [T] { /// ``` /// /// [pdqsort]: https://github.com/orlp/pdqsort - // FIXME #40585: Mention `sort_unstable_by_key` in the documentation for `sort_by_key`. - #[unstable(feature = "sort_unstable", issue = "40585")] + #[stable(feature = "sort_unstable", since = "1.20.0")] #[inline] pub fn sort_unstable_by_key(&mut self, f: F) where F: FnMut(&T) -> B, diff --git a/src/libcore/slice/sort.rs b/src/libcore/slice/sort.rs index 6f9f2915dfe..518d56095d6 100644 --- a/src/libcore/slice/sort.rs +++ b/src/libcore/slice/sort.rs @@ -351,7 +351,7 @@ fn partition_in_blocks(v: &mut [T], pivot: &T, is_less: &mut F) -> usize if start_l < end_l { // The left block remains. - // Move it's remaining out-of-order elements to the far right. + // Move its remaining out-of-order elements to the far right. debug_assert_eq!(width(l, r), block_l); while start_l < end_l { unsafe { @@ -363,7 +363,7 @@ fn partition_in_blocks(v: &mut [T], pivot: &T, is_less: &mut F) -> usize width(v.as_mut_ptr(), r) } else if start_r < end_r { // The right block remains. - // Move it's remaining out-of-order elements to the far left. + // Move its remaining out-of-order elements to the far left. debug_assert_eq!(width(l, r), block_r); while start_r < end_r { unsafe { From dcd332ed94fb3dd6bf2f5789c8dd42f509337992 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 1 Jul 2017 19:18:02 -0700 Subject: [PATCH 124/162] Delete deprecated & unstable range-specific `step_by` Replacement: 41439 Deprecation: 42310 for 1.19 Fixes 41477 --- src/liballoc/tests/vec_deque.rs | 3 +- src/libcore/iter/mod.rs | 6 - src/libcore/iter/range.rs | 213 ------------------ src/libcore/tests/iter.rs | 42 ++-- src/libcore/tests/lib.rs | 1 - src/librand/lib.rs | 2 +- src/test/run-pass/range_inclusive.rs | 2 +- .../sync-send-iterators-in-libcore.rs | 2 +- 8 files changed, 20 insertions(+), 251 deletions(-) diff --git a/src/liballoc/tests/vec_deque.rs b/src/liballoc/tests/vec_deque.rs index a992351653d..f2935c05d4f 100644 --- a/src/liballoc/tests/vec_deque.rs +++ b/src/liballoc/tests/vec_deque.rs @@ -510,8 +510,7 @@ fn test_from_iter() { let u: Vec<_> = deq.iter().cloned().collect(); assert_eq!(u, v); - // FIXME #27741: Remove `.skip(0)` when Range::step_by is fully removed - let seq = (0..).skip(0).step_by(2).take(256); + let seq = (0..).step_by(2).take(256); let deq: VecDeque<_> = seq.collect(); for (i, &x) in deq.iter().enumerate() { assert_eq!(2 * i, x); diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index d6a9be4437d..decd718d65e 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -314,12 +314,6 @@ pub use self::iterator::Iterator; reason = "likely to be replaced by finer-grained traits", issue = "42168")] pub use self::range::Step; -#[unstable(feature = "step_by", reason = "recent addition", - issue = "27741")] -#[rustc_deprecated(since = "1.19.0", - reason = "replaced by `iter::StepBy`")] -#[allow(deprecated)] -pub use self::range::StepBy as DeprecatedStepBy; #[stable(feature = "rust1", since = "1.0.0")] pub use self::sources::{Repeat, repeat}; diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index 9aea4477fb7..1dad8157948 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -244,219 +244,6 @@ step_impl_signed!(i64); step_impl_no_between!(u64 i64); step_impl_no_between!(u128 i128); -/// An adapter for stepping range iterators by a custom amount. -/// -/// The resulting iterator handles overflow by stopping. The `A` -/// parameter is the type being iterated over, while `R` is the range -/// type (usually one of `std::ops::{Range, RangeFrom, RangeInclusive}`. -#[derive(Clone, Debug)] -#[unstable(feature = "step_by", reason = "recent addition", - issue = "27741")] -#[rustc_deprecated(since = "1.19.0", - reason = "replaced by `iter::StepBy`")] -#[allow(deprecated)] -pub struct StepBy { - step_by: A, - range: R, -} - -impl ops::RangeFrom { - /// Creates an iterator starting at the same point, but stepping by - /// the given amount at each iteration. - /// - /// # Examples - /// - /// ``` - /// #![feature(step_by)] - /// fn main() { - /// let result: Vec<_> = (0..).step_by(2).take(5).collect(); - /// assert_eq!(result, vec![0, 2, 4, 6, 8]); - /// } - /// ``` - #[unstable(feature = "step_by", reason = "recent addition", - issue = "27741")] - #[rustc_deprecated(since = "1.19.0", - reason = "replaced by `Iterator::step_by`")] - #[allow(deprecated)] - pub fn step_by(self, by: A) -> StepBy { - StepBy { - step_by: by, - range: self - } - } -} - -impl ops::Range { - /// Creates an iterator with the same range, but stepping by the - /// given amount at each iteration. - /// - /// The resulting iterator handles overflow by stopping. - /// - /// # Examples - /// - /// ``` - /// #![feature(step_by)] - /// fn main() { - /// let result: Vec<_> = (0..10).step_by(2).collect(); - /// assert_eq!(result, vec![0, 2, 4, 6, 8]); - /// } - /// ``` - #[unstable(feature = "step_by", reason = "recent addition", - issue = "27741")] - #[rustc_deprecated(since = "1.19.0", - reason = "replaced by `Iterator::step_by`")] - #[allow(deprecated)] - pub fn step_by(self, by: A) -> StepBy { - StepBy { - step_by: by, - range: self - } - } -} - -impl ops::RangeInclusive { - /// Creates an iterator with the same range, but stepping by the - /// given amount at each iteration. - /// - /// The resulting iterator handles overflow by stopping. - /// - /// # Examples - /// - /// ``` - /// #![feature(step_by, inclusive_range_syntax)] - /// - /// let result: Vec<_> = (0...10).step_by(2).collect(); - /// assert_eq!(result, vec![0, 2, 4, 6, 8, 10]); - /// ``` - #[unstable(feature = "step_by", reason = "recent addition", - issue = "27741")] - #[rustc_deprecated(since = "1.19.0", - reason = "replaced by `Iterator::step_by`")] - #[allow(deprecated)] - pub fn step_by(self, by: A) -> StepBy { - StepBy { - step_by: by, - range: self - } - } -} - -#[unstable(feature = "step_by", reason = "recent addition", - issue = "27741")] -#[allow(deprecated)] -impl Iterator for StepBy> where - A: Clone, - for<'a> &'a A: Add<&'a A, Output = A> -{ - type Item = A; - - #[inline] - fn next(&mut self) -> Option { - let mut n = &self.range.start + &self.step_by; - mem::swap(&mut n, &mut self.range.start); - Some(n) - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - (usize::MAX, None) // Too bad we can't specify an infinite lower bound - } -} - -#[unstable(feature = "fused", issue = "35602")] -#[allow(deprecated)] -impl FusedIterator for StepBy> - where A: Clone, for<'a> &'a A: Add<&'a A, Output = A> {} - -#[unstable(feature = "step_by", reason = "recent addition", - issue = "27741")] -#[allow(deprecated)] -impl Iterator for StepBy> { - type Item = A; - - #[inline] - fn next(&mut self) -> Option { - let rev = self.step_by.is_negative(); - if (rev && self.range.start > self.range.end) || - (!rev && self.range.start < self.range.end) - { - match self.range.start.step(&self.step_by) { - Some(mut n) => { - mem::swap(&mut self.range.start, &mut n); - Some(n) - }, - None => { - let mut n = self.range.end.clone(); - mem::swap(&mut self.range.start, &mut n); - Some(n) - } - } - } else { - None - } - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - match Step::steps_between(&self.range.start, - &self.range.end, - &self.step_by) { - Some(hint) => (hint, Some(hint)), - None => (0, None) - } - } -} - -#[unstable(feature = "fused", issue = "35602")] -#[allow(deprecated)] -impl FusedIterator for StepBy> {} - -#[unstable(feature = "inclusive_range", - reason = "recently added, follows RFC", - issue = "28237")] -#[allow(deprecated)] -impl Iterator for StepBy> { - type Item = A; - - #[inline] - fn next(&mut self) -> Option { - let rev = self.step_by.is_negative(); - - if (rev && self.range.start >= self.range.end) || - (!rev && self.range.start <= self.range.end) - { - match self.range.start.step(&self.step_by) { - Some(n) => { - Some(mem::replace(&mut self.range.start, n)) - }, - None => { - let last = self.range.start.replace_one(); - self.range.end.replace_zero(); - self.step_by.replace_one(); - Some(last) - }, - } - } - else { - None - } - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - match Step::steps_between(&self.range.start, - &self.range.end, - &self.step_by) { - Some(hint) => (hint.saturating_add(1), hint.checked_add(1)), - None => (0, None) - } - } -} - -#[unstable(feature = "fused", issue = "35602")] -#[allow(deprecated)] -impl FusedIterator for StepBy> {} - macro_rules! range_exact_iter_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index 4f9951cd153..14f0260f571 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -12,15 +12,6 @@ use core::iter::*; use core::{i8, i16, isize}; use core::usize; -// FIXME #27741: This is here to simplify calling Iterator::step_by. Remove -// once Range::step_by is completely gone (not just deprecated). -trait IterEx: Sized { - fn iter_step_by(self, n: usize) -> StepBy; -} -impl IterEx for I { - fn iter_step_by(self, n: usize) -> StepBy { self.step_by(n) } -} - #[test] fn test_lt() { let empty: [isize; 0] = []; @@ -76,7 +67,7 @@ fn test_multi_iter() { #[test] fn test_counter_from_iter() { - let it = (0..).iter_step_by(5).take(10); + let it = (0..).step_by(5).take(10); let xs: Vec = FromIterator::from_iter(it); assert_eq!(xs, [0, 5, 10, 15, 20, 25, 30, 35, 40, 45]); } @@ -94,7 +85,7 @@ fn test_iterator_chain() { } assert_eq!(i, expected.len()); - let ys = (30..).iter_step_by(10).take(4); + let ys = (30..).step_by(10).take(4); let it = xs.iter().cloned().chain(ys); let mut i = 0; for x in it { @@ -156,13 +147,13 @@ fn test_iterator_chain_find() { #[test] fn test_iterator_step_by() { // Identity - let mut it = (0..).iter_step_by(1).take(3); + let mut it = (0..).step_by(1).take(3); assert_eq!(it.next(), Some(0)); assert_eq!(it.next(), Some(1)); assert_eq!(it.next(), Some(2)); assert_eq!(it.next(), None); - let mut it = (0..).iter_step_by(3).take(4); + let mut it = (0..).step_by(3).take(4); assert_eq!(it.next(), Some(0)); assert_eq!(it.next(), Some(3)); assert_eq!(it.next(), Some(6)); @@ -173,7 +164,7 @@ fn test_iterator_step_by() { #[test] #[should_panic] fn test_iterator_step_by_zero() { - let mut it = (0..).iter_step_by(0); + let mut it = (0..).step_by(0); it.next(); } @@ -252,7 +243,7 @@ fn test_iterator_step_by_size_hint() { #[test] fn test_filter_map() { - let it = (0..).iter_step_by(1).take(10) + let it = (0..).step_by(1).take(10) .filter_map(|x| if x % 2 == 0 { Some(x*x) } else { None }); assert_eq!(it.collect::>(), [0*0, 2*2, 4*4, 6*6, 8*8]); } @@ -654,7 +645,7 @@ fn test_iterator_scan() { fn test_iterator_flat_map() { let xs = [0, 3, 6]; let ys = [0, 1, 2, 3, 4, 5, 6, 7, 8]; - let it = xs.iter().flat_map(|&x| (x..).iter_step_by(1).take(3)); + let it = xs.iter().flat_map(|&x| (x..).step_by(1).take(3)); let mut i = 0; for x in it { assert_eq!(x, ys[i]); @@ -680,13 +671,13 @@ fn test_inspect() { #[test] fn test_cycle() { let cycle_len = 3; - let it = (0..).iter_step_by(1).take(cycle_len).cycle(); + let it = (0..).step_by(1).take(cycle_len).cycle(); assert_eq!(it.size_hint(), (usize::MAX, None)); for (i, x) in it.take(100).enumerate() { assert_eq!(i % cycle_len, x); } - let mut it = (0..).iter_step_by(1).take(0).cycle(); + let mut it = (0..).step_by(1).take(0).cycle(); assert_eq!(it.size_hint(), (0, Some(0))); assert_eq!(it.next(), None); } @@ -765,7 +756,7 @@ fn test_iterator_min() { #[test] fn test_iterator_size_hint() { - let c = (0..).iter_step_by(1); + let c = (0..).step_by(1); let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; let v2 = &[10, 11, 12]; let vi = v.iter(); @@ -1090,8 +1081,8 @@ fn test_range_step() { #![allow(deprecated)] assert_eq!((0..20).step_by(5).collect::>(), [0, 5, 10, 15]); - assert_eq!((20..0).step_by(-5).collect::>(), [20, 15, 10, 5]); - assert_eq!((20..0).step_by(-6).collect::>(), [20, 14, 8, 2]); + assert_eq!((1..21).rev().step_by(5).collect::>(), [20, 15, 10, 5]); + assert_eq!((1..21).rev().step_by(6).collect::>(), [20, 14, 8, 2]); assert_eq!((200..255).step_by(50).collect::>(), [200, 250]); assert_eq!((200..-5).step_by(1).collect::>(), []); assert_eq!((200..200).step_by(1).collect::>(), []); @@ -1099,13 +1090,12 @@ fn test_range_step() { assert_eq!((0..20).step_by(1).size_hint(), (20, Some(20))); assert_eq!((0..20).step_by(21).size_hint(), (1, Some(1))); assert_eq!((0..20).step_by(5).size_hint(), (4, Some(4))); - assert_eq!((20..0).step_by(-5).size_hint(), (4, Some(4))); - assert_eq!((20..0).step_by(-6).size_hint(), (4, Some(4))); + assert_eq!((1..21).rev().step_by(5).size_hint(), (4, Some(4))); + assert_eq!((1..21).rev().step_by(6).size_hint(), (4, Some(4))); assert_eq!((20..-5).step_by(1).size_hint(), (0, Some(0))); assert_eq!((20..20).step_by(1).size_hint(), (0, Some(0))); - assert_eq!((0..1).step_by(0).size_hint(), (0, None)); - assert_eq!((i8::MAX..i8::MIN).step_by(i8::MIN).size_hint(), (2, Some(2))); - assert_eq!((i16::MIN..i16::MAX).step_by(i16::MAX).size_hint(), (3, Some(3))); + assert_eq!((i8::MIN..i8::MAX).step_by(-(i8::MIN as i32) as usize).size_hint(), (2, Some(2))); + assert_eq!((i16::MIN..i16::MAX).step_by(i16::MAX as usize).size_hint(), (3, Some(3))); assert_eq!((isize::MIN..isize::MAX).step_by(1).size_hint(), (usize::MAX, Some(usize::MAX))); } diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index 337f8aa31dc..3b86e8e9744 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -36,7 +36,6 @@ #![feature(sort_internals)] #![feature(sort_unstable)] #![feature(specialization)] -#![feature(step_by)] #![feature(step_trait)] #![feature(test)] #![feature(trusted_len)] diff --git a/src/librand/lib.rs b/src/librand/lib.rs index ca05db15ffe..5e56b0d8ab1 100644 --- a/src/librand/lib.rs +++ b/src/librand/lib.rs @@ -31,7 +31,7 @@ issue = "27703")] #![feature(core_intrinsics)] #![feature(staged_api)] -#![feature(step_by)] +#![feature(iterator_step_by)] #![feature(custom_attribute)] #![feature(specialization)] #![allow(unused_attributes)] diff --git a/src/test/run-pass/range_inclusive.rs b/src/test/run-pass/range_inclusive.rs index 372d4a8b732..f6119e70999 100644 --- a/src/test/run-pass/range_inclusive.rs +++ b/src/test/run-pass/range_inclusive.rs @@ -10,7 +10,7 @@ // Test inclusive range syntax. -#![feature(inclusive_range_syntax, inclusive_range, step_by)] +#![feature(inclusive_range_syntax, inclusive_range, iterator_step_by)] use std::ops::{RangeInclusive, RangeToInclusive}; diff --git a/src/test/run-pass/sync-send-iterators-in-libcore.rs b/src/test/run-pass/sync-send-iterators-in-libcore.rs index d12bdf182fa..c11a0d391a4 100644 --- a/src/test/run-pass/sync-send-iterators-in-libcore.rs +++ b/src/test/run-pass/sync-send-iterators-in-libcore.rs @@ -14,7 +14,7 @@ #![feature(iter_empty)] #![feature(iter_once)] #![feature(iter_unfold)] -#![feature(step_by)] +#![feature(iterator_step_by)] #![feature(str_escape)] use std::iter::{empty, once, repeat}; From bfbe4039f8e3708b1e4ca043c7ac06971e7d40a5 Mon Sep 17 00:00:00 2001 From: Stjepan Glavina Date: Sun, 2 Jul 2017 11:16:37 +0200 Subject: [PATCH 125/162] Fix tidy errors --- src/libcore/slice/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index ce5da9ec2d5..62c7e7aa1cc 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -212,15 +212,15 @@ pub trait SliceExt { #[stable(feature = "copy_from_slice", since = "1.9.0")] fn copy_from_slice(&mut self, src: &[Self::Item]) where Self::Item: Copy; - #[unstable(feature = "sort_unstable", issue = "40585")] + #[stable(feature = "sort_unstable", since = "1.20.0")] fn sort_unstable(&mut self) where Self::Item: Ord; - #[unstable(feature = "sort_unstable", issue = "40585")] + #[stable(feature = "sort_unstable", since = "1.20.0")] fn sort_unstable_by(&mut self, compare: F) where F: FnMut(&Self::Item, &Self::Item) -> Ordering; - #[unstable(feature = "sort_unstable", issue = "40585")] + #[stable(feature = "sort_unstable", since = "1.20.0")] fn sort_unstable_by_key(&mut self, f: F) where F: FnMut(&Self::Item) -> B, B: Ord; From 77f40223033bf0c744eb8b4edb07672c13a21557 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Sun, 2 Jul 2017 13:49:30 +0300 Subject: [PATCH 126/162] Revert "Change error count messages" This reverts commit 5558c64f33446225739c1153b43d2e309bb4f50e. --- src/librustc_driver/lib.rs | 3 ++- src/librustc_errors/lib.rs | 5 ++++- src/test/ui/borrowck/borrowck-in-static.stderr | 2 +- ...oxed-closures-move-upvar-from-non-once-ref-closure.stderr | 2 +- src/test/ui/check_match/issue-35609.stderr | 2 +- src/test/ui/closure_context/issue-42065.stderr | 2 +- src/test/ui/codemap_tests/bad-format-args.stderr | 2 +- .../coherence-overlapping-inherent-impl-trait.stderr | 2 +- src/test/ui/codemap_tests/empty_span.stderr | 2 +- src/test/ui/codemap_tests/huge_multispan_highlight.stderr | 2 +- src/test/ui/codemap_tests/issue-11715.stderr | 2 +- src/test/ui/codemap_tests/issue-28308.stderr | 2 +- src/test/ui/codemap_tests/one_line.stderr | 2 +- src/test/ui/codemap_tests/overlapping_inherent_impls.stderr | 2 +- src/test/ui/codemap_tests/overlapping_spans.stderr | 2 +- src/test/ui/codemap_tests/tab.stderr | 2 +- src/test/ui/codemap_tests/unicode.stderr | 2 +- src/test/ui/coercion-missing-tail-expected-type.stderr | 2 +- src/test/ui/compare-method/proj-outlives-region.stderr | 2 +- src/test/ui/compare-method/region-extra-2.stderr | 2 +- src/test/ui/compare-method/region-extra.stderr | 2 +- src/test/ui/compare-method/region-unrelated.stderr | 2 +- src/test/ui/compare-method/reordered-type-param.stderr | 2 +- .../ui/compare-method/trait-bound-on-type-parameter.stderr | 2 +- src/test/ui/compare-method/traits-misc-mismatch-1.stderr | 2 +- src/test/ui/compare-method/traits-misc-mismatch-2.stderr | 2 +- src/test/ui/cross-crate-macro-backtrace/main.stderr | 2 +- src/test/ui/did_you_mean/E0178.stderr | 2 +- .../issue-21659-show-relevant-trait-impls-1.stderr | 2 +- .../issue-21659-show-relevant-trait-impls-2.stderr | 2 +- src/test/ui/did_you_mean/issue-31424.stderr | 2 +- src/test/ui/did_you_mean/issue-34126.stderr | 2 +- src/test/ui/did_you_mean/issue-34337.stderr | 2 +- src/test/ui/did_you_mean/issue-35937.stderr | 2 +- src/test/ui/did_you_mean/issue-36798.stderr | 2 +- src/test/ui/did_you_mean/issue-36798_unknown_field.stderr | 2 +- src/test/ui/did_you_mean/issue-37139.stderr | 2 +- .../issue-38054-do-not-show-unresolved-names.stderr | 2 +- src/test/ui/did_you_mean/issue-38147-1.stderr | 2 +- src/test/ui/did_you_mean/issue-38147-2.stderr | 2 +- src/test/ui/did_you_mean/issue-38147-3.stderr | 2 +- src/test/ui/did_you_mean/issue-38147-4.stderr | 2 +- src/test/ui/did_you_mean/issue-39544.stderr | 2 +- .../ui/did_you_mean/issue-39802-show-5-trait-impls.stderr | 2 +- src/test/ui/did_you_mean/issue-40006.stderr | 2 +- src/test/ui/did_you_mean/issue-40396.stderr | 2 +- src/test/ui/did_you_mean/issue-40823.stderr | 2 +- src/test/ui/did_you_mean/issue-41679.stderr | 2 +- src/test/ui/did_you_mean/recursion_limit.stderr | 2 +- src/test/ui/did_you_mean/recursion_limit_deref.stderr | 2 +- .../trait-object-reference-without-parens-suggestion.stderr | 2 +- src/test/ui/dropck/dropck-eyepatch-extern-crate.stderr | 2 +- .../ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr | 2 +- src/test/ui/dropck/dropck-eyepatch-reorder.stderr | 2 +- src/test/ui/dropck/dropck-eyepatch.stderr | 2 +- src/test/ui/fmt/format-string-error.stderr | 2 +- src/test/ui/impl-trait/equality.stderr | 2 +- .../invalid-module-declaration.stderr | 2 +- src/test/ui/issue-37311-type-length-limit/issue-37311.stderr | 2 +- src/test/ui/issue-40402-ref-hints/issue-40402-1.stderr | 2 +- src/test/ui/issue-40402-ref-hints/issue-40402-2.stderr | 2 +- src/test/ui/issue-41652/issue_41652.stderr | 2 +- .../ex1-return-one-existing-name-if-else.stderr | 2 +- .../ui/lifetime-errors/ex1b-return-no-names-if-else.stderr | 2 +- .../ui/lifetime-errors/ex2a-push-one-existing-name.stderr | 2 +- .../ui/lifetime-errors/ex2b-push-no-existing-names.stderr | 2 +- .../ui/lifetime-errors/ex2c-push-inference-variable.stderr | 2 +- .../ui/lifetime-errors/ex2d-push-inference-variable-2.stderr | 2 +- .../ui/lifetime-errors/ex2e-push-inference-variable-3.stderr | 2 +- src/test/ui/lifetimes/borrowck-let-suggestion.stderr | 2 +- src/test/ui/lint/command-line-lint-group-deny.stderr | 2 +- src/test/ui/lint/command-line-lint-group-forbid.stderr | 2 +- src/test/ui/lint/lint-group-style.stderr | 2 +- src/test/ui/loop-break-value-no-repeat.stderr | 2 +- src/test/ui/macros/bad_hello.stderr | 2 +- src/test/ui/macros/format-foreign.stderr | 2 +- src/test/ui/macros/macro-backtrace-invalid-internals.stderr | 2 +- src/test/ui/macros/macro-backtrace-nested.stderr | 2 +- src/test/ui/macros/macro-backtrace-println.stderr | 2 +- src/test/ui/mismatched_types/E0053.stderr | 2 +- src/test/ui/mismatched_types/E0281.stderr | 2 +- src/test/ui/mismatched_types/E0409.stderr | 2 +- src/test/ui/mismatched_types/abridged.stderr | 2 +- src/test/ui/mismatched_types/binops.stderr | 2 +- src/test/ui/mismatched_types/cast-rfc0401.stderr | 2 +- src/test/ui/mismatched_types/closure-arg-count.stderr | 2 +- src/test/ui/mismatched_types/closure-mismatch.stderr | 2 +- src/test/ui/mismatched_types/const-fn-in-trait.stderr | 2 +- src/test/ui/mismatched_types/fn-variance-1.stderr | 2 +- src/test/ui/mismatched_types/issue-19109.stderr | 2 +- src/test/ui/mismatched_types/issue-26480.stderr | 2 +- src/test/ui/mismatched_types/issue-35030.stderr | 2 +- src/test/ui/mismatched_types/issue-36053-2.stderr | 2 +- src/test/ui/mismatched_types/issue-38371.stderr | 2 +- src/test/ui/mismatched_types/main.stderr | 2 +- .../ui/mismatched_types/method-help-unsatisfied-bound.stderr | 2 +- src/test/ui/mismatched_types/overloaded-calls-bad.stderr | 2 +- src/test/ui/mismatched_types/trait-bounds-cant-coerce.stderr | 2 +- .../ui/mismatched_types/trait-impl-fn-incompatibility.stderr | 2 +- .../mismatched_types/unboxed-closures-vtable-mismatch.stderr | 2 +- src/test/ui/missing-items/issue-40221.stderr | 2 +- src/test/ui/missing-items/m2.stderr | 2 +- src/test/ui/missing-items/missing-type-parameter.stderr | 2 +- src/test/ui/pub/pub-restricted-error-fn.stderr | 2 +- src/test/ui/pub/pub-restricted-error.stderr | 2 +- src/test/ui/pub/pub-restricted-non-path.stderr | 2 +- src/test/ui/pub/pub-restricted.stderr | 2 +- src/test/ui/reachable/expr_add.stderr | 2 +- src/test/ui/reachable/expr_again.stderr | 2 +- src/test/ui/reachable/expr_array.stderr | 2 +- src/test/ui/reachable/expr_assign.stderr | 2 +- src/test/ui/reachable/expr_block.stderr | 2 +- src/test/ui/reachable/expr_box.stderr | 2 +- src/test/ui/reachable/expr_call.stderr | 2 +- src/test/ui/reachable/expr_cast.stderr | 2 +- src/test/ui/reachable/expr_if.stderr | 2 +- src/test/ui/reachable/expr_loop.stderr | 2 +- src/test/ui/reachable/expr_match.stderr | 2 +- src/test/ui/reachable/expr_method.stderr | 2 +- src/test/ui/reachable/expr_repeat.stderr | 2 +- src/test/ui/reachable/expr_return.stderr | 2 +- src/test/ui/reachable/expr_struct.stderr | 2 +- src/test/ui/reachable/expr_tup.stderr | 2 +- src/test/ui/reachable/expr_type.stderr | 2 +- src/test/ui/reachable/expr_unary.stderr | 2 +- src/test/ui/reachable/expr_while.stderr | 2 +- src/test/ui/regions-fn-subtyping-return-static.stderr | 2 +- src/test/ui/resolve/enums-are-namespaced-xc.stderr | 2 +- src/test/ui/resolve/issue-14254.stderr | 2 +- src/test/ui/resolve/issue-16058.stderr | 2 +- src/test/ui/resolve/issue-17518.stderr | 2 +- src/test/ui/resolve/issue-18252.stderr | 2 +- src/test/ui/resolve/issue-19452.stderr | 2 +- src/test/ui/resolve/issue-23305.stderr | 2 +- src/test/ui/resolve/issue-2356.stderr | 2 +- src/test/ui/resolve/issue-24968.stderr | 2 +- src/test/ui/resolve/issue-33876.stderr | 2 +- src/test/ui/resolve/issue-3907-2.stderr | 2 +- src/test/ui/resolve/issue-39226.stderr | 2 +- src/test/ui/resolve/issue-5035-2.stderr | 2 +- src/test/ui/resolve/issue-6702.stderr | 2 +- src/test/ui/resolve/levenshtein.stderr | 2 +- src/test/ui/resolve/privacy-struct-ctor.stderr | 2 +- src/test/ui/resolve/resolve-assoc-suggestions.stderr | 2 +- src/test/ui/resolve/resolve-hint-macro.stderr | 2 +- src/test/ui/resolve/resolve-speculative-adjustment.stderr | 2 +- .../ui/resolve/suggest-path-instead-of-mod-dot-item.stderr | 2 +- src/test/ui/resolve/token-error-correct-2.stderr | 2 +- src/test/ui/resolve/token-error-correct-3.stderr | 2 +- src/test/ui/resolve/token-error-correct.stderr | 2 +- src/test/ui/resolve/tuple-struct-alias.stderr | 2 +- src/test/ui/resolve/unresolved_static_type_field.stderr | 2 +- src/test/ui/span/E0046.stderr | 2 +- src/test/ui/span/E0057.stderr | 2 +- src/test/ui/span/E0072.stderr | 2 +- src/test/ui/span/E0204.stderr | 2 +- src/test/ui/span/E0493.stderr | 2 +- src/test/ui/span/E0535.stderr | 2 +- src/test/ui/span/E0536.stderr | 2 +- src/test/ui/span/E0537.stderr | 2 +- .../ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr | 2 +- src/test/ui/span/borrowck-borrow-overloaded-deref-mut.stderr | 2 +- src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr | 2 +- .../ui/span/borrowck-call-method-from-mut-aliasable.stderr | 2 +- src/test/ui/span/borrowck-fn-in-const-b.stderr | 2 +- src/test/ui/span/borrowck-let-suggestion-suffixes.stderr | 2 +- src/test/ui/span/borrowck-object-mutability.stderr | 2 +- src/test/ui/span/borrowck-ref-into-rvalue.stderr | 2 +- src/test/ui/span/coerce-suggestions.stderr | 2 +- src/test/ui/span/destructor-restrictions.stderr | 2 +- src/test/ui/span/dropck-object-cycle.stderr | 2 +- src/test/ui/span/dropck_arr_cycle_checked.stderr | 2 +- src/test/ui/span/dropck_direct_cycle_with_drop.stderr | 2 +- src/test/ui/span/dropck_misc_variants.stderr | 2 +- src/test/ui/span/dropck_vec_cycle_checked.stderr | 2 +- src/test/ui/span/impl-wrong-item-for-trait.stderr | 2 +- src/test/ui/span/issue-11925.stderr | 2 +- src/test/ui/span/issue-15480.stderr | 2 +- .../span/issue-23338-locals-die-before-temps-of-body.stderr | 2 +- src/test/ui/span/issue-23729.stderr | 2 +- src/test/ui/span/issue-23827.stderr | 2 +- src/test/ui/span/issue-24356.stderr | 2 +- src/test/ui/span/issue-24690.stderr | 2 +- .../issue-24805-dropck-child-has-items-via-parent.stderr | 2 +- src/test/ui/span/issue-24805-dropck-trait-has-items.stderr | 2 +- src/test/ui/span/issue-24895-copy-clone-dropck.stderr | 2 +- src/test/ui/span/issue-25199.stderr | 2 +- src/test/ui/span/issue-26656.stderr | 2 +- src/test/ui/span/issue-27522.stderr | 2 +- src/test/ui/span/issue-29106.stderr | 2 +- src/test/ui/span/issue-29595.stderr | 2 +- src/test/ui/span/issue-33884.stderr | 2 +- src/test/ui/span/issue-34264.stderr | 2 +- src/test/ui/span/issue-36530.stderr | 2 +- src/test/ui/span/issue-36537.stderr | 2 +- src/test/ui/span/issue-37767.stderr | 2 +- src/test/ui/span/issue-39018.stderr | 2 +- src/test/ui/span/issue-39698.stderr | 2 +- src/test/ui/span/issue-40157.stderr | 2 +- src/test/ui/span/issue-7575.stderr | 2 +- src/test/ui/span/issue28498-reject-ex1.stderr | 2 +- src/test/ui/span/issue28498-reject-lifetime-param.stderr | 2 +- src/test/ui/span/issue28498-reject-passed-to-fn.stderr | 2 +- src/test/ui/span/issue28498-reject-trait-bound.stderr | 2 +- src/test/ui/span/lint-unused-unsafe.stderr | 2 +- src/test/ui/span/loan-extend.stderr | 2 +- src/test/ui/span/move-closure.stderr | 2 +- src/test/ui/span/multiline-span-E0072.stderr | 2 +- src/test/ui/span/multiline-span-simple.stderr | 2 +- src/test/ui/span/mut-arg-hint.stderr | 2 +- src/test/ui/span/mut-ptr-cant-outlive-ref.stderr | 2 +- src/test/ui/span/pub-struct-field.stderr | 2 +- src/test/ui/span/range-2.stderr | 2 +- src/test/ui/span/recursive-type-field.stderr | 2 +- src/test/ui/span/regionck-unboxed-closure-lifetimes.stderr | 2 +- .../ui/span/regions-close-over-borrowed-ref-in-obj.stderr | 2 +- src/test/ui/span/regions-close-over-type-parameter-2.stderr | 2 +- src/test/ui/span/regions-escape-loop-via-variable.stderr | 2 +- src/test/ui/span/regions-escape-loop-via-vec.stderr | 2 +- .../ui/span/regions-infer-borrow-scope-within-loop.stderr | 2 +- src/test/ui/span/send-is-not-static-ensures-scoping.stderr | 2 +- src/test/ui/span/send-is-not-static-std-sync-2.stderr | 2 +- src/test/ui/span/send-is-not-static-std-sync.stderr | 2 +- src/test/ui/span/slice-borrow.stderr | 2 +- src/test/ui/span/suggestion-non-ascii.stderr | 2 +- src/test/ui/span/type-binding.stderr | 2 +- src/test/ui/span/typo-suggestion.stderr | 2 +- src/test/ui/span/vec-must-not-hide-type-from-dropck.stderr | 2 +- src/test/ui/span/vec_refs_data_with_early_death.stderr | 2 +- src/test/ui/span/wf-method-late-bound-regions.stderr | 2 +- src/test/ui/static-lifetime.stderr | 2 +- .../suggestions/confuse-field-and-method/issue-18343.stderr | 2 +- .../suggestions/confuse-field-and-method/issue-2392.stderr | 2 +- .../suggestions/confuse-field-and-method/issue-32128.stderr | 2 +- .../suggestions/confuse-field-and-method/issue-33784.stderr | 2 +- .../confuse-field-and-method/private-field.stderr | 2 +- src/test/ui/suggestions/tuple-float-index.stderr | 2 +- src/test/ui/token/bounds-obj-parens.stderr | 2 +- src/test/ui/token/issue-10636-2.stderr | 2 +- src/test/ui/token/issue-41155.stderr | 2 +- src/test/ui/token/macro-incomplete-parse.stderr | 2 +- src/test/ui/token/trailing-plus-in-bounds.stderr | 2 +- src/test/ui/type-check/cannot_infer_local_or_array.stderr | 2 +- src/test/ui/type-check/cannot_infer_local_or_vec.stderr | 2 +- .../ui/type-check/cannot_infer_local_or_vec_in_tuples.stderr | 2 +- src/test/ui/type-check/issue-22897.stderr | 2 +- src/test/ui/type-check/issue-40294.stderr | 2 +- src/test/ui/type-check/unknown_type_for_closure.stderr | 2 +- 248 files changed, 252 insertions(+), 248 deletions(-) diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 54e7c398fe6..061e21fadeb 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -113,7 +113,8 @@ const BUG_REPORT_URL: &'static str = "https://github.com/rust-lang/rust/blob/mas fn abort_msg(err_count: usize) -> String { match err_count { 0 => "aborting with no errors (maybe a bug?)".to_owned(), - _ => "aborting due to previous error(s)".to_owned(), + 1 => "aborting due to previous error".to_owned(), + e => format!("aborting due to {} previous errors", e), } } diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index ada1c632bc0..dd25f969414 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -506,7 +506,10 @@ impl Handler { return; } - _ => s = "aborting due to previous error(s)".to_string(), + 1 => s = "aborting due to previous error".to_string(), + _ => { + s = format!("aborting due to {} previous errors", self.err_count.get()); + } } panic!(self.fatal(&s)); diff --git a/src/test/ui/borrowck/borrowck-in-static.stderr b/src/test/ui/borrowck/borrowck-in-static.stderr index a30d4cbd64c..6083a82b1b6 100644 --- a/src/test/ui/borrowck/borrowck-in-static.stderr +++ b/src/test/ui/borrowck/borrowck-in-static.stderr @@ -6,5 +6,5 @@ error[E0507]: cannot move out of captured outer variable in an `Fn` closure 15 | Box::new(|| x) //~ ERROR cannot move out of captured outer variable | ^ cannot move out of captured outer variable in an `Fn` closure -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr b/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr index a13971d32de..dbfcb2e0c2f 100644 --- a/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr +++ b/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr @@ -7,5 +7,5 @@ error[E0507]: cannot move out of captured outer variable in an `Fn` closure 21 | y.into_iter(); | ^ cannot move out of captured outer variable in an `Fn` closure -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/check_match/issue-35609.stderr b/src/test/ui/check_match/issue-35609.stderr index 0cb264ff35e..0aafe3f17b3 100644 --- a/src/test/ui/check_match/issue-35609.stderr +++ b/src/test/ui/check_match/issue-35609.stderr @@ -46,5 +46,5 @@ error[E0004]: non-exhaustive patterns: `Some(B)`, `Some(C)`, `Some(D)` and 2 mor 49 | match Some(A) { | ^^^^^^^ patterns `Some(B)`, `Some(C)`, `Some(D)` and 2 more not covered -error: aborting due to previous error(s) +error: aborting due to 8 previous errors diff --git a/src/test/ui/closure_context/issue-42065.stderr b/src/test/ui/closure_context/issue-42065.stderr index 5bbd372adb6..c195940ade6 100644 --- a/src/test/ui/closure_context/issue-42065.stderr +++ b/src/test/ui/closure_context/issue-42065.stderr @@ -12,5 +12,5 @@ note: closure cannot be invoked more than once because it moves the variable `di 16 | for (key, value) in dict { | ^^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/codemap_tests/bad-format-args.stderr b/src/test/ui/codemap_tests/bad-format-args.stderr index cddc7df85ae..87255dfe774 100644 --- a/src/test/ui/codemap_tests/bad-format-args.stderr +++ b/src/test/ui/codemap_tests/bad-format-args.stderr @@ -22,5 +22,5 @@ error: expected token: `,` | = note: this error originates in a macro outside of the current crate -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/codemap_tests/coherence-overlapping-inherent-impl-trait.stderr b/src/test/ui/codemap_tests/coherence-overlapping-inherent-impl-trait.stderr index 1c32ce44109..7f1ab929c6f 100644 --- a/src/test/ui/codemap_tests/coherence-overlapping-inherent-impl-trait.stderr +++ b/src/test/ui/codemap_tests/coherence-overlapping-inherent-impl-trait.stderr @@ -6,5 +6,5 @@ error[E0592]: duplicate definitions with name `f` 15 | impl C { fn f() {} } | --------- other definition for `f` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/codemap_tests/empty_span.stderr b/src/test/ui/codemap_tests/empty_span.stderr index 84e6e336b93..b33dee6b4a4 100644 --- a/src/test/ui/codemap_tests/empty_span.stderr +++ b/src/test/ui/codemap_tests/empty_span.stderr @@ -4,5 +4,5 @@ error[E0321]: cross-crate traits with a default impl, like `std::marker::Send`, 17 | unsafe impl Send for &'static Foo { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/codemap_tests/huge_multispan_highlight.stderr b/src/test/ui/codemap_tests/huge_multispan_highlight.stderr index 46b3db18e8a..914db98c784 100644 --- a/src/test/ui/codemap_tests/huge_multispan_highlight.stderr +++ b/src/test/ui/codemap_tests/huge_multispan_highlight.stderr @@ -7,5 +7,5 @@ error[E0596]: cannot borrow immutable local variable `x` as mutable 100 | let y = &mut x; | ^ cannot borrow mutably -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/codemap_tests/issue-11715.stderr b/src/test/ui/codemap_tests/issue-11715.stderr index dcc21672c56..4947cbedd20 100644 --- a/src/test/ui/codemap_tests/issue-11715.stderr +++ b/src/test/ui/codemap_tests/issue-11715.stderr @@ -8,5 +8,5 @@ error[E0499]: cannot borrow `x` as mutable more than once at a time 101 | } | - first borrow ends here -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/codemap_tests/issue-28308.stderr b/src/test/ui/codemap_tests/issue-28308.stderr index 43743b796d5..7a1478104fd 100644 --- a/src/test/ui/codemap_tests/issue-28308.stderr +++ b/src/test/ui/codemap_tests/issue-28308.stderr @@ -6,5 +6,5 @@ error[E0600]: cannot apply unary operator `!` to type `&'static str` | = note: this error originates in a macro outside of the current crate -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/codemap_tests/one_line.stderr b/src/test/ui/codemap_tests/one_line.stderr index e2e0537226a..a73575a8d57 100644 --- a/src/test/ui/codemap_tests/one_line.stderr +++ b/src/test/ui/codemap_tests/one_line.stderr @@ -7,5 +7,5 @@ error[E0499]: cannot borrow `v` as mutable more than once at a time | | second mutable borrow occurs here | first mutable borrow occurs here -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/codemap_tests/overlapping_inherent_impls.stderr b/src/test/ui/codemap_tests/overlapping_inherent_impls.stderr index 0af8c06cfda..de8a24cf33f 100644 --- a/src/test/ui/codemap_tests/overlapping_inherent_impls.stderr +++ b/src/test/ui/codemap_tests/overlapping_inherent_impls.stderr @@ -25,5 +25,5 @@ error[E0592]: duplicate definitions with name `baz` 43 | fn baz(&self) {} | ---------------- other definition for `baz` -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/codemap_tests/overlapping_spans.stderr b/src/test/ui/codemap_tests/overlapping_spans.stderr index 9778015766c..d32b18d6703 100644 --- a/src/test/ui/codemap_tests/overlapping_spans.stderr +++ b/src/test/ui/codemap_tests/overlapping_spans.stderr @@ -7,5 +7,5 @@ error[E0509]: cannot move out of type `S`, which implements the `Drop` trait | | hint: to prevent move, use `ref _s` or `ref mut _s` | cannot move out of here -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/codemap_tests/tab.stderr b/src/test/ui/codemap_tests/tab.stderr index a3b76159b46..657deca4e6d 100644 --- a/src/test/ui/codemap_tests/tab.stderr +++ b/src/test/ui/codemap_tests/tab.stderr @@ -4,5 +4,5 @@ error[E0425]: cannot find value `bar` in this scope 14 | \tbar; | \t^^^ not found in this scope -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/codemap_tests/unicode.stderr b/src/test/ui/codemap_tests/unicode.stderr index 0f1e008d589..0828fd28b58 100644 --- a/src/test/ui/codemap_tests/unicode.stderr +++ b/src/test/ui/codemap_tests/unicode.stderr @@ -4,5 +4,5 @@ error: invalid ABI: expected one of [cdecl, stdcall, fastcall, vectorcall, thisc 11 | extern "路濫狼á́́" fn foo() {} | ^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/coercion-missing-tail-expected-type.stderr b/src/test/ui/coercion-missing-tail-expected-type.stderr index 49e8b9febc2..5f9a82d972a 100644 --- a/src/test/ui/coercion-missing-tail-expected-type.stderr +++ b/src/test/ui/coercion-missing-tail-expected-type.stderr @@ -24,5 +24,5 @@ error[E0308]: mismatched types = note: expected type `std::result::Result` found type `()` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/compare-method/proj-outlives-region.stderr b/src/test/ui/compare-method/proj-outlives-region.stderr index 63c48ffe26b..2a707c6eb8b 100644 --- a/src/test/ui/compare-method/proj-outlives-region.stderr +++ b/src/test/ui/compare-method/proj-outlives-region.stderr @@ -11,5 +11,5 @@ error[E0276]: impl has stricter requirements than trait = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #37166 -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/compare-method/region-extra-2.stderr b/src/test/ui/compare-method/region-extra-2.stderr index 7adcc66d75c..af974d50183 100644 --- a/src/test/ui/compare-method/region-extra-2.stderr +++ b/src/test/ui/compare-method/region-extra-2.stderr @@ -10,5 +10,5 @@ error[E0276]: impl has stricter requirements than trait 22 | | } | |_____^ impl has extra requirement `'a: 'b` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/compare-method/region-extra.stderr b/src/test/ui/compare-method/region-extra.stderr index a29a292ac65..e657813221a 100644 --- a/src/test/ui/compare-method/region-extra.stderr +++ b/src/test/ui/compare-method/region-extra.stderr @@ -7,5 +7,5 @@ error[E0276]: impl has stricter requirements than trait 22 | fn foo() where 'a: 'b { } | ^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `'a: 'b` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/compare-method/region-unrelated.stderr b/src/test/ui/compare-method/region-unrelated.stderr index 04de54cd05d..9e822bd8b07 100644 --- a/src/test/ui/compare-method/region-unrelated.stderr +++ b/src/test/ui/compare-method/region-unrelated.stderr @@ -11,5 +11,5 @@ error[E0276]: impl has stricter requirements than trait = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #37166 -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/compare-method/reordered-type-param.stderr b/src/test/ui/compare-method/reordered-type-param.stderr index b5e9c89f2f5..4620248e2ef 100644 --- a/src/test/ui/compare-method/reordered-type-param.stderr +++ b/src/test/ui/compare-method/reordered-type-param.stderr @@ -10,5 +10,5 @@ error[E0053]: method `b` has an incompatible type for trait = note: expected type `fn(&E, F) -> F` found type `fn(&E, G) -> G` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/compare-method/trait-bound-on-type-parameter.stderr b/src/test/ui/compare-method/trait-bound-on-type-parameter.stderr index c4a4921289b..7112a00c7b7 100644 --- a/src/test/ui/compare-method/trait-bound-on-type-parameter.stderr +++ b/src/test/ui/compare-method/trait-bound-on-type-parameter.stderr @@ -7,5 +7,5 @@ error[E0276]: impl has stricter requirements than trait 25 | fn b(&self, _x: F) -> F { panic!() } //~ ERROR E0276 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `F: std::marker::Sync` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/compare-method/traits-misc-mismatch-1.stderr b/src/test/ui/compare-method/traits-misc-mismatch-1.stderr index 6374b83e794..f221ebe3302 100644 --- a/src/test/ui/compare-method/traits-misc-mismatch-1.stderr +++ b/src/test/ui/compare-method/traits-misc-mismatch-1.stderr @@ -61,5 +61,5 @@ error[E0276]: impl has stricter requirements than trait 76 | fn method>(&self) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `G: Getter` -error: aborting due to previous error(s) +error: aborting due to 7 previous errors diff --git a/src/test/ui/compare-method/traits-misc-mismatch-2.stderr b/src/test/ui/compare-method/traits-misc-mismatch-2.stderr index 7ff2d93d820..622e144c53a 100644 --- a/src/test/ui/compare-method/traits-misc-mismatch-2.stderr +++ b/src/test/ui/compare-method/traits-misc-mismatch-2.stderr @@ -10,5 +10,5 @@ error[E0276]: impl has stricter requirements than trait 26 | | } | |_____^ impl has extra requirement `U: Iterator` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/cross-crate-macro-backtrace/main.stderr b/src/test/ui/cross-crate-macro-backtrace/main.stderr index 3642a702a82..84db85ac092 100644 --- a/src/test/ui/cross-crate-macro-backtrace/main.stderr +++ b/src/test/ui/cross-crate-macro-backtrace/main.stderr @@ -6,5 +6,5 @@ error: invalid reference to argument `0` (no arguments given) | = note: this error originates in a macro outside of the current crate -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/E0178.stderr b/src/test/ui/did_you_mean/E0178.stderr index bcf00df9832..15e7131cfd3 100644 --- a/src/test/ui/did_you_mean/E0178.stderr +++ b/src/test/ui/did_you_mean/E0178.stderr @@ -22,5 +22,5 @@ error[E0178]: expected a path on the left-hand side of `+`, not `fn() -> Foo` 17 | z: fn() -> Foo + 'a, | ^^^^^^^^^^^^^^^^ perhaps you forgot parentheses? -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr index 73b8e06183b..9010de081da 100644 --- a/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr +++ b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr @@ -8,5 +8,5 @@ error[E0277]: the trait bound `Bar: Foo` is not satisfied > > -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr index e1e4e14b215..e9591a64784 100644 --- a/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr +++ b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr @@ -11,5 +11,5 @@ error[E0277]: the trait bound `Bar: Foo` is not satisfied > and 2 others -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-31424.stderr b/src/test/ui/did_you_mean/issue-31424.stderr index eecb164a83f..c7d43a0fc0b 100644 --- a/src/test/ui/did_you_mean/issue-31424.stderr +++ b/src/test/ui/did_you_mean/issue-31424.stderr @@ -15,5 +15,5 @@ error[E0596]: cannot borrow immutable argument `self` as mutable 23 | (&mut self).bar(); | ^^^^ cannot borrow mutably -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/did_you_mean/issue-34126.stderr b/src/test/ui/did_you_mean/issue-34126.stderr index d5d6ee133b8..63d59a59238 100644 --- a/src/test/ui/did_you_mean/issue-34126.stderr +++ b/src/test/ui/did_you_mean/issue-34126.stderr @@ -7,5 +7,5 @@ error[E0596]: cannot borrow immutable argument `self` as mutable | try removing `&mut` here | cannot reborrow mutably -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-34337.stderr b/src/test/ui/did_you_mean/issue-34337.stderr index 2769c74be5e..9eb88cdeddb 100644 --- a/src/test/ui/did_you_mean/issue-34337.stderr +++ b/src/test/ui/did_you_mean/issue-34337.stderr @@ -7,5 +7,5 @@ error[E0596]: cannot borrow immutable local variable `key` as mutable | try removing `&mut` here | cannot reborrow mutably -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-35937.stderr b/src/test/ui/did_you_mean/issue-35937.stderr index 4760d28566f..1cd1fb76aa3 100644 --- a/src/test/ui/did_you_mean/issue-35937.stderr +++ b/src/test/ui/did_you_mean/issue-35937.stderr @@ -22,5 +22,5 @@ error[E0594]: cannot assign to immutable field `s.x` 30 | s.x += 1; | ^^^^^^^^ cannot mutably borrow immutable field -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/did_you_mean/issue-36798.stderr b/src/test/ui/did_you_mean/issue-36798.stderr index a8d978d5514..72fd09c0357 100644 --- a/src/test/ui/did_you_mean/issue-36798.stderr +++ b/src/test/ui/did_you_mean/issue-36798.stderr @@ -4,5 +4,5 @@ error[E0609]: no field `baz` on type `Foo` 17 | f.baz; | ^^^ did you mean `bar`? -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-36798_unknown_field.stderr b/src/test/ui/did_you_mean/issue-36798_unknown_field.stderr index 8228f9f3fac..82e3eab0836 100644 --- a/src/test/ui/did_you_mean/issue-36798_unknown_field.stderr +++ b/src/test/ui/did_you_mean/issue-36798_unknown_field.stderr @@ -4,5 +4,5 @@ error[E0609]: no field `zz` on type `Foo` 17 | f.zz; | ^^ unknown field -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-37139.stderr b/src/test/ui/did_you_mean/issue-37139.stderr index 6debbaadb1a..4348b6fca63 100644 --- a/src/test/ui/did_you_mean/issue-37139.stderr +++ b/src/test/ui/did_you_mean/issue-37139.stderr @@ -7,5 +7,5 @@ error[E0596]: cannot borrow immutable local variable `x` as mutable | try removing `&mut` here | cannot reborrow mutably -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.stderr b/src/test/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.stderr index 10f5972e369..325f55e686c 100644 --- a/src/test/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.stderr +++ b/src/test/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.stderr @@ -10,5 +10,5 @@ error[E0432]: unresolved import `Foo1` 13 | use Foo1; | ^^^^ no `Foo1` in the root -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/did_you_mean/issue-38147-1.stderr b/src/test/ui/did_you_mean/issue-38147-1.stderr index 85eecd037dd..e9f2b1dad80 100644 --- a/src/test/ui/did_you_mean/issue-38147-1.stderr +++ b/src/test/ui/did_you_mean/issue-38147-1.stderr @@ -6,5 +6,5 @@ error[E0389]: cannot borrow data mutably in a `&` reference 27 | self.s.push('x'); | ^^^^^^ assignment into an immutable reference -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-38147-2.stderr b/src/test/ui/did_you_mean/issue-38147-2.stderr index 2834fc6262f..e81bc722fa0 100644 --- a/src/test/ui/did_you_mean/issue-38147-2.stderr +++ b/src/test/ui/did_you_mean/issue-38147-2.stderr @@ -7,5 +7,5 @@ error[E0596]: cannot borrow immutable borrowed content `*self.s` as mutable 17 | self.s.push('x'); | ^^^^^^ cannot borrow as mutable -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-38147-3.stderr b/src/test/ui/did_you_mean/issue-38147-3.stderr index d950e82003c..749795f4d8f 100644 --- a/src/test/ui/did_you_mean/issue-38147-3.stderr +++ b/src/test/ui/did_you_mean/issue-38147-3.stderr @@ -7,5 +7,5 @@ error[E0596]: cannot borrow immutable borrowed content `*self.s` as mutable 17 | self.s.push('x'); | ^^^^^^ cannot borrow as mutable -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-38147-4.stderr b/src/test/ui/did_you_mean/issue-38147-4.stderr index 6fa152c970b..9a8853f4fbb 100644 --- a/src/test/ui/did_you_mean/issue-38147-4.stderr +++ b/src/test/ui/did_you_mean/issue-38147-4.stderr @@ -6,5 +6,5 @@ error[E0389]: cannot borrow data mutably in a `&` reference 16 | f.s.push('x'); | ^^^ assignment into an immutable reference -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-39544.stderr b/src/test/ui/did_you_mean/issue-39544.stderr index 94afe896d5e..28aaab97bda 100644 --- a/src/test/ui/did_you_mean/issue-39544.stderr +++ b/src/test/ui/did_you_mean/issue-39544.stderr @@ -96,5 +96,5 @@ error[E0594]: cannot assign to immutable borrowed content `*x.0` 58 | *x.0 = 1; | ^^^^^^^^ cannot borrow as mutable -error: aborting due to previous error(s) +error: aborting due to 12 previous errors diff --git a/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr b/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr index 6a0e94bf138..4ea4adfcfe0 100644 --- a/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr +++ b/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr @@ -39,5 +39,5 @@ error[E0277]: the trait bound `bool: Foo` is not satisfied and 2 others = note: required by `Foo::bar` -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/did_you_mean/issue-40006.stderr b/src/test/ui/did_you_mean/issue-40006.stderr index b1dab01d81f..8e8773eba3e 100644 --- a/src/test/ui/did_you_mean/issue-40006.stderr +++ b/src/test/ui/did_you_mean/issue-40006.stderr @@ -64,5 +64,5 @@ error[E0038]: the trait `X` cannot be made into an object | = note: method `xxx` has no receiver -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-40396.stderr b/src/test/ui/did_you_mean/issue-40396.stderr index daee8df7ed8..1a0c74dc01a 100644 --- a/src/test/ui/did_you_mean/issue-40396.stderr +++ b/src/test/ui/did_you_mean/issue-40396.stderr @@ -30,5 +30,5 @@ error: chained comparison operators require parentheses | = help: use `::<...>` instead of `<...>` if you meant to specify type arguments -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/did_you_mean/issue-40823.stderr b/src/test/ui/did_you_mean/issue-40823.stderr index a034ea80969..7daab09c09e 100644 --- a/src/test/ui/did_you_mean/issue-40823.stderr +++ b/src/test/ui/did_you_mean/issue-40823.stderr @@ -4,5 +4,5 @@ error[E0596]: cannot borrow immutable borrowed content `*buf` as mutable 13 | buf.iter_mut(); | ^^^ cannot borrow as mutable -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-41679.stderr b/src/test/ui/did_you_mean/issue-41679.stderr index 4f210bb0b11..2abbbf65ba9 100644 --- a/src/test/ui/did_you_mean/issue-41679.stderr +++ b/src/test/ui/did_you_mean/issue-41679.stderr @@ -6,5 +6,5 @@ error: `~` can not be used as a unary operator | = help: use `!` instead of `~` if you meant to perform bitwise negation -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/recursion_limit.stderr b/src/test/ui/did_you_mean/recursion_limit.stderr index 32f9d90ec2d..d157c5de6c7 100644 --- a/src/test/ui/did_you_mean/recursion_limit.stderr +++ b/src/test/ui/did_you_mean/recursion_limit.stderr @@ -17,5 +17,5 @@ error[E0275]: overflow evaluating the requirement `K: std::marker::Send` = note: required because it appears within the type `A` = note: required by `is_send` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/recursion_limit_deref.stderr b/src/test/ui/did_you_mean/recursion_limit_deref.stderr index ba8d3815181..57b28d03736 100644 --- a/src/test/ui/did_you_mean/recursion_limit_deref.stderr +++ b/src/test/ui/did_you_mean/recursion_limit_deref.stderr @@ -19,5 +19,5 @@ error[E0308]: mismatched types = note: expected type `&Bottom` found type `&Top` -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr b/src/test/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr index 50e296a1bc5..c4858b63c2d 100644 --- a/src/test/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr +++ b/src/test/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr @@ -18,5 +18,5 @@ error[E0038]: the trait `std::marker::Copy` cannot be made into an object | = note: the trait cannot require that `Self : Sized` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/dropck/dropck-eyepatch-extern-crate.stderr b/src/test/ui/dropck/dropck-eyepatch-extern-crate.stderr index a5a3c48ab97..62ce3209c91 100644 --- a/src/test/ui/dropck/dropck-eyepatch-extern-crate.stderr +++ b/src/test/ui/dropck/dropck-eyepatch-extern-crate.stderr @@ -42,5 +42,5 @@ error[E0597]: `c` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr b/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr index e1bfb4d8c1e..2c788e952ed 100644 --- a/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr +++ b/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr @@ -20,5 +20,5 @@ error[E0569]: requires an `unsafe impl` declaration due to `#[may_dangle]` attri 43 | | } | |_^ -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/dropck/dropck-eyepatch-reorder.stderr b/src/test/ui/dropck/dropck-eyepatch-reorder.stderr index de04a1c4283..d94808bbcb6 100644 --- a/src/test/ui/dropck/dropck-eyepatch-reorder.stderr +++ b/src/test/ui/dropck/dropck-eyepatch-reorder.stderr @@ -42,5 +42,5 @@ error[E0597]: `c` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/dropck/dropck-eyepatch.stderr b/src/test/ui/dropck/dropck-eyepatch.stderr index 26fee852fb2..811eee0e85f 100644 --- a/src/test/ui/dropck/dropck-eyepatch.stderr +++ b/src/test/ui/dropck/dropck-eyepatch.stderr @@ -42,5 +42,5 @@ error[E0597]: `c` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/fmt/format-string-error.stderr b/src/test/ui/fmt/format-string-error.stderr index 2466d2b43b6..58b392f0b8d 100644 --- a/src/test/ui/fmt/format-string-error.stderr +++ b/src/test/ui/fmt/format-string-error.stderr @@ -16,5 +16,5 @@ error: invalid format string: unmatched `}` found = note: if you intended to print `}`, you can escape it using `}}` = note: this error originates in a macro outside of the current crate -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/impl-trait/equality.stderr b/src/test/ui/impl-trait/equality.stderr index 2206234b777..3fc08a0900f 100644 --- a/src/test/ui/impl-trait/equality.stderr +++ b/src/test/ui/impl-trait/equality.stderr @@ -51,5 +51,5 @@ error[E0308]: mismatched types = note: expected type `impl Foo` (i32) found type `impl Foo` (u32) -error: aborting due to previous error(s) +error: aborting due to 6 previous errors diff --git a/src/test/ui/invalid-module-declaration/invalid-module-declaration.stderr b/src/test/ui/invalid-module-declaration/invalid-module-declaration.stderr index a444d5f5a40..3e9b21cdb74 100644 --- a/src/test/ui/invalid-module-declaration/invalid-module-declaration.stderr +++ b/src/test/ui/invalid-module-declaration/invalid-module-declaration.stderr @@ -10,5 +10,5 @@ note: maybe move this module `$DIR/auxiliary/foo/bar.rs` to its own directory vi 11 | pub mod baz; | ^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/issue-37311-type-length-limit/issue-37311.stderr b/src/test/ui/issue-37311-type-length-limit/issue-37311.stderr index 62223c553e3..b51b683a1ac 100644 --- a/src/test/ui/issue-37311-type-length-limit/issue-37311.stderr +++ b/src/test/ui/issue-37311-type-length-limit/issue-37311.stderr @@ -8,5 +8,5 @@ error: reached the type-length limit while instantiating `<(&(&(&(&(&( | = note: consider adding a `#![type_length_limit="2097152"]` attribute to your crate -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/issue-40402-ref-hints/issue-40402-1.stderr b/src/test/ui/issue-40402-ref-hints/issue-40402-1.stderr index 80f608c1d37..de110ac12b7 100644 --- a/src/test/ui/issue-40402-ref-hints/issue-40402-1.stderr +++ b/src/test/ui/issue-40402-ref-hints/issue-40402-1.stderr @@ -7,5 +7,5 @@ error[E0507]: cannot move out of indexed content | help: consider using a reference instead `&f.v[0]` | cannot move out of indexed content -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/issue-40402-ref-hints/issue-40402-2.stderr b/src/test/ui/issue-40402-ref-hints/issue-40402-2.stderr index d35800ac1e7..0060b683bba 100644 --- a/src/test/ui/issue-40402-ref-hints/issue-40402-2.stderr +++ b/src/test/ui/issue-40402-ref-hints/issue-40402-2.stderr @@ -7,5 +7,5 @@ error[E0507]: cannot move out of indexed content | | ...and here (use `ref b` or `ref mut b`) | hint: to prevent move, use `ref a` or `ref mut a` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/issue-41652/issue_41652.stderr b/src/test/ui/issue-41652/issue_41652.stderr index b7b1ddb7b88..8a55c9989e1 100644 --- a/src/test/ui/issue-41652/issue_41652.stderr +++ b/src/test/ui/issue-41652/issue_41652.stderr @@ -13,5 +13,5 @@ note: candidate #1 is defined in the trait `issue_41652_b::Tr` | |__________________________^ = help: to disambiguate the method call, write `issue_41652_b::Tr::f(3)` instead -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.stderr index 892a6dcd1e9..5d1336c7c3a 100644 --- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.stderr +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.stderr @@ -6,5 +6,5 @@ error[E0621]: explicit lifetime required in the type of `y` 12 | if x > y { x } else { y } | ^ lifetime `'a` required -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/lifetime-errors/ex1b-return-no-names-if-else.stderr b/src/test/ui/lifetime-errors/ex1b-return-no-names-if-else.stderr index d005eeb4045..fccc44caac8 100644 --- a/src/test/ui/lifetime-errors/ex1b-return-no-names-if-else.stderr +++ b/src/test/ui/lifetime-errors/ex1b-return-no-names-if-else.stderr @@ -6,5 +6,5 @@ error[E0106]: missing lifetime specifier | = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `x` or `y` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr index 1630ae32ba6..e529d6ffe46 100644 --- a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr +++ b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr @@ -6,5 +6,5 @@ error[E0621]: explicit lifetime required in the type of `y` 16 | x.push(y); | ^ lifetime `'a` required -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.stderr b/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.stderr index 6380a885f44..6764c58f4bb 100644 --- a/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.stderr +++ b/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.stderr @@ -21,5 +21,5 @@ note: ...does not necessarily outlive the anonymous lifetime #2 defined on the f 17 | | } | |_^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/lifetime-errors/ex2c-push-inference-variable.stderr b/src/test/ui/lifetime-errors/ex2c-push-inference-variable.stderr index b28a3c0c135..7356fc11862 100644 --- a/src/test/ui/lifetime-errors/ex2c-push-inference-variable.stderr +++ b/src/test/ui/lifetime-errors/ex2c-push-inference-variable.stderr @@ -31,5 +31,5 @@ note: ...so that expression is assignable (expected Ref<'b, _>, found Ref<'_, _> 17 | x.push(z); | ^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/lifetime-errors/ex2d-push-inference-variable-2.stderr b/src/test/ui/lifetime-errors/ex2d-push-inference-variable-2.stderr index dd716bac513..38b0acf9339 100644 --- a/src/test/ui/lifetime-errors/ex2d-push-inference-variable-2.stderr +++ b/src/test/ui/lifetime-errors/ex2d-push-inference-variable-2.stderr @@ -33,5 +33,5 @@ note: ...so that expression is assignable (expected &mut std::vec::Vec> = x; | ^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/lifetime-errors/ex2e-push-inference-variable-3.stderr b/src/test/ui/lifetime-errors/ex2e-push-inference-variable-3.stderr index 141f5a7c452..035e516e862 100644 --- a/src/test/ui/lifetime-errors/ex2e-push-inference-variable-3.stderr +++ b/src/test/ui/lifetime-errors/ex2e-push-inference-variable-3.stderr @@ -33,5 +33,5 @@ note: ...so that expression is assignable (expected &mut std::vec::Vec> = x; | ^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/lifetimes/borrowck-let-suggestion.stderr b/src/test/ui/lifetimes/borrowck-let-suggestion.stderr index 2bc0acd626c..d1ba9246588 100644 --- a/src/test/ui/lifetimes/borrowck-let-suggestion.stderr +++ b/src/test/ui/lifetimes/borrowck-let-suggestion.stderr @@ -10,5 +10,5 @@ error[E0597]: borrowed value does not live long enough | = note: consider using a `let` binding to increase its lifetime -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/lint/command-line-lint-group-deny.stderr b/src/test/ui/lint/command-line-lint-group-deny.stderr index d441702374b..23fac66cc6c 100644 --- a/src/test/ui/lint/command-line-lint-group-deny.stderr +++ b/src/test/ui/lint/command-line-lint-group-deny.stderr @@ -6,5 +6,5 @@ error: variable `_InappropriateCamelCasing` should have a snake case name such a | = note: `-D non-snake-case` implied by `-D bad-style` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/lint/command-line-lint-group-forbid.stderr b/src/test/ui/lint/command-line-lint-group-forbid.stderr index 9d4d0b12b18..0babd7f6fe4 100644 --- a/src/test/ui/lint/command-line-lint-group-forbid.stderr +++ b/src/test/ui/lint/command-line-lint-group-forbid.stderr @@ -6,5 +6,5 @@ error: variable `_InappropriateCamelCasing` should have a snake case name such a | = note: `-F non-snake-case` implied by `-F bad-style` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/lint/lint-group-style.stderr b/src/test/ui/lint/lint-group-style.stderr index 636370de302..862e94b873a 100644 --- a/src/test/ui/lint/lint-group-style.stderr +++ b/src/test/ui/lint/lint-group-style.stderr @@ -63,5 +63,5 @@ note: lint level defined here | ^^^^^^^^^ = note: #[warn(non_camel_case_types)] implied by #[warn(bad_style)] -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/loop-break-value-no-repeat.stderr b/src/test/ui/loop-break-value-no-repeat.stderr index 7a4a9c3f012..c154ea6f8c2 100644 --- a/src/test/ui/loop-break-value-no-repeat.stderr +++ b/src/test/ui/loop-break-value-no-repeat.stderr @@ -4,5 +4,5 @@ error[E0571]: `break` with value from a `for` loop 22 | break 22 | ^^^^^^^^ can only break with a value inside `loop` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/macros/bad_hello.stderr b/src/test/ui/macros/bad_hello.stderr index b8337c81834..bffb33f468f 100644 --- a/src/test/ui/macros/bad_hello.stderr +++ b/src/test/ui/macros/bad_hello.stderr @@ -4,5 +4,5 @@ error: expected a literal 12 | println!(3 + 4); | ^^^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/macros/format-foreign.stderr b/src/test/ui/macros/format-foreign.stderr index a964b92712d..0283052a89f 100644 --- a/src/test/ui/macros/format-foreign.stderr +++ b/src/test/ui/macros/format-foreign.stderr @@ -48,5 +48,5 @@ error: named argument never used = help: `$NAME` should be written as `{NAME}` = note: shell formatting not supported; see the documentation for `std::fmt` -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/macros/macro-backtrace-invalid-internals.stderr b/src/test/ui/macros/macro-backtrace-invalid-internals.stderr index 5ed4ab4552a..0f0d6d8ded3 100644 --- a/src/test/ui/macros/macro-backtrace-invalid-internals.stderr +++ b/src/test/ui/macros/macro-backtrace-invalid-internals.stderr @@ -52,5 +52,5 @@ error[E0613]: attempted to access tuple index `0` on type `{integer}`, but the t 56 | let _ = fake_anon_field_expr!(); | ----------------------- in this macro invocation -error: aborting due to previous error(s) +error: aborting due to 6 previous errors diff --git a/src/test/ui/macros/macro-backtrace-nested.stderr b/src/test/ui/macros/macro-backtrace-nested.stderr index 7835b85eafc..8b69d112d4d 100644 --- a/src/test/ui/macros/macro-backtrace-nested.stderr +++ b/src/test/ui/macros/macro-backtrace-nested.stderr @@ -16,5 +16,5 @@ error[E0425]: cannot find value `fake` in this scope 28 | call_nested_expr_sum!(); | ------------------------ in this macro invocation -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/macros/macro-backtrace-println.stderr b/src/test/ui/macros/macro-backtrace-println.stderr index 4177240d976..f21253bb67f 100644 --- a/src/test/ui/macros/macro-backtrace-println.stderr +++ b/src/test/ui/macros/macro-backtrace-println.stderr @@ -7,5 +7,5 @@ error: invalid reference to argument `0` (no arguments given) 28 | myprintln!("{}"); | ----------------- in this macro invocation -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/mismatched_types/E0053.stderr b/src/test/ui/mismatched_types/E0053.stderr index 2ba2069677e..d9871b8970c 100644 --- a/src/test/ui/mismatched_types/E0053.stderr +++ b/src/test/ui/mismatched_types/E0053.stderr @@ -22,5 +22,5 @@ error[E0053]: method `bar` has an incompatible type for trait = note: expected type `fn(&Bar)` found type `fn(&mut Bar)` -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/mismatched_types/E0281.stderr b/src/test/ui/mismatched_types/E0281.stderr index 3eb5c125789..8a306ea4192 100644 --- a/src/test/ui/mismatched_types/E0281.stderr +++ b/src/test/ui/mismatched_types/E0281.stderr @@ -9,5 +9,5 @@ error[E0281]: type mismatch: `[closure@$DIR/E0281.rs:14:9: 14:24]` implements th | = note: required by `foo` -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/mismatched_types/E0409.stderr b/src/test/ui/mismatched_types/E0409.stderr index a5f63aca13e..45a42b1c271 100644 --- a/src/test/ui/mismatched_types/E0409.stderr +++ b/src/test/ui/mismatched_types/E0409.stderr @@ -15,5 +15,5 @@ error[E0308]: mismatched types = note: expected type `&{integer}` found type `{integer}` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/mismatched_types/abridged.stderr b/src/test/ui/mismatched_types/abridged.stderr index 8513da1e1d2..d40bc3b3339 100644 --- a/src/test/ui/mismatched_types/abridged.stderr +++ b/src/test/ui/mismatched_types/abridged.stderr @@ -52,5 +52,5 @@ error[E0308]: mismatched types = note: expected type `X, _>` found type `X, _>` -error: aborting due to previous error(s) +error: aborting due to 6 previous errors diff --git a/src/test/ui/mismatched_types/binops.stderr b/src/test/ui/mismatched_types/binops.stderr index cebdc12f568..bb90a19a3ba 100644 --- a/src/test/ui/mismatched_types/binops.stderr +++ b/src/test/ui/mismatched_types/binops.stderr @@ -46,5 +46,5 @@ error[E0277]: the trait bound `{integer}: std::cmp::PartialEq>` is not implemented for `{integer}` -error: aborting due to previous error(s) +error: aborting due to 7 previous errors diff --git a/src/test/ui/mismatched_types/cast-rfc0401.stderr b/src/test/ui/mismatched_types/cast-rfc0401.stderr index 879acbcf9d9..fb363c388b6 100644 --- a/src/test/ui/mismatched_types/cast-rfc0401.stderr +++ b/src/test/ui/mismatched_types/cast-rfc0401.stderr @@ -246,5 +246,5 @@ help: did you mean `*s`? 81 | vec![0.0].iter().map(|s| s as f32).collect::>(); | ^ -error: aborting due to previous error(s) +error: aborting due to 34 previous errors diff --git a/src/test/ui/mismatched_types/closure-arg-count.stderr b/src/test/ui/mismatched_types/closure-arg-count.stderr index 85734dfac70..f2509040b00 100644 --- a/src/test/ui/mismatched_types/closure-arg-count.stderr +++ b/src/test/ui/mismatched_types/closure-arg-count.stderr @@ -31,5 +31,5 @@ error[E0593]: closure takes 1 argument but 2 arguments are required | | | expected closure that takes 2 arguments -error: aborting due to previous error(s) +error: aborting due to 7 previous errors diff --git a/src/test/ui/mismatched_types/closure-mismatch.stderr b/src/test/ui/mismatched_types/closure-mismatch.stderr index 2c9c918168d..5b3eb593189 100644 --- a/src/test/ui/mismatched_types/closure-mismatch.stderr +++ b/src/test/ui/mismatched_types/closure-mismatch.stderr @@ -20,5 +20,5 @@ error[E0281]: type mismatch: `[closure@$DIR/closure-mismatch.rs:18:9: 18:15]` im = note: required because of the requirements on the impl of `Foo` for `[closure@$DIR/closure-mismatch.rs:18:9: 18:15]` = note: required by `baz` -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/mismatched_types/const-fn-in-trait.stderr b/src/test/ui/mismatched_types/const-fn-in-trait.stderr index 5f67a66eb32..f7b7635e41a 100644 --- a/src/test/ui/mismatched_types/const-fn-in-trait.stderr +++ b/src/test/ui/mismatched_types/const-fn-in-trait.stderr @@ -10,5 +10,5 @@ error[E0379]: trait fns cannot be declared const 21 | const fn f() -> u32 { 22 } | ^^^^^ trait fns cannot be const -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/mismatched_types/fn-variance-1.stderr b/src/test/ui/mismatched_types/fn-variance-1.stderr index 2030ad6c13b..120fb87cdc8 100644 --- a/src/test/ui/mismatched_types/fn-variance-1.stderr +++ b/src/test/ui/mismatched_types/fn-variance-1.stderr @@ -14,5 +14,5 @@ error[E0281]: type mismatch: `fn(&isize) {takes_imm}` implements the trait `for< | = note: required by `apply` -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/mismatched_types/issue-19109.stderr b/src/test/ui/mismatched_types/issue-19109.stderr index 083c1f95333..2b4b8242af6 100644 --- a/src/test/ui/mismatched_types/issue-19109.stderr +++ b/src/test/ui/mismatched_types/issue-19109.stderr @@ -9,5 +9,5 @@ error[E0308]: mismatched types = note: expected type `()` found type `*mut Trait` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/mismatched_types/issue-26480.stderr b/src/test/ui/mismatched_types/issue-26480.stderr index 9da9042e78e..fae831ffb86 100644 --- a/src/test/ui/mismatched_types/issue-26480.stderr +++ b/src/test/ui/mismatched_types/issue-26480.stderr @@ -18,5 +18,5 @@ error[E0605]: non-primitive cast: `{integer}` as `()` | = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/mismatched_types/issue-35030.stderr b/src/test/ui/mismatched_types/issue-35030.stderr index 463d9fdf171..46d690c5f03 100644 --- a/src/test/ui/mismatched_types/issue-35030.stderr +++ b/src/test/ui/mismatched_types/issue-35030.stderr @@ -7,5 +7,5 @@ error[E0308]: mismatched types = note: expected type `bool` (type parameter) found type `bool` (bool) -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr index f818bd8bcb1..88309ab146f 100644 --- a/src/test/ui/mismatched_types/issue-36053-2.stderr +++ b/src/test/ui/mismatched_types/issue-36053-2.stderr @@ -17,5 +17,5 @@ error[E0281]: type mismatch: `[closure@$DIR/issue-36053-2.rs:17:39: 17:53]` impl | requires `for<'r> std::ops::FnMut<(&'r &str,)>` | expected &str, found str -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/mismatched_types/issue-38371.stderr b/src/test/ui/mismatched_types/issue-38371.stderr index 76ffa6e50e1..9efee4cc559 100644 --- a/src/test/ui/mismatched_types/issue-38371.stderr +++ b/src/test/ui/mismatched_types/issue-38371.stderr @@ -32,5 +32,5 @@ error[E0529]: expected an array or slice, found `u32` 34 | fn ugh(&[bar]: &u32) { | ^^^^^ pattern cannot match with input type `u32` -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/mismatched_types/main.stderr b/src/test/ui/mismatched_types/main.stderr index b4e688e025e..c8941fbf950 100644 --- a/src/test/ui/mismatched_types/main.stderr +++ b/src/test/ui/mismatched_types/main.stderr @@ -9,5 +9,5 @@ error[E0308]: mismatched types = note: expected type `u32` found type `()` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr index 80f95da0bbe..ab5b3e17915 100644 --- a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr +++ b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr @@ -7,5 +7,5 @@ error[E0599]: no method named `unwrap` found for type `std::result::Result<(), F = note: the method `unwrap` exists but the following trait bounds were not satisfied: `Foo : std::fmt::Debug` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/mismatched_types/overloaded-calls-bad.stderr b/src/test/ui/mismatched_types/overloaded-calls-bad.stderr index 7c644e3a72d..cd05684f15d 100644 --- a/src/test/ui/mismatched_types/overloaded-calls-bad.stderr +++ b/src/test/ui/mismatched_types/overloaded-calls-bad.stderr @@ -19,5 +19,5 @@ error[E0057]: this function takes 1 parameter but 2 parameters were supplied 45 | let ans = s("burma", "shave"); | ^^^^^^^^^^^^^^^^ expected 1 parameter -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/mismatched_types/trait-bounds-cant-coerce.stderr b/src/test/ui/mismatched_types/trait-bounds-cant-coerce.stderr index 9e7f79df35a..ccc9fb56772 100644 --- a/src/test/ui/mismatched_types/trait-bounds-cant-coerce.stderr +++ b/src/test/ui/mismatched_types/trait-bounds-cant-coerce.stderr @@ -7,5 +7,5 @@ error[E0308]: mismatched types = note: expected type `std::boxed::Box` found type `std::boxed::Box` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/mismatched_types/trait-impl-fn-incompatibility.stderr b/src/test/ui/mismatched_types/trait-impl-fn-incompatibility.stderr index 8741589f846..349432f64bb 100644 --- a/src/test/ui/mismatched_types/trait-impl-fn-incompatibility.stderr +++ b/src/test/ui/mismatched_types/trait-impl-fn-incompatibility.stderr @@ -22,5 +22,5 @@ error[E0053]: method `bar` has an incompatible type for trait = note: expected type `fn(&mut Bar, &mut Bar)` found type `fn(&mut Bar, &Bar)` -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr index 643c9b36dbd..4ba6dc73023 100644 --- a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr +++ b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr @@ -12,5 +12,5 @@ error[E0281]: type mismatch: `[closure@$DIR/unboxed-closures-vtable-mismatch.rs: | = note: required by `call_it` -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/missing-items/issue-40221.stderr b/src/test/ui/missing-items/issue-40221.stderr index 87854493790..fc90c8a2b20 100644 --- a/src/test/ui/missing-items/issue-40221.stderr +++ b/src/test/ui/missing-items/issue-40221.stderr @@ -4,5 +4,5 @@ error[E0004]: non-exhaustive patterns: `C(QA)` not covered 21 | match proto { | ^^^^^ pattern `C(QA)` not covered -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/missing-items/m2.stderr b/src/test/ui/missing-items/m2.stderr index 2d699c66359..b7ba5efacc4 100644 --- a/src/test/ui/missing-items/m2.stderr +++ b/src/test/ui/missing-items/m2.stderr @@ -11,5 +11,5 @@ error[E0046]: not all trait items implemented, missing: `CONSTANT`, `Type`, `met = note: `Type` from trait: `type Type;` = note: `method` from trait: `fn(&Self, std::string::String) -> ::Type` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/missing-items/missing-type-parameter.stderr b/src/test/ui/missing-items/missing-type-parameter.stderr index ce38178bf87..a16ae5538bf 100644 --- a/src/test/ui/missing-items/missing-type-parameter.stderr +++ b/src/test/ui/missing-items/missing-type-parameter.stderr @@ -4,5 +4,5 @@ error[E0282]: type annotations needed 14 | foo(); | ^^^ cannot infer type for `X` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/pub/pub-restricted-error-fn.stderr b/src/test/ui/pub/pub-restricted-error-fn.stderr index 94fc8f15c2b..470e8331247 100644 --- a/src/test/ui/pub/pub-restricted-error-fn.stderr +++ b/src/test/ui/pub/pub-restricted-error-fn.stderr @@ -4,5 +4,5 @@ error: unmatched visibility `pub` 13 | pub(crate) () fn foo() {} | ^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/pub/pub-restricted-error.stderr b/src/test/ui/pub/pub-restricted-error.stderr index eebb2428ba3..b8b4c80778d 100644 --- a/src/test/ui/pub/pub-restricted-error.stderr +++ b/src/test/ui/pub/pub-restricted-error.stderr @@ -4,5 +4,5 @@ error: expected identifier, found `(` 16 | pub(crate) () foo: usize, | ^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/pub/pub-restricted-non-path.stderr b/src/test/ui/pub/pub-restricted-non-path.stderr index 865b1d409e1..ebfccc4d720 100644 --- a/src/test/ui/pub/pub-restricted-non-path.stderr +++ b/src/test/ui/pub/pub-restricted-non-path.stderr @@ -4,5 +4,5 @@ error: expected identifier, found `.` 13 | pub (.) fn afn() {} | ^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/pub/pub-restricted.stderr b/src/test/ui/pub/pub-restricted.stderr index 34cc80fcc75..ae283f1fb63 100644 --- a/src/test/ui/pub/pub-restricted.stderr +++ b/src/test/ui/pub/pub-restricted.stderr @@ -48,5 +48,5 @@ error: visibilities can only be restricted to ancestor modules 33 | pub (in x) non_parent_invalid: usize, | ^ -error: aborting due to previous error(s) +error: aborting due to 5 previous errors diff --git a/src/test/ui/reachable/expr_add.stderr b/src/test/ui/reachable/expr_add.stderr index cbcbf88d86e..1a2cc252051 100644 --- a/src/test/ui/reachable/expr_add.stderr +++ b/src/test/ui/reachable/expr_add.stderr @@ -10,5 +10,5 @@ note: lint level defined here 13 | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/reachable/expr_again.stderr b/src/test/ui/reachable/expr_again.stderr index 20640c0a897..bf4e4dc4711 100644 --- a/src/test/ui/reachable/expr_again.stderr +++ b/src/test/ui/reachable/expr_again.stderr @@ -11,5 +11,5 @@ note: lint level defined here | ^^^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/reachable/expr_array.stderr b/src/test/ui/reachable/expr_array.stderr index c778aec0810..f8dbdb5f8bb 100644 --- a/src/test/ui/reachable/expr_array.stderr +++ b/src/test/ui/reachable/expr_array.stderr @@ -16,5 +16,5 @@ error: unreachable expression 25 | let x: [usize; 2] = [22, return]; | ^^^^^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/reachable/expr_assign.stderr b/src/test/ui/reachable/expr_assign.stderr index 9310c000192..807f6a1c1d5 100644 --- a/src/test/ui/reachable/expr_assign.stderr +++ b/src/test/ui/reachable/expr_assign.stderr @@ -22,5 +22,5 @@ error: unreachable expression 36 | *{return; &mut i} = 22; | ^^^^^^ -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/reachable/expr_block.stderr b/src/test/ui/reachable/expr_block.stderr index ea7b962e190..542ce1c3fd9 100644 --- a/src/test/ui/reachable/expr_block.stderr +++ b/src/test/ui/reachable/expr_block.stderr @@ -18,5 +18,5 @@ error: unreachable statement | = note: this error originates in a macro outside of the current crate -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/reachable/expr_box.stderr b/src/test/ui/reachable/expr_box.stderr index ee89104df9e..78ba231cef9 100644 --- a/src/test/ui/reachable/expr_box.stderr +++ b/src/test/ui/reachable/expr_box.stderr @@ -10,5 +10,5 @@ note: lint level defined here 13 | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/reachable/expr_call.stderr b/src/test/ui/reachable/expr_call.stderr index 5e072ed1dc7..5526827f59f 100644 --- a/src/test/ui/reachable/expr_call.stderr +++ b/src/test/ui/reachable/expr_call.stderr @@ -16,5 +16,5 @@ error: unreachable expression 28 | bar(return); | ^^^^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/reachable/expr_cast.stderr b/src/test/ui/reachable/expr_cast.stderr index a8668dc7355..a22300dcc13 100644 --- a/src/test/ui/reachable/expr_cast.stderr +++ b/src/test/ui/reachable/expr_cast.stderr @@ -10,5 +10,5 @@ note: lint level defined here 14 | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/reachable/expr_if.stderr b/src/test/ui/reachable/expr_if.stderr index 7f901511f72..2cf17474f6e 100644 --- a/src/test/ui/reachable/expr_if.stderr +++ b/src/test/ui/reachable/expr_if.stderr @@ -11,5 +11,5 @@ note: lint level defined here | ^^^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/reachable/expr_loop.stderr b/src/test/ui/reachable/expr_loop.stderr index 4fb6392f405..6e98e754c54 100644 --- a/src/test/ui/reachable/expr_loop.stderr +++ b/src/test/ui/reachable/expr_loop.stderr @@ -27,5 +27,5 @@ error: unreachable statement | = note: this error originates in a macro outside of the current crate -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/reachable/expr_match.stderr b/src/test/ui/reachable/expr_match.stderr index 387f7900f49..f5857a5b345 100644 --- a/src/test/ui/reachable/expr_match.stderr +++ b/src/test/ui/reachable/expr_match.stderr @@ -26,5 +26,5 @@ error: unreachable statement | = note: this error originates in a macro outside of the current crate -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/reachable/expr_method.stderr b/src/test/ui/reachable/expr_method.stderr index 68fd4973414..177d4352a37 100644 --- a/src/test/ui/reachable/expr_method.stderr +++ b/src/test/ui/reachable/expr_method.stderr @@ -16,5 +16,5 @@ error: unreachable expression 31 | Foo.bar(return); | ^^^^^^^^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/reachable/expr_repeat.stderr b/src/test/ui/reachable/expr_repeat.stderr index 01b2e1009ee..19afc5dd7b5 100644 --- a/src/test/ui/reachable/expr_repeat.stderr +++ b/src/test/ui/reachable/expr_repeat.stderr @@ -10,5 +10,5 @@ note: lint level defined here 14 | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/reachable/expr_return.stderr b/src/test/ui/reachable/expr_return.stderr index ee958aa9089..3eb70a4dd7c 100644 --- a/src/test/ui/reachable/expr_return.stderr +++ b/src/test/ui/reachable/expr_return.stderr @@ -10,5 +10,5 @@ note: lint level defined here 14 | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/reachable/expr_struct.stderr b/src/test/ui/reachable/expr_struct.stderr index 08866bf32b8..4b7ac660413 100644 --- a/src/test/ui/reachable/expr_struct.stderr +++ b/src/test/ui/reachable/expr_struct.stderr @@ -28,5 +28,5 @@ error: unreachable expression 40 | let x = Foo { a: 22, b: return }; | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/reachable/expr_tup.stderr b/src/test/ui/reachable/expr_tup.stderr index 780fb02f790..63f477fd0c3 100644 --- a/src/test/ui/reachable/expr_tup.stderr +++ b/src/test/ui/reachable/expr_tup.stderr @@ -16,5 +16,5 @@ error: unreachable expression 25 | let x: (usize, usize) = (2, return); | ^^^^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/reachable/expr_type.stderr b/src/test/ui/reachable/expr_type.stderr index 1216ec2676e..6ed79974ccb 100644 --- a/src/test/ui/reachable/expr_type.stderr +++ b/src/test/ui/reachable/expr_type.stderr @@ -10,5 +10,5 @@ note: lint level defined here 14 | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/reachable/expr_unary.stderr b/src/test/ui/reachable/expr_unary.stderr index f47791455af..328b75fd236 100644 --- a/src/test/ui/reachable/expr_unary.stderr +++ b/src/test/ui/reachable/expr_unary.stderr @@ -4,5 +4,5 @@ error[E0600]: cannot apply unary operator `!` to type `!` 18 | let x: ! = ! { return; 22 }; | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/reachable/expr_while.stderr b/src/test/ui/reachable/expr_while.stderr index 3da057f4bbd..066cfc86c64 100644 --- a/src/test/ui/reachable/expr_while.stderr +++ b/src/test/ui/reachable/expr_while.stderr @@ -27,5 +27,5 @@ error: unreachable statement | = note: this error originates in a macro outside of the current crate -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/regions-fn-subtyping-return-static.stderr b/src/test/ui/regions-fn-subtyping-return-static.stderr index 121a50d0eda..0c7b44af949 100644 --- a/src/test/ui/regions-fn-subtyping-return-static.stderr +++ b/src/test/ui/regions-fn-subtyping-return-static.stderr @@ -9,5 +9,5 @@ error[E0308]: mismatched types = note: lifetime parameter `'b` declared on fn `bar` appears only in the return type, but here is required to be higher-ranked, which means that `'b` must appear in both argument and return types = note: this error is the result of a recent bug fix; for more information, see issue #33685 -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/resolve/enums-are-namespaced-xc.stderr b/src/test/ui/resolve/enums-are-namespaced-xc.stderr index 03e80046f67..17c5d5d15d4 100644 --- a/src/test/ui/resolve/enums-are-namespaced-xc.stderr +++ b/src/test/ui/resolve/enums-are-namespaced-xc.stderr @@ -25,5 +25,5 @@ error[E0422]: cannot find struct, variant or union type `C` in module `namespace help: possible candidate is found in another module, you can import it into scope | use namespaced_enums::Foo::C; -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/resolve/issue-14254.stderr b/src/test/ui/resolve/issue-14254.stderr index 009d969fc28..11268e593c4 100644 --- a/src/test/ui/resolve/issue-14254.stderr +++ b/src/test/ui/resolve/issue-14254.stderr @@ -144,5 +144,5 @@ error[E0425]: cannot find value `bah` in this scope error[E0601]: main function not found -error: aborting due to previous error(s) +error: aborting due to 25 previous errors diff --git a/src/test/ui/resolve/issue-16058.stderr b/src/test/ui/resolve/issue-16058.stderr index 2fbf7d7185d..63d2ce10914 100644 --- a/src/test/ui/resolve/issue-16058.stderr +++ b/src/test/ui/resolve/issue-16058.stderr @@ -9,5 +9,5 @@ help: possible better candidates are found in other modules, you can import them | use std::io::Result; | use std::thread::Result; -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/resolve/issue-17518.stderr b/src/test/ui/resolve/issue-17518.stderr index 69eeb178dff..c0438abfe43 100644 --- a/src/test/ui/resolve/issue-17518.stderr +++ b/src/test/ui/resolve/issue-17518.stderr @@ -7,5 +7,5 @@ error[E0422]: cannot find struct, variant or union type `E` in this scope help: possible candidate is found in another module, you can import it into scope | use SomeEnum::E; -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/resolve/issue-18252.stderr b/src/test/ui/resolve/issue-18252.stderr index 225e31010da..edc7196d846 100644 --- a/src/test/ui/resolve/issue-18252.stderr +++ b/src/test/ui/resolve/issue-18252.stderr @@ -4,5 +4,5 @@ error[E0423]: expected function, found struct variant `Foo::Variant` 16 | let f = Foo::Variant(42); | ^^^^^^^^^^^^ did you mean `Foo::Variant { /* fields */ }`? -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/resolve/issue-19452.stderr b/src/test/ui/resolve/issue-19452.stderr index 25ee3a02146..7b14d49af51 100644 --- a/src/test/ui/resolve/issue-19452.stderr +++ b/src/test/ui/resolve/issue-19452.stderr @@ -10,5 +10,5 @@ error[E0423]: expected value, found struct variant `issue_19452_aux::Homura::Mad 22 | let homura = issue_19452_aux::Homura::Madoka; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ did you mean `issue_19452_aux::Homura::Madoka { /* fields */ }`? -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/resolve/issue-23305.stderr b/src/test/ui/resolve/issue-23305.stderr index 2ca541c161b..fda87de9b9c 100644 --- a/src/test/ui/resolve/issue-23305.stderr +++ b/src/test/ui/resolve/issue-23305.stderr @@ -11,5 +11,5 @@ note: the cycle begins when processing ``, completing the cycle. -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/resolve/issue-2356.stderr b/src/test/ui/resolve/issue-2356.stderr index 559598dd38a..039887d8da6 100644 --- a/src/test/ui/resolve/issue-2356.stderr +++ b/src/test/ui/resolve/issue-2356.stderr @@ -106,5 +106,5 @@ error[E0424]: expected value, found module `self` 122 | self += 1; | ^^^^ `self` value is only available in methods with `self` parameter -error: aborting due to previous error(s) +error: aborting due to 17 previous errors diff --git a/src/test/ui/resolve/issue-24968.stderr b/src/test/ui/resolve/issue-24968.stderr index 14a2413feee..111710d515a 100644 --- a/src/test/ui/resolve/issue-24968.stderr +++ b/src/test/ui/resolve/issue-24968.stderr @@ -4,5 +4,5 @@ error[E0411]: cannot find type `Self` in this scope 11 | fn foo(_: Self) { | ^^^^ `Self` is only available in traits and impls -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/resolve/issue-33876.stderr b/src/test/ui/resolve/issue-33876.stderr index a950075715a..5dbecc4f0c5 100644 --- a/src/test/ui/resolve/issue-33876.stderr +++ b/src/test/ui/resolve/issue-33876.stderr @@ -4,5 +4,5 @@ error[E0423]: expected value, found trait `Bar` 20 | let any: &Any = &Bar; //~ ERROR expected value, found trait `Bar` | ^^^ not a value -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/resolve/issue-3907-2.stderr b/src/test/ui/resolve/issue-3907-2.stderr index 4e1ef25f803..2ef8c830eb2 100644 --- a/src/test/ui/resolve/issue-3907-2.stderr +++ b/src/test/ui/resolve/issue-3907-2.stderr @@ -6,5 +6,5 @@ error[E0038]: the trait `issue_3907::Foo` cannot be made into an object | = note: method `bar` has no receiver -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/resolve/issue-39226.stderr b/src/test/ui/resolve/issue-39226.stderr index 134a4540a8d..f6ee0b025bb 100644 --- a/src/test/ui/resolve/issue-39226.stderr +++ b/src/test/ui/resolve/issue-39226.stderr @@ -7,5 +7,5 @@ error[E0423]: expected value, found struct `Handle` | did you mean `handle`? | did you mean `Handle { /* fields */ }`? -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/resolve/issue-5035-2.stderr b/src/test/ui/resolve/issue-5035-2.stderr index 9bdd7ee4fd4..791b20725f3 100644 --- a/src/test/ui/resolve/issue-5035-2.stderr +++ b/src/test/ui/resolve/issue-5035-2.stderr @@ -7,5 +7,5 @@ error[E0277]: the trait bound `I + 'static: std::marker::Sized` is not satisfied = help: the trait `std::marker::Sized` is not implemented for `I + 'static` = note: all local variables must have a statically known size -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/resolve/issue-6702.stderr b/src/test/ui/resolve/issue-6702.stderr index 620958190ca..b50295752f2 100644 --- a/src/test/ui/resolve/issue-6702.stderr +++ b/src/test/ui/resolve/issue-6702.stderr @@ -4,5 +4,5 @@ error[E0423]: expected function, found struct `Monster` 17 | let _m = Monster(); //~ ERROR expected function, found struct `Monster` | ^^^^^^^ did you mean `Monster { /* fields */ }`? -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/resolve/levenshtein.stderr b/src/test/ui/resolve/levenshtein.stderr index d25c52eeab3..4dff2620319 100644 --- a/src/test/ui/resolve/levenshtein.stderr +++ b/src/test/ui/resolve/levenshtein.stderr @@ -46,5 +46,5 @@ error[E0425]: cannot find value `second` in module `m` 32 | let b: m::first = m::second; // Misspelled item in module. | ^^^^^^ did you mean `Second`? -error: aborting due to previous error(s) +error: aborting due to 8 previous errors diff --git a/src/test/ui/resolve/privacy-struct-ctor.stderr b/src/test/ui/resolve/privacy-struct-ctor.stderr index a1ec5f0b713..18efb17dd46 100644 --- a/src/test/ui/resolve/privacy-struct-ctor.stderr +++ b/src/test/ui/resolve/privacy-struct-ctor.stderr @@ -65,5 +65,5 @@ error[E0603]: tuple struct `Z` is private 45 | xcrate::m::n::Z; //~ ERROR tuple struct `Z` is private | ^^^^^^^^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to 8 previous errors diff --git a/src/test/ui/resolve/resolve-assoc-suggestions.stderr b/src/test/ui/resolve/resolve-assoc-suggestions.stderr index c346612a68b..7975c168de7 100644 --- a/src/test/ui/resolve/resolve-assoc-suggestions.stderr +++ b/src/test/ui/resolve/resolve-assoc-suggestions.stderr @@ -52,5 +52,5 @@ error[E0425]: cannot find value `method` in this scope 52 | method; | ^^^^^^ did you mean `self.method(...)`? -error: aborting due to previous error(s) +error: aborting due to 9 previous errors diff --git a/src/test/ui/resolve/resolve-hint-macro.stderr b/src/test/ui/resolve/resolve-hint-macro.stderr index 92f13f705b0..ffb3f848430 100644 --- a/src/test/ui/resolve/resolve-hint-macro.stderr +++ b/src/test/ui/resolve/resolve-hint-macro.stderr @@ -4,5 +4,5 @@ error[E0423]: expected function, found macro `assert` 12 | assert(true); | ^^^^^^ did you mean `assert!(...)`? -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/resolve/resolve-speculative-adjustment.stderr b/src/test/ui/resolve/resolve-speculative-adjustment.stderr index 04c8087ace9..e7df8140bc5 100644 --- a/src/test/ui/resolve/resolve-speculative-adjustment.stderr +++ b/src/test/ui/resolve/resolve-speculative-adjustment.stderr @@ -22,5 +22,5 @@ error[E0425]: cannot find function `method` in this scope 38 | method(); | ^^^^^^ did you mean `self.method(...)`? -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr b/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr index a34c27a47da..d1794d19f6a 100644 --- a/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr +++ b/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr @@ -74,5 +74,5 @@ error[E0423]: expected function, found module `a::b` error[E0601]: main function not found -error: aborting due to previous error(s) +error: aborting due to 10 previous errors diff --git a/src/test/ui/resolve/token-error-correct-2.stderr b/src/test/ui/resolve/token-error-correct-2.stderr index 7307f19c74d..feb12612e66 100644 --- a/src/test/ui/resolve/token-error-correct-2.stderr +++ b/src/test/ui/resolve/token-error-correct-2.stderr @@ -16,5 +16,5 @@ error[E0425]: cannot find value `foo` in this scope 14 | if foo { | ^^^ not found in this scope -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/resolve/token-error-correct-3.stderr b/src/test/ui/resolve/token-error-correct-3.stderr index 53e9cb21778..4384822f404 100644 --- a/src/test/ui/resolve/token-error-correct-3.stderr +++ b/src/test/ui/resolve/token-error-correct-3.stderr @@ -42,5 +42,5 @@ error[E0308]: mismatched types = note: expected type `()` found type `std::result::Result` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/resolve/token-error-correct.stderr b/src/test/ui/resolve/token-error-correct.stderr index 1dd263affd4..226fa6469bc 100644 --- a/src/test/ui/resolve/token-error-correct.stderr +++ b/src/test/ui/resolve/token-error-correct.stderr @@ -52,5 +52,5 @@ error[E0425]: cannot find function `bar` in this scope 14 | foo(bar(; | ^^^ not found in this scope -error: aborting due to previous error(s) +error: aborting due to 7 previous errors diff --git a/src/test/ui/resolve/tuple-struct-alias.stderr b/src/test/ui/resolve/tuple-struct-alias.stderr index 2fc5979a606..e2ef8f0e568 100644 --- a/src/test/ui/resolve/tuple-struct-alias.stderr +++ b/src/test/ui/resolve/tuple-struct-alias.stderr @@ -28,5 +28,5 @@ error[E0532]: expected tuple struct/variant, found type alias `A` | did you mean `S`? | did you mean `A { /* fields */ }`? -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/resolve/unresolved_static_type_field.stderr b/src/test/ui/resolve/unresolved_static_type_field.stderr index ff6bcf2a532..5fbaf66e014 100644 --- a/src/test/ui/resolve/unresolved_static_type_field.stderr +++ b/src/test/ui/resolve/unresolved_static_type_field.stderr @@ -7,5 +7,5 @@ error[E0425]: cannot find value `cx` in this scope | did you mean `self.cx`? | `self` value is only available in methods with `self` parameter -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/E0046.stderr b/src/test/ui/span/E0046.stderr index f722908ec10..729a5156124 100644 --- a/src/test/ui/span/E0046.stderr +++ b/src/test/ui/span/E0046.stderr @@ -7,5 +7,5 @@ error[E0046]: not all trait items implemented, missing: `foo` 18 | impl Foo for Bar {} | ^^^^^^^^^^^^^^^^^^^ missing `foo` in implementation -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/E0057.stderr b/src/test/ui/span/E0057.stderr index bc3a3908dca..0d6b0a552e4 100644 --- a/src/test/ui/span/E0057.stderr +++ b/src/test/ui/span/E0057.stderr @@ -10,5 +10,5 @@ error[E0057]: this function takes 1 parameter but 2 parameters were supplied 15 | let c = f(2, 3); //~ ERROR E0057 | ^^^^ expected 1 parameter -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/E0072.stderr b/src/test/ui/span/E0072.stderr index 14e6bcb73b0..1f6dd6b1d16 100644 --- a/src/test/ui/span/E0072.stderr +++ b/src/test/ui/span/E0072.stderr @@ -9,5 +9,5 @@ error[E0072]: recursive type `ListNode` has infinite size | = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `ListNode` representable -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/E0204.stderr b/src/test/ui/span/E0204.stderr index fab2436922d..4fe6afaca8e 100644 --- a/src/test/ui/span/E0204.stderr +++ b/src/test/ui/span/E0204.stderr @@ -34,5 +34,5 @@ error[E0204]: the trait `Copy` may not be implemented for this type 31 | Bar(&'a mut bool), | ------------- this field does not implement `Copy` -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/span/E0493.stderr b/src/test/ui/span/E0493.stderr index 5f8b57294d5..afcc9a240eb 100644 --- a/src/test/ui/span/E0493.stderr +++ b/src/test/ui/span/E0493.stderr @@ -7,5 +7,5 @@ error[E0493]: constants are not allowed to have destructors 27 | const F : Foo = Foo { a : 0 }; | ^^^^^^^^^^^^^ constants cannot have destructors -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/E0535.stderr b/src/test/ui/span/E0535.stderr index 64c0016085f..23070e1555b 100644 --- a/src/test/ui/span/E0535.stderr +++ b/src/test/ui/span/E0535.stderr @@ -4,5 +4,5 @@ error[E0535]: invalid argument 11 | #[inline(unknown)] //~ ERROR E0535 | ^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/E0536.stderr b/src/test/ui/span/E0536.stderr index 8a4cf34e565..b2da0c6a296 100644 --- a/src/test/ui/span/E0536.stderr +++ b/src/test/ui/span/E0536.stderr @@ -4,5 +4,5 @@ error[E0536]: expected 1 cfg-pattern 11 | #[cfg(not())] //~ ERROR E0536 | ^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/E0537.stderr b/src/test/ui/span/E0537.stderr index 1bd54a6a007..29873943f44 100644 --- a/src/test/ui/span/E0537.stderr +++ b/src/test/ui/span/E0537.stderr @@ -4,5 +4,5 @@ error[E0537]: invalid predicate `unknown` 11 | #[cfg(unknown())] //~ ERROR E0537 | ^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr b/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr index 4b01f5bea7c..2d580e7c20e 100644 --- a/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr +++ b/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr @@ -82,5 +82,5 @@ error[E0596]: cannot borrow immutable borrowed content `*x` as mutable 143 | *x.y_mut() = 3; //~ ERROR cannot borrow | ^ cannot borrow as mutable -error: aborting due to previous error(s) +error: aborting due to 10 previous errors diff --git a/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.stderr b/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.stderr index 886cc142039..3d380a9a2e8 100644 --- a/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.stderr +++ b/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.stderr @@ -30,5 +30,5 @@ error[E0596]: cannot borrow immutable borrowed content `*x` as mutable 63 | **x = 3; //~ ERROR cannot borrow | ^^ cannot borrow as mutable -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr index a26ca490dd5..6e7d0c17f1d 100644 --- a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr +++ b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr @@ -47,5 +47,5 @@ error[E0507]: cannot move out of captured outer variable in an `FnMut` closure 72 | foo(f); | ^ cannot move out of captured outer variable in an `FnMut` closure -error: aborting due to previous error(s) +error: aborting due to 5 previous errors diff --git a/src/test/ui/span/borrowck-call-method-from-mut-aliasable.stderr b/src/test/ui/span/borrowck-call-method-from-mut-aliasable.stderr index dea95d6bf6d..a57cc94b9ba 100644 --- a/src/test/ui/span/borrowck-call-method-from-mut-aliasable.stderr +++ b/src/test/ui/span/borrowck-call-method-from-mut-aliasable.stderr @@ -7,5 +7,5 @@ error[E0596]: cannot borrow immutable borrowed content `*x` as mutable 27 | x.h(); //~ ERROR cannot borrow | ^ cannot borrow as mutable -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/borrowck-fn-in-const-b.stderr b/src/test/ui/span/borrowck-fn-in-const-b.stderr index 3bf56881c54..45712d1a710 100644 --- a/src/test/ui/span/borrowck-fn-in-const-b.stderr +++ b/src/test/ui/span/borrowck-fn-in-const-b.stderr @@ -6,5 +6,5 @@ error[E0596]: cannot borrow immutable borrowed content `*x` as mutable 17 | x.push(format!("this is broken")); | ^ cannot borrow as mutable -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/borrowck-let-suggestion-suffixes.stderr b/src/test/ui/span/borrowck-let-suggestion-suffixes.stderr index 04dbcd2ef49..6ed1b7c2622 100644 --- a/src/test/ui/span/borrowck-let-suggestion-suffixes.stderr +++ b/src/test/ui/span/borrowck-let-suggestion-suffixes.stderr @@ -48,5 +48,5 @@ error[E0597]: borrowed value does not live long enough | = note: consider using a `let` binding to increase its lifetime -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/span/borrowck-object-mutability.stderr b/src/test/ui/span/borrowck-object-mutability.stderr index 877b17dc27d..530993f399a 100644 --- a/src/test/ui/span/borrowck-object-mutability.stderr +++ b/src/test/ui/span/borrowck-object-mutability.stderr @@ -16,5 +16,5 @@ error[E0596]: cannot borrow immutable `Box` content `*x` as mutable 29 | x.borrowed_mut(); //~ ERROR cannot borrow | ^ cannot borrow as mutable -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/borrowck-ref-into-rvalue.stderr b/src/test/ui/span/borrowck-ref-into-rvalue.stderr index e0a484bcb37..ced1f762af4 100644 --- a/src/test/ui/span/borrowck-ref-into-rvalue.stderr +++ b/src/test/ui/span/borrowck-ref-into-rvalue.stderr @@ -12,5 +12,5 @@ error[E0597]: borrowed value does not live long enough | = note: consider using a `let` binding to increase its lifetime -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/coerce-suggestions.stderr b/src/test/ui/span/coerce-suggestions.stderr index e3bc64a2cfd..b703632bf90 100644 --- a/src/test/ui/span/coerce-suggestions.stderr +++ b/src/test/ui/span/coerce-suggestions.stderr @@ -58,5 +58,5 @@ error[E0308]: mismatched types = help: try with `&mut format!("foo")` = note: this error originates in a macro outside of the current crate -error: aborting due to previous error(s) +error: aborting due to 6 previous errors diff --git a/src/test/ui/span/destructor-restrictions.stderr b/src/test/ui/span/destructor-restrictions.stderr index 1472a364863..ee885454169 100644 --- a/src/test/ui/span/destructor-restrictions.stderr +++ b/src/test/ui/span/destructor-restrictions.stderr @@ -8,5 +8,5 @@ error[E0597]: `*a` does not live long enough | | | `*a` dropped here while still borrowed -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/dropck-object-cycle.stderr b/src/test/ui/span/dropck-object-cycle.stderr index d0fceb2a03e..49115b244e6 100644 --- a/src/test/ui/span/dropck-object-cycle.stderr +++ b/src/test/ui/span/dropck-object-cycle.stderr @@ -9,5 +9,5 @@ error[E0597]: `*m` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/dropck_arr_cycle_checked.stderr b/src/test/ui/span/dropck_arr_cycle_checked.stderr index 2a9c2c8413f..4179ac1a946 100644 --- a/src/test/ui/span/dropck_arr_cycle_checked.stderr +++ b/src/test/ui/span/dropck_arr_cycle_checked.stderr @@ -63,5 +63,5 @@ error[E0597]: `b2` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to 6 previous errors diff --git a/src/test/ui/span/dropck_direct_cycle_with_drop.stderr b/src/test/ui/span/dropck_direct_cycle_with_drop.stderr index e6421cd4785..597d42aabd2 100644 --- a/src/test/ui/span/dropck_direct_cycle_with_drop.stderr +++ b/src/test/ui/span/dropck_direct_cycle_with_drop.stderr @@ -19,5 +19,5 @@ error[E0597]: `d1` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/dropck_misc_variants.stderr b/src/test/ui/span/dropck_misc_variants.stderr index 7fbdcba7eb6..958f229f659 100644 --- a/src/test/ui/span/dropck_misc_variants.stderr +++ b/src/test/ui/span/dropck_misc_variants.stderr @@ -19,5 +19,5 @@ error[E0597]: `v` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/dropck_vec_cycle_checked.stderr b/src/test/ui/span/dropck_vec_cycle_checked.stderr index 3861b145c1b..d7d0fe5323b 100644 --- a/src/test/ui/span/dropck_vec_cycle_checked.stderr +++ b/src/test/ui/span/dropck_vec_cycle_checked.stderr @@ -63,5 +63,5 @@ error[E0597]: `c2` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to 6 previous errors diff --git a/src/test/ui/span/impl-wrong-item-for-trait.stderr b/src/test/ui/span/impl-wrong-item-for-trait.stderr index ca7286f5027..ae290b3b11a 100644 --- a/src/test/ui/span/impl-wrong-item-for-trait.stderr +++ b/src/test/ui/span/impl-wrong-item-for-trait.stderr @@ -85,5 +85,5 @@ error[E0046]: not all trait items implemented, missing: `fmt` | = note: `fmt` from trait: `fn(&Self, &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error>` -error: aborting due to previous error(s) +error: aborting due to 7 previous errors diff --git a/src/test/ui/span/issue-11925.stderr b/src/test/ui/span/issue-11925.stderr index 67d60fe085a..6b2942bc7a8 100644 --- a/src/test/ui/span/issue-11925.stderr +++ b/src/test/ui/span/issue-11925.stderr @@ -10,5 +10,5 @@ error[E0597]: `x` does not live long enough 23 | } | - borrowed value needs to live until here -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/issue-15480.stderr b/src/test/ui/span/issue-15480.stderr index f5f987c823f..ce1c6e81b96 100644 --- a/src/test/ui/span/issue-15480.stderr +++ b/src/test/ui/span/issue-15480.stderr @@ -11,5 +11,5 @@ error[E0597]: borrowed value does not live long enough | = note: consider using a `let` binding to increase its lifetime -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.stderr b/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.stderr index e564b7ccef2..02c03315372 100644 --- a/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.stderr +++ b/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.stderr @@ -18,5 +18,5 @@ error[E0597]: `y` does not live long enough | | | `y` dropped here while still borrowed -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/issue-23729.stderr b/src/test/ui/span/issue-23729.stderr index d6aed36c8f6..d9f4bacce35 100644 --- a/src/test/ui/span/issue-23729.stderr +++ b/src/test/ui/span/issue-23729.stderr @@ -12,5 +12,5 @@ error[E0046]: not all trait items implemented, missing: `Item` | = note: `Item` from trait: `type Item;` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/issue-23827.stderr b/src/test/ui/span/issue-23827.stderr index a1d3f5c11df..3127af157a6 100644 --- a/src/test/ui/span/issue-23827.stderr +++ b/src/test/ui/span/issue-23827.stderr @@ -12,5 +12,5 @@ error[E0046]: not all trait items implemented, missing: `Output` | = note: `Output` from trait: `type Output;` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/issue-24356.stderr b/src/test/ui/span/issue-24356.stderr index 771ea787304..71ab82d98b8 100644 --- a/src/test/ui/span/issue-24356.stderr +++ b/src/test/ui/span/issue-24356.stderr @@ -11,5 +11,5 @@ error[E0046]: not all trait items implemented, missing: `Target` | = note: `Target` from trait: `type Target;` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/issue-24690.stderr b/src/test/ui/span/issue-24690.stderr index edc150f65ea..8332ba50a73 100644 --- a/src/test/ui/span/issue-24690.stderr +++ b/src/test/ui/span/issue-24690.stderr @@ -30,5 +30,5 @@ note: lint level defined here | ^^^^^^^^ = note: #[deny(unused_variables)] implied by #[deny(warnings)] -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/span/issue-24805-dropck-child-has-items-via-parent.stderr b/src/test/ui/span/issue-24805-dropck-child-has-items-via-parent.stderr index 314ef0ecbbc..29587b7fbde 100644 --- a/src/test/ui/span/issue-24805-dropck-child-has-items-via-parent.stderr +++ b/src/test/ui/span/issue-24805-dropck-child-has-items-via-parent.stderr @@ -9,5 +9,5 @@ error[E0597]: `d1` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/issue-24805-dropck-trait-has-items.stderr b/src/test/ui/span/issue-24805-dropck-trait-has-items.stderr index 66f22d14578..c88d4a0202f 100644 --- a/src/test/ui/span/issue-24805-dropck-trait-has-items.stderr +++ b/src/test/ui/span/issue-24805-dropck-trait-has-items.stderr @@ -28,5 +28,5 @@ error[E0597]: `d1` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/span/issue-24895-copy-clone-dropck.stderr b/src/test/ui/span/issue-24895-copy-clone-dropck.stderr index cfa8359088a..7f80e6e115a 100644 --- a/src/test/ui/span/issue-24895-copy-clone-dropck.stderr +++ b/src/test/ui/span/issue-24895-copy-clone-dropck.stderr @@ -8,5 +8,5 @@ error[E0597]: `d1` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/issue-25199.stderr b/src/test/ui/span/issue-25199.stderr index 999871db093..4f403b38f5a 100644 --- a/src/test/ui/span/issue-25199.stderr +++ b/src/test/ui/span/issue-25199.stderr @@ -19,5 +19,5 @@ error[E0597]: `container` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/issue-26656.stderr b/src/test/ui/span/issue-26656.stderr index b4f0195f6a8..748fcae48fc 100644 --- a/src/test/ui/span/issue-26656.stderr +++ b/src/test/ui/span/issue-26656.stderr @@ -8,5 +8,5 @@ error[E0597]: `ticking` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/issue-27522.stderr b/src/test/ui/span/issue-27522.stderr index 443595c6d2c..117b109780b 100644 --- a/src/test/ui/span/issue-27522.stderr +++ b/src/test/ui/span/issue-27522.stderr @@ -7,5 +7,5 @@ error[E0308]: mismatched method receiver = note: expected type `&Self` found type `&SomeType` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/issue-29106.stderr b/src/test/ui/span/issue-29106.stderr index b645cbf402d..f146028c2fc 100644 --- a/src/test/ui/span/issue-29106.stderr +++ b/src/test/ui/span/issue-29106.stderr @@ -18,5 +18,5 @@ error[E0597]: `x` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/issue-29595.stderr b/src/test/ui/span/issue-29595.stderr index 4065c4fb857..abbac245f89 100644 --- a/src/test/ui/span/issue-29595.stderr +++ b/src/test/ui/span/issue-29595.stderr @@ -6,5 +6,5 @@ error[E0277]: the trait bound `u8: Tr` is not satisfied | = note: required by `Tr::C` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/issue-33884.stderr b/src/test/ui/span/issue-33884.stderr index 38256ec944b..2a874181c7a 100644 --- a/src/test/ui/span/issue-33884.stderr +++ b/src/test/ui/span/issue-33884.stderr @@ -8,5 +8,5 @@ error[E0308]: mismatched types found type `std::string::String` = note: this error originates in a macro outside of the current crate -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/issue-34264.stderr b/src/test/ui/span/issue-34264.stderr index 48ed0b4ac89..98183e2f082 100644 --- a/src/test/ui/span/issue-34264.stderr +++ b/src/test/ui/span/issue-34264.stderr @@ -45,5 +45,5 @@ error[E0061]: this function takes 2 parameters but 3 parameters were supplied 19 | bar(1, 2, 3); | ^^^^^^^ expected 2 parameters -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/span/issue-36530.stderr b/src/test/ui/span/issue-36530.stderr index 5dc9bd8b79b..dc6190c2e76 100644 --- a/src/test/ui/span/issue-36530.stderr +++ b/src/test/ui/span/issue-36530.stderr @@ -14,5 +14,5 @@ error: The attribute `foo` is currently unknown to the compiler and may have mea | = help: add #![feature(custom_attribute)] to the crate attributes to enable -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/issue-36537.stderr b/src/test/ui/span/issue-36537.stderr index df06cd1d0ea..803e476b749 100644 --- a/src/test/ui/span/issue-36537.stderr +++ b/src/test/ui/span/issue-36537.stderr @@ -8,5 +8,5 @@ error[E0597]: `a` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/issue-37767.stderr b/src/test/ui/span/issue-37767.stderr index bd271641e7e..7cf74eaab8d 100644 --- a/src/test/ui/span/issue-37767.stderr +++ b/src/test/ui/span/issue-37767.stderr @@ -55,5 +55,5 @@ note: candidate #2 is defined in the trait `F` | ^^^^^^^^^^^^^^^ = help: to disambiguate the method call, write `F::foo(a)` instead -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/span/issue-39018.stderr b/src/test/ui/span/issue-39018.stderr index f0b940cdf3f..cd3a41b037c 100644 --- a/src/test/ui/span/issue-39018.stderr +++ b/src/test/ui/span/issue-39018.stderr @@ -15,5 +15,5 @@ error[E0369]: binary operation `+` cannot be applied to type `World` | = note: an implementation of `std::ops::Add` might be missing for `World` -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/issue-39698.stderr b/src/test/ui/span/issue-39698.stderr index 0d0a07629c4..97d802f8398 100644 --- a/src/test/ui/span/issue-39698.stderr +++ b/src/test/ui/span/issue-39698.stderr @@ -38,5 +38,5 @@ error[E0408]: variable `c` is not bound in all patterns | | pattern doesn't bind `c` | pattern doesn't bind `c` -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/span/issue-40157.stderr b/src/test/ui/span/issue-40157.stderr index 50183aa3bde..b689bef63f1 100644 --- a/src/test/ui/span/issue-40157.stderr +++ b/src/test/ui/span/issue-40157.stderr @@ -10,5 +10,5 @@ error[E0597]: `foo` does not live long enough | = note: this error originates in a macro outside of the current crate -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/issue-7575.stderr b/src/test/ui/span/issue-7575.stderr index 9bf00b1b574..858c099d374 100644 --- a/src/test/ui/span/issue-7575.stderr +++ b/src/test/ui/span/issue-7575.stderr @@ -63,5 +63,5 @@ note: candidate #1 is defined in the trait `ManyImplTrait` = note: the following trait defines an item `is_str`, perhaps you need to implement it: candidate #1: `ManyImplTrait` -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/span/issue28498-reject-ex1.stderr b/src/test/ui/span/issue28498-reject-ex1.stderr index a2ef99f9d76..6beb3109c75 100644 --- a/src/test/ui/span/issue28498-reject-ex1.stderr +++ b/src/test/ui/span/issue28498-reject-ex1.stderr @@ -19,5 +19,5 @@ error[E0597]: `foo.data` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/issue28498-reject-lifetime-param.stderr b/src/test/ui/span/issue28498-reject-lifetime-param.stderr index cb77cd3dc99..358fa9b7c45 100644 --- a/src/test/ui/span/issue28498-reject-lifetime-param.stderr +++ b/src/test/ui/span/issue28498-reject-lifetime-param.stderr @@ -20,5 +20,5 @@ error[E0597]: `first_dropped` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/issue28498-reject-passed-to-fn.stderr b/src/test/ui/span/issue28498-reject-passed-to-fn.stderr index 49116c340ec..0aaf2b27f60 100644 --- a/src/test/ui/span/issue28498-reject-passed-to-fn.stderr +++ b/src/test/ui/span/issue28498-reject-passed-to-fn.stderr @@ -20,5 +20,5 @@ error[E0597]: `first_dropped` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/issue28498-reject-trait-bound.stderr b/src/test/ui/span/issue28498-reject-trait-bound.stderr index bb4de82422a..27a4d2384ab 100644 --- a/src/test/ui/span/issue28498-reject-trait-bound.stderr +++ b/src/test/ui/span/issue28498-reject-trait-bound.stderr @@ -20,5 +20,5 @@ error[E0597]: `first_dropped` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/lint-unused-unsafe.stderr b/src/test/ui/span/lint-unused-unsafe.stderr index 2f5e60a1b3c..f4998e08907 100644 --- a/src/test/ui/span/lint-unused-unsafe.stderr +++ b/src/test/ui/span/lint-unused-unsafe.stderr @@ -106,5 +106,5 @@ note: because it's nested under this `unsafe` fn 44 | | } | |_^ -error: aborting due to previous error(s) +error: aborting due to 8 previous errors diff --git a/src/test/ui/span/loan-extend.stderr b/src/test/ui/span/loan-extend.stderr index 036c4bd6b8d..91bdd8a8cad 100644 --- a/src/test/ui/span/loan-extend.stderr +++ b/src/test/ui/span/loan-extend.stderr @@ -9,5 +9,5 @@ error[E0597]: `short` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/move-closure.stderr b/src/test/ui/span/move-closure.stderr index f76c5b049c4..2294e6476d6 100644 --- a/src/test/ui/span/move-closure.stderr +++ b/src/test/ui/span/move-closure.stderr @@ -7,5 +7,5 @@ error[E0308]: mismatched types = note: expected type `()` found type `[closure@$DIR/move-closure.rs:15:17: 15:27]` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/multiline-span-E0072.stderr b/src/test/ui/span/multiline-span-E0072.stderr index 881c2f5df45..a06cbd04deb 100644 --- a/src/test/ui/span/multiline-span-E0072.stderr +++ b/src/test/ui/span/multiline-span-E0072.stderr @@ -12,5 +12,5 @@ error[E0072]: recursive type `ListNode` has infinite size | = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `ListNode` representable -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/multiline-span-simple.stderr b/src/test/ui/span/multiline-span-simple.stderr index 0224cef8da1..3915f1b655c 100644 --- a/src/test/ui/span/multiline-span-simple.stderr +++ b/src/test/ui/span/multiline-span-simple.stderr @@ -6,5 +6,5 @@ error[E0277]: the trait bound `u32: std::ops::Add<()>` is not satisfied | = help: the trait `std::ops::Add<()>` is not implemented for `u32` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/mut-arg-hint.stderr b/src/test/ui/span/mut-arg-hint.stderr index 754e96aa808..f8584c67390 100644 --- a/src/test/ui/span/mut-arg-hint.stderr +++ b/src/test/ui/span/mut-arg-hint.stderr @@ -22,5 +22,5 @@ error[E0596]: cannot borrow immutable borrowed content `*a` as mutable 25 | a.push_str("foo"); | ^ cannot borrow as mutable -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/span/mut-ptr-cant-outlive-ref.stderr b/src/test/ui/span/mut-ptr-cant-outlive-ref.stderr index 5bd6a786cfd..007a9fad830 100644 --- a/src/test/ui/span/mut-ptr-cant-outlive-ref.stderr +++ b/src/test/ui/span/mut-ptr-cant-outlive-ref.stderr @@ -8,5 +8,5 @@ error[E0597]: `b` does not live long enough 20 | } | - borrowed value needs to live until here -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/pub-struct-field.stderr b/src/test/ui/span/pub-struct-field.stderr index 835b08f8907..c66361c8546 100644 --- a/src/test/ui/span/pub-struct-field.stderr +++ b/src/test/ui/span/pub-struct-field.stderr @@ -15,5 +15,5 @@ error[E0124]: field `bar` is already declared 17 | pub(crate) bar: u8, | ^^^^^^^^^^^^^^^^^^ field already declared -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/range-2.stderr b/src/test/ui/span/range-2.stderr index 465a663a741..285ab4aee4b 100644 --- a/src/test/ui/span/range-2.stderr +++ b/src/test/ui/span/range-2.stderr @@ -20,5 +20,5 @@ error[E0597]: `b` does not live long enough 21 | } | - borrowed value needs to live until here -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/recursive-type-field.stderr b/src/test/ui/span/recursive-type-field.stderr index 72177754681..b4d0b5a6a25 100644 --- a/src/test/ui/span/recursive-type-field.stderr +++ b/src/test/ui/span/recursive-type-field.stderr @@ -27,5 +27,5 @@ error[E0072]: recursive type `Bar` has infinite size | = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Bar` representable -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/regionck-unboxed-closure-lifetimes.stderr b/src/test/ui/span/regionck-unboxed-closure-lifetimes.stderr index 80dadd97a17..29848412e4e 100644 --- a/src/test/ui/span/regionck-unboxed-closure-lifetimes.stderr +++ b/src/test/ui/span/regionck-unboxed-closure-lifetimes.stderr @@ -9,5 +9,5 @@ error[E0597]: `c` does not live long enough 20 | } | - borrowed value needs to live until here -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.stderr b/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.stderr index 25386cb30b1..e671f1daf61 100644 --- a/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.stderr +++ b/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.stderr @@ -9,5 +9,5 @@ error[E0597]: borrowed value does not live long enough 23 | } | - temporary value needs to live until here -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/regions-close-over-type-parameter-2.stderr b/src/test/ui/span/regions-close-over-type-parameter-2.stderr index 9b5383877a0..a89127b1436 100644 --- a/src/test/ui/span/regions-close-over-type-parameter-2.stderr +++ b/src/test/ui/span/regions-close-over-type-parameter-2.stderr @@ -9,5 +9,5 @@ error[E0597]: `tmp0` does not live long enough | | | `tmp0` dropped here while still borrowed -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/regions-escape-loop-via-variable.stderr b/src/test/ui/span/regions-escape-loop-via-variable.stderr index 9f8c91cb9cd..cfdd1c8b153 100644 --- a/src/test/ui/span/regions-escape-loop-via-variable.stderr +++ b/src/test/ui/span/regions-escape-loop-via-variable.stderr @@ -8,5 +8,5 @@ error[E0597]: `x` does not live long enough 23 | } | - borrowed value needs to live until here -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/regions-escape-loop-via-vec.stderr b/src/test/ui/span/regions-escape-loop-via-vec.stderr index 4f0e61f1133..b61df82e8a1 100644 --- a/src/test/ui/span/regions-escape-loop-via-vec.stderr +++ b/src/test/ui/span/regions-escape-loop-via-vec.stderr @@ -37,5 +37,5 @@ error[E0506]: cannot assign to `x` because it is borrowed 24 | x += 1; //~ ERROR cannot assign | ^^^^^^ assignment to borrowed `x` occurs here -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/span/regions-infer-borrow-scope-within-loop.stderr b/src/test/ui/span/regions-infer-borrow-scope-within-loop.stderr index 43103e619a5..0960f5e1b25 100644 --- a/src/test/ui/span/regions-infer-borrow-scope-within-loop.stderr +++ b/src/test/ui/span/regions-infer-borrow-scope-within-loop.stderr @@ -10,5 +10,5 @@ error[E0597]: `*x` does not live long enough 30 | } | - borrowed value needs to live until here -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/send-is-not-static-ensures-scoping.stderr b/src/test/ui/span/send-is-not-static-ensures-scoping.stderr index b5e55adfb45..02fc9820495 100644 --- a/src/test/ui/span/send-is-not-static-ensures-scoping.stderr +++ b/src/test/ui/span/send-is-not-static-ensures-scoping.stderr @@ -24,5 +24,5 @@ error[E0597]: `y` does not live long enough 35 | } | - borrowed value needs to live until here -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/send-is-not-static-std-sync-2.stderr b/src/test/ui/span/send-is-not-static-std-sync-2.stderr index 2845c4f6bda..318dab599f5 100644 --- a/src/test/ui/span/send-is-not-static-std-sync-2.stderr +++ b/src/test/ui/span/send-is-not-static-std-sync-2.stderr @@ -32,5 +32,5 @@ error[E0597]: `x` does not live long enough 44 | } | - borrowed value needs to live until here -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/span/send-is-not-static-std-sync.stderr b/src/test/ui/span/send-is-not-static-std-sync.stderr index 3d75a1b717a..988ff228105 100644 --- a/src/test/ui/span/send-is-not-static-std-sync.stderr +++ b/src/test/ui/span/send-is-not-static-std-sync.stderr @@ -52,5 +52,5 @@ error[E0505]: cannot move out of `y` because it is borrowed 49 | drop(y); //~ ERROR cannot move out | ^ move out of `y` occurs here -error: aborting due to previous error(s) +error: aborting due to 6 previous errors diff --git a/src/test/ui/span/slice-borrow.stderr b/src/test/ui/span/slice-borrow.stderr index 0c07d068d28..b60ccd0fbf3 100644 --- a/src/test/ui/span/slice-borrow.stderr +++ b/src/test/ui/span/slice-borrow.stderr @@ -9,5 +9,5 @@ error[E0597]: borrowed value does not live long enough 19 | } | - temporary value needs to live until here -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/suggestion-non-ascii.stderr b/src/test/ui/span/suggestion-non-ascii.stderr index 68d43d3f5cd..c2ab7542d8a 100644 --- a/src/test/ui/span/suggestion-non-ascii.stderr +++ b/src/test/ui/span/suggestion-non-ascii.stderr @@ -4,5 +4,5 @@ error[E0608]: cannot index into a value of type `({integer},)` 14 | println!("☃{}", tup[0]); | ^^^^^^ help: to access tuple elements, use `tup.0` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/type-binding.stderr b/src/test/ui/span/type-binding.stderr index afe069e7aa6..dc37acaf3f9 100644 --- a/src/test/ui/span/type-binding.stderr +++ b/src/test/ui/span/type-binding.stderr @@ -4,5 +4,5 @@ error[E0220]: associated type `Trget` not found for `std::ops::Deref` 16 | fn homura>(_: T) {} | ^^^^^^^^^^^ associated type `Trget` not found -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/span/typo-suggestion.stderr b/src/test/ui/span/typo-suggestion.stderr index 6556e5b4c00..dca0a93f897 100644 --- a/src/test/ui/span/typo-suggestion.stderr +++ b/src/test/ui/span/typo-suggestion.stderr @@ -10,5 +10,5 @@ error[E0425]: cannot find value `fob` in this scope 18 | println!("Hello {}", fob); | ^^^ did you mean `foo`? -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/vec-must-not-hide-type-from-dropck.stderr b/src/test/ui/span/vec-must-not-hide-type-from-dropck.stderr index 0efbd8472ae..f7c94ed9f73 100644 --- a/src/test/ui/span/vec-must-not-hide-type-from-dropck.stderr +++ b/src/test/ui/span/vec-must-not-hide-type-from-dropck.stderr @@ -19,5 +19,5 @@ error[E0597]: `c1` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/vec_refs_data_with_early_death.stderr b/src/test/ui/span/vec_refs_data_with_early_death.stderr index 0dee15b4231..282e5caf207 100644 --- a/src/test/ui/span/vec_refs_data_with_early_death.stderr +++ b/src/test/ui/span/vec_refs_data_with_early_death.stderr @@ -20,5 +20,5 @@ error[E0597]: `y` does not live long enough | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/wf-method-late-bound-regions.stderr b/src/test/ui/span/wf-method-late-bound-regions.stderr index d5e663ff26d..a37b5d17aac 100644 --- a/src/test/ui/span/wf-method-late-bound-regions.stderr +++ b/src/test/ui/span/wf-method-late-bound-regions.stderr @@ -9,5 +9,5 @@ error[E0597]: `pointer` does not live long enough 33 | } | - borrowed value needs to live until here -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/static-lifetime.stderr b/src/test/ui/static-lifetime.stderr index 89008828ac5..f73dff4f73d 100644 --- a/src/test/ui/static-lifetime.stderr +++ b/src/test/ui/static-lifetime.stderr @@ -6,5 +6,5 @@ error[E0477]: the type `std::borrow::Cow<'a, A>` does not fulfill the required l | = note: type must satisfy the static lifetime -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/suggestions/confuse-field-and-method/issue-18343.stderr b/src/test/ui/suggestions/confuse-field-and-method/issue-18343.stderr index b69d90cf8f7..0ca61127634 100644 --- a/src/test/ui/suggestions/confuse-field-and-method/issue-18343.stderr +++ b/src/test/ui/suggestions/confuse-field-and-method/issue-18343.stderr @@ -6,5 +6,5 @@ error[E0599]: no method named `closure` found for type `Obj<[closure@$DIR/issue- | = help: use `(o.closure)(...)` if you meant to call the function stored in the `closure` field -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/suggestions/confuse-field-and-method/issue-2392.stderr b/src/test/ui/suggestions/confuse-field-and-method/issue-2392.stderr index 21865323908..c6f134f118d 100644 --- a/src/test/ui/suggestions/confuse-field-and-method/issue-2392.stderr +++ b/src/test/ui/suggestions/confuse-field-and-method/issue-2392.stderr @@ -86,5 +86,5 @@ error[E0599]: no method named `f3` found for type `FuncContainer` in the current | = help: use `((*self.container).f3)(...)` if you meant to call the function stored in the `f3` field -error: aborting due to previous error(s) +error: aborting due to 11 previous errors diff --git a/src/test/ui/suggestions/confuse-field-and-method/issue-32128.stderr b/src/test/ui/suggestions/confuse-field-and-method/issue-32128.stderr index f1d8df81639..a45e70d48c9 100644 --- a/src/test/ui/suggestions/confuse-field-and-method/issue-32128.stderr +++ b/src/test/ui/suggestions/confuse-field-and-method/issue-32128.stderr @@ -6,5 +6,5 @@ error[E0599]: no method named `example` found for type `Example` in the current | = help: use `(demo.example)(...)` if you meant to call the function stored in the `example` field -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/suggestions/confuse-field-and-method/issue-33784.stderr b/src/test/ui/suggestions/confuse-field-and-method/issue-33784.stderr index 7918fc1e89d..d41f7cbdf56 100644 --- a/src/test/ui/suggestions/confuse-field-and-method/issue-33784.stderr +++ b/src/test/ui/suggestions/confuse-field-and-method/issue-33784.stderr @@ -22,5 +22,5 @@ error[E0599]: no method named `c_fn_ptr` found for type `&D` in the current scop | = help: use `(s.c_fn_ptr)(...)` if you meant to call the function stored in the `c_fn_ptr` field -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/suggestions/confuse-field-and-method/private-field.stderr b/src/test/ui/suggestions/confuse-field-and-method/private-field.stderr index 5b1c63822f9..94519266260 100644 --- a/src/test/ui/suggestions/confuse-field-and-method/private-field.stderr +++ b/src/test/ui/suggestions/confuse-field-and-method/private-field.stderr @@ -4,5 +4,5 @@ error[E0599]: no method named `dog_age` found for type `animal::Dog` in the curr 26 | let dog_age = dog.dog_age(); | ^^^^^^^ private field, not a method -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/suggestions/tuple-float-index.stderr b/src/test/ui/suggestions/tuple-float-index.stderr index 47a1b53cc60..8a121b14536 100644 --- a/src/test/ui/suggestions/tuple-float-index.stderr +++ b/src/test/ui/suggestions/tuple-float-index.stderr @@ -7,5 +7,5 @@ error: unexpected token: `1.1` | | unexpected token | help: try parenthesizing the first index `((1, (2, 3)).1).1` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/token/bounds-obj-parens.stderr b/src/test/ui/token/bounds-obj-parens.stderr index 15e4d4c72bc..4d60be15eca 100644 --- a/src/test/ui/token/bounds-obj-parens.stderr +++ b/src/test/ui/token/bounds-obj-parens.stderr @@ -4,5 +4,5 @@ error: expected one of `!` or `::`, found `` 15 | FAIL | ^^^^ expected one of `!` or `::` here -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/token/issue-10636-2.stderr b/src/test/ui/token/issue-10636-2.stderr index 4b0b05ca65a..48bbeac75d3 100644 --- a/src/test/ui/token/issue-10636-2.stderr +++ b/src/test/ui/token/issue-10636-2.stderr @@ -24,5 +24,5 @@ error: expected expression, found `)` error[E0601]: main function not found -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/token/issue-41155.stderr b/src/test/ui/token/issue-41155.stderr index 56f71a29953..50a38da9d8c 100644 --- a/src/test/ui/token/issue-41155.stderr +++ b/src/test/ui/token/issue-41155.stderr @@ -14,5 +14,5 @@ error[E0412]: cannot find type `S` in this scope error[E0601]: main function not found -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/token/macro-incomplete-parse.stderr b/src/test/ui/token/macro-incomplete-parse.stderr index 14a7186aab1..f23d97586b8 100644 --- a/src/test/ui/token/macro-incomplete-parse.stderr +++ b/src/test/ui/token/macro-incomplete-parse.stderr @@ -28,5 +28,5 @@ note: caused by the macro expansion here; the usage of `ignored_pat!` is likely 37 | ignored_pat!() => (), //~ NOTE caused by the macro expansion here | ^^^^^^^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/token/trailing-plus-in-bounds.stderr b/src/test/ui/token/trailing-plus-in-bounds.stderr index 5fe0b3594f6..c765a434b8a 100644 --- a/src/test/ui/token/trailing-plus-in-bounds.stderr +++ b/src/test/ui/token/trailing-plus-in-bounds.stderr @@ -4,5 +4,5 @@ error: expected one of `!` or `::`, found `` 19 | FAIL | ^^^^ expected one of `!` or `::` here -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/type-check/cannot_infer_local_or_array.stderr b/src/test/ui/type-check/cannot_infer_local_or_array.stderr index 007480dc44f..8c52bb5a1d3 100644 --- a/src/test/ui/type-check/cannot_infer_local_or_array.stderr +++ b/src/test/ui/type-check/cannot_infer_local_or_array.stderr @@ -6,5 +6,5 @@ error[E0282]: type annotations needed | | | consider giving `x` a type -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/type-check/cannot_infer_local_or_vec.stderr b/src/test/ui/type-check/cannot_infer_local_or_vec.stderr index 4650df5411b..4788fad2088 100644 --- a/src/test/ui/type-check/cannot_infer_local_or_vec.stderr +++ b/src/test/ui/type-check/cannot_infer_local_or_vec.stderr @@ -8,5 +8,5 @@ error[E0282]: type annotations needed | = note: this error originates in a macro outside of the current crate -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/type-check/cannot_infer_local_or_vec_in_tuples.stderr b/src/test/ui/type-check/cannot_infer_local_or_vec_in_tuples.stderr index 08b5ae4bbb6..ccffadebe9e 100644 --- a/src/test/ui/type-check/cannot_infer_local_or_vec_in_tuples.stderr +++ b/src/test/ui/type-check/cannot_infer_local_or_vec_in_tuples.stderr @@ -8,5 +8,5 @@ error[E0282]: type annotations needed | = note: this error originates in a macro outside of the current crate -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/type-check/issue-22897.stderr b/src/test/ui/type-check/issue-22897.stderr index b3c736c3b68..95684118851 100644 --- a/src/test/ui/type-check/issue-22897.stderr +++ b/src/test/ui/type-check/issue-22897.stderr @@ -4,5 +4,5 @@ error[E0282]: type annotations needed 14 | []; | ^^ cannot infer type for `[_; 0]` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/type-check/issue-40294.stderr b/src/test/ui/type-check/issue-40294.stderr index cd474b14193..bb3a371b26e 100644 --- a/src/test/ui/type-check/issue-40294.stderr +++ b/src/test/ui/type-check/issue-40294.stderr @@ -12,5 +12,5 @@ error[E0283]: type annotations required: cannot resolve `&'a T: Foo` | = note: required by `Foo` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/type-check/unknown_type_for_closure.stderr b/src/test/ui/type-check/unknown_type_for_closure.stderr index 200864dfbf7..afbd15ca486 100644 --- a/src/test/ui/type-check/unknown_type_for_closure.stderr +++ b/src/test/ui/type-check/unknown_type_for_closure.stderr @@ -4,5 +4,5 @@ error[E0282]: type annotations needed 12 | let x = |_| { }; | ^ consider giving this closure parameter a type -error: aborting due to previous error(s) +error: aborting due to previous error From da887074fc70a9f8d2afec8dbe6e2eeea6fc1406 Mon Sep 17 00:00:00 2001 From: est31 Date: Tue, 27 Jun 2017 04:26:52 +0200 Subject: [PATCH 127/162] Output line column info when panicking --- src/libcore/lib.rs | 11 +++-- src/libcore/macros.rs | 10 ++-- src/libcore/panicking.rs | 30 ++++++++---- src/libcore/panicking_stage0.rs | 86 +++++++++++++++++++++++++++++++++ src/librustc_trans/mir/block.rs | 32 ++++++------ src/libstd/macros.rs | 10 ++-- src/libstd/panicking.rs | 69 +++++++++++++++++++++----- src/libstd/rt.rs | 2 +- src/libsyntax/ext/build.rs | 11 +++-- 9 files changed, 207 insertions(+), 54 deletions(-) create mode 100644 src/libcore/panicking_stage0.rs diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index b6ab1ecaf4e..5acc6c3848a 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -39,9 +39,9 @@ //! * `rust_begin_panic` - This function takes three arguments, a //! `fmt::Arguments`, a `&'static str`, and a `u32`. These three arguments //! dictate the panic message, the file at which panic was invoked, and the -//! line. It is up to consumers of this core library to define this panic -//! function; it is only required to never return. This requires a `lang` -//! attribute named `panic_fmt`. +//! line and column inside the file. It is up to consumers of this core +//! library to define this panic function; it is only required to never +//! return. This requires a `lang` attribute named `panic_fmt`. //! //! * `rust_eh_personality` - is used by the failure mechanisms of the //! compiler. This is often mapped to GCC's personality function, but crates @@ -160,6 +160,11 @@ pub mod array; pub mod sync; pub mod cell; pub mod char; +// FIXME: remove when SNAP +#[cfg(stage0)] +#[path = "panicking_stage0.rs"] +pub mod panicking; +#[cfg(not(stage0))] pub mod panicking; pub mod iter; pub mod option; diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index 5bb6a772aeb..c9761bbe611 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -17,16 +17,18 @@ macro_rules! panic { panic!("explicit panic") ); ($msg:expr) => ({ - static _MSG_FILE_LINE: (&'static str, &'static str, u32) = ($msg, file!(), line!()); - $crate::panicking::panic(&_MSG_FILE_LINE) + static _MSG_FILE_LINE_COL: (&'static str, &'static str, u32, u32) = + ($msg, file!(), line!(), column!()); + $crate::panicking::panic_new(&_MSG_FILE_LINE_COL) }); ($fmt:expr, $($arg:tt)*) => ({ // The leading _'s are to avoid dead code warnings if this is // used inside a dead function. Just `#[allow(dead_code)]` is // insufficient, since the user may have // `#[forbid(dead_code)]` and which cannot be overridden. - static _FILE_LINE: (&'static str, u32) = (file!(), line!()); - $crate::panicking::panic_fmt(format_args!($fmt, $($arg)*), &_FILE_LINE) + static _MSG_FILE_LINE_COL: (&'static str, u32, u32) = + (file!(), line!(), column!()); + $crate::panicking::panic_fmt_new(format_args!($fmt, $($arg)*), &_MSG_FILE_LINE_COL) }); } diff --git a/src/libcore/panicking.rs b/src/libcore/panicking.rs index 60b7669f3b2..d4df0f69b90 100644 --- a/src/libcore/panicking.rs +++ b/src/libcore/panicking.rs @@ -17,7 +17,7 @@ //! //! ``` //! # use std::fmt; -//! fn panic_impl(fmt: fmt::Arguments, file_line: &(&'static str, u32)) -> ! +//! fn panic_impl(fmt: fmt::Arguments, file_line_col: &(&'static str, u32, u32)) -> ! //! # { loop {} } //! ``` //! @@ -38,35 +38,45 @@ use fmt; +#[cold] #[inline(never)] +pub fn panic_new(expr_file_line_col: &(&'static str, &'static str, u32, u32)) -> ! { + panic(&expr_file_line_col) +} + #[cold] #[inline(never)] // this is the slow path, always #[lang = "panic"] -pub fn panic(expr_file_line: &(&'static str, &'static str, u32)) -> ! { +pub fn panic(expr_file_line_col: &(&'static str, &'static str, u32, u32)) -> ! { // Use Arguments::new_v1 instead of format_args!("{}", expr) to potentially // reduce size overhead. The format_args! macro uses str's Display trait to // write expr, which calls Formatter::pad, which must accommodate string // truncation and padding (even though none is used here). Using // Arguments::new_v1 may allow the compiler to omit Formatter::pad from the // output binary, saving up to a few kilobytes. - let (expr, file, line) = *expr_file_line; - panic_fmt(fmt::Arguments::new_v1(&[expr], &[]), &(file, line)) + let (expr, file, line, col) = *expr_file_line_col; + panic_fmt(fmt::Arguments::new_v1(&[expr], &[]), &(file, line, col)) } #[cold] #[inline(never)] #[lang = "panic_bounds_check"] -fn panic_bounds_check(file_line: &(&'static str, u32), +fn panic_bounds_check(file_line_col: &(&'static str, u32, u32), index: usize, len: usize) -> ! { panic_fmt(format_args!("index out of bounds: the len is {} but the index is {}", - len, index), file_line) + len, index), file_line_col) } #[cold] #[inline(never)] -pub fn panic_fmt(fmt: fmt::Arguments, file_line: &(&'static str, u32)) -> ! { +pub fn panic_fmt_new(fmt: fmt::Arguments, file_line_col: &(&'static str, u32, u32)) -> ! { + panic_fmt(fmt, &file_line_col) +} + +#[cold] #[inline(never)] +pub fn panic_fmt(fmt: fmt::Arguments, file_line_col: &(&'static str, u32, u32)) -> ! { #[allow(improper_ctypes)] extern { #[lang = "panic_fmt"] #[unwind] - fn panic_impl(fmt: fmt::Arguments, file: &'static str, line: u32) -> !; + fn panic_impl(fmt: fmt::Arguments, file: &'static str, line: u32, col :u32) -> !; } - let (file, line) = *file_line; - unsafe { panic_impl(fmt, file, line) } + let (file, line, col) = *file_line_col; + unsafe { panic_impl(fmt, file, line, col) } } diff --git a/src/libcore/panicking_stage0.rs b/src/libcore/panicking_stage0.rs new file mode 100644 index 00000000000..3506f6a93bc --- /dev/null +++ b/src/libcore/panicking_stage0.rs @@ -0,0 +1,86 @@ +// 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. + +//! Panic support for libcore +//! +//! The core library cannot define panicking, but it does *declare* panicking. This +//! means that the functions inside of libcore are allowed to panic, but to be +//! useful an upstream crate must define panicking for libcore to use. The current +//! interface for panicking is: +//! +//! ``` +//! # use std::fmt; +//! fn panic_impl(fmt: fmt::Arguments, file_line: &(&'static str, u32)) -> ! +//! # { loop {} } +//! ``` +//! +//! This definition allows for panicking with any general message, but it does not +//! allow for failing with a `Box` value. The reason for this is that libcore +//! is not allowed to allocate. +//! +//! This module contains a few other panicking functions, but these are just the +//! necessary lang items for the compiler. All panics are funneled through this +//! one function. Currently, the actual symbol is declared in the standard +//! library, but the location of this may change over time. + +#![allow(dead_code, missing_docs)] +#![unstable(feature = "core_panic", + reason = "internal details of the implementation of the `panic!` \ + and related macros", + issue = "0")] + +use fmt; + +#[cold] #[inline(never)] +pub fn panic_new(expr_file_line_col: &(&'static str, &'static str, u32, u32)) -> ! { + let (expr, file, line, _) = *expr_file_line_col; + let expr_file_line = (expr, file, line); + panic(&expr_file_line) +} + +#[cold] #[inline(never)] // this is the slow path, always +#[lang = "panic"] +pub fn panic(expr_file_line: &(&'static str, &'static str, u32)) -> ! { + // Use Arguments::new_v1 instead of format_args!("{}", expr) to potentially + // reduce size overhead. The format_args! macro uses str's Display trait to + // write expr, which calls Formatter::pad, which must accommodate string + // truncation and padding (even though none is used here). Using + // Arguments::new_v1 may allow the compiler to omit Formatter::pad from the + // output binary, saving up to a few kilobytes. + let (expr, file, line) = *expr_file_line; + panic_fmt(fmt::Arguments::new_v1(&[expr], &[]), &(file, line)) +} + +#[cold] #[inline(never)] +#[lang = "panic_bounds_check"] +fn panic_bounds_check(file_line: &(&'static str, u32), + index: usize, len: usize) -> ! { + panic_fmt(format_args!("index out of bounds: the len is {} but the index is {}", + len, index), file_line) +} + +#[cold] #[inline(never)] +pub fn panic_fmt_new(fmt: fmt::Arguments, file_line_col: &(&'static str, u32, u32)) -> ! { + let (file, line, _) = *file_line_col; + let file_line = (file, line); + panic_fmt(fmt, &file_line) +} + +#[cold] #[inline(never)] +pub fn panic_fmt(fmt: fmt::Arguments, file_line: &(&'static str, u32)) -> ! { + #[allow(improper_ctypes)] + extern { + #[lang = "panic_fmt"] + #[unwind] + fn panic_impl(fmt: fmt::Arguments, file: &'static str, line: u32, col: u32) -> !; + } + let (file, line) = *file_line; + unsafe { panic_impl(fmt, file, line, 0) } +} diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs index 16972a1b1ae..48b166c61de 100644 --- a/src/librustc_trans/mir/block.rs +++ b/src/librustc_trans/mir/block.rs @@ -28,6 +28,7 @@ use type_of; use type_::Type; use syntax::symbol::Symbol; +use syntax_pos::Pos; use std::cmp; @@ -333,6 +334,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { let filename = Symbol::intern(&loc.file.name).as_str(); let filename = C_str_slice(bcx.ccx, filename); let line = C_u32(bcx.ccx, loc.line as u32); + let col = C_u32(bcx.ccx, loc.col.to_usize() as u32 + 1); // Put together the arguments to the panic entry point. let (lang_item, args, const_err) = match *msg { @@ -347,29 +349,29 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { index: index as u64 })); - let file_line = C_struct(bcx.ccx, &[filename, line], false); - let align = llalign_of_min(bcx.ccx, common::val_ty(file_line)); - let file_line = consts::addr_of(bcx.ccx, - file_line, - align, - "panic_bounds_check_loc"); + let file_line_col = C_struct(bcx.ccx, &[filename, line, col], false); + let align = llalign_of_min(bcx.ccx, common::val_ty(file_line_col)); + let file_line_col = consts::addr_of(bcx.ccx, + file_line_col, + align, + "panic_bounds_check_loc"); (lang_items::PanicBoundsCheckFnLangItem, - vec![file_line, index, len], + vec![file_line_col, index, len], const_err) } mir::AssertMessage::Math(ref err) => { let msg_str = Symbol::intern(err.description()).as_str(); let msg_str = C_str_slice(bcx.ccx, msg_str); - let msg_file_line = C_struct(bcx.ccx, - &[msg_str, filename, line], + let msg_file_line_col = C_struct(bcx.ccx, + &[msg_str, filename, line, col], false); - let align = llalign_of_min(bcx.ccx, common::val_ty(msg_file_line)); - let msg_file_line = consts::addr_of(bcx.ccx, - msg_file_line, - align, - "panic_loc"); + let align = llalign_of_min(bcx.ccx, common::val_ty(msg_file_line_col)); + let msg_file_line_col = consts::addr_of(bcx.ccx, + msg_file_line_col, + align, + "panic_loc"); (lang_items::PanicFnLangItem, - vec![msg_file_line], + vec![msg_file_line_col], Some(ErrKind::Math(err.clone()))) } }; diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index 9a4c5ec8f6b..6eb9faacf7f 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -41,10 +41,10 @@ macro_rules! panic { panic!("explicit panic") }); ($msg:expr) => ({ - $crate::rt::begin_panic($msg, { + $crate::rt::begin_panic_new($msg, { // static requires less code at runtime, more constant data - static _FILE_LINE: (&'static str, u32) = (file!(), line!()); - &_FILE_LINE + static _FILE_LINE_COL: (&'static str, u32, u32) = (file!(), line!(), column!()); + &_FILE_LINE_COL }) }); ($fmt:expr, $($arg:tt)+) => ({ @@ -53,8 +53,8 @@ macro_rules! panic { // used inside a dead function. Just `#[allow(dead_code)]` is // insufficient, since the user may have // `#[forbid(dead_code)]` and which cannot be overridden. - static _FILE_LINE: (&'static str, u32) = (file!(), line!()); - &_FILE_LINE + static _FILE_LINE_COL: (&'static str, u32, u32) = (file!(), line!(), column!()); + &_FILE_LINE_COL }) }); } diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index 6f46a73698f..1a8d3b09009 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -262,6 +262,7 @@ impl<'a> PanicInfo<'a> { pub struct Location<'a> { file: &'a str, line: u32, + col: u32, } impl<'a> Location<'a> { @@ -308,6 +309,28 @@ impl<'a> Location<'a> { pub fn line(&self) -> u32 { self.line } + + /// Returns the column from which the panic originated. + /// + /// # Examples + /// + /// ```should_panic + /// use std::panic; + /// + /// panic::set_hook(Box::new(|panic_info| { + /// if let Some(location) = panic_info.location() { + /// println!("panic occured at column {}", location.column()); + /// } else { + /// println!("panic occured but can't get location information..."); + /// } + /// })); + /// + /// panic!("Normal panic"); + /// ``` + #[unstable(feature = "panic_col", issue = "42939")] + pub fn column(&self) -> u32 { + self.col + } } fn default_hook(info: &PanicInfo) { @@ -329,6 +352,7 @@ fn default_hook(info: &PanicInfo) { let file = info.location.file; let line = info.location.line; + let col = info.location.col; let msg = match info.payload.downcast_ref::<&'static str>() { Some(s) => *s, @@ -342,8 +366,8 @@ fn default_hook(info: &PanicInfo) { let name = thread.as_ref().and_then(|t| t.name()).unwrap_or(""); let write = |err: &mut ::io::Write| { - let _ = writeln!(err, "thread '{}' panicked at '{}', {}:{}", - name, msg, file, line); + let _ = writeln!(err, "thread '{}' panicked at '{}', {}:{}:{}", + name, msg, file, line, col); #[cfg(feature = "backtrace")] { @@ -467,8 +491,9 @@ pub fn panicking() -> bool { #[unwind] pub extern fn rust_begin_panic(msg: fmt::Arguments, file: &'static str, - line: u32) -> ! { - begin_panic_fmt(&msg, &(file, line)) + line: u32, + col: u32) -> ! { + begin_panic_fmt(&msg, &(file, line, col)) } /// The entry point for panicking with a formatted message. @@ -482,7 +507,7 @@ pub extern fn rust_begin_panic(msg: fmt::Arguments, issue = "0")] #[inline(never)] #[cold] pub fn begin_panic_fmt(msg: &fmt::Arguments, - file_line: &(&'static str, u32)) -> ! { + file_line_col: &(&'static str, u32, u32)) -> ! { use fmt::Write; // We do two allocations here, unfortunately. But (a) they're @@ -492,7 +517,25 @@ pub fn begin_panic_fmt(msg: &fmt::Arguments, let mut s = String::new(); let _ = s.write_fmt(*msg); - begin_panic(s, file_line) + begin_panic_new(s, file_line_col) +} + +// FIXME: remove begin_panic and rename begin_panic_new to begin_panic when SNAP + +/// This is the entry point of panicking for panic!() and assert!(). +#[unstable(feature = "libstd_sys_internals", + reason = "used by the panic! macro", + issue = "0")] +#[inline(never)] #[cold] // avoid code bloat at the call sites as much as possible +pub fn begin_panic_new(msg: M, file_line_col: &(&'static str, u32, u32)) -> ! { + // Note that this should be the only allocation performed in this code path. + // Currently this means that panic!() on OOM will invoke this code path, + // but then again we're not really ready for panic on OOM anyway. If + // we do start doing this, then we should propagate this allocation to + // be performed in the parent of this thread instead of the thread that's + // panicking. + + rust_panic_with_hook(Box::new(msg), file_line_col) } /// This is the entry point of panicking for panic!() and assert!(). @@ -508,7 +551,10 @@ pub fn begin_panic(msg: M, file_line: &(&'static str, u32)) -> ! // be performed in the parent of this thread instead of the thread that's // panicking. - rust_panic_with_hook(Box::new(msg), file_line) + let (file, line) = *file_line; + let file_line_col = (file, line, 0); + + rust_panic_with_hook(Box::new(msg), &file_line_col) } /// Executes the primary logic for a panic, including checking for recursive @@ -520,8 +566,8 @@ pub fn begin_panic(msg: M, file_line: &(&'static str, u32)) -> ! #[inline(never)] #[cold] fn rust_panic_with_hook(msg: Box, - file_line: &(&'static str, u32)) -> ! { - let (file, line) = *file_line; + file_line_col: &(&'static str, u32, u32)) -> ! { + let (file, line, col) = *file_line_col; let panics = update_panic_count(1); @@ -540,8 +586,9 @@ fn rust_panic_with_hook(msg: Box, let info = PanicInfo { payload: &*msg, location: Location { - file: file, - line: line, + file, + line, + col, }, }; HOOK_LOCK.read(); diff --git a/src/libstd/rt.rs b/src/libstd/rt.rs index 06fd838ea06..2ee63527c14 100644 --- a/src/libstd/rt.rs +++ b/src/libstd/rt.rs @@ -25,7 +25,7 @@ // Reexport some of our utilities which are expected by other crates. -pub use panicking::{begin_panic, begin_panic_fmt, update_panic_count}; +pub use panicking::{begin_panic_new, begin_panic, begin_panic_fmt, update_panic_count}; #[cfg(not(test))] #[lang = "start"] diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index a4580ea3939..412a3493208 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -11,7 +11,7 @@ use abi::Abi; use ast::{self, Ident, Generics, Expr, BlockCheckMode, UnOp, PatKind}; use attr; -use syntax_pos::{Span, DUMMY_SP}; +use syntax_pos::{Pos, Span, DUMMY_SP}; use codemap::{dummy_spanned, respan, Spanned}; use ext::base::ExtCtxt; use ptr::P; @@ -768,14 +768,15 @@ impl<'a> AstBuilder for ExtCtxt<'a> { let loc = self.codemap().lookup_char_pos(span.lo); let expr_file = self.expr_str(span, Symbol::intern(&loc.file.name)); let expr_line = self.expr_u32(span, loc.line as u32); - let expr_file_line_tuple = self.expr_tuple(span, vec![expr_file, expr_line]); - let expr_file_line_ptr = self.expr_addr_of(span, expr_file_line_tuple); + let expr_col = self.expr_u32(span, loc.col.to_usize() as u32 + 1); + let expr_loc_tuple = self.expr_tuple(span, vec![expr_file, expr_line, expr_col]); + let expr_loc_ptr = self.expr_addr_of(span, expr_loc_tuple); self.expr_call_global( span, - self.std_path(&["rt", "begin_panic"]), + self.std_path(&["rt", "begin_panic_new"]), vec![ self.expr_str(span, msg), - expr_file_line_ptr]) + expr_loc_ptr]) } fn expr_unreachable(&self, span: Span) -> P { From eb5fb21bd5871a0dd3bb7bc135bc1a083ad32292 Mon Sep 17 00:00:00 2001 From: est31 Date: Wed, 28 Jun 2017 01:15:29 +0200 Subject: [PATCH 128/162] Fix the test failure, add comment, and refactor a little bit --- src/libcore/lib.rs | 5 -- src/libcore/macros.rs | 4 +- src/libcore/panicking.rs | 29 +++++++---- src/libcore/panicking_stage0.rs | 86 --------------------------------- src/libstd/panicking.rs | 19 +++++++- 5 files changed, 39 insertions(+), 104 deletions(-) delete mode 100644 src/libcore/panicking_stage0.rs diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 5acc6c3848a..46467cd3c3e 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -160,11 +160,6 @@ pub mod array; pub mod sync; pub mod cell; pub mod char; -// FIXME: remove when SNAP -#[cfg(stage0)] -#[path = "panicking_stage0.rs"] -pub mod panicking; -#[cfg(not(stage0))] pub mod panicking; pub mod iter; pub mod option; diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index c9761bbe611..70820dce5f9 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -19,7 +19,7 @@ macro_rules! panic { ($msg:expr) => ({ static _MSG_FILE_LINE_COL: (&'static str, &'static str, u32, u32) = ($msg, file!(), line!(), column!()); - $crate::panicking::panic_new(&_MSG_FILE_LINE_COL) + $crate::panicking::panic(&_MSG_FILE_LINE_COL) }); ($fmt:expr, $($arg:tt)*) => ({ // The leading _'s are to avoid dead code warnings if this is @@ -28,7 +28,7 @@ macro_rules! panic { // `#[forbid(dead_code)]` and which cannot be overridden. static _MSG_FILE_LINE_COL: (&'static str, u32, u32) = (file!(), line!(), column!()); - $crate::panicking::panic_fmt_new(format_args!($fmt, $($arg)*), &_MSG_FILE_LINE_COL) + $crate::panicking::panic_fmt(format_args!($fmt, $($arg)*), &_MSG_FILE_LINE_COL) }); } diff --git a/src/libcore/panicking.rs b/src/libcore/panicking.rs index d4df0f69b90..eae33cf0422 100644 --- a/src/libcore/panicking.rs +++ b/src/libcore/panicking.rs @@ -38,13 +38,8 @@ use fmt; -#[cold] #[inline(never)] -pub fn panic_new(expr_file_line_col: &(&'static str, &'static str, u32, u32)) -> ! { - panic(&expr_file_line_col) -} - #[cold] #[inline(never)] // this is the slow path, always -#[lang = "panic"] +#[cfg_attr(not(stage0), lang = "panic")] pub fn panic(expr_file_line_col: &(&'static str, &'static str, u32, u32)) -> ! { // Use Arguments::new_v1 instead of format_args!("{}", expr) to potentially // reduce size overhead. The format_args! macro uses str's Display trait to @@ -56,17 +51,33 @@ pub fn panic(expr_file_line_col: &(&'static str, &'static str, u32, u32)) -> ! { panic_fmt(fmt::Arguments::new_v1(&[expr], &[]), &(file, line, col)) } +// FIXME: remove when SNAP #[cold] #[inline(never)] -#[lang = "panic_bounds_check"] +#[cfg(stage0)] +#[lang = "panic"] +pub fn panic_old(expr_file_line: &(&'static str, &'static str, u32)) -> ! { + let (expr, file, line) = *expr_file_line; + let expr_file_line_col = (expr, file, line, 0); + panic(&expr_file_line_col) +} + +#[cold] #[inline(never)] +#[cfg_attr(not(stage0), lang = "panic_bounds_check")] fn panic_bounds_check(file_line_col: &(&'static str, u32, u32), index: usize, len: usize) -> ! { panic_fmt(format_args!("index out of bounds: the len is {} but the index is {}", len, index), file_line_col) } +// FIXME: remove when SNAP #[cold] #[inline(never)] -pub fn panic_fmt_new(fmt: fmt::Arguments, file_line_col: &(&'static str, u32, u32)) -> ! { - panic_fmt(fmt, &file_line_col) +#[cfg(stage0)] +#[lang = "panic_bounds_check"] +fn panic_bounds_check_old(file_line: &(&'static str, u32), + index: usize, len: usize) -> ! { + let (file, line) = *file_line; + panic_fmt(format_args!("index out of bounds: the len is {} but the index is {}", + len, index), &(file, line, 0)) } #[cold] #[inline(never)] diff --git a/src/libcore/panicking_stage0.rs b/src/libcore/panicking_stage0.rs deleted file mode 100644 index 3506f6a93bc..00000000000 --- a/src/libcore/panicking_stage0.rs +++ /dev/null @@ -1,86 +0,0 @@ -// 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. - -//! Panic support for libcore -//! -//! The core library cannot define panicking, but it does *declare* panicking. This -//! means that the functions inside of libcore are allowed to panic, but to be -//! useful an upstream crate must define panicking for libcore to use. The current -//! interface for panicking is: -//! -//! ``` -//! # use std::fmt; -//! fn panic_impl(fmt: fmt::Arguments, file_line: &(&'static str, u32)) -> ! -//! # { loop {} } -//! ``` -//! -//! This definition allows for panicking with any general message, but it does not -//! allow for failing with a `Box` value. The reason for this is that libcore -//! is not allowed to allocate. -//! -//! This module contains a few other panicking functions, but these are just the -//! necessary lang items for the compiler. All panics are funneled through this -//! one function. Currently, the actual symbol is declared in the standard -//! library, but the location of this may change over time. - -#![allow(dead_code, missing_docs)] -#![unstable(feature = "core_panic", - reason = "internal details of the implementation of the `panic!` \ - and related macros", - issue = "0")] - -use fmt; - -#[cold] #[inline(never)] -pub fn panic_new(expr_file_line_col: &(&'static str, &'static str, u32, u32)) -> ! { - let (expr, file, line, _) = *expr_file_line_col; - let expr_file_line = (expr, file, line); - panic(&expr_file_line) -} - -#[cold] #[inline(never)] // this is the slow path, always -#[lang = "panic"] -pub fn panic(expr_file_line: &(&'static str, &'static str, u32)) -> ! { - // Use Arguments::new_v1 instead of format_args!("{}", expr) to potentially - // reduce size overhead. The format_args! macro uses str's Display trait to - // write expr, which calls Formatter::pad, which must accommodate string - // truncation and padding (even though none is used here). Using - // Arguments::new_v1 may allow the compiler to omit Formatter::pad from the - // output binary, saving up to a few kilobytes. - let (expr, file, line) = *expr_file_line; - panic_fmt(fmt::Arguments::new_v1(&[expr], &[]), &(file, line)) -} - -#[cold] #[inline(never)] -#[lang = "panic_bounds_check"] -fn panic_bounds_check(file_line: &(&'static str, u32), - index: usize, len: usize) -> ! { - panic_fmt(format_args!("index out of bounds: the len is {} but the index is {}", - len, index), file_line) -} - -#[cold] #[inline(never)] -pub fn panic_fmt_new(fmt: fmt::Arguments, file_line_col: &(&'static str, u32, u32)) -> ! { - let (file, line, _) = *file_line_col; - let file_line = (file, line); - panic_fmt(fmt, &file_line) -} - -#[cold] #[inline(never)] -pub fn panic_fmt(fmt: fmt::Arguments, file_line: &(&'static str, u32)) -> ! { - #[allow(improper_ctypes)] - extern { - #[lang = "panic_fmt"] - #[unwind] - fn panic_impl(fmt: fmt::Arguments, file: &'static str, line: u32, col: u32) -> !; - } - let (file, line) = *file_line; - unsafe { panic_impl(fmt, file, line, 0) } -} diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index 1a8d3b09009..494376b831e 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -315,6 +315,7 @@ impl<'a> Location<'a> { /// # Examples /// /// ```should_panic + /// #![feature(panic_col)] /// use std::panic; /// /// panic::set_hook(Box::new(|panic_info| { @@ -327,7 +328,7 @@ impl<'a> Location<'a> { /// /// panic!("Normal panic"); /// ``` - #[unstable(feature = "panic_col", issue = "42939")] + #[unstable(feature = "panic_col", reason = "recently added", issue = "42939")] pub fn column(&self) -> u32 { self.col } @@ -520,7 +521,21 @@ pub fn begin_panic_fmt(msg: &fmt::Arguments, begin_panic_new(s, file_line_col) } -// FIXME: remove begin_panic and rename begin_panic_new to begin_panic when SNAP +// FIXME: In PR #42938, we have added the column as info passed to the panic +// handling code. For this, we want to break the ABI of begin_panic. +// This is not possible to do directly, as the stage0 compiler is hardcoded +// to emit a call to begin_panic in src/libsyntax/ext/build.rs, only +// with the file and line number being passed, but not the colum number. +// By changing the compiler source, we can only affect behaviour of higher +// stages. We need to perform the switch over two stage0 replacements, using +// a temporary function begin_panic_new while performing the switch: +// 0. Right now, we tell stage1 onward to emit a call to begin_panic_new. +// 1. In the first SNAP, stage0 calls begin_panic_new with the new ABI, +// begin_panic stops being used. Now we can change begin_panic to +// the new ABI, and start emitting calls to begin_panic in higher +// stages again, this time with the new ABI. +// 2. After the second SNAP, stage0 calls begin_panic with the new ABI, +// and we can remove the temporary begin_panic_new function. /// This is the entry point of panicking for panic!() and assert!(). #[unstable(feature = "libstd_sys_internals", From 1561954ea4c403ce7ea54cb83c944857c255b909 Mon Sep 17 00:00:00 2001 From: est31 Date: Wed, 28 Jun 2017 02:41:24 +0200 Subject: [PATCH 129/162] Documentation --- src/doc/unstable-book/src/language-features/lang-items.md | 6 ++++-- src/libcore/lib.rs | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/doc/unstable-book/src/language-features/lang-items.md b/src/doc/unstable-book/src/language-features/lang-items.md index 375b8bd6b82..a2368ee5f4a 100644 --- a/src/doc/unstable-book/src/language-features/lang-items.md +++ b/src/doc/unstable-book/src/language-features/lang-items.md @@ -143,7 +143,8 @@ pub extern fn rust_eh_unwind_resume() { #[no_mangle] pub extern fn rust_begin_panic(_msg: core::fmt::Arguments, _file: &'static str, - _line: u32) -> ! { + _line: u32, + _column: u32) -> ! { unsafe { intrinsics::abort() } } ``` @@ -187,7 +188,8 @@ pub extern fn rust_eh_unwind_resume() { #[no_mangle] pub extern fn rust_begin_panic(_msg: core::fmt::Arguments, _file: &'static str, - _line: u32) -> ! { + _line: u32, + _column: u32) -> ! { unsafe { intrinsics::abort() } } ``` diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 46467cd3c3e..97aaaffe8bc 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -36,8 +36,8 @@ //! These functions are often provided by the system libc, but can also be //! provided by the [rlibc crate](https://crates.io/crates/rlibc). //! -//! * `rust_begin_panic` - This function takes three arguments, a -//! `fmt::Arguments`, a `&'static str`, and a `u32`. These three arguments +//! * `rust_begin_panic` - This function takes four arguments, a +//! `fmt::Arguments`, a `&'static str`, and two `u32`'s. These four arguments //! dictate the panic message, the file at which panic was invoked, and the //! line and column inside the file. It is up to consumers of this core //! library to define this panic function; it is only required to never From 57f0514febd7593f6034c293f8c0d56765bc8d51 Mon Sep 17 00:00:00 2001 From: est31 Date: Sun, 2 Jul 2017 09:06:08 +0200 Subject: [PATCH 130/162] Style fix --- src/libcore/panicking.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/panicking.rs b/src/libcore/panicking.rs index eae33cf0422..f5a7e78d0fa 100644 --- a/src/libcore/panicking.rs +++ b/src/libcore/panicking.rs @@ -86,7 +86,7 @@ pub fn panic_fmt(fmt: fmt::Arguments, file_line_col: &(&'static str, u32, u32)) extern { #[lang = "panic_fmt"] #[unwind] - fn panic_impl(fmt: fmt::Arguments, file: &'static str, line: u32, col :u32) -> !; + fn panic_impl(fmt: fmt::Arguments, file: &'static str, line: u32, col: u32) -> !; } let (file, line, col) = *file_line_col; unsafe { panic_impl(fmt, file, line, col) } From fb7ab9e43da3727e1c58faf9451857968270dc77 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Sun, 2 Jul 2017 16:09:09 +0300 Subject: [PATCH 131/162] report the total number of errors on compilation failure Prior to this PR, when we aborted because a "critical pass" failed, we displayed the number of errors from that critical pass. While that's the number of errors that caused compilation to abort in *that place*, that's not what people really want to know. Instead, always report the total number of errors, and don't bother to track the number of errors from the last pass that failed. This changes the compiler driver API to handle errors more smoothly, and therefore is a compiler-api-[breaking-change]. Fixes #42793. --- src/librustc/middle/resolve_lifetime.rs | 3 +- src/librustc/session/mod.rs | 25 +++++++--- src/librustc_driver/driver.rs | 34 ++++++------- src/librustc_driver/lib.rs | 49 +++++++++---------- src/librustc_passes/static_recursion.rs | 7 ++- src/librustc_typeck/check/mod.rs | 16 +++--- src/librustc_typeck/lib.rs | 12 ++--- src/librustdoc/test.rs | 38 ++++++-------- src/test/run-make/llvm-phase/test.rs | 2 +- .../block-must-not-have-result-do.stderr | 2 +- .../block-must-not-have-result-res.stderr | 2 +- .../block-must-not-have-result-while.stderr | 2 +- .../consider-removing-last-semi.stderr | 2 +- src/test/ui/block-result/issue-11714.stderr | 2 +- src/test/ui/block-result/issue-13428.stderr | 2 +- src/test/ui/block-result/issue-13624.stderr | 2 +- src/test/ui/block-result/issue-20862.stderr | 2 +- src/test/ui/block-result/issue-22645.stderr | 2 +- src/test/ui/block-result/issue-3563.stderr | 2 +- src/test/ui/block-result/issue-5500.stderr | 2 +- .../unexpected-return-on-unit.stderr | 2 +- .../closure_context/issue-26046-fn-mut.stderr | 2 +- .../issue-26046-fn-once.stderr | 2 +- ...coercion-missing-tail-expected-type.stderr | 2 +- src/test/ui/did_you_mean/issue-40006.stderr | 2 +- ...reference-without-parens-suggestion.stderr | 2 +- ...e-21659-show-relevant-trait-impls-3.stderr | 2 +- .../method-suggestion-no-duplication.stderr | 2 +- .../no-method-suggested-traits.stderr | 2 +- src/test/ui/impl-trait/trait_type.stderr | 2 +- .../interior-mutability.stderr | 2 +- src/test/ui/issue-22644.stderr | 2 +- src/test/ui/issue-26548.stderr | 2 +- src/test/ui/issue-33525.rs | 15 ++++++ src/test/ui/issue-33525.stderr | 20 ++++++++ src/test/ui/issue-38875/issue_38875.stderr | 2 +- ...-return-one-existing-name-if-else-2.stderr | 2 +- ...-return-one-existing-name-if-else-3.stderr | 2 +- ...-existing-name-if-else-using-impl-2.stderr | 2 +- ...-existing-name-if-else-using-impl-3.stderr | 2 +- ...ne-existing-name-if-else-using-impl.stderr | 2 +- ...e-existing-name-return-type-is-anon.stderr | 2 +- ...turn-one-existing-name-self-is-anon.stderr | 2 +- .../ex2a-push-one-existing-name-2.stderr | 2 +- src/test/ui/lint/outer-forbid.stderr | 2 +- src/test/ui/mismatched_types/E0281.stderr | 2 +- src/test/ui/mismatched_types/E0409.stderr | 2 +- src/test/ui/mismatched_types/binops.stderr | 2 +- .../mismatched_types/closure-arg-count.stderr | 2 +- .../for-loop-has-unit-body.stderr | 2 +- .../ui/mismatched_types/issue-36053-2.stderr | 2 +- .../unboxed-closures-vtable-mismatch.stderr | 2 +- src/test/ui/missing-items/m2.stderr | 2 +- .../ui/resolve/token-error-correct-3.stderr | 2 +- src/test/ui/shadowed-type-parameter.stderr | 2 +- .../ui/span/impl-wrong-item-for-trait.stderr | 2 +- src/test/ui/span/issue-34264.stderr | 2 +- src/test/ui/transmute/main.stderr | 2 +- .../transmute-from-fn-item-types-error.stderr | 2 +- .../transmute-type-parameters.stderr | 2 +- .../ui/type-check/assignment-in-if.stderr | 2 +- 61 files changed, 175 insertions(+), 146 deletions(-) create mode 100644 src/test/ui/issue-33525.rs create mode 100644 src/test/ui/issue-33525.stderr diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index ce5d58f5800..b347a931851 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -28,6 +28,7 @@ use syntax::attr; use syntax::ptr::P; use syntax_pos::Span; use errors::DiagnosticBuilder; +use util::common::ErrorReported; use util::nodemap::{NodeMap, NodeSet, FxHashSet, FxHashMap, DefIdMap}; use rustc_back::slice; @@ -255,7 +256,7 @@ const ROOT_SCOPE: ScopeRef<'static> = &Scope::Root; pub fn krate(sess: &Session, hir_map: &Map) - -> Result { + -> Result { let krate = hir_map.krate(); let mut map = NamedRegionMap { defs: NodeMap(), diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index fb513f573d7..8bafdda234a 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -21,7 +21,7 @@ use session::search_paths::PathKind; use session::config::DebugInfoLevel; use ty::tls; use util::nodemap::{FxHashMap, FxHashSet}; -use util::common::duration_to_secs_str; +use util::common::{duration_to_secs_str, ErrorReported}; use syntax::ast::NodeId; use errors::{self, DiagnosticBuilder}; @@ -255,7 +255,10 @@ impl Session { pub fn abort_if_errors(&self) { self.diagnostic().abort_if_errors(); } - pub fn track_errors(&self, f: F) -> Result + pub fn compile_status(&self) -> Result<(), CompileIncomplete> { + compile_result_from_err_count(self.err_count()) + } + pub fn track_errors(&self, f: F) -> Result where F: FnOnce() -> T { let old_count = self.err_count(); @@ -264,7 +267,7 @@ impl Session { if errors == 0 { Ok(result) } else { - Err(errors) + Err(ErrorReported) } } pub fn span_warn>(&self, sp: S, msg: &str) { @@ -802,15 +805,23 @@ pub fn early_warn(output: config::ErrorOutputType, msg: &str) { handler.emit(&MultiSpan::new(), msg, errors::Level::Warning); } -// Err(0) means compilation was stopped, but no errors were found. -// This would be better as a dedicated enum, but using try! is so convenient. -pub type CompileResult = Result<(), usize>; +#[derive(Copy, Clone, Debug)] +pub enum CompileIncomplete { + Stopped, + Errored(ErrorReported) +} +impl From for CompileIncomplete { + fn from(err: ErrorReported) -> CompileIncomplete { + CompileIncomplete::Errored(err) + } +} +pub type CompileResult = Result<(), CompileIncomplete>; pub fn compile_result_from_err_count(err_count: usize) -> CompileResult { if err_count == 0 { Ok(()) } else { - Err(err_count) + Err(CompileIncomplete::Errored(ErrorReported)) } } diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 98278949d51..a3e1cf7c1a8 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -13,7 +13,8 @@ use rustc::hir::lowering::lower_crate; use rustc::ich::Fingerprint; use rustc_data_structures::stable_hasher::StableHasher; use rustc_mir as mir; -use rustc::session::{Session, CompileResult, compile_result_from_err_count}; +use rustc::session::{Session, CompileResult}; +use rustc::session::CompileIncomplete; use rustc::session::config::{self, Input, OutputFilenames, OutputType, OutputTypes}; use rustc::session::search_paths::PathKind; @@ -23,7 +24,7 @@ use rustc::middle::privacy::AccessLevels; use rustc::mir::transform::{MIR_CONST, MIR_VALIDATED, MIR_OPTIMIZED, Passes}; use rustc::ty::{self, TyCtxt, Resolutions, GlobalArenas}; use rustc::traits; -use rustc::util::common::time; +use rustc::util::common::{ErrorReported, time}; use rustc::util::nodemap::NodeSet; use rustc::util::fs::rename_or_copy_remove; use rustc_borrowck as borrowck; @@ -78,7 +79,9 @@ pub fn compile_input(sess: &Session, } if control.$point.stop == Compilation::Stop { - return compile_result_from_err_count($tsess.err_count()); + // FIXME: shouldn't this return Err(CompileIncomplete::Stopped) + // if there are no errors? + return $tsess.compile_status(); } }} } @@ -91,7 +94,7 @@ pub fn compile_input(sess: &Session, Ok(krate) => krate, Err(mut parse_error) => { parse_error.emit(); - return Err(1); + return Err(CompileIncomplete::Errored(ErrorReported)); } }; @@ -194,7 +197,7 @@ pub fn compile_input(sess: &Session, (control.after_analysis.callback)(&mut state); if control.after_analysis.stop == Compilation::Stop { - return result.and_then(|_| Err(0usize)); + return result.and_then(|_| Err(CompileIncomplete::Stopped)); } } @@ -564,7 +567,7 @@ pub fn phase_2_configure_and_expand(sess: &Session, addl_plugins: Option>, make_glob_map: MakeGlobMap, after_expand: F) - -> Result + -> Result where F: FnOnce(&ast::Crate) -> CompileResult, { let time_passes = sess.time_passes(); @@ -636,7 +639,7 @@ pub fn phase_2_configure_and_expand(sess: &Session, // Lint plugins are registered; now we can process command line flags. if sess.opts.describe_lints { super::describe_lints(&sess.lint_store.borrow(), true); - return Err(0); + return Err(CompileIncomplete::Stopped); } sess.track_errors(|| sess.lint_store.borrow_mut().process_command_line(sess))?; @@ -839,7 +842,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, arenas: &'tcx GlobalArenas<'tcx>, name: &str, f: F) - -> Result + -> Result where F: for<'a> FnOnce(TyCtxt<'a, 'tcx, 'tcx>, ty::CrateAnalysis, IncrementalHashesMap, @@ -1019,7 +1022,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, // lint warnings and so on -- kindck used to do this abort, but // kindck is gone now). -nmatsakis if sess.err_count() > 0 { - return Ok(f(tcx, analysis, incremental_hashes_map, Err(sess.err_count()))); + return Ok(f(tcx, analysis, incremental_hashes_map, sess.compile_status())); } analysis.reachable = @@ -1035,12 +1038,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, time(time_passes, "lint checking", || lint::check_crate(tcx)); - // The above three passes generate errors w/o aborting - if sess.err_count() > 0 { - return Ok(f(tcx, analysis, incremental_hashes_map, Err(sess.err_count()))); - } - - Ok(f(tcx, analysis, incremental_hashes_map, Ok(()))) + return Ok(f(tcx, analysis, incremental_hashes_map, tcx.sess.compile_status())); }) } @@ -1116,11 +1114,7 @@ pub fn phase_5_run_llvm_passes(sess: &Session, "serialize work products", move || rustc_incremental::save_work_products(sess)); - if sess.err_count() > 0 { - Err(sess.err_count()) - } else { - Ok(()) - } + sess.compile_status() } /// Run the linker on any artifacts that resulted from the LLVM run. diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 061e21fadeb..f2aacbc629f 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -67,6 +67,7 @@ use rustc_trans::back::link; use rustc_trans::back::write::{RELOC_MODEL_ARGS, CODE_GEN_MODEL_ARGS}; use rustc::dep_graph::DepGraph; use rustc::session::{self, config, Session, build_session, CompileResult}; +use rustc::session::CompileIncomplete; use rustc::session::config::{Input, PrintRequest, OutputType, ErrorOutputType}; use rustc::session::config::nightly_options; use rustc::session::{early_error, early_warn}; @@ -74,7 +75,7 @@ use rustc::lint::Lint; use rustc::lint; use rustc_metadata::locator; use rustc_metadata::cstore::CStore; -use rustc::util::common::time; +use rustc::util::common::{time, ErrorReported}; use serialize::json::ToJson; @@ -109,19 +110,14 @@ mod derive_registrar; const BUG_REPORT_URL: &'static str = "https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.\ md#bug-reports"; -#[inline] -fn abort_msg(err_count: usize) -> String { - match err_count { - 0 => "aborting with no errors (maybe a bug?)".to_owned(), - 1 => "aborting due to previous error".to_owned(), - e => format!("aborting due to {} previous errors", e), - } -} - -pub fn abort_on_err(result: Result, sess: &Session) -> T { +pub fn abort_on_err(result: Result, sess: &Session) -> T { match result { - Err(err_count) => { - sess.fatal(&abort_msg(err_count)); + Err(CompileIncomplete::Errored(ErrorReported)) => { + sess.abort_if_errors(); + panic!("error reported but abort_if_errors didn't abort???"); + } + Err(CompileIncomplete::Stopped) => { + sess.fatal("compilation terminated"); } Ok(x) => x, } @@ -132,19 +128,20 @@ pub fn run(run_compiler: F) -> isize { monitor(move || { let (result, session) = run_compiler(); - if let Err(err_count) = result { - if err_count > 0 { - match session { - Some(sess) => sess.fatal(&abort_msg(err_count)), - None => { - let emitter = - errors::emitter::EmitterWriter::stderr(errors::ColorConfig::Auto, None); - let handler = errors::Handler::with_emitter(true, false, Box::new(emitter)); - handler.emit(&MultiSpan::new(), - &abort_msg(err_count), - errors::Level::Fatal); - exit_on_err(); - } + if let Err(CompileIncomplete::Errored(_)) = result { + match session { + Some(sess) => { + sess.abort_if_errors(); + panic!("error reported but abort_if_errors didn't abort???"); + } + None => { + let emitter = + errors::emitter::EmitterWriter::stderr(errors::ColorConfig::Auto, None); + let handler = errors::Handler::with_emitter(true, false, Box::new(emitter)); + handler.emit(&MultiSpan::new(), + "aborting due to previous error(s)", + errors::Level::Fatal); + exit_on_err(); } } } diff --git a/src/librustc_passes/static_recursion.rs b/src/librustc_passes/static_recursion.rs index 8d455adc23c..0dbb2d1d4d0 100644 --- a/src/librustc_passes/static_recursion.rs +++ b/src/librustc_passes/static_recursion.rs @@ -12,8 +12,9 @@ // recursively. use rustc::hir::map as hir_map; -use rustc::session::{CompileResult, Session}; +use rustc::session::Session; use rustc::hir::def::{Def, CtorKind}; +use rustc::util::common::ErrorReported; use rustc::util::nodemap::{NodeMap, NodeSet}; use syntax::ast; @@ -86,7 +87,9 @@ impl<'a, 'hir: 'a> Visitor<'hir> for CheckCrateVisitor<'a, 'hir> { } } -pub fn check_crate<'hir>(sess: &Session, hir_map: &hir_map::Map<'hir>) -> CompileResult { +pub fn check_crate<'hir>(sess: &Session, hir_map: &hir_map::Map<'hir>) + -> Result<(), ErrorReported> +{ let mut visitor = CheckCrateVisitor { sess: sess, hir_map: hir_map, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 0dfd9a1838e..3241267bbc2 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -102,7 +102,7 @@ use rustc::ty::maps::Providers; use rustc::ty::util::{Representability, IntTypeExt}; use errors::DiagnosticBuilder; use require_c_abi_if_variadic; -use session::{Session, CompileResult}; +use session::{CompileIncomplete, Session}; use TypeAndSubsts; use lint; use util::common::{ErrorReported, indenter}; @@ -691,30 +691,32 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for CheckItemTypesVisitor<'a, 'tcx> { fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem) { } } -pub fn check_wf_new<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> CompileResult { +pub fn check_wf_new<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Result<(), ErrorReported> { tcx.sess.track_errors(|| { let mut visit = wfcheck::CheckTypeWellFormedVisitor::new(tcx); tcx.hir.krate().visit_all_item_likes(&mut visit.as_deep_visitor()); }) } -pub fn check_item_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> CompileResult { +pub fn check_item_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Result<(), ErrorReported> { tcx.sess.track_errors(|| { tcx.hir.krate().visit_all_item_likes(&mut CheckItemTypesVisitor { tcx }); }) } -pub fn check_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> CompileResult { +pub fn check_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Result<(), CompileIncomplete> { tcx.typeck_item_bodies(LOCAL_CRATE) } -fn typeck_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) -> CompileResult { +fn typeck_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) + -> Result<(), CompileIncomplete> +{ debug_assert!(crate_num == LOCAL_CRATE); - tcx.sess.track_errors(|| { + Ok(tcx.sess.track_errors(|| { for body_owner_def_id in tcx.body_owners() { tcx.typeck_tables_of(body_owner_def_id); } - }) + })?) } pub fn provide(providers: &mut Providers) { diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 2857b5fb5e0..9b829e6e3ff 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -108,7 +108,7 @@ use rustc::ty::subst::Substs; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::maps::Providers; use rustc::traits::{FulfillmentContext, ObligationCause, ObligationCauseCode, Reveal}; -use session::config; +use session::{CompileIncomplete, config}; use util::common::time; use syntax::ast; @@ -293,7 +293,8 @@ pub fn provide(providers: &mut Providers) { } pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) - -> Result<(), usize> { + -> Result<(), CompileIncomplete> +{ let time_passes = tcx.sess.time_passes(); // this ensures that later parts of type checking can assume that items @@ -328,12 +329,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) check_unused::check_crate(tcx); check_for_entry_fn(tcx); - let err_count = tcx.sess.err_count(); - if err_count == 0 { - Ok(()) - } else { - Err(err_count) - } + tcx.sess.compile_status() } /// A quasi-deprecated helper used in rustdoc and save-analysis to get diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 4766778eed1..f012fd974b5 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -25,7 +25,7 @@ use rustc_lint; use rustc::dep_graph::DepGraph; use rustc::hir; use rustc::hir::intravisit; -use rustc::session::{self, config}; +use rustc::session::{self, CompileIncomplete, config}; use rustc::session::config::{OutputType, OutputTypes, Externs}; use rustc::session::search_paths::{SearchPaths, PathKind}; use rustc_back::dynamic_lib::DynamicLibrary; @@ -253,35 +253,25 @@ fn runtest(test: &str, cratename: &str, cfgs: Vec, libs: SearchPaths, driver::compile_input(&sess, &cstore, &input, &out, &None, None, &control) })); - match res { - Ok(r) => { - match r { - Err(count) => { - if count > 0 && !compile_fail { - sess.fatal("aborting due to previous error(s)") - } else if count == 0 && compile_fail { - panic!("test compiled while it wasn't supposed to") - } - if count > 0 && error_codes.len() > 0 { - let out = String::from_utf8(data.lock().unwrap().to_vec()).unwrap(); - error_codes.retain(|err| !out.contains(err)); - } - } - Ok(()) if compile_fail => { - panic!("test compiled while it wasn't supposed to") - } - _ => {} - } + let compile_result = match res { + Ok(Ok(())) | Ok(Err(CompileIncomplete::Stopped)) => Ok(()), + Err(_) | Ok(Err(CompileIncomplete::Errored(_))) => Err(()) + }; + + match (compile_result, compile_fail) { + (Ok(()), true) => { + panic!("test compiled while it wasn't supposed to") } - Err(_) => { - if !compile_fail { - panic!("couldn't compile the test"); - } + (Ok(()), false) => {} + (Err(()), true) => { if error_codes.len() > 0 { let out = String::from_utf8(data.lock().unwrap().to_vec()).unwrap(); error_codes.retain(|err| !out.contains(err)); } } + (Err(()), false) => { + panic!("couldn't compile the test") + } } if error_codes.len() > 0 { diff --git a/src/test/run-make/llvm-phase/test.rs b/src/test/run-make/llvm-phase/test.rs index ca58e007852..a75dc7e57a9 100644 --- a/src/test/run-make/llvm-phase/test.rs +++ b/src/test/run-make/llvm-phase/test.rs @@ -85,6 +85,6 @@ fn main() { let (result, _) = rustc_driver::run_compiler( &args, &mut JitCalls, Some(box JitLoader), None); if let Err(n) = result { - panic!("Error {}", n); + panic!("Error {:?}", n); } } diff --git a/src/test/ui/block-result/block-must-not-have-result-do.stderr b/src/test/ui/block-result/block-must-not-have-result-do.stderr index a770ebeab35..d4024f41c26 100644 --- a/src/test/ui/block-result/block-must-not-have-result-do.stderr +++ b/src/test/ui/block-result/block-must-not-have-result-do.stderr @@ -7,5 +7,5 @@ error[E0308]: mismatched types = note: expected type `()` found type `bool` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/block-result/block-must-not-have-result-res.stderr b/src/test/ui/block-result/block-must-not-have-result-res.stderr index b1146864566..f60a0c2e5f6 100644 --- a/src/test/ui/block-result/block-must-not-have-result-res.stderr +++ b/src/test/ui/block-result/block-must-not-have-result-res.stderr @@ -7,5 +7,5 @@ error[E0308]: mismatched types = note: expected type `()` found type `bool` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/block-result/block-must-not-have-result-while.stderr b/src/test/ui/block-result/block-must-not-have-result-while.stderr index 31ec7cdd3c5..888a64c1bb1 100644 --- a/src/test/ui/block-result/block-must-not-have-result-while.stderr +++ b/src/test/ui/block-result/block-must-not-have-result-while.stderr @@ -7,5 +7,5 @@ error[E0308]: mismatched types = note: expected type `()` found type `bool` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/block-result/consider-removing-last-semi.stderr b/src/test/ui/block-result/consider-removing-last-semi.stderr index 282583d32a6..5905cfa9322 100644 --- a/src/test/ui/block-result/consider-removing-last-semi.stderr +++ b/src/test/ui/block-result/consider-removing-last-semi.stderr @@ -26,5 +26,5 @@ error[E0308]: mismatched types = note: expected type `std::string::String` found type `()` -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/block-result/issue-11714.stderr b/src/test/ui/block-result/issue-11714.stderr index ed61ec6ca29..376834beab0 100644 --- a/src/test/ui/block-result/issue-11714.stderr +++ b/src/test/ui/block-result/issue-11714.stderr @@ -13,5 +13,5 @@ error[E0308]: mismatched types = note: expected type `i32` found type `()` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/block-result/issue-13428.stderr b/src/test/ui/block-result/issue-13428.stderr index 5e8d92f64e2..7bd4529c463 100644 --- a/src/test/ui/block-result/issue-13428.stderr +++ b/src/test/ui/block-result/issue-13428.stderr @@ -29,5 +29,5 @@ error[E0308]: mismatched types = note: expected type `std::string::String` found type `()` -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/block-result/issue-13624.stderr b/src/test/ui/block-result/issue-13624.stderr index 72ff859d7e9..41113eb7a57 100644 --- a/src/test/ui/block-result/issue-13624.stderr +++ b/src/test/ui/block-result/issue-13624.stderr @@ -16,5 +16,5 @@ error[E0308]: mismatched types = note: expected type `()` found type `a::Enum` -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/block-result/issue-20862.stderr b/src/test/ui/block-result/issue-20862.stderr index e4367f170ce..7c88d789fd3 100644 --- a/src/test/ui/block-result/issue-20862.stderr +++ b/src/test/ui/block-result/issue-20862.stderr @@ -15,5 +15,5 @@ error[E0618]: expected function, found `()` 17 | let x = foo(5)(2); | ^^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/block-result/issue-22645.stderr b/src/test/ui/block-result/issue-22645.stderr index 3921a301c92..a9bcc8bea94 100644 --- a/src/test/ui/block-result/issue-22645.stderr +++ b/src/test/ui/block-result/issue-22645.stderr @@ -17,5 +17,5 @@ error[E0308]: mismatched types = note: expected type `()` found type `Bob` -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/block-result/issue-3563.stderr b/src/test/ui/block-result/issue-3563.stderr index c6ab4cbb2a7..4b1f8b032b7 100644 --- a/src/test/ui/block-result/issue-3563.stderr +++ b/src/test/ui/block-result/issue-3563.stderr @@ -15,5 +15,5 @@ error[E0308]: mismatched types = note: expected type `()` found type `[closure@$DIR/issue-3563.rs:13:9: 13:20 self:_]` -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/block-result/issue-5500.stderr b/src/test/ui/block-result/issue-5500.stderr index bffe2a82ca8..bd670a14f24 100644 --- a/src/test/ui/block-result/issue-5500.stderr +++ b/src/test/ui/block-result/issue-5500.stderr @@ -7,5 +7,5 @@ error[E0308]: mismatched types = note: expected type `()` found type `&_` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/block-result/unexpected-return-on-unit.stderr b/src/test/ui/block-result/unexpected-return-on-unit.stderr index 18d0cc48140..68afd2084f1 100644 --- a/src/test/ui/block-result/unexpected-return-on-unit.stderr +++ b/src/test/ui/block-result/unexpected-return-on-unit.stderr @@ -11,5 +11,5 @@ help: did you mean to add a semicolon here? help: possibly return type missing here? | fn bar() -> usize { -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/closure_context/issue-26046-fn-mut.stderr b/src/test/ui/closure_context/issue-26046-fn-mut.stderr index dbf702e4503..42fc2909dfb 100644 --- a/src/test/ui/closure_context/issue-26046-fn-mut.stderr +++ b/src/test/ui/closure_context/issue-26046-fn-mut.stderr @@ -16,5 +16,5 @@ note: closure is `FnMut` because it mutates the variable `num` here 15 | num += 1; | ^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/closure_context/issue-26046-fn-once.stderr b/src/test/ui/closure_context/issue-26046-fn-once.stderr index 3ec3f0cc9aa..7bfe72d3d6c 100644 --- a/src/test/ui/closure_context/issue-26046-fn-once.stderr +++ b/src/test/ui/closure_context/issue-26046-fn-once.stderr @@ -16,5 +16,5 @@ note: closure is `FnOnce` because it moves the variable `vec` out of its environ 15 | vec | ^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/coercion-missing-tail-expected-type.stderr b/src/test/ui/coercion-missing-tail-expected-type.stderr index 5f9a82d972a..0de0a25e68e 100644 --- a/src/test/ui/coercion-missing-tail-expected-type.stderr +++ b/src/test/ui/coercion-missing-tail-expected-type.stderr @@ -24,5 +24,5 @@ error[E0308]: mismatched types = note: expected type `std::result::Result` found type `()` -error: aborting due to previous error +error: aborting due to 2 previous errors diff --git a/src/test/ui/did_you_mean/issue-40006.stderr b/src/test/ui/did_you_mean/issue-40006.stderr index 8e8773eba3e..3b7f32cf890 100644 --- a/src/test/ui/did_you_mean/issue-40006.stderr +++ b/src/test/ui/did_you_mean/issue-40006.stderr @@ -64,5 +64,5 @@ error[E0038]: the trait `X` cannot be made into an object | = note: method `xxx` has no receiver -error: aborting due to previous error +error: aborting due to 9 previous errors diff --git a/src/test/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr b/src/test/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr index c4858b63c2d..498255cb9ea 100644 --- a/src/test/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr +++ b/src/test/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr @@ -18,5 +18,5 @@ error[E0038]: the trait `std::marker::Copy` cannot be made into an object | = note: the trait cannot require that `Self : Sized` -error: aborting due to previous error +error: aborting due to 3 previous errors diff --git a/src/test/ui/impl-trait/issue-21659-show-relevant-trait-impls-3.stderr b/src/test/ui/impl-trait/issue-21659-show-relevant-trait-impls-3.stderr index 1b1e0eaf203..3bc281726ef 100644 --- a/src/test/ui/impl-trait/issue-21659-show-relevant-trait-impls-3.stderr +++ b/src/test/ui/impl-trait/issue-21659-show-relevant-trait-impls-3.stderr @@ -8,5 +8,5 @@ error[E0599]: no method named `foo` found for type `Bar` in the current scope = note: the following trait defines an item `foo`, perhaps you need to implement it: candidate #1: `Foo` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr b/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr index fa08c3bee9c..d3dbb77490b 100644 --- a/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr +++ b/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr @@ -10,5 +10,5 @@ error[E0599]: no method named `is_empty` found for type `Foo` in the current sco candidate #2: `core::slice::SliceExt` candidate #3: `core::str::StrExt` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/impl-trait/no-method-suggested-traits.stderr b/src/test/ui/impl-trait/no-method-suggested-traits.stderr index 95d3007a4fb..fc441f94842 100644 --- a/src/test/ui/impl-trait/no-method-suggested-traits.stderr +++ b/src/test/ui/impl-trait/no-method-suggested-traits.stderr @@ -226,5 +226,5 @@ error[E0599]: no method named `method3` found for type `std::rc::Rc<&mut std::bo 131 | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method3(); | ^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to 24 previous errors diff --git a/src/test/ui/impl-trait/trait_type.stderr b/src/test/ui/impl-trait/trait_type.stderr index cc7a7153a38..9216c6e2907 100644 --- a/src/test/ui/impl-trait/trait_type.stderr +++ b/src/test/ui/impl-trait/trait_type.stderr @@ -31,5 +31,5 @@ error[E0046]: not all trait items implemented, missing: `fmt` | = note: `fmt` from trait: `fn(&Self, &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error>` -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/interior-mutability/interior-mutability.stderr b/src/test/ui/interior-mutability/interior-mutability.stderr index a9535f1c830..76362f1f494 100644 --- a/src/test/ui/interior-mutability/interior-mutability.stderr +++ b/src/test/ui/interior-mutability/interior-mutability.stderr @@ -10,5 +10,5 @@ error[E0277]: the trait bound `std::cell::UnsafeCell: std::panic::RefUnwind = note: required because it appears within the type `[closure@$DIR/interior-mutability.rs:15:18: 15:35 x:&std::cell::Cell]` = note: required by `std::panic::catch_unwind` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/issue-22644.stderr b/src/test/ui/issue-22644.stderr index a22496357d9..22c16ada05d 100644 --- a/src/test/ui/issue-22644.stderr +++ b/src/test/ui/issue-22644.stderr @@ -20,5 +20,5 @@ error: `<` is interpreted as a start of generic arguments for `usize`, not a com help: if you want to compare the casted value then write: | println!("{}", (a as usize) < 4); -error: aborting due to previous error(s) +error: aborting due to 2 previous errors diff --git a/src/test/ui/issue-26548.stderr b/src/test/ui/issue-26548.stderr index c27ad7680a5..8bfe4ac733b 100644 --- a/src/test/ui/issue-26548.stderr +++ b/src/test/ui/issue-26548.stderr @@ -5,5 +5,5 @@ note: ...which then requires computing layout of `std::option::Option<::It`... = note: ...which then again requires computing layout of `S`, completing the cycle. -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/issue-33525.rs b/src/test/ui/issue-33525.rs new file mode 100644 index 00000000000..0e777fe8a94 --- /dev/null +++ b/src/test/ui/issue-33525.rs @@ -0,0 +1,15 @@ +// Copyright 2017 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() { + a; + "".lorem; + "".ipsum; +} diff --git a/src/test/ui/issue-33525.stderr b/src/test/ui/issue-33525.stderr new file mode 100644 index 00000000000..5de2d98f86a --- /dev/null +++ b/src/test/ui/issue-33525.stderr @@ -0,0 +1,20 @@ +error[E0425]: cannot find value `a` in this scope + --> $DIR/issue-33525.rs:12:5 + | +12 | a; + | ^ not found in this scope + +error[E0609]: no field `lorem` on type `&'static str` + --> $DIR/issue-33525.rs:13:8 + | +13 | "".lorem; + | ^^^^^ + +error[E0609]: no field `ipsum` on type `&'static str` + --> $DIR/issue-33525.rs:14:8 + | +14 | "".ipsum; + | ^^^^^ + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/issue-38875/issue_38875.stderr b/src/test/ui/issue-38875/issue_38875.stderr index ceed83d9313..10bb61ee22a 100644 --- a/src/test/ui/issue-38875/issue_38875.stderr +++ b/src/test/ui/issue-38875/issue_38875.stderr @@ -10,5 +10,5 @@ note: for repeat count here 16 | let test_x = [0; issue_38875_b::FOO]; | ^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.stderr index 4d8c5e039af..83716b7791d 100644 --- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.stderr +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.stderr @@ -6,5 +6,5 @@ error[E0621]: explicit lifetime required in the type of `x` 12 | if x > y { x } else { y } | ^ lifetime `'a` required -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.stderr index 07b276601f4..6d5e94a5e78 100644 --- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.stderr +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.stderr @@ -6,5 +6,5 @@ error[E0621]: explicit lifetime required in parameter type 12 | if x > y { x } else { y } | ^ lifetime `'a` required -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.stderr index 2adf0cd762c..4288fdf89a4 100644 --- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.stderr +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.stderr @@ -6,5 +6,5 @@ error[E0621]: explicit lifetime required in the type of `x` 14 | if x > y { x } else { y } | ^ lifetime `'a` required -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr index 15825017d15..95076bfbdc7 100644 --- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr @@ -7,5 +7,5 @@ error[E0621]: explicit lifetime required in the type of `x` 18 | if true { &self.field } else { x } | ^ lifetime `'a` required -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.stderr index 15ecca61805..9e4f6c42179 100644 --- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.stderr +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.stderr @@ -23,5 +23,5 @@ note: ...but the borrowed content is only valid for the anonymous lifetime #1 de 23 | | } | |_____^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr index 471b3401827..e3fd0192053 100644 --- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr @@ -23,5 +23,5 @@ note: ...but the borrowed content is only valid for the lifetime 'a as defined o 20 | | } | |___^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.stderr index 46fc43eaf57..8551f015db5 100644 --- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.stderr +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.stderr @@ -23,5 +23,5 @@ note: ...but the borrowed content is only valid for the anonymous lifetime #1 de 20 | | } | |_____^ -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.stderr b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.stderr index ea696c51d62..8dba0c33f20 100644 --- a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.stderr +++ b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.stderr @@ -6,5 +6,5 @@ error[E0621]: explicit lifetime required in the type of `x` 16 | y.push(x); | ^ lifetime `'a` required -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/lint/outer-forbid.stderr b/src/test/ui/lint/outer-forbid.stderr index 831b3f65634..df62f5acc00 100644 --- a/src/test/ui/lint/outer-forbid.stderr +++ b/src/test/ui/lint/outer-forbid.stderr @@ -25,5 +25,5 @@ error[E0453]: allow(bad_style) overruled by outer forbid(non_snake_case) 19 | #[allow(unused, unused_variables, bad_style)] | ^^^^^^^^^ overruled by previous forbid -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/mismatched_types/E0281.stderr b/src/test/ui/mismatched_types/E0281.stderr index 8a306ea4192..887412d1be7 100644 --- a/src/test/ui/mismatched_types/E0281.stderr +++ b/src/test/ui/mismatched_types/E0281.stderr @@ -9,5 +9,5 @@ error[E0281]: type mismatch: `[closure@$DIR/E0281.rs:14:9: 14:24]` implements th | = note: required by `foo` -error: aborting due to 2 previous errors +error: aborting due to previous error diff --git a/src/test/ui/mismatched_types/E0409.stderr b/src/test/ui/mismatched_types/E0409.stderr index 45a42b1c271..cc7c0179070 100644 --- a/src/test/ui/mismatched_types/E0409.stderr +++ b/src/test/ui/mismatched_types/E0409.stderr @@ -15,5 +15,5 @@ error[E0308]: mismatched types = note: expected type `&{integer}` found type `{integer}` -error: aborting due to previous error +error: aborting due to 2 previous errors diff --git a/src/test/ui/mismatched_types/binops.stderr b/src/test/ui/mismatched_types/binops.stderr index bb90a19a3ba..6d1a39e0d93 100644 --- a/src/test/ui/mismatched_types/binops.stderr +++ b/src/test/ui/mismatched_types/binops.stderr @@ -46,5 +46,5 @@ error[E0277]: the trait bound `{integer}: std::cmp::PartialEq>` is not implemented for `{integer}` -error: aborting due to 7 previous errors +error: aborting due to 6 previous errors diff --git a/src/test/ui/mismatched_types/closure-arg-count.stderr b/src/test/ui/mismatched_types/closure-arg-count.stderr index f2509040b00..ca71154e872 100644 --- a/src/test/ui/mismatched_types/closure-arg-count.stderr +++ b/src/test/ui/mismatched_types/closure-arg-count.stderr @@ -31,5 +31,5 @@ error[E0593]: closure takes 1 argument but 2 arguments are required | | | expected closure that takes 2 arguments -error: aborting due to 7 previous errors +error: aborting due to 4 previous errors diff --git a/src/test/ui/mismatched_types/for-loop-has-unit-body.stderr b/src/test/ui/mismatched_types/for-loop-has-unit-body.stderr index 6787fe91bf3..4a619804a6c 100644 --- a/src/test/ui/mismatched_types/for-loop-has-unit-body.stderr +++ b/src/test/ui/mismatched_types/for-loop-has-unit-body.stderr @@ -7,5 +7,5 @@ error[E0308]: mismatched types = note: expected type `()` found type `{integer}` -error: aborting due to previous error(s) +error: aborting due to previous error diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr index 88309ab146f..51acdb719b6 100644 --- a/src/test/ui/mismatched_types/issue-36053-2.stderr +++ b/src/test/ui/mismatched_types/issue-36053-2.stderr @@ -17,5 +17,5 @@ error[E0281]: type mismatch: `[closure@$DIR/issue-36053-2.rs:17:39: 17:53]` impl | requires `for<'r> std::ops::FnMut<(&'r &str,)>` | expected &str, found str -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors diff --git a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr index 4ba6dc73023..995a1258454 100644 --- a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr +++ b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr @@ -12,5 +12,5 @@ error[E0281]: type mismatch: `[closure@$DIR/unboxed-closures-vtable-mismatch.rs: | = note: required by `call_it` -error: aborting due to 2 previous errors +error: aborting due to previous error diff --git a/src/test/ui/missing-items/m2.stderr b/src/test/ui/missing-items/m2.stderr index b7ba5efacc4..51afb95b896 100644 --- a/src/test/ui/missing-items/m2.stderr +++ b/src/test/ui/missing-items/m2.stderr @@ -11,5 +11,5 @@ error[E0046]: not all trait items implemented, missing: `CONSTANT`, `Type`, `met = note: `Type` from trait: `type Type;` = note: `method` from trait: `fn(&Self, std::string::String) -> ::Type` -error: aborting due to previous error +error: aborting due to 2 previous errors diff --git a/src/test/ui/resolve/token-error-correct-3.stderr b/src/test/ui/resolve/token-error-correct-3.stderr index 4384822f404..bd3bdf35da6 100644 --- a/src/test/ui/resolve/token-error-correct-3.stderr +++ b/src/test/ui/resolve/token-error-correct-3.stderr @@ -42,5 +42,5 @@ error[E0308]: mismatched types = note: expected type `()` found type `std::result::Result` -error: aborting due to previous error +error: aborting due to 5 previous errors diff --git a/src/test/ui/shadowed-type-parameter.stderr b/src/test/ui/shadowed-type-parameter.stderr index d77523299bc..a16a9c0244f 100644 --- a/src/test/ui/shadowed-type-parameter.stderr +++ b/src/test/ui/shadowed-type-parameter.stderr @@ -24,5 +24,5 @@ error[E0194]: type parameter `T` shadows another type parameter of the same name 18 | fn shadow_in_method(&self) {} | ^ shadows another type parameter -error: aborting due to previous error(s) +error: aborting due to 3 previous errors diff --git a/src/test/ui/span/impl-wrong-item-for-trait.stderr b/src/test/ui/span/impl-wrong-item-for-trait.stderr index ae290b3b11a..2c4c6a148d7 100644 --- a/src/test/ui/span/impl-wrong-item-for-trait.stderr +++ b/src/test/ui/span/impl-wrong-item-for-trait.stderr @@ -85,5 +85,5 @@ error[E0046]: not all trait items implemented, missing: `fmt` | = note: `fmt` from trait: `fn(&Self, &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error>` -error: aborting due to 7 previous errors +error: aborting due to 8 previous errors diff --git a/src/test/ui/span/issue-34264.stderr b/src/test/ui/span/issue-34264.stderr index 98183e2f082..e25caacac8f 100644 --- a/src/test/ui/span/issue-34264.stderr +++ b/src/test/ui/span/issue-34264.stderr @@ -45,5 +45,5 @@ error[E0061]: this function takes 2 parameters but 3 parameters were supplied 19 | bar(1, 2, 3); | ^^^^^^^ expected 2 parameters -error: aborting due to 3 previous errors +error: aborting due to 6 previous errors diff --git a/src/test/ui/transmute/main.stderr b/src/test/ui/transmute/main.stderr index c5d5a4ed8a6..a7fc0808e18 100644 --- a/src/test/ui/transmute/main.stderr +++ b/src/test/ui/transmute/main.stderr @@ -34,5 +34,5 @@ error[E0512]: transmute called with types of different sizes = note: source type: i32 (32 bits) = note: target type: Foo (0 bits) -error: aborting due to previous error(s) +error: aborting due to 4 previous errors diff --git a/src/test/ui/transmute/transmute-from-fn-item-types-error.stderr b/src/test/ui/transmute/transmute-from-fn-item-types-error.stderr index 61ee5cf6128..7f1929050bb 100644 --- a/src/test/ui/transmute/transmute-from-fn-item-types-error.stderr +++ b/src/test/ui/transmute/transmute-from-fn-item-types-error.stderr @@ -104,5 +104,5 @@ error[E0512]: transmute called with types of different sizes = note: source type: std::option::Option (64 bits) = note: target type: u32 (32 bits) -error: aborting due to previous error(s) +error: aborting due to 11 previous errors diff --git a/src/test/ui/transmute/transmute-type-parameters.stderr b/src/test/ui/transmute/transmute-type-parameters.stderr index bb21cfd3e4c..816c62812f3 100644 --- a/src/test/ui/transmute/transmute-type-parameters.stderr +++ b/src/test/ui/transmute/transmute-type-parameters.stderr @@ -52,5 +52,5 @@ error[E0512]: transmute called with types of different sizes = note: source type: std::option::Option (size can vary because of T) = note: target type: i32 (32 bits) -error: aborting due to previous error(s) +error: aborting due to 6 previous errors diff --git a/src/test/ui/type-check/assignment-in-if.stderr b/src/test/ui/type-check/assignment-in-if.stderr index 29439999273..a077f37eae6 100644 --- a/src/test/ui/type-check/assignment-in-if.stderr +++ b/src/test/ui/type-check/assignment-in-if.stderr @@ -55,5 +55,5 @@ error[E0308]: mismatched types = note: expected type `bool` found type `()` -error: aborting due to previous error(s) +error: aborting due to 5 previous errors From 3b91f9406cd4b00ef09d19aca8203ce3539a202d Mon Sep 17 00:00:00 2001 From: est31 Date: Sun, 2 Jul 2017 13:51:28 +0200 Subject: [PATCH 132/162] Update cargo ... to get https://github.com/rust-lang/cargo/pull/4244 and https://github.com/rust-lang/cargo/pull/4246 --- src/Cargo.lock | 2 +- src/tools/cargo | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index c66396973f8..2d42903ad0a 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -157,7 +157,7 @@ dependencies = [ [[package]] name = "cargo" version = "0.21.0" -source = "git+https://github.com/rust-lang/cargo#854bc167bbf74053f821f65cb86d506033f3d3a7" +source = "git+https://github.com/rust-lang/cargo#eb6cf012a6cc23c9c89c4009564de9fccc38b9cb" replace = "cargo 0.21.0" [[package]] diff --git a/src/tools/cargo b/src/tools/cargo index d2d6e675fcb..eb6cf012a6c 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit d2d6e675fcb70cfb91c2cf2fad8cdd345c120316 +Subproject commit eb6cf012a6cc23c9c89c4009564de9fccc38b9cb From d1316b468f969db58ccfc907f8b404d999b6e391 Mon Sep 17 00:00:00 2001 From: Ryan Thomas Date: Thu, 22 Jun 2017 20:49:22 +0100 Subject: [PATCH 133/162] Add docs for Debug* structs. #29355 This adds docs for the Debug* structs as well as examples from the Formatter::debug_* methods, so that a user knows how to construct them. I added these examples as the builders module is not public and hence the debug_*_new() functions are not available to a user. r? @steveklabnik Review comments. Mainly adding in the links for all of the structs and functions. Remove rust tag on code blocks. --- src/libcore/fmt/builders.rs | 139 +++++++++++++++++++++++++++++++++--- 1 file changed, 129 insertions(+), 10 deletions(-) diff --git a/src/libcore/fmt/builders.rs b/src/libcore/fmt/builders.rs index 102e3c0bd7b..322df6e5b47 100644 --- a/src/libcore/fmt/builders.rs +++ b/src/libcore/fmt/builders.rs @@ -49,9 +49,37 @@ impl<'a, 'b: 'a> fmt::Write for PadAdapter<'a, 'b> { } } -/// A struct to help with `fmt::Debug` implementations. +/// A struct to help with [`fmt::Debug`](trait.Debug.html) implementations. /// -/// Constructed by the `Formatter::debug_struct` method. +/// This is useful when you wish to output a formatted struct as a part of your +/// [`Debug::fmt`](trait.Debug.html#tymethod.fmt) implementation. +/// +/// This can be constructed by the +/// [`Formatter::debug_struct`](struct.Formatter.html#method.debug_struct) +/// method. +/// +/// # Example +/// +/// ``` +/// use std::fmt; +/// +/// struct Foo { +/// bar: i32, +/// baz: String, +/// } +/// +/// impl fmt::Debug for Foo { +/// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { +/// fmt.debug_struct("Foo") +/// .field("bar", &self.bar) +/// .field("baz", &self.baz) +/// .finish() +/// } +/// } +/// +/// // prints "Foo { bar: 10, baz: "Hello World" }" +/// println!("{:?}", Foo { bar: 10, baz: "Hello World".to_string() }); +/// ``` #[must_use] #[allow(missing_debug_implementations)] #[stable(feature = "debug_builders", since = "1.2.0")] @@ -116,9 +144,34 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> { } } -/// A struct to help with `fmt::Debug` implementations. +/// A struct to help with [`fmt::Debug`](trait.Debug.html) implementations. /// -/// Constructed by the `Formatter::debug_tuple` method. +/// This is useful when you wish to output a formatted tuple as a part of your +/// [`Debug::fmt`](trait.Debug.html#tymethod.fmt) implementation. +/// +/// This can be constructed by the +/// [`Formatter::debug_tuple`](struct.Formatter.html#method.debug_tuple) +/// method. +/// +/// # Example +/// +/// ``` +/// use std::fmt; +/// +/// struct Foo(i32, String); +/// +/// impl fmt::Debug for Foo { +/// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { +/// fmt.debug_tuple("Foo") +/// .field(&self.0) +/// .field(&self.1) +/// .finish() +/// } +/// } +/// +/// // prints "Foo(10, "Hello World")" +/// println!("{:?}", Foo(10, "Hello World".to_string())); +/// ``` #[must_use] #[allow(missing_debug_implementations)] #[stable(feature = "debug_builders", since = "1.2.0")] @@ -228,9 +281,31 @@ impl<'a, 'b: 'a> DebugInner<'a, 'b> { } } -/// A struct to help with `fmt::Debug` implementations. +/// A struct to help with [`fmt::Debug`](trait.Debug.html) implementations. /// -/// Constructed by the `Formatter::debug_set` method. +/// This is useful when you wish to output a formatted set of items as a part +/// of your [`Debug::fmt`](trait.Debug.html#tymethod.fmt) implementation. +/// +/// This can be constructed by the +/// [`Formatter::debug_set`](struct.Formatter.html#method.debug_set) +/// method. +/// +/// # Example +/// +/// ``` +/// use std::fmt; +/// +/// struct Foo(Vec); +/// +/// impl fmt::Debug for Foo { +/// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { +/// fmt.debug_set().entries(self.0.iter()).finish() +/// } +/// } +/// +/// // prints "{10, 11}" +/// println!("{:?}", Foo(vec![10, 11])); +/// ``` #[must_use] #[allow(missing_debug_implementations)] #[stable(feature = "debug_builders", since = "1.2.0")] @@ -277,9 +352,31 @@ impl<'a, 'b: 'a> DebugSet<'a, 'b> { } } -/// A struct to help with `fmt::Debug` implementations. +/// A struct to help with [`fmt::Debug`](trait.Debug.html) implementations. /// -/// Constructed by the `Formatter::debug_list` method. +/// This is useful when you wish to output a formatted list of items as a part +/// of your [`Debug::fmt`](trait.Debug.html#tymethod.fmt) implementation. +/// +/// This can be constructed by the +/// [`Formatter::debug_list`](struct.Formatter.html#method.debug_list) +/// method. +/// +/// # Example +/// +/// ``` +/// use std::fmt; +/// +/// struct Foo(Vec); +/// +/// impl fmt::Debug for Foo { +/// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { +/// fmt.debug_list().entries(self.0.iter()).finish() +/// } +/// } +/// +/// // prints "[10, 11]" +/// println!("{:?}", Foo(vec![10, 11])); +/// ``` #[must_use] #[allow(missing_debug_implementations)] #[stable(feature = "debug_builders", since = "1.2.0")] @@ -326,9 +423,31 @@ impl<'a, 'b: 'a> DebugList<'a, 'b> { } } -/// A struct to help with `fmt::Debug` implementations. +/// A struct to help with [`fmt::Debug`](trait.Debug.html) implementations. /// -/// Constructed by the `Formatter::debug_map` method. +/// This is useful when you wish to output a formatted map as a part of your +/// [`Debug::fmt`](trait.Debug.html#tymethod.fmt) implementation. +/// +/// This can be constructed by the +/// [`Formatter::debug_map`](struct.Formatter.html#method.debug_map) +/// method. +/// +/// # Example +/// +/// ``` +/// use std::fmt; +/// +/// struct Foo(Vec<(String, i32)>); +/// +/// impl fmt::Debug for Foo { +/// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { +/// fmt.debug_map().entries(self.0.iter().map(|&(ref k, ref v)| (k, v))).finish() +/// } +/// } +/// +/// // prints "{"A": 10, "B": 11}" +/// println!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])); +/// ``` #[must_use] #[allow(missing_debug_implementations)] #[stable(feature = "debug_builders", since = "1.2.0")] From 21149bcd530e3dcd817a9cc2053f3a6b82b7a379 Mon Sep 17 00:00:00 2001 From: Stjepan Glavina Date: Sun, 2 Jul 2017 19:14:16 +0200 Subject: [PATCH 134/162] Fix lint errors --- src/liballoc/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 6f4e300fd3c..8bdf93fd2ed 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -83,7 +83,6 @@ #![cfg_attr(not(test), feature(core_float))] #![cfg_attr(not(test), feature(exact_size_is_empty))] #![cfg_attr(not(test), feature(slice_rotate))] -#![cfg_attr(not(test), feature(sort_unstable))] #![cfg_attr(not(test), feature(str_checked_slicing))] #![cfg_attr(test, feature(rand, test))] #![feature(allocator)] From 66f8cddae55ae3699932b424823dc21cfa566e6b Mon Sep 17 00:00:00 2001 From: Stjepan Glavina Date: Sun, 2 Jul 2017 21:29:39 +0200 Subject: [PATCH 135/162] Remove the remaining feature gates --- src/liballoc/benches/lib.rs | 1 - src/libcore/tests/lib.rs | 1 - src/librustc/lib.rs | 1 - src/librustc_incremental/lib.rs | 1 - src/librustc_metadata/lib.rs | 1 - 5 files changed, 5 deletions(-) diff --git a/src/liballoc/benches/lib.rs b/src/liballoc/benches/lib.rs index 958020d0b0e..5a5eb846b73 100644 --- a/src/liballoc/benches/lib.rs +++ b/src/liballoc/benches/lib.rs @@ -14,7 +14,6 @@ #![feature(rand)] #![feature(repr_simd)] #![feature(slice_rotate)] -#![feature(sort_unstable)] #![feature(test)] extern crate test; diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index 337f8aa31dc..b0a57d97d5e 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -34,7 +34,6 @@ #![feature(slice_patterns)] #![feature(slice_rotate)] #![feature(sort_internals)] -#![feature(sort_unstable)] #![feature(specialization)] #![feature(step_by)] #![feature(step_trait)] diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index b81c56e5ee8..e4cf893375c 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -39,7 +39,6 @@ #![feature(specialization)] #![feature(unboxed_closures)] #![feature(discriminant_value)] -#![feature(sort_unstable)] #![feature(trace_macros)] #![feature(test)] diff --git a/src/librustc_incremental/lib.rs b/src/librustc_incremental/lib.rs index 5bd7a24bdaf..ac3149b90b8 100644 --- a/src/librustc_incremental/lib.rs +++ b/src/librustc_incremental/lib.rs @@ -20,7 +20,6 @@ #![feature(rand)] #![feature(conservative_impl_trait)] -#![feature(sort_unstable)] extern crate graphviz; #[macro_use] extern crate rustc; diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index 12997f24c74..99b718ea07b 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -26,7 +26,6 @@ #![feature(specialization)] #![feature(discriminant_value)] #![feature(rustc_private)] -#![feature(sort_unstable)] #[macro_use] extern crate log; From 3146e552d199a4db223773e0b80ce8cd510df78a Mon Sep 17 00:00:00 2001 From: Cengiz Can Date: Tue, 30 May 2017 00:13:09 +0300 Subject: [PATCH 136/162] use PAGER to view --explain output #32665 --- src/librustc_driver/lib.rs | 46 +++++++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index f2aacbc629f..f408316c9f9 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -84,10 +84,11 @@ use std::cmp::max; use std::cmp::Ordering::Equal; use std::default::Default; use std::env; +use std::ffi::OsString; use std::io::{self, Read, Write}; use std::iter::repeat; use std::path::PathBuf; -use std::process; +use std::process::{self, Command, Stdio}; use std::rc::Rc; use std::str; use std::sync::{Arc, Mutex}; @@ -354,6 +355,8 @@ fn handle_explain(code: &str, match descriptions.find_description(&normalised) { Some(ref description) => { let mut is_in_code_block = false; + let mut text = String::new(); + // Slice off the leading newline and print. for line in description[1..].lines() { let indent_level = line.find(|c: char| !c.is_whitespace()) @@ -361,13 +364,17 @@ fn handle_explain(code: &str, let dedented_line = &line[indent_level..]; if dedented_line.starts_with("```") { is_in_code_block = !is_in_code_block; - println!("{}", &line[..(indent_level+3)]); + text.push_str(&line[..(indent_level+3)]); + text.push('\n'); } else if is_in_code_block && dedented_line.starts_with("# ") { continue; } else { - println!("{}", line); + text.push_str(line); + text.push('\n'); } } + + show_content_with_pager(&text); } None => { early_error(output, &format!("no extended information for {}", code)); @@ -375,6 +382,39 @@ fn handle_explain(code: &str, } } +fn show_content_with_pager(content: &String) { + let pager_name = env::var_os("PAGER").unwrap_or(if cfg!(windows) { + OsString::from("more.com") + } else { + OsString::from("less") + }); + + let mut fallback_to_println = false; + + match Command::new(pager_name).stdin(Stdio::piped()).spawn() { + Ok(mut pager) => { + if let Some(mut pipe) = pager.stdin.as_mut() { + if pipe.write_all(content.as_bytes()).is_err() { + fallback_to_println = true; + } + } + + if pager.wait().is_err() { + fallback_to_println = true; + } + } + Err(_) => { + fallback_to_println = true; + } + } + + // If pager fails for whatever reason, we should still print the content + // to standard output + if fallback_to_println { + println!("{}", content); + } +} + impl<'a> CompilerCalls<'a> for RustcDefaultCalls { fn early_callback(&mut self, matches: &getopts::Matches, From 1beeb5a277ee18a8817b85d31595c7980fdf3627 Mon Sep 17 00:00:00 2001 From: Cengiz Can Date: Thu, 29 Jun 2017 10:40:51 +0300 Subject: [PATCH 137/162] do not append an extra newline char --- src/librustc_driver/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index f408316c9f9..58dd21c9292 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -411,7 +411,7 @@ fn show_content_with_pager(content: &String) { // If pager fails for whatever reason, we should still print the content // to standard output if fallback_to_println { - println!("{}", content); + print!("{}", content); } } From 08b6bebbad39874a71f37dfb4c607544b6c943e9 Mon Sep 17 00:00:00 2001 From: Cengiz Can Date: Thu, 29 Jun 2017 17:57:54 +0300 Subject: [PATCH 138/162] use unwrap_or_else to prevent unnecessary alloc --- src/librustc_driver/lib.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 58dd21c9292..41a36141cbf 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -365,13 +365,12 @@ fn handle_explain(code: &str, if dedented_line.starts_with("```") { is_in_code_block = !is_in_code_block; text.push_str(&line[..(indent_level+3)]); - text.push('\n'); } else if is_in_code_block && dedented_line.starts_with("# ") { continue; } else { text.push_str(line); - text.push('\n'); } + text.push('\n'); } show_content_with_pager(&text); @@ -383,7 +382,7 @@ fn handle_explain(code: &str, } fn show_content_with_pager(content: &String) { - let pager_name = env::var_os("PAGER").unwrap_or(if cfg!(windows) { + let pager_name = env::var_os("PAGER").unwrap_or_else(|| if cfg!(windows) { OsString::from("more.com") } else { OsString::from("less") From 7b0a7fdaf250ba5b5c436c8de9aacf94b519b57f Mon Sep 17 00:00:00 2001 From: Cengiz Can Date: Sun, 2 Jul 2017 23:27:10 +0300 Subject: [PATCH 139/162] do not spawn pager if not tty --- src/Cargo.lock | 12 ++++++++++++ src/librustc_driver/Cargo.toml | 1 + src/librustc_driver/lib.rs | 9 ++++++++- 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 2d42903ad0a..075a2167ea3 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -551,6 +551,16 @@ dependencies = [ "xz2 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "isatty" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "itoa" version = "0.3.1" @@ -1202,6 +1212,7 @@ dependencies = [ "arena 0.0.0", "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "graphviz 0.0.0", + "isatty 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "proc_macro_plugin 0.0.0", "rustc 0.0.0", @@ -2056,6 +2067,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum handlebars 0.25.3 (registry+https://github.com/rust-lang/crates.io-index)" = "15bdf598fc3c2de40c6b340213028301c0d225eea55a2294e6cc148074e557a1" "checksum hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d6a22814455d41612f41161581c2883c0c6a1c41852729b17d5ed88f01e153aa" "checksum idna 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2233d4940b1f19f0418c158509cd7396b8d70a5db5705ce410914dc8fa603b37" +"checksum isatty 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fa500db770a99afe2a0f2229be2a3d09c7ed9d7e4e8440bf71253141994e240f" "checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c" "checksum jobserver 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4e28adc987f6d0521ef66ad60b055968107b164b3bb3cf3dc8474e0a380474a6" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml index 2e949f48c17..6415dbccbfc 100644 --- a/src/librustc_driver/Cargo.toml +++ b/src/librustc_driver/Cargo.toml @@ -35,3 +35,4 @@ serialize = { path = "../libserialize" } syntax = { path = "../libsyntax" } syntax_ext = { path = "../libsyntax_ext" } syntax_pos = { path = "../libsyntax_pos" } +isatty = "0.1" diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 41a36141cbf..2ecbb89361e 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -56,6 +56,7 @@ extern crate log; extern crate syntax; extern crate syntax_ext; extern crate syntax_pos; +extern crate isatty; use driver::CompileController; use pretty::{PpMode, UserIdentifiedItem}; @@ -100,6 +101,8 @@ use syntax::feature_gate::{GatedCfg, UnstableFeatures}; use syntax::parse::{self, PResult}; use syntax_pos::{DUMMY_SP, MultiSpan}; +use isatty::stdout_isatty; + #[cfg(test)] pub mod test; @@ -373,7 +376,11 @@ fn handle_explain(code: &str, text.push('\n'); } - show_content_with_pager(&text); + if stdout_isatty() { + show_content_with_pager(&text); + } else { + print!("{}", text); + } } None => { early_error(output, &format!("no extended information for {}", code)); From 0e18a9cd55826eca5f2804a06527541140a71925 Mon Sep 17 00:00:00 2001 From: Cengiz Can Date: Mon, 3 Jul 2017 01:34:25 +0300 Subject: [PATCH 140/162] use embedded implementation instead of istty crate --- src/librustc_driver/lib.rs | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 2ecbb89361e..934015c9536 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -56,7 +56,6 @@ extern crate log; extern crate syntax; extern crate syntax_ext; extern crate syntax_pos; -extern crate isatty; use driver::CompileController; use pretty::{PpMode, UserIdentifiedItem}; @@ -101,8 +100,6 @@ use syntax::feature_gate::{GatedCfg, UnstableFeatures}; use syntax::parse::{self, PResult}; use syntax_pos::{DUMMY_SP, MultiSpan}; -use isatty::stdout_isatty; - #[cfg(test)] pub mod test; @@ -347,6 +344,35 @@ pub trait CompilerCalls<'a> { #[derive(Copy, Clone)] pub struct RustcDefaultCalls; +/** + * TODO remove these and use winapi 0.3 instead + * + * These are duplicated in + * - bootstrap/compile.rs#L478 + * - librustc_errors/emitter.rs#L1253 + */ +#[cfg(unix)] +fn stdout_isatty() -> bool { + unsafe { libc::isatty(libc::STDOUT_FILENO) != 0 } +} +#[cfg(windows)] +fn stdout_isatty() -> bool { + type DWORD = u32; + type BOOL = i32; + type HANDLE = *mut u8; + type LPDWORD = *mut u32; + const STD_OUTPUT_HANDLE: DWORD = -11i32 as DWORD; + extern "system" { + fn GetStdHandle(which: DWORD) -> HANDLE; + fn GetConsoleMode(hConsoleHandle: HANDLE, lpMode: LPDWORD) -> BOOL; + } + unsafe { + let handle = GetStdHandle(STD_OUTPUT_HANDLE); + let mut out = 0; + GetConsoleMode(handle, &mut out) != 0 + } +} + fn handle_explain(code: &str, descriptions: &errors::registry::Registry, output: ErrorOutputType) { From e1a91443cdd78101b0c96c84848b99e07ee133d6 Mon Sep 17 00:00:00 2001 From: Cengiz Can Date: Mon, 3 Jul 2017 11:45:31 +0300 Subject: [PATCH 141/162] use single line comments --- src/librustc_driver/lib.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 934015c9536..802ed2a489b 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -344,17 +344,13 @@ pub trait CompilerCalls<'a> { #[derive(Copy, Clone)] pub struct RustcDefaultCalls; -/** - * TODO remove these and use winapi 0.3 instead - * - * These are duplicated in - * - bootstrap/compile.rs#L478 - * - librustc_errors/emitter.rs#L1253 - */ +// FIXME remove these and use winapi 0.3 instead +// Duplicates: bootstrap/compile.rs, librustc_errors/emitter.rs #[cfg(unix)] fn stdout_isatty() -> bool { unsafe { libc::isatty(libc::STDOUT_FILENO) != 0 } } + #[cfg(windows)] fn stdout_isatty() -> bool { type DWORD = u32; From 06de114f898f6f92a3c6cfb220dc957611087ef9 Mon Sep 17 00:00:00 2001 From: Cengiz Can Date: Mon, 3 Jul 2017 11:46:12 +0300 Subject: [PATCH 142/162] remove isatty dependency --- src/Cargo.lock | 12 ------------ src/librustc_driver/Cargo.toml | 1 - 2 files changed, 13 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 075a2167ea3..2d42903ad0a 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -551,16 +551,6 @@ dependencies = [ "xz2 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "isatty" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "itoa" version = "0.3.1" @@ -1212,7 +1202,6 @@ dependencies = [ "arena 0.0.0", "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "graphviz 0.0.0", - "isatty 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "proc_macro_plugin 0.0.0", "rustc 0.0.0", @@ -2067,7 +2056,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum handlebars 0.25.3 (registry+https://github.com/rust-lang/crates.io-index)" = "15bdf598fc3c2de40c6b340213028301c0d225eea55a2294e6cc148074e557a1" "checksum hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d6a22814455d41612f41161581c2883c0c6a1c41852729b17d5ed88f01e153aa" "checksum idna 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2233d4940b1f19f0418c158509cd7396b8d70a5db5705ce410914dc8fa603b37" -"checksum isatty 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fa500db770a99afe2a0f2229be2a3d09c7ed9d7e4e8440bf71253141994e240f" "checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c" "checksum jobserver 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4e28adc987f6d0521ef66ad60b055968107b164b3bb3cf3dc8474e0a380474a6" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml index 6415dbccbfc..2e949f48c17 100644 --- a/src/librustc_driver/Cargo.toml +++ b/src/librustc_driver/Cargo.toml @@ -35,4 +35,3 @@ serialize = { path = "../libserialize" } syntax = { path = "../libsyntax" } syntax_ext = { path = "../libsyntax_ext" } syntax_pos = { path = "../libsyntax_pos" } -isatty = "0.1" From 3ba0f07f08516c365bc33615e162f83ab182f0b5 Mon Sep 17 00:00:00 2001 From: est31 Date: Mon, 3 Jul 2017 16:16:45 +0200 Subject: [PATCH 143/162] Make sNaN removal code tolerate different sNaN encodings IEEE 754-1985 specifies the encoding of NaN floating point numbers, but while it mentions that NaNs can be subdivided into signaling and quiet ones, it doesn't fix the encoding of signaling NaNs in binary formats. This led to different implementations (CPUs) having different encodings. IEEE 754-2008 finally specified the encoding of signaling NaNs but some architectures are compatible with it, while others aren't. Certain MIPS and PA-RISC CPUs have different encodings for signaling NaNs. In order to have the float <-> binary cast feature of the std library be portable to them, we don't mask any quiet NaNs like we did before (only being compliant to IEEE 754-2008 and nothing else), but instead we simply pass a known good NaN instead. Note that in the code removed there was a bug; the 64 bit mask for quiet NaNs should have been `0x0008000000000000` instead of the specified `0x0001000000000000`. --- src/libstd/f32.rs | 24 ++++++++++++++++-------- src/libstd/f64.rs | 13 ++++++++----- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs index 7d79fb07811..a6eb17c8fa4 100644 --- a/src/libstd/f32.rs +++ b/src/libstd/f32.rs @@ -1131,13 +1131,16 @@ impl f32 { #[inline] pub fn from_bits(mut v: u32) -> Self { const EXP_MASK: u32 = 0x7F800000; - const QNAN_MASK: u32 = 0x00400000; const FRACT_MASK: u32 = 0x007FFFFF; if v & EXP_MASK == EXP_MASK && v & FRACT_MASK != 0 { - // If we have a NaN value, we - // convert signaling NaN values to quiet NaN - // by setting the the highest bit of the fraction - v |= QNAN_MASK; + // While IEEE 754-2008 specifies encodings for quiet NaNs + // and signaling ones, certain MIPS and PA-RISC + // CPUs treat signaling NaNs differently. + // Therefore to be safe, we pass a known quiet NaN + // if v is any kind of NaN. + // The check above only assumes IEEE 754-1985 to be + // valid. + v = unsafe { ::mem::transmute(NAN) }; } unsafe { ::mem::transmute(v) } } @@ -1732,8 +1735,15 @@ mod tests { } #[test] fn test_snan_masking() { + // NOTE: this test assumes that our current platform + // implements IEEE 754-2008 that specifies the difference + // in encoding of quiet and signaling NaNs. + // If you are porting Rust to a platform that does not + // implement IEEE 754-2008 (but e.g. IEEE 754-1985, which + // only says that "Signaling NaNs shall be reserved operands" + // but doesn't specify the actual setup), feel free to + // cfg out this test. let snan: u32 = 0x7F801337; - const PAYLOAD_MASK: u32 = 0x003FFFFF; const QNAN_MASK: u32 = 0x00400000; let nan_masked_fl = f32::from_bits(snan); let nan_masked = nan_masked_fl.to_bits(); @@ -1742,7 +1752,5 @@ mod tests { // Ensure that we have a quiet NaN assert_ne!(nan_masked & QNAN_MASK, 0); assert!(nan_masked_fl.is_nan()); - // Ensure the payload wasn't touched during conversion - assert_eq!(nan_masked & PAYLOAD_MASK, snan & PAYLOAD_MASK); } } diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs index d5b0cd3a1fc..4d8d8b4ebe6 100644 --- a/src/libstd/f64.rs +++ b/src/libstd/f64.rs @@ -1046,13 +1046,16 @@ impl f64 { #[inline] pub fn from_bits(mut v: u64) -> Self { const EXP_MASK: u64 = 0x7FF0000000000000; - const QNAN_MASK: u64 = 0x0001000000000000; const FRACT_MASK: u64 = 0x000FFFFFFFFFFFFF; if v & EXP_MASK == EXP_MASK && v & FRACT_MASK != 0 { - // If we have a NaN value, we - // convert signaling NaN values to quiet NaN - // by setting the the highest bit of the fraction - v |= QNAN_MASK; + // While IEEE 754-2008 specifies encodings for quiet NaNs + // and signaling ones, certain MIPS and PA-RISC + // CPUs treat signaling NaNs differently. + // Therefore to be safe, we pass a known quiet NaN + // if v is any kind of NaN. + // The check above only assumes IEEE 754-1985 to be + // valid. + v = unsafe { ::mem::transmute(NAN) }; } unsafe { ::mem::transmute(v) } } From d68c3ab17b6f6c3b71d0531063aec8e64098f59c Mon Sep 17 00:00:00 2001 From: Anders Kaseorg Date: Mon, 3 Jul 2017 17:18:01 -0400 Subject: [PATCH 144/162] Document unintuitive argument order for Vec::dedup_by relation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When trying to use dedup_by to merge some auxiliary information from removed elements into kept elements, I was surprised to observe that vec.dedup_by(same_bucket) calls same_bucket(a, b) where b appears before a in the vector, and discards a when true is returned. This argument order is probably a bug, but since it has already been stabilized, I guess we should document it as a feature and move on. (Vec::dedup also uses == with this unexpected argument order, but I figure that’s not important since == is expected to be symmetric with no side effects.) Signed-off-by: Anders Kaseorg --- src/liballoc/tests/vec.rs | 5 +++++ src/liballoc/vec.rs | 11 +++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/liballoc/tests/vec.rs b/src/liballoc/tests/vec.rs index fdf453b39cf..17f1229c206 100644 --- a/src/liballoc/tests/vec.rs +++ b/src/liballoc/tests/vec.rs @@ -274,6 +274,11 @@ fn test_dedup_by() { vec.dedup_by(|a, b| a.eq_ignore_ascii_case(b)); assert_eq!(vec, ["foo", "bar", "baz", "bar"]); + + let mut vec = vec![("foo", 1), ("foo", 2), ("bar", 3), ("bar", 4), ("bar", 5)]; + vec.dedup_by(|a, b| a.0 == b.0 && { b.1 += a.1; true }); + + assert_eq!(vec, [("foo", 3), ("bar", 12)]); } #[test] diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 5d1999a4262..1a5975686df 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -823,7 +823,8 @@ impl Vec { } } - /// Removes consecutive elements in the vector that resolve to the same key. + /// Removes all but the first of consecutive elements in the vector that resolve to the same + /// key. /// /// If the vector is sorted, this removes all duplicates. /// @@ -842,11 +843,13 @@ impl Vec { self.dedup_by(|a, b| key(a) == key(b)) } - /// Removes consecutive elements in the vector according to a predicate. + /// Removes all but the first of consecutive elements in the vector satisfying a given equality + /// relation. /// /// The `same_bucket` function is passed references to two elements from the vector, and - /// returns `true` if the elements compare equal, or `false` if they do not. Only the first - /// of adjacent equal items is kept. + /// returns `true` if the elements compare equal, or `false` if they do not. The elements are + /// passed in opposite order from their order in the vector, so if `same_bucket(a, b)` returns + /// `true`, `a` is removed. /// /// If the vector is sorted, this removes all duplicates. /// From dcd7c5f4e8356c786923f86dc544aff03fba29bb Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Mon, 3 Jul 2017 13:46:37 -1000 Subject: [PATCH 145/162] Add a stability marker for core::cmp::Reverse.0 Closes #43027 --- src/libcore/cmp.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 7882a8ce5c8..f133bd93c91 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -343,7 +343,7 @@ impl Ordering { /// ``` #[derive(PartialEq, Eq, Debug)] #[stable(feature = "reverse_cmp_key", since = "1.19.0")] -pub struct Reverse(pub T); +pub struct Reverse(#[stable(feature = "reverse_cmp_key", since = "1.19.0")] pub T); #[stable(feature = "reverse_cmp_key", since = "1.19.0")] impl PartialOrd for Reverse { From 857d9dbabab5cb2ad8809e46703f77071278954a Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Mon, 3 Jul 2017 22:04:57 -0400 Subject: [PATCH 146/162] README: note how to enable debugging for rustc --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0b209fd3e94..a1f01861075 100644 --- a/README.md +++ b/README.md @@ -40,8 +40,9 @@ Read ["Installation"] from [The Book]. > ***Note:*** Install locations can be adjusted by copying the config file > from `./src/bootstrap/config.toml.example` to `./config.toml`, and - > adjusting the `prefix` option under `[install]`. Various other options are - > also supported, and are documented in the config file. + > adjusting the `prefix` option under `[install]`. Various other options, such + > as enabling debug information, are also supported, and are documented in + > the config file. When complete, `sudo ./x.py install` will place several programs into `/usr/local/bin`: `rustc`, the Rust compiler, and `rustdoc`, the From 558ce91e09226abb12b70cf03df133224c467376 Mon Sep 17 00:00:00 2001 From: Stjepan Glavina Date: Tue, 4 Jul 2017 15:14:08 +0200 Subject: [PATCH 147/162] Minor fix in docs for Vec --- src/liballoc/vec.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index e118d406ecf..6918e057ab1 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -221,7 +221,7 @@ use raw_vec::RawVec; /// on an empty Vec, it will not allocate memory. Similarly, if you store zero-sized /// types inside a `Vec`, it will not allocate space for them. *Note that in this case /// the `Vec` may not report a [`capacity`] of 0*. `Vec` will allocate if and only -/// if [`mem::size_of::`]` * capacity() > 0`. In general, `Vec`'s allocation +/// if [`mem::size_of::`]`() * capacity() > 0`. In general, `Vec`'s allocation /// details are subtle enough that it is strongly recommended that you only /// free memory allocated by a `Vec` by creating a new `Vec` and dropping it. /// From 01e83a362ca2eee456e222e72cc6b65b951920dc Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Wed, 21 Jun 2017 11:15:49 -0600 Subject: [PATCH 148/162] Don't allocate args in order to run find. --- src/bootstrap/flags.rs | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index dc9dac73627..cb455ca6a14 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -122,16 +122,15 @@ To learn more about a subcommand, run `./x.py -h`"); // the subcommand. Therefore we must manually identify the subcommand first, so that we can // complete the definition of the options. Then we can use the getopt::Matches object from // there on out. - let mut possible_subcommands = args.iter().collect::>(); - possible_subcommands.retain(|&s| - (s == "build") - || (s == "test") - || (s == "bench") - || (s == "doc") - || (s == "clean") - || (s == "dist") - || (s == "install")); - let subcommand = match possible_subcommands.first() { + let subcommand = args.iter().find(|&s| + (s == "build") + || (s == "test") + || (s == "bench") + || (s == "doc") + || (s == "clean") + || (s == "dist") + || (s == "install")); + let subcommand = match subcommand { Some(s) => s, None => { // No subcommand -- show the general usage and subcommand help From 7ed4ee272e5adf8cd267278acb62b9d9312ee34b Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Wed, 21 Jun 2017 17:03:14 -0600 Subject: [PATCH 149/162] Clean up and restructure sanity checking. --- src/bootstrap/config.rs | 1 + src/bootstrap/flags.rs | 2 +- src/bootstrap/sanity.rs | 143 +++++++++++++++++++--------------------- 3 files changed, 69 insertions(+), 77 deletions(-) diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 3ada846e382..12862e136da 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -119,6 +119,7 @@ pub struct Config { /// Per-target configuration stored in the global configuration structure. #[derive(Default)] pub struct Target { + /// Some(path to llvm-config) if using an external LLVM. pub llvm_config: Option, pub jemalloc: Option, pub cc: Option, diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index cb455ca6a14..029118eb647 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -163,7 +163,7 @@ To learn more about a subcommand, run `./x.py -h`"); let mut pass_sanity_check = true; match matches.free.get(0) { Some(check_subcommand) => { - if &check_subcommand != subcommand { + if check_subcommand != subcommand { pass_sanity_check = false; } }, diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index 46d047bb015..41482ac57f9 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -18,9 +18,9 @@ //! In theory if we get past this phase it's a bug if a build fails, but in //! practice that's likely not true! -use std::collections::HashSet; +use std::collections::HashMap; use std::env; -use std::ffi::{OsStr, OsString}; +use std::ffi::{OsString, OsStr}; use std::fs; use std::process::Command; use std::path::PathBuf; @@ -29,9 +29,46 @@ use build_helper::output; use Build; +struct Finder { + cache: HashMap>, + path: OsString, +} + +impl Finder { + fn new() -> Self { + Self { + cache: HashMap::new(), + path: env::var_os("PATH").unwrap_or_default() + } + } + + fn maybe_have>(&mut self, cmd: S) -> Option { + let cmd: OsString = cmd.as_ref().into(); + let path = self.path.clone(); + self.cache.entry(cmd.clone()).or_insert_with(|| { + for path in env::split_paths(&path) { + let target = path.join(&cmd); + let mut cmd_alt = cmd.clone(); + cmd_alt.push(".exe"); + if target.is_file() || // some/path/git + target.with_extension("exe").exists() || // some/path/git.exe + target.join(&cmd_alt).exists() { // some/path/git/git.exe + return Some(target); + } + } + return None; + }).clone() + } + + fn must_have>(&mut self, cmd: S) -> PathBuf { + self.maybe_have(&cmd).unwrap_or_else(|| { + panic!("\n\ncouldn't find required command: {:?}\n\n", cmd.as_ref()); + }) + } +} + pub fn check(build: &mut Build) { - let mut checked = HashSet::new(); - let path = env::var_os("PATH").unwrap_or(OsString::new()); + let path = env::var_os("PATH").unwrap_or_default(); // On Windows, quotes are invalid characters for filename paths, and if // one is present as part of the PATH then that can lead to the system // being unable to identify the files properly. See @@ -41,33 +78,12 @@ pub fn check(build: &mut Build) { panic!("PATH contains invalid character '\"'"); } } - let have_cmd = |cmd: &OsStr| { - for path in env::split_paths(&path) { - let target = path.join(cmd); - let mut cmd_alt = cmd.to_os_string(); - cmd_alt.push(".exe"); - if target.is_file() || - target.with_extension("exe").exists() || - target.join(cmd_alt).exists() { - return Some(target); - } - } - return None; - }; - - let mut need_cmd = |cmd: &OsStr| { - if !checked.insert(cmd.to_owned()) { - return - } - if have_cmd(cmd).is_none() { - panic!("\n\ncouldn't find required command: {:?}\n\n", cmd); - } - }; + let mut cmd_finder = Finder::new(); // If we've got a git directory we're gona need git to update // submodules and learn about various other aspects. if build.src_is_git { - need_cmd("git".as_ref()); + cmd_finder.must_have("git"); } // We need cmake, but only if we're actually building LLVM or sanitizers. @@ -75,57 +91,34 @@ pub fn check(build: &mut Build) { .filter_map(|host| build.config.target_config.get(host)) .any(|config| config.llvm_config.is_none()); if building_llvm || build.config.sanitizers { - need_cmd("cmake".as_ref()); + cmd_finder.must_have("cmake"); } // Ninja is currently only used for LLVM itself. if building_llvm && build.config.ninja { // Some Linux distros rename `ninja` to `ninja-build`. // CMake can work with either binary name. - if have_cmd("ninja-build".as_ref()).is_none() { - need_cmd("ninja".as_ref()); + if cmd_finder.maybe_have("ninja-build").is_none() { + cmd_finder.must_have("ninja"); } } - if build.config.python.is_none() { - // set by bootstrap.py - if let Some(v) = env::var_os("BOOTSTRAP_PYTHON") { - build.config.python = Some(PathBuf::from(v)); - } - } - if build.config.python.is_none() { - build.config.python = have_cmd("python2.7".as_ref()); - } - if build.config.python.is_none() { - build.config.python = have_cmd("python2".as_ref()); - } - if build.config.python.is_none() { - need_cmd("python".as_ref()); - build.config.python = Some("python".into()); - } - need_cmd(build.config.python.as_ref().unwrap().as_ref()); + build.config.python = build.config.python.take().map(|p| cmd_finder.must_have(p)) + .or_else(|| env::var_os("BOOTSTRAP_PYTHON").map(PathBuf::from)) // set by bootstrap.py + .or_else(|| cmd_finder.maybe_have("python2.7")) + .or_else(|| cmd_finder.maybe_have("python2")) + .or_else(|| Some(cmd_finder.must_have("python"))); + build.config.nodejs = build.config.nodejs.take().map(|p| cmd_finder.must_have(p)) + .or_else(|| cmd_finder.maybe_have("node")) + .or_else(|| cmd_finder.maybe_have("nodejs")); - if let Some(ref s) = build.config.nodejs { - need_cmd(s.as_ref()); - } else { - // Look for the nodejs command, needed for emscripten testing - if let Some(node) = have_cmd("node".as_ref()) { - build.config.nodejs = Some(node); - } else if let Some(node) = have_cmd("nodejs".as_ref()) { - build.config.nodejs = Some(node); - } - } - - if let Some(ref gdb) = build.config.gdb { - need_cmd(gdb.as_ref()); - } else { - build.config.gdb = have_cmd("gdb".as_ref()); - } + build.config.gdb = build.config.gdb.take().map(|p| cmd_finder.must_have(p)) + .or_else(|| cmd_finder.maybe_have("gdb")); // We're gonna build some custom C code here and there, host triples // also build some C++ shims for LLVM so we need a C++ compiler. - for target in build.config.target.iter() { + for target in &build.config.target { // On emscripten we don't actually need the C compiler to just // build the target artifacts, only for testing. For the sake // of easier bot configuration, just skip detection. @@ -133,18 +126,17 @@ pub fn check(build: &mut Build) { continue; } - need_cmd(build.cc(target).as_ref()); + cmd_finder.must_have(build.cc(target)); if let Some(ar) = build.ar(target) { - need_cmd(ar.as_ref()); + cmd_finder.must_have(ar); } } - for host in build.config.host.iter() { - need_cmd(build.cxx(host).unwrap().as_ref()); - } - // The msvc hosts don't use jemalloc, turn it off globally to - // avoid packaging the dummy liballoc_jemalloc on that platform. for host in build.config.host.iter() { + cmd_finder.must_have(build.cxx(host).unwrap()); + + // The msvc hosts don't use jemalloc, turn it off globally to + // avoid packaging the dummy liballoc_jemalloc on that platform. if host.contains("msvc") { build.config.use_jemalloc = false; } @@ -156,7 +148,7 @@ pub fn check(build: &mut Build) { panic!("FileCheck executable {:?} does not exist", filecheck); } - for target in build.config.target.iter() { + for target in &build.config.target { // Can't compile for iOS unless we're on macOS if target.contains("apple-ios") && !build.config.build.contains("apple-darwin") { @@ -208,13 +200,12 @@ $ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake for host in build.flags.host.iter() { if !build.config.host.contains(host) { - panic!("specified host `{}` is not in the ./configure list", host); + panic!("specified host `{}` is not in configuration", host); } } for target in build.flags.target.iter() { if !build.config.target.contains(target) { - panic!("specified target `{}` is not in the ./configure list", - target); + panic!("specified target `{}` is not in configuration", target); } } @@ -231,6 +222,6 @@ $ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake } if let Some(ref s) = build.config.ccache { - need_cmd(s.as_ref()); + cmd_finder.must_have(s); } } From d3bf6e562ecab27844924af741412865babeed84 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Sat, 24 Jun 2017 05:42:38 -0600 Subject: [PATCH 150/162] Remove 'static lifetimes from channels. --- src/bootstrap/channel.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/channel.rs b/src/bootstrap/channel.rs index 4664b1f765e..db0691fb1c2 100644 --- a/src/bootstrap/channel.rs +++ b/src/bootstrap/channel.rs @@ -23,12 +23,12 @@ use build_helper::output; use Build; // The version number -pub const CFG_RELEASE_NUM: &'static str = "1.20.0"; +pub const CFG_RELEASE_NUM: &str = "1.20.0"; // An optional number to put after the label, e.g. '.2' -> '-beta.2' // Be sure to make this starts with a dot to conform to semver pre-release // versions (section 9) -pub const CFG_PRERELEASE_VERSION: &'static str = ".1"; +pub const CFG_PRERELEASE_VERSION: &str = ".1"; pub struct GitInfo { inner: Option, From 5b44cbc39fc591cfc0339ad641be393c4a2612f1 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Mon, 26 Jun 2017 10:23:50 -0600 Subject: [PATCH 151/162] Cleanups to check code. --- src/bootstrap/check.rs | 41 ++++++++++++++++++----------------------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 277728b90b7..a542200bbba 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -13,23 +13,22 @@ //! This file implements the various regression test suites that we execute on //! our CI. -extern crate build_helper; - use std::collections::HashSet; use std::env; +use std::iter; use std::fmt; use std::fs::{self, File}; use std::path::{PathBuf, Path}; use std::process::Command; use std::io::Read; -use build_helper::output; +use build_helper::{self, output}; use {Build, Compiler, Mode}; use dist; use util::{self, dylib_path, dylib_path_var, exe}; -const ADB_TEST_DIR: &'static str = "/data/tmp/work"; +const ADB_TEST_DIR: &str = "/data/tmp/work"; /// The two modes of the test runner; tests or benchmarks. #[derive(Copy, Clone)] @@ -99,7 +98,7 @@ pub fn linkcheck(build: &Build, host: &str) { /// This tool in `src/tools` will check out a few Rust projects and run `cargo /// test` to ensure that we don't regress the test suites there. pub fn cargotest(build: &Build, stage: u32, host: &str) { - let ref compiler = Compiler::new(stage, host); + let compiler = Compiler::new(stage, host); // Note that this is a short, cryptic, and not scoped directory name. This // is currently to minimize the length of path on Windows where we otherwise @@ -109,11 +108,11 @@ pub fn cargotest(build: &Build, stage: u32, host: &str) { let _time = util::timeit(); let mut cmd = Command::new(build.tool(&Compiler::new(0, host), "cargotest")); - build.prepare_tool_cmd(compiler, &mut cmd); + build.prepare_tool_cmd(&compiler, &mut cmd); try_run(build, cmd.arg(&build.cargo) .arg(&out_dir) - .env("RUSTC", build.compiler_path(compiler)) - .env("RUSTDOC", build.rustdoc(compiler))); + .env("RUSTC", build.compiler_path(&compiler)) + .env("RUSTDOC", build.rustdoc(&compiler))); } /// Runs `cargo test` for `cargo` packaged with Rust. @@ -124,9 +123,8 @@ pub fn cargo(build: &Build, stage: u32, host: &str) { // and not RUSTC because the Cargo test suite has tests that will // fail if rustc is not spelled `rustc`. let path = build.sysroot(compiler).join("bin"); - let old_path = ::std::env::var("PATH").expect(""); - let sep = if cfg!(windows) { ";" } else {":" }; - let ref newpath = format!("{}{}{}", path.display(), sep, old_path); + let old_path = env::var_os("PATH").unwrap_or_default(); + let newpath = env::join_paths(iter::once(path).chain(env::split_paths(&old_path))).expect(""); let mut cargo = build.cargo(compiler, Mode::Tool, host, "test"); cargo.arg("--manifest-path").arg(build.src.join("src/tools/cargo/Cargo.toml")); @@ -200,7 +198,7 @@ pub fn compiletest(build: &Build, cmd.arg("--host").arg(compiler.host); cmd.arg("--llvm-filecheck").arg(build.llvm_filecheck(&build.config.build)); - if let Some(nodejs) = build.config.nodejs.as_ref() { + if let Some(ref nodejs) = build.config.nodejs { cmd.arg("--nodejs").arg(nodejs); } @@ -520,16 +518,14 @@ fn krate_emscripten(build: &Build, compiler: &Compiler, target: &str, mode: Mode) { - let mut tests = Vec::new(); let out_dir = build.cargo_out(compiler, mode, target); - find_tests(&out_dir.join("deps"), target, &mut tests); + let tests = find_tests(&out_dir.join("deps"), target); + let nodejs = build.config.nodejs.as_ref().expect("nodejs not configured"); for test in tests { - let test_file_name = test.to_string_lossy().into_owned(); - println!("running {}", test_file_name); - let nodejs = build.config.nodejs.as_ref().expect("nodejs not configured"); + println!("running {}", test.display()); let mut cmd = Command::new(nodejs); - cmd.arg(&test_file_name); + cmd.arg(&test); if build.config.quiet_tests { cmd.arg("--quiet"); } @@ -541,9 +537,8 @@ fn krate_remote(build: &Build, compiler: &Compiler, target: &str, mode: Mode) { - let mut tests = Vec::new(); let out_dir = build.cargo_out(compiler, mode, target); - find_tests(&out_dir.join("deps"), target, &mut tests); + let tests = find_tests(&out_dir.join("deps"), target); let tool = build.tool(&Compiler::new(0, &build.config.build), "remote-test-client"); @@ -559,9 +554,8 @@ fn krate_remote(build: &Build, } } -fn find_tests(dir: &Path, - target: &str, - dst: &mut Vec) { +fn find_tests(dir: &Path, target: &str) -> Vec { + let mut dst = Vec::new(); for e in t!(dir.read_dir()).map(|e| t!(e)) { let file_type = t!(e.file_type()); if !file_type.is_file() { @@ -576,6 +570,7 @@ fn find_tests(dir: &Path, dst.push(e.path()); } } + dst } pub fn remote_copy_libs(build: &Build, compiler: &Compiler, target: &str) { From 388fca81f6605ce32a79d484723262f0e50965e4 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Mon, 26 Jun 2017 18:13:10 -0600 Subject: [PATCH 152/162] Cleanup compile.rs. --- src/bootstrap/compile.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index b2bd792e93b..61840d81b52 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -50,7 +50,7 @@ pub fn std(build: &Build, target: &str, compiler: &Compiler) { let mut cargo = build.cargo(compiler, Mode::Libstd, target, "build"); let mut features = build.std_features(); - if let Ok(target) = env::var("MACOSX_STD_DEPLOYMENT_TARGET") { + if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") { cargo.env("MACOSX_DEPLOYMENT_TARGET", target); } @@ -199,7 +199,7 @@ pub fn test(build: &Build, target: &str, compiler: &Compiler) { let out_dir = build.cargo_out(compiler, Mode::Libtest, target); build.clear_if_dirty(&out_dir, &libstd_stamp(build, compiler, target)); let mut cargo = build.cargo(compiler, Mode::Libtest, target, "build"); - if let Ok(target) = env::var("MACOSX_STD_DEPLOYMENT_TARGET") { + if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") { cargo.env("MACOSX_DEPLOYMENT_TARGET", target); } cargo.arg("--manifest-path") @@ -247,7 +247,7 @@ pub fn rustc(build: &Build, target: &str, compiler: &Compiler) { cargo.env("CFG_RELEASE", build.rust_release()) .env("CFG_RELEASE_CHANNEL", &build.config.channel) .env("CFG_VERSION", build.rust_version()) - .env("CFG_PREFIX", build.config.prefix.clone().unwrap_or(PathBuf::new())); + .env("CFG_PREFIX", build.config.prefix.clone().unwrap_or_default()); if compiler.stage == 0 { cargo.env("CFG_LIBDIR_RELATIVE", "lib"); @@ -385,7 +385,7 @@ pub fn assemble_rustc(build: &Build, stage: u32, host: &str) { let rustc = out_dir.join(exe("rustc", host)); let bindir = sysroot.join("bin"); t!(fs::create_dir_all(&bindir)); - let compiler = build.compiler_path(&Compiler::new(stage, host)); + let compiler = build.compiler_path(&target_compiler); let _ = fs::remove_file(&compiler); copy(&rustc, &compiler); @@ -407,6 +407,8 @@ fn add_to_sysroot(sysroot_dst: &Path, stamp: &Path) { t!(fs::create_dir_all(&sysroot_dst)); let mut contents = Vec::new(); t!(t!(File::open(stamp)).read_to_end(&mut contents)); + // This is the method we use for extracting paths from the stamp file passed to us. See + // run_cargo for more information (in this file). for part in contents.split(|b| *b == 0) { if part.is_empty() { continue From c6ece966ac6745f71f21f98454193e41ad85fe42 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Tue, 27 Jun 2017 09:05:40 -0600 Subject: [PATCH 153/162] Cleanup utils --- src/bootstrap/util.rs | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs index 61bd85e76c5..092fb04637b 100644 --- a/src/bootstrap/util.rs +++ b/src/bootstrap/util.rs @@ -14,7 +14,6 @@ //! not a lot of interesting happenings here unfortunately. use std::env; -use std::ffi::OsString; use std::fs; use std::io::{self, Write}; use std::path::{Path, PathBuf}; @@ -32,16 +31,9 @@ pub fn staticlib(name: &str, target: &str) -> String { } } -/// Copies a file from `src` to `dst`, attempting to use hard links and then -/// falling back to an actually filesystem copy if necessary. +/// Copies a file from `src` to `dst` pub fn copy(src: &Path, dst: &Path) { - // A call to `hard_link` will fail if `dst` exists, so remove it if it - // already exists so we can try to help `hard_link` succeed. let _ = fs::remove_file(&dst); - - // Attempt to "easy copy" by creating a hard link (symlinks don't work on - // windows), but if that fails just fall back to a slow `copy` operation. - // let res = fs::hard_link(src, dst); let res = fs::copy(src, dst); if let Err(e) = res { panic!("failed to copy `{}` to `{}`: {}", src.display(), @@ -149,8 +141,7 @@ pub fn dylib_path_var() -> &'static str { /// Parses the `dylib_path_var()` environment variable, returning a list of /// paths that are members of this lookup path. pub fn dylib_path() -> Vec { - env::split_paths(&env::var_os(dylib_path_var()).unwrap_or(OsString::new())) - .collect() + env::split_paths(&env::var_os(dylib_path_var()).unwrap_or_default()).collect() } /// `push` all components to `buf`. On windows, append `.exe` to the last component. @@ -422,4 +413,4 @@ impl CiEnv { cmd.env("TERM", "xterm").args(&["--color", "always"]); } } -} \ No newline at end of file +} From 802b6db0041115d261f3d0ea1855f35658141c0b Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Tue, 27 Jun 2017 09:05:47 -0600 Subject: [PATCH 154/162] Cleanup dist --- src/bootstrap/dist.rs | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 753bd1df0d8..cfcba07228b 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -97,7 +97,7 @@ pub fn docs(build: &Build, stage: u32, host: &str) { } fn find_files(files: &[&str], path: &[PathBuf]) -> Vec { - let mut found = Vec::new(); + let mut found = Vec::with_capacity(files.len()); for file in files { let file_path = @@ -119,17 +119,9 @@ fn make_win_dist(rust_root: &Path, plat_root: &Path, target_triple: &str, build: //Ask gcc where it keeps its stuff let mut cmd = Command::new(build.cc(target_triple)); cmd.arg("-print-search-dirs"); - build.run_quiet(&mut cmd); - let gcc_out = - String::from_utf8( - cmd - .output() - .expect("failed to execute gcc") - .stdout).expect("gcc.exe output was not utf8"); + let gcc_out = output(&mut cmd); - let mut bin_path: Vec<_> = - env::split_paths(&env::var_os("PATH").unwrap_or_default()) - .collect(); + let mut bin_path: Vec<_> = env::split_paths(&env::var_os("PATH").unwrap_or_default()).collect(); let mut lib_path = Vec::new(); for line in gcc_out.lines() { @@ -140,7 +132,7 @@ fn make_win_dist(rust_root: &Path, plat_root: &Path, target_triple: &str, build: line[(idx + 1)..] .trim_left_matches(trim_chars) .split(';') - .map(|s| PathBuf::from(s)); + .map(PathBuf::from); if key == "programs" { bin_path.extend(value); @@ -149,7 +141,7 @@ fn make_win_dist(rust_root: &Path, plat_root: &Path, target_triple: &str, build: } } - let target_tools = vec!["gcc.exe", "ld.exe", "ar.exe", "dlltool.exe", "libwinpthread-1.dll"]; + let target_tools = ["gcc.exe", "ld.exe", "ar.exe", "dlltool.exe", "libwinpthread-1.dll"]; let mut rustc_dlls = vec!["libstdc++-6.dll", "libwinpthread-1.dll"]; if target_triple.starts_with("i686-") { rustc_dlls.push("libgcc_s_dw2-1.dll"); @@ -157,7 +149,7 @@ fn make_win_dist(rust_root: &Path, plat_root: &Path, target_triple: &str, build: rustc_dlls.push("libgcc_s_seh-1.dll"); } - let target_libs = vec![ //MinGW libs + let target_libs = [ //MinGW libs "libgcc.a", "libgcc_eh.a", "libgcc_s.a", @@ -203,7 +195,7 @@ fn make_win_dist(rust_root: &Path, plat_root: &Path, target_triple: &str, build: let target_libs = find_files(&target_libs, &lib_path); fn copy_to_folder(src: &Path, dest_folder: &Path) { - let file_name = src.file_name().unwrap().to_os_string(); + let file_name = src.file_name().unwrap(); let dest = dest_folder.join(file_name); copy(src, &dest); } @@ -234,8 +226,6 @@ fn make_win_dist(rust_root: &Path, plat_root: &Path, target_triple: &str, build: /// /// This contains all the bits and pieces to run the MinGW Windows targets /// without any extra installed software (e.g. we bundle gcc, libraries, etc). -/// Currently just shells out to a python script, but that should be rewritten -/// in Rust. pub fn mingw(build: &Build, host: &str) { println!("Dist mingw ({})", host); let name = pkgname(build, "rust-mingw"); @@ -366,9 +356,9 @@ pub fn rustc(build: &Build, stage: u32, host: &str) { pub fn debugger_scripts(build: &Build, sysroot: &Path, host: &str) { + let dst = sysroot.join("lib/rustlib/etc"); + t!(fs::create_dir_all(&dst)); let cp_debugger_script = |file: &str| { - let dst = sysroot.join("lib/rustlib/etc"); - t!(fs::create_dir_all(&dst)); install(&build.src.join("src/etc/").join(file), &dst, 0o644); }; if host.contains("windows-msvc") { @@ -595,7 +585,7 @@ pub fn rust_src(build: &Build) { t!(fs::remove_dir_all(&image)); } -const CARGO_VENDOR_VERSION: &'static str = "0.1.4"; +const CARGO_VENDOR_VERSION: &str = "0.1.4"; /// Creates the plain source tarball pub fn plain_source_tarball(build: &Build) { From 6766abbfa9959581ebfdba32131125e2b3b624f3 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Tue, 27 Jun 2017 09:51:26 -0600 Subject: [PATCH 155/162] Clippy lints --- src/bootstrap/channel.rs | 2 +- src/bootstrap/compile.rs | 17 +++++++++-------- src/bootstrap/config.rs | 2 +- src/bootstrap/dist.rs | 11 +++++------ src/bootstrap/flags.rs | 6 ++---- src/bootstrap/install.rs | 2 +- src/bootstrap/lib.rs | 14 +++++++------- src/bootstrap/sanity.rs | 18 +++++++----------- src/bootstrap/step.rs | 8 ++++---- 9 files changed, 37 insertions(+), 43 deletions(-) diff --git a/src/bootstrap/channel.rs b/src/bootstrap/channel.rs index db0691fb1c2..199c01cf821 100644 --- a/src/bootstrap/channel.rs +++ b/src/bootstrap/channel.rs @@ -99,6 +99,6 @@ impl GitInfo { version.push_str(&inner.commit_date); version.push_str(")"); } - return version + version } } diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 61840d81b52..5123e59a5db 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -559,23 +559,24 @@ fn run_cargo(build: &Build, cargo: &mut Command, stamp: &Path) { // If this was an output file in the "host dir" we don't actually // worry about it, it's not relevant for us. if filename.starts_with(&host_root_dir) { - continue + continue; + } // If this was output in the `deps` dir then this is a precise file // name (hash included) so we start tracking it. - } else if filename.starts_with(&target_deps_dir) { + if filename.starts_with(&target_deps_dir) { deps.push(filename.to_path_buf()); + continue; + } // Otherwise this was a "top level artifact" which right now doesn't // have a hash in the name, but there's a version of this file in // the `deps` folder which *does* have a hash in the name. That's // the one we'll want to we'll probe for it later. - } else { - toplevel.push((filename.file_stem().unwrap() - .to_str().unwrap().to_string(), - filename.extension().unwrap().to_owned() - .to_str().unwrap().to_string())); - } + toplevel.push((filename.file_stem().unwrap() + .to_str().unwrap().to_string(), + filename.extension().unwrap().to_owned() + .to_str().unwrap().to_string())); } } diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 12862e136da..56808d69ee2 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -417,7 +417,7 @@ impl Config { config.update_with_config_mk(); } - return config + config } /// "Temporary" routine to parse `config.mk` into this configuration. diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index cfcba07228b..8e3f88c8a34 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -488,12 +488,11 @@ fn copy_src_dirs(build: &Build, src_dirs: &[&str], exclude_dirs: &[&str], dst_di if spath.ends_with("~") || spath.ends_with(".pyc") { return false } - if spath.contains("llvm/test") || spath.contains("llvm\\test") { - if spath.ends_with(".ll") || - spath.ends_with(".td") || - spath.ends_with(".s") { - return false - } + if (spath.contains("llvm/test") || spath.contains("llvm\\test")) && + (spath.ends_with(".ll") || + spath.ends_with(".td") || + spath.ends_with(".s")) { + return false } let full_path = Path::new(dir).join(path); diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index 029118eb647..1a73c489665 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -315,10 +315,8 @@ Arguments: let mut stage = matches.opt_str("stage").map(|j| j.parse().unwrap()); - if matches.opt_present("incremental") { - if stage.is_none() { - stage = Some(1); - } + if matches.opt_present("incremental") && stage.is_none() { + stage = Some(1); } Flags { diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs index 21e21628dc9..8e2ef527b16 100644 --- a/src/bootstrap/install.rs +++ b/src/bootstrap/install.rs @@ -146,5 +146,5 @@ fn add_destdir(path: &Path, destdir: &Option) -> PathBuf { _ => {} } } - return ret + ret } diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 86180077b82..35abe214523 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -496,7 +496,7 @@ impl Build { self.ci_env.force_coloring_in_ci(&mut cargo); - return cargo + cargo } /// Get a path to the compiler specified. @@ -519,7 +519,7 @@ impl Build { let mut rustdoc = self.compiler_path(compiler); rustdoc.pop(); rustdoc.push(exe("rustdoc", compiler.host)); - return rustdoc + rustdoc } /// Get a `Command` which is ready to run `tool` in `stage` built for @@ -527,7 +527,7 @@ impl Build { fn tool_cmd(&self, compiler: &Compiler, tool: &str) -> Command { let mut cmd = Command::new(self.tool(&compiler, tool)); self.prepare_tool_cmd(compiler, &mut cmd); - return cmd + cmd } /// Prepares the `cmd` provided to be able to run the `compiler` provided. @@ -578,7 +578,7 @@ impl Build { if self.config.profiler { features.push_str(" profiler"); } - return features + features } /// Get the space-separated set of activated features for the compiler. @@ -587,7 +587,7 @@ impl Build { if self.config.use_jemalloc { features.push_str(" jemalloc"); } - return features + features } /// Component directory that Cargo will produce output into (e.g. @@ -834,7 +834,7 @@ impl Build { if target == "i686-pc-windows-gnu" { base.push("-fno-omit-frame-pointer".into()); } - return base + base } /// Returns the path to the `ar` archive utility for the target specified. @@ -866,7 +866,7 @@ impl Build { !target.contains("emscripten") { base.push(format!("-Clinker={}", self.cc(target).display())); } - return base + base } /// Returns the "musl root" for this `target`, if defined diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index 41482ac57f9..d6def25cfaa 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -56,7 +56,7 @@ impl Finder { return Some(target); } } - return None; + None }).clone() } @@ -73,10 +73,8 @@ pub fn check(build: &mut Build) { // one is present as part of the PATH then that can lead to the system // being unable to identify the files properly. See // https://github.com/rust-lang/rust/issues/34959 for more details. - if cfg!(windows) { - if path.to_string_lossy().contains("\"") { - panic!("PATH contains invalid character '\"'"); - } + if cfg!(windows) && path.to_string_lossy().contains("\"") { + panic!("PATH contains invalid character '\"'"); } let mut cmd_finder = Finder::new(); @@ -95,12 +93,10 @@ pub fn check(build: &mut Build) { } // Ninja is currently only used for LLVM itself. - if building_llvm && build.config.ninja { - // Some Linux distros rename `ninja` to `ninja-build`. - // CMake can work with either binary name. - if cmd_finder.maybe_have("ninja-build").is_none() { - cmd_finder.must_have("ninja"); - } + // Some Linux distros rename `ninja` to `ninja-build`. + // CMake can work with either binary name. + if building_llvm && build.config.ninja && cmd_finder.maybe_have("ninja-build").is_none() { + cmd_finder.must_have("ninja"); } build.config.python = build.config.python.take().map(|p| cmd_finder.must_have(p)) diff --git a/src/bootstrap/step.rs b/src/bootstrap/step.rs index 5f0724c6577..61e9a0d16da 100644 --- a/src/bootstrap/step.rs +++ b/src/bootstrap/step.rs @@ -148,7 +148,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { } } } - return ret + ret }; // ======================================================================== @@ -237,7 +237,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { s.target) } }); - return rule + rule } // Similar to the `libstd`, `libtest`, and `librustc` rules above, except @@ -1326,7 +1326,7 @@ invalid rule dependency graph detected, was a rule added and maybe typo'd? for idx in 0..nodes.len() { self.topo_sort(idx, &idx_to_node, &edges, &mut visited, &mut order); } - return order + order } /// Builds the dependency graph rooted at `step`. @@ -1365,7 +1365,7 @@ invalid rule dependency graph detected, was a rule added and maybe typo'd? } edges.entry(idx).or_insert(HashSet::new()).extend(deps); - return idx + idx } /// Given a dependency graph with a finished list of `nodes`, fill out more From 743af95d4be6423a4123aa81bf587756d006ed9c Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Tue, 27 Jun 2017 13:24:37 -0600 Subject: [PATCH 156/162] Update a few comments. --- src/bootstrap/bin/rustc.rs | 15 +++++---------- src/bootstrap/lib.rs | 14 ++++++-------- 2 files changed, 11 insertions(+), 18 deletions(-) diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index 8c6eaee24f2..7232208b522 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -75,16 +75,11 @@ fn main() { Err(_) => 0, }; - // Build scripts always use the snapshot compiler which is guaranteed to be - // able to produce an executable, whereas intermediate compilers may not - // have the standard library built yet and may not be able to produce an - // executable. Otherwise we just use the standard compiler we're - // bootstrapping with. - // - // Also note that cargo will detect the version of the compiler to trigger - // a rebuild when the compiler changes. If this happens, we want to make - // sure to use the actual compiler instead of the snapshot compiler becase - // that's the one that's actually changing. + // Use a different compiler for build scripts, since there may not yet be a + // libstd for the real compiler to use. However, if Cargo is attempting to + // determine the version of the compiler, the real compiler needs to be + // used. Currently, these two states are differentiated based on whether + // --target and -vV is/isn't passed. let (rustc, libdir) = if target.is_none() && version.is_none() { ("RUSTC_SNAPSHOT", "RUSTC_SNAPSHOT_LIBDIR") } else { diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 35abe214523..91ace0805e4 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -175,7 +175,9 @@ pub struct Build { lldb_python_dir: Option, // Runtime state filled in later on + // target -> (cc, ar) cc: HashMap)>, + // host -> (cc, ar) cxx: HashMap, crates: HashMap, is_sudo: bool, @@ -202,20 +204,16 @@ struct Crate { /// build system, with each mod generating output in a different directory. #[derive(Clone, Copy, PartialEq, Eq)] pub enum Mode { - /// This cargo is going to build the standard library, placing output in the - /// "stageN-std" directory. + /// Build the standard library, placing output in the "stageN-std" directory. Libstd, - /// This cargo is going to build libtest, placing output in the - /// "stageN-test" directory. + /// Build libtest, placing output in the "stageN-test" directory. Libtest, - /// This cargo is going to build librustc and compiler libraries, placing - /// output in the "stageN-rustc" directory. + /// Build librustc and compiler libraries, placing output in the "stageN-rustc" directory. Librustc, - /// This cargo is going to build some tool, placing output in the - /// "stageN-tools" directory. + /// Build some tool, placing output in the "stageN-tools" directory. Tool, } From 2cc5b084a0fdbd08ecc873be33bafd08d4faf273 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Tue, 27 Jun 2017 13:32:04 -0600 Subject: [PATCH 157/162] Clarify meaning of Build.cargo, Build.rustc. Rename Build.{cargo, rustc} to {initial_cargo, initial_rustc}. --- src/bootstrap/check.rs | 8 ++++---- src/bootstrap/config.rs | 26 ++++++++++++++++++++------ src/bootstrap/dist.rs | 8 ++++---- src/bootstrap/flags.rs | 9 +++++++-- src/bootstrap/lib.rs | 38 ++++++++++++++------------------------ src/bootstrap/metadata.rs | 2 +- 6 files changed, 50 insertions(+), 41 deletions(-) diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index a542200bbba..04ae7e1e009 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -109,7 +109,7 @@ pub fn cargotest(build: &Build, stage: u32, host: &str) { let _time = util::timeit(); let mut cmd = Command::new(build.tool(&Compiler::new(0, host), "cargotest")); build.prepare_tool_cmd(&compiler, &mut cmd); - try_run(build, cmd.arg(&build.cargo) + try_run(build, cmd.arg(&build.initial_cargo) .arg(&out_dir) .env("RUSTC", build.compiler_path(&compiler)) .env("RUSTDOC", build.rustdoc(&compiler))); @@ -654,7 +654,7 @@ pub fn distcheck(build: &Build) { build.run(&mut cmd); let toml = dir.join("rust-src/lib/rustlib/src/rust/src/libstd/Cargo.toml"); - build.run(Command::new(&build.cargo) + build.run(Command::new(&build.initial_cargo) .arg("generate-lockfile") .arg("--manifest-path") .arg(&toml) @@ -663,12 +663,12 @@ pub fn distcheck(build: &Build) { /// Test the build system itself pub fn bootstrap(build: &Build) { - let mut cmd = Command::new(&build.cargo); + let mut cmd = Command::new(&build.initial_cargo); cmd.arg("test") .current_dir(build.src.join("src/bootstrap")) .env("CARGO_TARGET_DIR", build.out.join("bootstrap")) .env("RUSTC_BOOTSTRAP", "1") - .env("RUSTC", &build.rustc); + .env("RUSTC", &build.initial_rustc); if build.flags.cmd.no_fail_fast() { cmd.arg("--no-fail-fast"); } diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 56808d69ee2..34628852ab3 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -81,8 +81,6 @@ pub struct Config { pub build: String, pub host: Vec, pub target: Vec, - pub rustc: Option, - pub cargo: Option, pub local_rebuild: bool, // dist misc @@ -114,6 +112,12 @@ pub struct Config { pub python: Option, pub configure_args: Vec, pub openssl_static: bool, + + + // These are either the stage0 downloaded binaries or the locally installed ones. + pub initial_cargo: PathBuf, + pub initial_rustc: PathBuf, + } /// Per-target configuration stored in the global configuration structure. @@ -308,8 +312,6 @@ impl Config { config.target.push(target.clone()); } } - config.rustc = build.rustc.map(PathBuf::from); - config.cargo = build.cargo.map(PathBuf::from); config.nodejs = build.nodejs.map(PathBuf::from); config.gdb = build.gdb.map(PathBuf::from); config.python = build.python.map(PathBuf::from); @@ -411,6 +413,18 @@ impl Config { set(&mut config.rust_dist_src, t.src_tarball); } + let cwd = t!(env::current_dir()); + let out = cwd.join("build"); + + let stage0_root = out.join(&config.build).join("stage0/bin"); + config.initial_rustc = match build.rustc { + Some(s) => PathBuf::from(s), + None => stage0_root.join(exe("rustc", &config.build)), + }; + config.initial_cargo = match build.cargo { + Some(s) => PathBuf::from(s), + None => stage0_root.join(exe("cargo", &config.build)), + }; // compat with `./configure` while we're still using that if fs::metadata("config.mk").is_ok() { @@ -610,8 +624,8 @@ impl Config { } "CFG_LOCAL_RUST_ROOT" if value.len() > 0 => { let path = parse_configure_path(value); - self.rustc = Some(push_exe_path(path.clone(), &["bin", "rustc"])); - self.cargo = Some(push_exe_path(path, &["bin", "cargo"])); + self.initial_rustc = push_exe_path(path.clone(), &["bin", "rustc"]); + self.initial_cargo = push_exe_path(path, &["bin", "cargo"]); } "CFG_PYTHON" if value.len() > 0 => { let path = parse_configure_path(value); diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 8e3f88c8a34..c91d6f0b77c 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -626,23 +626,23 @@ pub fn plain_source_tarball(build: &Build) { if build.src_is_git { // Get cargo-vendor installed, if it isn't already. let mut has_cargo_vendor = false; - let mut cmd = Command::new(&build.cargo); + let mut cmd = Command::new(&build.initial_cargo); for line in output(cmd.arg("install").arg("--list")).lines() { has_cargo_vendor |= line.starts_with("cargo-vendor "); } if !has_cargo_vendor { - let mut cmd = Command::new(&build.cargo); + let mut cmd = Command::new(&build.initial_cargo); cmd.arg("install") .arg("--force") .arg("--debug") .arg("--vers").arg(CARGO_VENDOR_VERSION) .arg("cargo-vendor") - .env("RUSTC", &build.rustc); + .env("RUSTC", &build.initial_rustc); build.run(&mut cmd); } // Vendor all Cargo dependencies - let mut cmd = Command::new(&build.cargo); + let mut cmd = Command::new(&build.initial_cargo); cmd.arg("vendor") .current_dir(&plain_dst_src.join("src")); build.run(&mut cmd); diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index 1a73c489665..4541b6623c4 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -35,7 +35,7 @@ pub struct Flags { pub host: Vec, pub target: Vec, pub config: Option, - pub src: Option, + pub src: PathBuf, pub jobs: Option, pub cmd: Subcommand, pub incremental: bool, @@ -319,6 +319,11 @@ Arguments: stage = Some(1); } + let cwd = t!(env::current_dir()); + let src = matches.opt_str("src").map(PathBuf::from) + .or_else(|| env::var_os("SRC").map(PathBuf::from)) + .unwrap_or(cwd); + Flags { verbose: matches.opt_count("verbose"), stage: stage, @@ -330,7 +335,7 @@ Arguments: host: split(matches.opt_strs("host")), target: split(matches.opt_strs("target")), config: cfg_file, - src: matches.opt_str("src").map(PathBuf::from), + src: src, jobs: matches.opt_str("jobs").map(|j| j.parse().unwrap()), cmd: cmd, incremental: matches.opt_present("incremental"), diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 91ace0805e4..bb82e711d7b 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -161,8 +161,6 @@ pub struct Build { flags: Flags, // Derived properties from the above two configurations - cargo: PathBuf, - rustc: PathBuf, src: PathBuf, out: PathBuf, rust_info: channel::GitInfo, @@ -170,6 +168,10 @@ pub struct Build { rls_info: channel::GitInfo, local_rebuild: bool, + // Stage 0 (downloaded) compiler and cargo or their local rust equivalents. + initial_rustc: PathBuf, + initial_cargo: PathBuf, + // Probed tools at runtime lldb_version: Option, lldb_python_dir: Option, @@ -224,22 +226,9 @@ impl Build { /// By default all build output will be placed in the current directory. pub fn new(flags: Flags, config: Config) -> Build { let cwd = t!(env::current_dir()); - let src = flags.src.clone().or_else(|| { - env::var_os("SRC").map(|x| x.into()) - }).unwrap_or(cwd.clone()); + let src = flags.src.clone(); let out = cwd.join("build"); - let stage0_root = out.join(&config.build).join("stage0/bin"); - let rustc = match config.rustc { - Some(ref s) => PathBuf::from(s), - None => stage0_root.join(exe("rustc", &config.build)), - }; - let cargo = match config.cargo { - Some(ref s) => PathBuf::from(s), - None => stage0_root.join(exe("cargo", &config.build)), - }; - let local_rebuild = config.local_rebuild; - let is_sudo = match env::var_os("SUDO_USER") { Some(sudo_user) => { match env::var_os("USER") { @@ -255,17 +244,18 @@ impl Build { let src_is_git = src.join(".git").exists(); Build { + initial_rustc: config.initial_rustc.clone(), + initial_cargo: config.initial_cargo.clone(), + local_rebuild: config.local_rebuild, + flags: flags, config: config, - cargo: cargo, - rustc: rustc, src: src, out: out, rust_info: rust_info, cargo_info: cargo_info, rls_info: rls_info, - local_rebuild: local_rebuild, cc: HashMap::new(), cxx: HashMap::new(), crates: HashMap::new(), @@ -294,7 +284,7 @@ impl Build { sanity::check(self); // If local-rust is the same major.minor as the current version, then force a local-rebuild let local_version_verbose = output( - Command::new(&self.rustc).arg("--version").arg("--verbose")); + Command::new(&self.initial_rustc).arg("--version").arg("--verbose")); let local_release = local_version_verbose .lines().filter(|x| x.starts_with("release:")) .next().unwrap().trim_left_matches("release:").trim(); @@ -336,7 +326,7 @@ impl Build { mode: Mode, target: &str, cmd: &str) -> Command { - let mut cargo = Command::new(&self.cargo); + let mut cargo = Command::new(&self.initial_cargo); let out_dir = self.stage_out(compiler, mode); cargo.env("CARGO_TARGET_DIR", out_dir) .arg(cmd) @@ -420,7 +410,7 @@ impl Build { // library up and running, so we can use the normal compiler to compile // build scripts in that situation. if mode == Mode::Libstd { - cargo.env("RUSTC_SNAPSHOT", &self.rustc) + cargo.env("RUSTC_SNAPSHOT", &self.initial_rustc) .env("RUSTC_SNAPSHOT_LIBDIR", self.rustc_snapshot_libdir()); } else { cargo.env("RUSTC_SNAPSHOT", self.compiler_path(compiler)) @@ -500,7 +490,7 @@ impl Build { /// Get a path to the compiler specified. fn compiler_path(&self, compiler: &Compiler) -> PathBuf { if compiler.is_snapshot(self) { - self.rustc.clone() + self.initial_rustc.clone() } else { self.sysroot(compiler).join("bin").join(exe("rustc", compiler.host)) } @@ -758,7 +748,7 @@ impl Build { /// Returns the libdir of the snapshot compiler. fn rustc_snapshot_libdir(&self) -> PathBuf { - self.rustc.parent().unwrap().parent().unwrap() + self.initial_rustc.parent().unwrap().parent().unwrap() .join(libdir(&self.config.build)) } diff --git a/src/bootstrap/metadata.rs b/src/bootstrap/metadata.rs index 7b6b01655df..9326bb7129a 100644 --- a/src/bootstrap/metadata.rs +++ b/src/bootstrap/metadata.rs @@ -56,7 +56,7 @@ fn build_krate(build: &mut Build, krate: &str) { // of packages we're going to have to know what `-p` arguments to pass it // to know what crates to test. Here we run `cargo metadata` to learn about // the dependency graph and what `-p` arguments there are. - let mut cargo = Command::new(&build.cargo); + let mut cargo = Command::new(&build.initial_cargo); cargo.arg("metadata") .arg("--format-version").arg("1") .arg("--manifest-path").arg(build.src.join(krate).join("Cargo.toml")); From 712bd0d841469f8ed42d555ed714fee06beb14fa Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Tue, 27 Jun 2017 13:34:26 -0600 Subject: [PATCH 158/162] Remove src_is_git, instead call method on rust_info directly. --- src/bootstrap/channel.rs | 4 ++++ src/bootstrap/dist.rs | 2 +- src/bootstrap/lib.rs | 2 -- src/bootstrap/sanity.rs | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/bootstrap/channel.rs b/src/bootstrap/channel.rs index 199c01cf821..1153acfa57d 100644 --- a/src/bootstrap/channel.rs +++ b/src/bootstrap/channel.rs @@ -101,4 +101,8 @@ impl GitInfo { } version } + + pub fn is_git(&self) -> bool { + self.inner.is_some() + } } diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index c91d6f0b77c..2f7c1f038a1 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -623,7 +623,7 @@ pub fn plain_source_tarball(build: &Build) { write_file(&plain_dst_src.join("version"), build.rust_version().as_bytes()); // If we're building from git sources, we need to vendor a complete distribution. - if build.src_is_git { + if build.rust_info.is_git() { // Get cargo-vendor installed, if it isn't already. let mut has_cargo_vendor = false; let mut cmd = Command::new(&build.initial_cargo); diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index bb82e711d7b..a6608972acd 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -183,7 +183,6 @@ pub struct Build { cxx: HashMap, crates: HashMap, is_sudo: bool, - src_is_git: bool, ci_env: CiEnv, delayed_failures: Cell, } @@ -262,7 +261,6 @@ impl Build { lldb_version: None, lldb_python_dir: None, is_sudo: is_sudo, - src_is_git: src_is_git, ci_env: CiEnv::current(), delayed_failures: Cell::new(0), } diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index d6def25cfaa..433ac3dedfd 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -80,7 +80,7 @@ pub fn check(build: &mut Build) { let mut cmd_finder = Finder::new(); // If we've got a git directory we're gona need git to update // submodules and learn about various other aspects. - if build.src_is_git { + if build.rust_info.is_git() { cmd_finder.must_have("git"); } From 4dc8fe90836c622e57293c1262a9f7728e5edfc8 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Tue, 27 Jun 2017 13:37:24 -0600 Subject: [PATCH 159/162] Store positive instead of negative fail_fast. This makes later negation much easier to interpret. --- src/bootstrap/check.rs | 10 +++++----- src/bootstrap/flags.rs | 8 ++++---- src/bootstrap/lib.rs | 3 ++- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 04ae7e1e009..1ee33c1f465 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -59,7 +59,7 @@ impl fmt::Display for TestKind { } fn try_run(build: &Build, cmd: &mut Command) { - if build.flags.cmd.no_fail_fast() { + if !build.fail_fast { if !build.try_run(cmd) { let failures = build.delayed_failures.get(); build.delayed_failures.set(failures + 1); @@ -70,7 +70,7 @@ fn try_run(build: &Build, cmd: &mut Command) { } fn try_run_quiet(build: &Build, cmd: &mut Command) { - if build.flags.cmd.no_fail_fast() { + if !build.fail_fast { if !build.try_run_quiet(cmd) { let failures = build.delayed_failures.get(); build.delayed_failures.set(failures + 1); @@ -128,7 +128,7 @@ pub fn cargo(build: &Build, stage: u32, host: &str) { let mut cargo = build.cargo(compiler, Mode::Tool, host, "test"); cargo.arg("--manifest-path").arg(build.src.join("src/tools/cargo/Cargo.toml")); - if build.flags.cmd.no_fail_fast() { + if !build.fail_fast { cargo.arg("--no-fail-fast"); } @@ -448,7 +448,7 @@ pub fn krate(build: &Build, cargo.arg("--manifest-path") .arg(build.src.join(path).join("Cargo.toml")) .arg("--features").arg(features); - if test_kind.subcommand() == "test" && build.flags.cmd.no_fail_fast() { + if test_kind.subcommand() == "test" && !build.fail_fast { cargo.arg("--no-fail-fast"); } @@ -669,7 +669,7 @@ pub fn bootstrap(build: &Build) { .env("CARGO_TARGET_DIR", build.out.join("bootstrap")) .env("RUSTC_BOOTSTRAP", "1") .env("RUSTC", &build.initial_rustc); - if build.flags.cmd.no_fail_fast() { + if !build.fail_fast { cmd.arg("--no-fail-fast"); } cmd.arg("--").args(&build.flags.cmd.test_args()); diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index 4541b6623c4..593b0651758 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -61,7 +61,7 @@ pub enum Subcommand { Test { paths: Vec, test_args: Vec, - no_fail_fast: bool, + fail_fast: bool, }, Bench { paths: Vec, @@ -278,7 +278,7 @@ Arguments: Subcommand::Test { paths: paths, test_args: matches.opt_strs("test-args"), - no_fail_fast: matches.opt_present("no-fail-fast"), + fail_fast: !matches.opt_present("no-fail-fast"), } } "bench" => { @@ -354,9 +354,9 @@ impl Subcommand { } } - pub fn no_fail_fast(&self) -> bool { + pub fn fail_fast(&self) -> bool { match *self { - Subcommand::Test { no_fail_fast, .. } => no_fail_fast, + Subcommand::Test { fail_fast, .. } => fail_fast, _ => false, } } diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index a6608972acd..978e1d2be16 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -167,6 +167,7 @@ pub struct Build { cargo_info: channel::GitInfo, rls_info: channel::GitInfo, local_rebuild: bool, + fail_fast: bool, // Stage 0 (downloaded) compiler and cargo or their local rust equivalents. initial_rustc: PathBuf, @@ -240,12 +241,12 @@ impl Build { let rust_info = channel::GitInfo::new(&src); let cargo_info = channel::GitInfo::new(&src.join("src/tools/cargo")); let rls_info = channel::GitInfo::new(&src.join("src/tools/rls")); - let src_is_git = src.join(".git").exists(); Build { initial_rustc: config.initial_rustc.clone(), initial_cargo: config.initial_cargo.clone(), local_rebuild: config.local_rebuild, + fail_fast: flags.cmd.fail_fast(), flags: flags, config: config, From 39cf1da81c73e9bcd7b60dad927cbe1f360bc1f3 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Tue, 27 Jun 2017 13:49:21 -0600 Subject: [PATCH 160/162] Store verbosity on Build Prevents accidental mistakes in not using the right verbosity by going to only config or flags. --- src/bootstrap/check.rs | 2 +- src/bootstrap/flags.rs | 10 ---------- src/bootstrap/lib.rs | 17 +++++++++++++---- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 1ee33c1f465..a06d925e2ef 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -249,7 +249,7 @@ pub fn compiletest(build: &Build, cmd.args(&build.flags.cmd.test_args()); - if build.config.verbose() || build.flags.verbose() { + if build.is_verbose() { cmd.arg("--verbose"); } diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index 593b0651758..5804df34e8b 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -41,16 +41,6 @@ pub struct Flags { pub incremental: bool, } -impl Flags { - pub fn verbose(&self) -> bool { - self.verbose > 0 - } - - pub fn very_verbose(&self) -> bool { - self.verbose > 1 - } -} - pub enum Subcommand { Build { paths: Vec, diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 978e1d2be16..be28975c3ea 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -168,6 +168,7 @@ pub struct Build { rls_info: channel::GitInfo, local_rebuild: bool, fail_fast: bool, + verbosity: usize, // Stage 0 (downloaded) compiler and cargo or their local rust equivalents. initial_rustc: PathBuf, @@ -247,6 +248,7 @@ impl Build { initial_cargo: config.initial_cargo.clone(), local_rebuild: config.local_rebuild, fail_fast: flags.cmd.fail_fast(), + verbosity: cmp::max(flags.verbose, config.verbose), flags: flags, config: config, @@ -428,8 +430,7 @@ impl Build { cargo.env("RUSTC_ON_FAIL", on_fail); } - let verbose = cmp::max(self.config.verbose, self.flags.verbose); - cargo.env("RUSTC_VERBOSE", format!("{}", verbose)); + cargo.env("RUSTC_VERBOSE", format!("{}", self.verbosity)); // Specify some various options for build scripts used throughout // the build. @@ -467,7 +468,7 @@ impl Build { // FIXME: should update code to not require this env var cargo.env("CFG_COMPILER_HOST_TRIPLE", target); - if self.config.verbose() || self.flags.verbose() { + if self.is_verbose() { cargo.arg("-v"); } // FIXME: cargo bench does not accept `--release` @@ -779,9 +780,17 @@ impl Build { try_run_suppressed(cmd) } + pub fn is_verbose(&self) -> bool { + self.verbosity > 0 + } + + pub fn is_very_verbose(&self) -> bool { + self.verbosity > 1 + } + /// Prints a message if this build is configured in verbose mode. fn verbose(&self, msg: &str) { - if self.flags.verbose() || self.config.verbose() { + if self.is_verbose() { println!("{}", msg); } } From 5809a7d0b76c7842582a43ea5516b3817b92f9d8 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Tue, 27 Jun 2017 15:52:46 -0600 Subject: [PATCH 161/162] Move targets, hosts, and build triple into Build. --- src/bootstrap/lib.rs | 38 +++++++++++++++++++++++++++++++++++++- src/bootstrap/sanity.rs | 11 ----------- src/bootstrap/step.rs | 22 +++++++--------------- 3 files changed, 44 insertions(+), 27 deletions(-) diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index be28975c3ea..92a57630ca5 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -170,6 +170,11 @@ pub struct Build { fail_fast: bool, verbosity: usize, + // Targets for which to build. + build: String, + hosts: Vec, + targets: Vec, + // Stage 0 (downloaded) compiler and cargo or their local rust equivalents. initial_rustc: PathBuf, initial_cargo: PathBuf, @@ -243,6 +248,27 @@ impl Build { let cargo_info = channel::GitInfo::new(&src.join("src/tools/cargo")); let rls_info = channel::GitInfo::new(&src.join("src/tools/rls")); + let hosts = if !flags.host.is_empty() { + for host in flags.host.iter() { + if !config.host.contains(host) { + panic!("specified host `{}` is not in configuration", host); + } + } + flags.host.clone() + } else { + config.host.clone() + }; + let targets = if !flags.target.is_empty() { + for target in flags.target.iter() { + if !config.target.contains(target) { + panic!("specified target `{}` is not in configuration", target); + } + } + flags.target.clone() + } else { + config.target.clone() + }; + Build { initial_rustc: config.initial_rustc.clone(), initial_cargo: config.initial_cargo.clone(), @@ -250,6 +276,10 @@ impl Build { fail_fast: flags.cmd.fail_fast(), verbosity: cmp::max(flags.verbose, config.verbose), + build: config.host[0].clone(), + hosts: hosts, + targets: targets, + flags: flags, config: config, src: src, @@ -269,6 +299,12 @@ impl Build { } } + fn build_slice(&self) -> &[String] { + unsafe { + std::slice::from_raw_parts(&self.build, 1) + } + } + /// Executes the entire build, as configured by the flags and configuration. pub fn build(&mut self) { unsafe { @@ -798,7 +834,7 @@ impl Build { /// Returns the number of parallel jobs that have been configured for this /// build. fn jobs(&self) -> u32 { - self.flags.jobs.unwrap_or(num_cpus::get() as u32) + self.flags.jobs.unwrap_or_else(|| num_cpus::get() as u32) } /// Returns the path to the C compiler for the target specified. diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index 433ac3dedfd..e2c955c4f4f 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -194,17 +194,6 @@ $ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake } } - for host in build.flags.host.iter() { - if !build.config.host.contains(host) { - panic!("specified host `{}` is not in configuration", host); - } - } - for target in build.flags.target.iter() { - if !build.config.target.contains(target) { - panic!("specified target `{}` is not in configuration", target); - } - } - let run = |cmd: &mut Command| { cmd.output().map(|output| { String::from_utf8_lossy(&output.stdout) diff --git a/src/bootstrap/step.rs b/src/bootstrap/step.rs index 61e9a0d16da..bcfa004ac3c 100644 --- a/src/bootstrap/step.rs +++ b/src/bootstrap/step.rs @@ -1218,16 +1218,9 @@ invalid rule dependency graph detected, was a rule added and maybe typo'd? rules.into_iter().flat_map(|(rule, _)| { let hosts = if rule.only_host_build || rule.only_build { - &self.build.config.host[..1] - } else if self.build.flags.host.len() > 0 { - &self.build.flags.host + self.build.build_slice() } else { - &self.build.config.host - }; - let targets = if self.build.flags.target.len() > 0 { - &self.build.flags.target - } else { - &self.build.config.target + &self.build.hosts }; // Determine the actual targets participating in this rule. // NOTE: We should keep the full projection from build triple to @@ -1236,19 +1229,18 @@ invalid rule dependency graph detected, was a rule added and maybe typo'd? // the original non-shadowed hosts array is used below. let arr = if rule.host { // If --target was specified but --host wasn't specified, - // don't run any host-only tests. Also, respect any `--host` - // overrides as done for `hosts`. + // don't run any host-only tests. if self.build.flags.host.len() > 0 { - &self.build.flags.host[..] + &self.build.hosts } else if self.build.flags.target.len() > 0 { &[] } else if rule.only_build { - &self.build.config.host[..1] + self.build.build_slice() } else { - &self.build.config.host[..] + &self.build.hosts } } else { - targets + &self.build.targets }; hosts.iter().flat_map(move |host| { From 1654a2f5aca29041df86a8edd7fc0c9e6c5c1c9b Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Tue, 27 Jun 2017 15:59:43 -0600 Subject: [PATCH 162/162] Use build.build instead of build.config.build --- src/bootstrap/cc.rs | 14 ++++-- src/bootstrap/check.rs | 16 +++--- src/bootstrap/compile.rs | 10 ++-- src/bootstrap/dist.rs | 14 +++--- src/bootstrap/doc.rs | 18 +++---- src/bootstrap/lib.rs | 2 +- src/bootstrap/native.rs | 8 +-- src/bootstrap/sanity.rs | 4 +- src/bootstrap/step.rs | 104 +++++++++++++++++++-------------------- 9 files changed, 98 insertions(+), 92 deletions(-) diff --git a/src/bootstrap/cc.rs b/src/bootstrap/cc.rs index 54c8194678e..7c7161916ee 100644 --- a/src/bootstrap/cc.rs +++ b/src/bootstrap/cc.rs @@ -42,10 +42,13 @@ use config::Target; pub fn find(build: &mut Build) { // For all targets we're going to need a C compiler for building some shims // and such as well as for being a linker for Rust code. - for target in build.config.target.iter() { + // + // This includes targets that aren't necessarily passed on the commandline + // (FIXME: Perhaps it shouldn't?) + for target in &build.config.target { let mut cfg = gcc::Config::new(); cfg.cargo_metadata(false).opt_level(0).debug(false) - .target(target).host(&build.config.build); + .target(target).host(&build.build); let config = build.config.target_config.get(target); if let Some(cc) = config.and_then(|c| c.cc.as_ref()) { @@ -64,10 +67,13 @@ pub fn find(build: &mut Build) { } // For all host triples we need to find a C++ compiler as well - for host in build.config.host.iter() { + // + // This includes hosts that aren't necessarily passed on the commandline + // (FIXME: Perhaps it shouldn't?) + for host in &build.config.host { let mut cfg = gcc::Config::new(); cfg.cargo_metadata(false).opt_level(0).debug(false).cpp(true) - .target(host).host(&build.config.build); + .target(host).host(&build.build); let config = build.config.target_config.get(host); if let Some(cxx) = config.and_then(|c| c.cxx.as_ref()) { cfg.compiler(cxx); diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index a06d925e2ef..b3b5ae8d67d 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -196,7 +196,7 @@ pub fn compiletest(build: &Build, cmd.arg("--mode").arg(mode); cmd.arg("--target").arg(target); cmd.arg("--host").arg(compiler.host); - cmd.arg("--llvm-filecheck").arg(build.llvm_filecheck(&build.config.build)); + cmd.arg("--llvm-filecheck").arg(build.llvm_filecheck(&build.build)); if let Some(ref nodejs) = build.config.nodejs { cmd.arg("--nodejs").arg(nodejs); @@ -222,7 +222,7 @@ pub fn compiletest(build: &Build, cmd.arg("--docck-python").arg(build.python()); - if build.config.build.ends_with("apple-darwin") { + if build.build.ends_with("apple-darwin") { // Force /usr/bin/python on macOS for LLDB tests because we're loading the // LLDB plugin's compiled module which only works with the system python // (namely not Homebrew-installed python) @@ -277,7 +277,7 @@ pub fn compiletest(build: &Build, if build.remote_tested(target) { cmd.arg("--remote-test-client") - .arg(build.tool(&Compiler::new(0, &build.config.build), + .arg(build.tool(&Compiler::new(0, &build.build), "remote-test-client")); } @@ -366,7 +366,7 @@ pub fn error_index(build: &Build, compiler: &Compiler) { "error_index_generator") .arg("markdown") .arg(&output) - .env("CFG_BUILD", &build.config.build)); + .env("CFG_BUILD", &build.build)); markdown_test(build, compiler, &output); } @@ -540,7 +540,7 @@ fn krate_remote(build: &Build, let out_dir = build.cargo_out(compiler, mode, target); let tests = find_tests(&out_dir.join("deps"), target); - let tool = build.tool(&Compiler::new(0, &build.config.build), + let tool = build.tool(&Compiler::new(0, &build.build), "remote-test-client"); for test in tests { let mut cmd = Command::new(&tool); @@ -585,7 +585,7 @@ pub fn remote_copy_libs(build: &Build, compiler: &Compiler, target: &str) { .join(exe("remote-test-server", target)); // Spawn the emulator and wait for it to come online - let tool = build.tool(&Compiler::new(0, &build.config.build), + let tool = build.tool(&Compiler::new(0, &build.build), "remote-test-client"); let mut cmd = Command::new(&tool); cmd.arg("spawn-emulator") @@ -611,7 +611,7 @@ pub fn remote_copy_libs(build: &Build, compiler: &Compiler, target: &str) { /// Run "distcheck", a 'make check' from a tarball pub fn distcheck(build: &Build) { - if build.config.build != "x86_64-unknown-linux-gnu" { + if build.build != "x86_64-unknown-linux-gnu" { return } if !build.config.host.iter().any(|s| s == "x86_64-unknown-linux-gnu") { @@ -636,7 +636,7 @@ pub fn distcheck(build: &Build) { .args(&build.config.configure_args) .arg("--enable-vendor") .current_dir(&dir)); - build.run(Command::new(build_helper::make(&build.config.build)) + build.run(Command::new(build_helper::make(&build.build)) .arg("check") .current_dir(&dir)); diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 5123e59a5db..5a3106c7d5e 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -158,7 +158,7 @@ pub fn build_startup_objects(build: &Build, for_compiler: &Compiler, target: &st return } - let compiler = Compiler::new(0, &build.config.build); + let compiler = Compiler::new(0, &build.build); let compiler_path = build.compiler_path(&compiler); let src_dir = &build.src.join("src/rtstartup"); let dst_dir = &build.native_dir(target).join("rtstartup"); @@ -351,7 +351,7 @@ pub fn create_sysroot(build: &Build, compiler: &Compiler) { /// Prepare a new compiler from the artifacts in `stage` /// /// This will assemble a compiler in `build/$host/stage$stage`. The compiler -/// must have been previously produced by the `stage - 1` build.config.build +/// must have been previously produced by the `stage - 1` build.build /// compiler. pub fn assemble_rustc(build: &Build, stage: u32, host: &str) { // nothing to do in stage0 @@ -365,7 +365,7 @@ pub fn assemble_rustc(build: &Build, stage: u32, host: &str) { let target_compiler = Compiler::new(stage, host); // The compiler that compiled the compiler we're assembling - let build_compiler = Compiler::new(stage - 1, &build.config.build); + let build_compiler = Compiler::new(stage - 1, &build.build); // Link in all dylibs to the libdir let sysroot = build.sysroot(&target_compiler); @@ -423,7 +423,7 @@ fn add_to_sysroot(sysroot_dst: &Path, stamp: &Path) { /// This will build the specified tool with the specified `host` compiler in /// `stage` into the normal cargo output directory. pub fn maybe_clean_tools(build: &Build, stage: u32, target: &str, mode: Mode) { - let compiler = Compiler::new(stage, &build.config.build); + let compiler = Compiler::new(stage, &build.build); let stamp = match mode { Mode::Libstd => libstd_stamp(build, &compiler, target), @@ -443,7 +443,7 @@ pub fn tool(build: &Build, stage: u32, target: &str, tool: &str) { let _folder = build.fold_output(|| format!("stage{}-{}", stage, tool)); println!("Building stage{} tool {} ({})", stage, tool, target); - let compiler = Compiler::new(stage, &build.config.build); + let compiler = Compiler::new(stage, &build.build); let mut cargo = build.cargo(&compiler, Mode::Tool, target, "build"); let dir = build.src.join("src/tools").join(tool); diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 2f7c1f038a1..efc33bcee9b 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -50,7 +50,7 @@ pub fn tmpdir(build: &Build) -> PathBuf { } fn rust_installer(build: &Build) -> Command { - build.tool_cmd(&Compiler::new(0, &build.config.build), "rust-installer") + build.tool_cmd(&Compiler::new(0, &build.build), "rust-installer") } /// Builds the `rust-docs` installer component. @@ -89,7 +89,7 @@ pub fn docs(build: &Build, stage: u32, host: &str) { // As part of this step, *also* copy the docs directory to a directory which // buildbot typically uploads. - if host == build.config.build { + if host == build.build { let dst = distdir(build).join("doc").join(build.rust_package_vers()); t!(fs::create_dir_all(&dst)); cp_r(&src, &dst); @@ -394,7 +394,7 @@ pub fn std(build: &Build, compiler: &Compiler, target: &str) { // The only true set of target libraries came from the build triple, so // let's reduce redundant work by only producing archives from that host. - if compiler.host != build.config.build { + if compiler.host != build.build { println!("\tskipping, not a build host"); return } @@ -440,7 +440,7 @@ pub fn analysis(build: &Build, compiler: &Compiler, target: &str) { assert!(build.config.extended); println!("Dist analysis"); - if compiler.host != build.config.build { + if compiler.host != build.build { println!("\tskipping, not a build host"); return; } @@ -705,7 +705,7 @@ fn write_file(path: &Path, data: &[u8]) { pub fn cargo(build: &Build, stage: u32, target: &str) { println!("Dist cargo stage{} ({})", stage, target); - let compiler = Compiler::new(stage, &build.config.build); + let compiler = Compiler::new(stage, &build.build); let src = build.src.join("src/tools/cargo"); let etc = src.join("src/etc"); @@ -766,7 +766,7 @@ pub fn cargo(build: &Build, stage: u32, target: &str) { pub fn rls(build: &Build, stage: u32, target: &str) { assert!(build.config.extended); println!("Dist RLS stage{} ({})", stage, target); - let compiler = Compiler::new(stage, &build.config.build); + let compiler = Compiler::new(stage, &build.build); let src = build.src.join("src/tools/rls"); let release_num = build.release_num("rls"); @@ -1198,7 +1198,7 @@ fn add_env(build: &Build, cmd: &mut Command, target: &str) { } pub fn hash_and_sign(build: &Build) { - let compiler = Compiler::new(0, &build.config.build); + let compiler = Compiler::new(0, &build.build); let mut cmd = build.tool_cmd(&compiler, "build-manifest"); let sign = build.config.dist_sign_folder.as_ref().unwrap_or_else(|| { panic!("\n\nfailed to specify `dist.sign-folder` in `config.toml`\n\n") diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 30f631ca2df..7dbc3e55539 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -45,7 +45,7 @@ pub fn rustbook_src(build: &Build, target: &str, name: &str, src: &Path) { t!(fs::create_dir_all(&out)); let out = out.join(name); - let compiler = Compiler::new(0, &build.config.build); + let compiler = Compiler::new(0, &build.build); let src = src.join(name); let index = out.join("index.html"); let rustbook = build.tool(&compiler, "rustbook"); @@ -95,7 +95,7 @@ pub fn book(build: &Build, target: &str, name: &str) { fn invoke_rustdoc(build: &Build, target: &str, markdown: &str) { let out = build.doc_out(target); - let compiler = Compiler::new(0, &build.config.build); + let compiler = Compiler::new(0, &build.build); let path = build.src.join("src/doc").join(markdown); @@ -150,7 +150,7 @@ pub fn standalone(build: &Build, target: &str) { let out = build.doc_out(target); t!(fs::create_dir_all(&out)); - let compiler = Compiler::new(0, &build.config.build); + let compiler = Compiler::new(0, &build.build); let favicon = build.src.join("src/doc/favicon.inc"); let footer = build.src.join("src/doc/footer.inc"); @@ -217,7 +217,7 @@ pub fn std(build: &Build, stage: u32, target: &str) { println!("Documenting stage{} std ({})", stage, target); let out = build.doc_out(target); t!(fs::create_dir_all(&out)); - let compiler = Compiler::new(stage, &build.config.build); + let compiler = Compiler::new(stage, &build.build); let compiler = if build.force_use_stage1(&compiler, target) { Compiler::new(1, compiler.host) } else { @@ -276,7 +276,7 @@ pub fn test(build: &Build, stage: u32, target: &str) { println!("Documenting stage{} test ({})", stage, target); let out = build.doc_out(target); t!(fs::create_dir_all(&out)); - let compiler = Compiler::new(stage, &build.config.build); + let compiler = Compiler::new(stage, &build.build); let compiler = if build.force_use_stage1(&compiler, target) { Compiler::new(1, compiler.host) } else { @@ -306,7 +306,7 @@ pub fn rustc(build: &Build, stage: u32, target: &str) { println!("Documenting stage{} compiler ({})", stage, target); let out = build.doc_out(target); t!(fs::create_dir_all(&out)); - let compiler = Compiler::new(stage, &build.config.build); + let compiler = Compiler::new(stage, &build.build); let compiler = if build.force_use_stage1(&compiler, target) { Compiler::new(1, compiler.host) } else { @@ -351,13 +351,13 @@ pub fn error_index(build: &Build, target: &str) { println!("Documenting error index ({})", target); let out = build.doc_out(target); t!(fs::create_dir_all(&out)); - let compiler = Compiler::new(0, &build.config.build); + let compiler = Compiler::new(0, &build.build); let mut index = build.tool_cmd(&compiler, "error_index_generator"); index.arg("html"); index.arg(out.join("error-index.html")); // FIXME: shouldn't have to pass this env var - index.env("CFG_BUILD", &build.config.build); + index.env("CFG_BUILD", &build.build); build.run(&mut index); } @@ -367,7 +367,7 @@ pub fn unstable_book_gen(build: &Build, target: &str) { let out = build.md_doc_out(target).join("unstable-book"); t!(fs::create_dir_all(&out)); t!(fs::remove_dir_all(&out)); - let compiler = Compiler::new(0, &build.config.build); + let compiler = Compiler::new(0, &build.build); let mut cmd = build.tool_cmd(&compiler, "unstable-book-gen"); cmd.arg(build.src.join("src")); cmd.arg(out); diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 92a57630ca5..69b0c4a2756 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -1079,7 +1079,7 @@ impl<'a> Compiler<'a> { /// Returns whether this is a snapshot compiler for `build`'s configuration fn is_snapshot(&self, build: &Build) -> bool { - self.stage == 0 && self.host == build.config.build + self.stage == 0 && self.host == build.build } /// Returns if this compiler should be treated as a final stage one in the diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index f150df6cdcd..20eec97d8e5 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -94,7 +94,7 @@ pub fn llvm(build: &Build, target: &str) { let assertions = if build.config.llvm_assertions {"ON"} else {"OFF"}; cfg.target(target) - .host(&build.config.build) + .host(&build.build) .out_dir(&out_dir) .profile(profile) .define("LLVM_ENABLE_ASSERTIONS", assertions) @@ -129,11 +129,11 @@ pub fn llvm(build: &Build, target: &str) { } // http://llvm.org/docs/HowToCrossCompileLLVM.html - if target != build.config.build { + if target != build.build { // FIXME: if the llvm root for the build triple is overridden then we // should use llvm-tblgen from there, also should verify that it // actually exists most of the time in normal installs of LLVM. - let host = build.llvm_out(&build.config.build).join("bin/llvm-tblgen"); + let host = build.llvm_out(&build.build).join("bin/llvm-tblgen"); cfg.define("CMAKE_CROSSCOMPILING", "True") .define("LLVM_TABLEGEN", &host); } @@ -243,7 +243,7 @@ pub fn test_helpers(build: &Build, target: &str) { cfg.cargo_metadata(false) .out_dir(&dst) .target(target) - .host(&build.config.build) + .host(&build.build) .opt_level(0) .debug(false) .file(build.src.join("src/rt/rust_test_helpers.c")) diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index e2c955c4f4f..a9c1b023dd4 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -139,7 +139,7 @@ pub fn check(build: &mut Build) { } // Externally configured LLVM requires FileCheck to exist - let filecheck = build.llvm_filecheck(&build.config.build); + let filecheck = build.llvm_filecheck(&build.build); if !filecheck.starts_with(&build.out) && !filecheck.exists() && build.config.codegen_tests { panic!("FileCheck executable {:?} does not exist", filecheck); } @@ -147,7 +147,7 @@ pub fn check(build: &mut Build) { for target in &build.config.target { // Can't compile for iOS unless we're on macOS if target.contains("apple-ios") && - !build.config.build.contains("apple-darwin") { + !build.build.contains("apple-darwin") { panic!("the iOS target is only supported on macOS"); } diff --git a/src/bootstrap/step.rs b/src/bootstrap/step.rs index bcfa004ac3c..c221d707683 100644 --- a/src/bootstrap/step.rs +++ b/src/bootstrap/step.rs @@ -104,10 +104,10 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { rules.build("llvm", "src/llvm") .host(true) .dep(move |s| { - if s.target == build.config.build { + if s.target == build.build { Step::noop() } else { - s.target(&build.config.build) + s.target(&build.build) } }) .run(move |s| native::llvm(build, s.target)); @@ -124,7 +124,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { Step::noop() } else { s.name("librustc") - .host(&build.config.build) + .host(&build.build) .stage(s.stage - 1) } }) @@ -215,24 +215,24 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { let mut rule = rules.build(&krate, "path/to/nowhere"); rule.dep(move |s| { if build.force_use_stage1(&s.compiler(), s.target) { - s.host(&build.config.build).stage(1) - } else if s.host == build.config.build { + s.host(&build.build).stage(1) + } else if s.host == build.build { s.name(dep) } else { - s.host(&build.config.build) + s.host(&build.build) } }) .run(move |s| { if build.force_use_stage1(&s.compiler(), s.target) { link(build, - &s.stage(1).host(&build.config.build).compiler(), + &s.stage(1).host(&build.build).compiler(), &s.compiler(), s.target) - } else if s.host == build.config.build { + } else if s.host == build.build { link(build, &s.compiler(), &s.compiler(), s.target) } else { link(build, - &s.host(&build.config.build).compiler(), + &s.host(&build.build).compiler(), &s.compiler(), s.target) } @@ -269,7 +269,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { for (krate, path, _default) in krates("std") { rules.build(&krate.build_step, path) .dep(|s| s.name("startup-objects")) - .dep(move |s| s.name("rustc").host(&build.config.build).target(s.host)) + .dep(move |s| s.name("rustc").host(&build.build).target(s.host)) .run(move |s| compile::std(build, s.target, &s.compiler())); } for (krate, path, _default) in krates("test") { @@ -280,7 +280,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { for (krate, path, _default) in krates("rustc-main") { rules.build(&krate.build_step, path) .dep(|s| s.name("libtest-link")) - .dep(move |s| s.name("llvm").host(&build.config.build).stage(0)) + .dep(move |s| s.name("llvm").host(&build.build).stage(0)) .dep(|s| s.name("may-run-build-script")) .run(move |s| compile::rustc(build, s.target, &s.compiler())); } @@ -291,8 +291,8 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { rules.build("may-run-build-script", "path/to/nowhere") .dep(move |s| { s.name("libstd-link") - .host(&build.config.build) - .target(&build.config.build) + .host(&build.build) + .target(&build.build) }); rules.build("startup-objects", "src/rtstartup") .dep(|s| s.name("create-sysroot").target(s.host)) @@ -332,7 +332,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { "incremental"); } - if build.config.build.contains("msvc") { + if build.build.contains("msvc") { // nothing to do for debuginfo tests } else { rules.test("check-debuginfo-lldb", "src/test/debuginfo-lldb") @@ -352,7 +352,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { "debuginfo-gdb", "debuginfo")); let mut rule = rules.test("check-debuginfo", "src/test/debuginfo"); rule.default(true); - if build.config.build.contains("apple") { + if build.build.contains("apple") { rule.dep(|s| s.name("check-debuginfo-lldb")); } else { rule.dep(|s| s.name("check-debuginfo-gdb")); @@ -594,8 +594,8 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { // Cargo depends on procedural macros, which requires a full host // compiler to be available, so we need to depend on that. s.name("librustc-link") - .target(&build.config.build) - .host(&build.config.build) + .target(&build.build) + .host(&build.build) }) .run(move |s| compile::tool(build, s.stage, s.target, "cargo")); rules.build("tool-rls", "src/tools/rls") @@ -606,8 +606,8 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { .dep(move |s| { // rls, like cargo, uses procedural macros s.name("librustc-link") - .target(&build.config.build) - .host(&build.config.build) + .target(&build.build) + .host(&build.build) }) .run(move |s| compile::tool(build, s.stage, s.target, "rls")); @@ -635,8 +635,8 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { rules.doc("doc-book", "src/doc/book") .dep(move |s| { s.name("tool-rustbook") - .host(&build.config.build) - .target(&build.config.build) + .host(&build.build) + .target(&build.build) .stage(0) }) .default(build.config.docs) @@ -644,8 +644,8 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { rules.doc("doc-nomicon", "src/doc/nomicon") .dep(move |s| { s.name("tool-rustbook") - .host(&build.config.build) - .target(&build.config.build) + .host(&build.build) + .target(&build.build) .stage(0) }) .default(build.config.docs) @@ -653,8 +653,8 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { rules.doc("doc-reference", "src/doc/reference") .dep(move |s| { s.name("tool-rustbook") - .host(&build.config.build) - .target(&build.config.build) + .host(&build.build) + .target(&build.build) .stage(0) }) .default(build.config.docs) @@ -662,8 +662,8 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { rules.doc("doc-unstable-book", "src/doc/unstable-book") .dep(move |s| { s.name("tool-rustbook") - .host(&build.config.build) - .target(&build.config.build) + .host(&build.build) + .target(&build.build) .stage(0) }) .dep(move |s| s.name("doc-unstable-book-gen")) @@ -675,14 +675,14 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { rules.doc("doc-standalone", "src/doc") .dep(move |s| { s.name("rustc") - .host(&build.config.build) - .target(&build.config.build) + .host(&build.build) + .target(&build.build) .stage(0) }) .default(build.config.docs) .run(move |s| doc::standalone(build, s.target)); rules.doc("doc-error-index", "src/tools/error_index_generator") - .dep(move |s| s.name("tool-error-index").target(&build.config.build).stage(0)) + .dep(move |s| s.name("tool-error-index").target(&build.build).stage(0)) .dep(move |s| s.name("librustc-link")) .default(build.config.docs) .host(true) @@ -690,8 +690,8 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { rules.doc("doc-unstable-book-gen", "src/tools/unstable-book-gen") .dep(move |s| { s.name("tool-unstable-book-gen") - .host(&build.config.build) - .target(&build.config.build) + .host(&build.build) + .target(&build.build) .stage(0) }) .dep(move |s| s.name("libstd-link")) @@ -725,7 +725,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { // ======================================================================== // Distribution targets rules.dist("dist-rustc", "src/librustc") - .dep(move |s| s.name("rustc").host(&build.config.build)) + .dep(move |s| s.name("rustc").host(&build.build)) .host(true) .only_host_build(true) .default(true) @@ -811,7 +811,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { .host(true) .only_build(true) .only_host_build(true) - .dep(move |s| s.name("tool-build-manifest").target(&build.config.build).stage(0)) + .dep(move |s| s.name("tool-build-manifest").target(&build.build).stage(0)) .run(move |_| dist::hash_and_sign(build)); rules.install("install-docs", "src/doc") @@ -861,8 +861,8 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { /// Helper to depend on a stage0 build-only rust-installer tool. fn tool_rust_installer<'a>(build: &'a Build, step: &Step<'a>) -> Step<'a> { step.name("tool-rust-installer") - .host(&build.config.build) - .target(&build.config.build) + .host(&build.build) + .target(&build.build) .stage(0) } } @@ -1058,8 +1058,8 @@ impl<'a> Rules<'a> { build: build, sbuild: Step { stage: build.flags.stage.unwrap_or(2), - target: &build.config.build, - host: &build.config.build, + target: &build.build, + host: &build.build, name: "", }, rules: BTreeMap::new(), @@ -1486,8 +1486,8 @@ mod tests { let step = super::Step { name: "", stage: 2, - host: &build.config.build, - target: &build.config.build, + host: &build.build, + target: &build.build, }; assert!(plan.contains(&step.name("dist-docs"))); @@ -1509,8 +1509,8 @@ mod tests { let step = super::Step { name: "", stage: 2, - host: &build.config.build, - target: &build.config.build, + host: &build.build, + target: &build.build, }; assert!(plan.contains(&step.name("dist-docs"))); @@ -1537,8 +1537,8 @@ mod tests { let step = super::Step { name: "", stage: 2, - host: &build.config.build, - target: &build.config.build, + host: &build.build, + target: &build.build, }; assert!(!plan.iter().any(|s| s.host == "B")); @@ -1567,8 +1567,8 @@ mod tests { let step = super::Step { name: "", stage: 2, - host: &build.config.build, - target: &build.config.build, + host: &build.build, + target: &build.build, }; assert!(!plan.iter().any(|s| s.host == "B")); @@ -1604,8 +1604,8 @@ mod tests { let step = super::Step { name: "", stage: 2, - host: &build.config.build, - target: &build.config.build, + host: &build.build, + target: &build.build, }; assert!(!plan.iter().any(|s| s.target == "A")); @@ -1631,8 +1631,8 @@ mod tests { let step = super::Step { name: "", stage: 2, - host: &build.config.build, - target: &build.config.build, + host: &build.build, + target: &build.build, }; assert!(!plan.iter().any(|s| s.target == "A")); @@ -1675,8 +1675,8 @@ mod tests { let step = super::Step { name: "", stage: 2, - host: &build.config.build, - target: &build.config.build, + host: &build.build, + target: &build.build, }; // rustc built for all for of (A, B) x (A, B)