From b0eee76d25fc3388cdc0eb78fe84228e90ae8c88 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Mon, 10 Oct 2016 15:27:08 +0200 Subject: [PATCH 01/60] Include attributes on generic parameter bindings in pretty printer. --- src/libsyntax/print/pprust.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 3c106970232cd..ee5e9a1d7d5dd 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1361,6 +1361,7 @@ impl<'a> State<'a> { if comma { try!(self.word_space(",")) } + try!(self.print_outer_attributes_inline(&lifetime_def.attrs)); try!(self.print_lifetime_bounds(&lifetime_def.lifetime, &lifetime_def.bounds)); comma = true; } @@ -2803,6 +2804,7 @@ impl<'a> State<'a> { try!(self.commasep(Inconsistent, &ints[..], |s, &idx| { if idx < generics.lifetimes.len() { let lifetime_def = &generics.lifetimes[idx]; + try!(s.print_outer_attributes_inline(&lifetime_def.attrs)); s.print_lifetime_bounds(&lifetime_def.lifetime, &lifetime_def.bounds) } else { let idx = idx - generics.lifetimes.len(); @@ -2816,6 +2818,7 @@ impl<'a> State<'a> { } pub fn print_ty_param(&mut self, param: &ast::TyParam) -> io::Result<()> { + try!(self.print_outer_attributes_inline(¶m.attrs)); try!(self.print_ident(param.ident)); try!(self.print_bounds(":", ¶m.bounds)); match param.default { From 4bb68be68106c655486a6a9d68780bd1b7cc9cd3 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 11 Oct 2016 16:07:14 +0200 Subject: [PATCH 02/60] Add feature gate for `dropck_eyepatch` feature (RFC 1327). --- src/libsyntax/feature_gate.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 9eed1d61244a4..c2eae29c16d5d 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -167,6 +167,9 @@ declare_features! ( // RFC 1238 (active, dropck_parametricity, "1.3.0", Some(28498)), + // Allows using the may_dangle attribute; RFC 1327 + (active, dropck_eyepatch, "1.10.0", Some(34761)), + // Allows the use of custom attributes; RFC 572 (active, custom_attribute, "1.0.0", Some(29642)), @@ -617,6 +620,11 @@ pub const KNOWN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeGat "unsafe_destructor_blind_to_params has unstable semantics \ and may be removed in the future", cfg_fn!(dropck_parametricity))), + ("may_dangle", + Normal, + Gated("dropck_eyepatch", + "may_dangle has unstable semantics and may be removed in the future", + cfg_fn!(dropck_eyepatch))), ("unwind", Whitelisted, Gated("unwind_attributes", "#[unwind] is experimental", cfg_fn!(unwind_attributes))), From e8ccc682542f9d77c6c02bf6e4520536b7c767c5 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 11 Oct 2016 16:06:43 +0200 Subject: [PATCH 03/60] Thread `pure_wrt_drop` field through lifetime and type parameters. --- src/librustc/hir/lowering.rs | 2 ++ src/librustc/hir/mod.rs | 2 ++ src/librustc/infer/error_reporting.rs | 11 +++++++---- src/librustc/ty/mod.rs | 10 ++++++++++ src/librustc/ty/structural_impls.rs | 2 ++ src/librustc_typeck/collect.rs | 5 ++++- 6 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index f56a27b9ae04a..3a06c6f3b9657 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -408,6 +408,7 @@ impl<'a> LoweringContext<'a> { bounds: self.lower_bounds(&tp.bounds), default: tp.default.as_ref().map(|x| self.lower_ty(x)), span: tp.span, + pure_wrt_drop: tp.attrs.iter().any(|attr| attr.check_name("may_dangle")), } } @@ -427,6 +428,7 @@ impl<'a> LoweringContext<'a> { hir::LifetimeDef { lifetime: self.lower_lifetime(&l.lifetime), bounds: self.lower_lifetimes(&l.bounds), + pure_wrt_drop: l.attrs.iter().any(|attr| attr.check_name("may_dangle")), } } diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index f64b0e9c7342c..3ecb731b5ed74 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -95,6 +95,7 @@ impl fmt::Debug for Lifetime { pub struct LifetimeDef { pub lifetime: Lifetime, pub bounds: HirVec, + pub pure_wrt_drop: bool, } /// A "Path" is essentially Rust's notion of a name; for instance: @@ -290,6 +291,7 @@ pub struct TyParam { pub bounds: TyParamBounds, pub default: Option>, pub span: Span, + pub pure_wrt_drop: bool, } /// Represents lifetimes and type parameters attached to a declaration diff --git a/src/librustc/infer/error_reporting.rs b/src/librustc/infer/error_reporting.rs index 3f216d6916851..f4b19cdc8ad12 100644 --- a/src/librustc/infer/error_reporting.rs +++ b/src/librustc/infer/error_reporting.rs @@ -1226,16 +1226,17 @@ impl<'a, 'gcx, 'tcx> Rebuilder<'a, 'gcx, 'tcx> { lifetime: hir::Lifetime, region_names: &HashSet) -> hir::HirVec { - ty_params.iter().map(|ty_param| { - let bounds = self.rebuild_ty_param_bounds(ty_param.bounds.clone(), + ty_params.into_iter().map(|ty_param| { + let bounds = self.rebuild_ty_param_bounds(ty_param.bounds, lifetime, region_names); hir::TyParam { name: ty_param.name, id: ty_param.id, bounds: bounds, - default: ty_param.default.clone(), + default: ty_param.default, span: ty_param.span, + pure_wrt_drop: ty_param.pure_wrt_drop, } }).collect() } @@ -1295,7 +1296,9 @@ impl<'a, 'gcx, 'tcx> Rebuilder<'a, 'gcx, 'tcx> { let mut lifetimes = Vec::new(); for lt in add { lifetimes.push(hir::LifetimeDef { lifetime: *lt, - bounds: hir::HirVec::new() }); + bounds: hir::HirVec::new(), + pure_wrt_drop: false, + }); } for lt in &generics.lifetimes { if keep.contains(<.lifetime.name) || diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 8e330ee8e824c..e1d8839bb37d8 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -680,6 +680,11 @@ pub struct TypeParameterDef<'tcx> { pub default_def_id: DefId, // for use in error reporing about defaults pub default: Option>, pub object_lifetime_default: ObjectLifetimeDefault<'tcx>, + + /// `pure_wrt_drop`, set by the (unsafe) `#[may_dangle]` attribute + /// on generic parameter `T`, asserts data behind the parameter + /// `T` won't be accessed during the parent type's `Drop` impl. + pub pure_wrt_drop: bool, } #[derive(Clone, RustcEncodable, RustcDecodable)] @@ -688,6 +693,11 @@ pub struct RegionParameterDef<'tcx> { pub def_id: DefId, pub index: u32, pub bounds: Vec<&'tcx ty::Region>, + + /// `pure_wrt_drop`, set by the (unsafe) `#[may_dangle]` attribute + /// on generic parameter `'a`, asserts data of lifetime `'a` + /// won't be accessed during the parent type's `Drop` impl. + pub pure_wrt_drop: bool, } impl<'tcx> RegionParameterDef<'tcx> { diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index abd5cb51f39ba..40eb6d71280a6 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -716,6 +716,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::TypeParameterDef<'tcx> { default: self.default.fold_with(folder), default_def_id: self.default_def_id, object_lifetime_default: self.object_lifetime_default.fold_with(folder), + pure_wrt_drop: self.pure_wrt_drop, } } @@ -754,6 +755,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::RegionParameterDef<'tcx> { def_id: self.def_id, index: self.index, bounds: self.bounds.fold_with(folder), + pure_wrt_drop: self.pure_wrt_drop, } } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 128db6ef5848a..6e47f4ed8c6be 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1482,6 +1482,7 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, default_def_id: tcx.map.local_def_id(parent), default: None, object_lifetime_default: ty::ObjectLifetimeDefault::BaseDefault, + pure_wrt_drop: false, }; tcx.ty_param_defs.borrow_mut().insert(param_id, def.clone()); opt_self = Some(def); @@ -1526,7 +1527,8 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, def_id: tcx.map.local_def_id(l.lifetime.id), bounds: l.bounds.iter().map(|l| { ast_region_to_region(tcx, l) - }).collect() + }).collect(), + pure_wrt_drop: l.pure_wrt_drop, } }).collect::>(); @@ -1926,6 +1928,7 @@ fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, default_def_id: ccx.tcx.map.local_def_id(parent), default: default, object_lifetime_default: object_lifetime_default, + pure_wrt_drop: param.pure_wrt_drop, }; if def.name == keywords::SelfType.name() { From 7d2d5bcbcf8342976609feeb46972d346b549cca Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 11 Oct 2016 16:07:33 +0200 Subject: [PATCH 04/60] Code for enforcing `#[may_dangle]` attribute. --- src/librustc_typeck/check/dropck.rs | 106 ++++++++++++++++++++++++---- 1 file changed, 91 insertions(+), 15 deletions(-) diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index cc958fb3b2343..b48c37b2fc9f3 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -402,16 +402,27 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'b, 'gcx, 'tcx>( // unbounded type parameter `T`, we must resume the recursive // analysis on `T` (since it would be ignored by // type_must_outlive). - if has_dtor_of_interest(tcx, ty) { - debug!("iterate_over_potentially_unsafe_regions_in_type \ - {}ty: {} - is a dtorck type!", - (0..depth).map(|_| ' ').collect::(), - ty); - - cx.rcx.type_must_outlive(infer::SubregionOrigin::SafeDestructor(cx.span), - ty, tcx.mk_region(ty::ReScope(cx.parent_scope))); - - return Ok(()); + let dropck_kind = has_dtor_of_interest(tcx, ty); + debug!("iterate_over_potentially_unsafe_regions_in_type \ + ty: {:?} dropck_kind: {:?}", ty, dropck_kind); + match dropck_kind { + DropckKind::NoBorrowedDataAccessedInMyDtor => { + // The maximally blind attribute. + } + DropckKind::BorrowedDataMustStrictlyOutliveSelf => { + cx.rcx.type_must_outlive(infer::SubregionOrigin::SafeDestructor(cx.span), + ty, tcx.mk_region(ty::ReScope(cx.parent_scope))); + return Ok(()); + } + DropckKind::RevisedSelf(revised_ty) => { + cx.rcx.type_must_outlive(infer::SubregionOrigin::SafeDestructor(cx.span), + revised_ty, tcx.mk_region(ty::ReScope(cx.parent_scope))); + // Do not return early from this case; we want + // to recursively process the internal structure of Self + // (because even though the Drop for Self has been asserted + // safe, the types instantiated for the generics of Self + // may themselves carry dropck constraints.) + } } debug!("iterate_over_potentially_unsafe_regions_in_type \ @@ -492,16 +503,81 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'b, 'gcx, 'tcx>( } } +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +enum DropckKind<'tcx> { + /// The "safe" kind; i.e. conservatively assume any borrow + /// accessed by dtor, and therefore such data must strictly + /// outlive self. + /// + /// Equivalent to RevisedTy with no change to the self type. + /// + /// FIXME: this name may not be general enough; it should be + /// talking about Phantom lifetimes rather than just borrows. + /// + /// (actually, pnkfelix is not 100% sure that's the right + /// viewpoint. If I'm holding a phantom lifetime just to + /// constrain a reference type that occurs solely in *negative* + /// type positions, then my destructor cannot itself ever actually + /// access such references, right? And don't we end up essentially + /// requring people to put a fake borrow inside a PhantomData in + /// order to make phantom lifetimes work anyway?) + BorrowedDataMustStrictlyOutliveSelf, + + /// The nearly completely-unsafe kind. + /// + /// Equivalent to RevisedSelf with *all* parameters remapped to () + /// (maybe...?) + NoBorrowedDataAccessedInMyDtor, + + /// Assume all borrowed data access by dtor occurs as if Self has the + /// type carried by this variant. In practice this means that some + /// of the type parameters are remapped to `()`, because the developer + /// has asserted that the destructor will not access their contents. + RevisedSelf(Ty<'tcx>), +} + +/// Returns the classification of what kind of check should be applied +/// to `ty`, which may include a revised type where some of the type +/// parameters are re-mapped to `()` to reflect the destructor's +/// "purity" with respect to their actual contents. fn has_dtor_of_interest<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, - ty: Ty<'tcx>) -> bool { + ty: Ty<'tcx>) -> DropckKind<'tcx> { match ty.sty { - ty::TyAdt(def, _) => { - def.is_dtorck(tcx) + ty::TyAdt(adt_def, substs) => { + if !adt_def.is_dtorck(tcx) { + return DropckKind::NoBorrowedDataAccessedInMyDtor; + } + + // Find the `impl<..> Drop for _` to inspect any + // attributes attached to the impl's generics. + let opt_dtor_method = adt_def.destructor(); + let dtor_method = if let Some(dtor_method) = opt_dtor_method { + dtor_method + } else { + return DropckKind::BorrowedDataMustStrictlyOutliveSelf; + }; + let method = tcx.impl_or_trait_item(dtor_method); + let substs = Substs::for_item(tcx, + method.container().id(), + |def, _| if def.pure_wrt_drop { + tcx.mk_region(ty::ReStatic) + } else { + substs.region_for_def(def) + }, + |def, _| if def.pure_wrt_drop { + tcx.mk_nil() + } else { + substs.type_for_def(def) + }); + let revised_ty = tcx.mk_adt(adt_def, &substs); + return DropckKind::RevisedSelf(revised_ty); } ty::TyTrait(..) | ty::TyProjection(..) | ty::TyAnon(..) => { debug!("ty: {:?} isn't known, and therefore is a dropck type", ty); - true + return DropckKind::BorrowedDataMustStrictlyOutliveSelf; }, - _ => false + _ => { + return DropckKind::NoBorrowedDataAccessedInMyDtor; + } } } From 9a649c328c50485de72f057a8003dcbbf3b4dc53 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Wed, 12 Oct 2016 14:23:38 +0200 Subject: [PATCH 05/60] Require destructors using `#[may_dangle]` to use `unsafe impl`. --- src/librustc/hir/mod.rs | 30 ++++++++++++ src/librustc_typeck/coherence/unsafety.rs | 34 +++++++++----- src/librustc_typeck/diagnostics.rs | 17 +++++++ .../dropck-eyepatch-implies-unsafe-impl.rs | 46 +++++++++++++++++++ 4 files changed, 116 insertions(+), 11 deletions(-) create mode 100644 src/test/compile-fail/dropck-eyepatch-implies-unsafe-impl.rs diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 3ecb731b5ed74..6e81c3e700ed2 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -330,6 +330,36 @@ impl Generics { } } +pub enum UnsafeGeneric { + Region(LifetimeDef, &'static str), + Type(TyParam, &'static str), +} + +impl UnsafeGeneric { + pub fn attr_name(&self) -> &'static str { + match *self { + UnsafeGeneric::Region(_, s) => s, + UnsafeGeneric::Type(_, s) => s, + } + } +} + +impl Generics { + pub fn carries_unsafe_attr(&self) -> Option { + for r in &self.lifetimes { + if r.pure_wrt_drop { + return Some(UnsafeGeneric::Region(r.clone(), "may_dangle")); + } + } + for t in &self.ty_params { + if t.pure_wrt_drop { + return Some(UnsafeGeneric::Type(t.clone(), "may_dangle")); + } + } + return None; + } +} + /// A `where` clause in a definition #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct WhereClause { diff --git a/src/librustc_typeck/coherence/unsafety.rs b/src/librustc_typeck/coherence/unsafety.rs index ff55ce0e5eb55..cca6c88430672 100644 --- a/src/librustc_typeck/coherence/unsafety.rs +++ b/src/librustc_typeck/coherence/unsafety.rs @@ -13,7 +13,7 @@ use rustc::ty::TyCtxt; use rustc::hir::intravisit; -use rustc::hir; +use rustc::hir::{self, Unsafety}; pub fn check<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { let mut orphan = UnsafetyChecker { tcx: tcx }; @@ -27,6 +27,7 @@ struct UnsafetyChecker<'cx, 'tcx: 'cx> { impl<'cx, 'tcx, 'v> UnsafetyChecker<'cx, 'tcx> { fn check_unsafety_coherence(&mut self, item: &'v hir::Item, + impl_generics: Option<&hir::Generics>, unsafety: hir::Unsafety, polarity: hir::ImplPolarity) { match self.tcx.impl_trait_ref(self.tcx.map.local_def_id(item.id)) { @@ -47,15 +48,16 @@ impl<'cx, 'tcx, 'v> UnsafetyChecker<'cx, 'tcx> { Some(trait_ref) => { let trait_def = self.tcx.lookup_trait_def(trait_ref.def_id); - match (trait_def.unsafety, unsafety, polarity) { - (hir::Unsafety::Unsafe, hir::Unsafety::Unsafe, hir::ImplPolarity::Negative) => { + let unsafe_attr = impl_generics.and_then(|g| g.carries_unsafe_attr()); + match (trait_def.unsafety, unsafe_attr, unsafety, polarity) { + (_, _, Unsafety::Unsafe, hir::ImplPolarity::Negative) => { span_err!(self.tcx.sess, item.span, E0198, "negative implementations are not unsafe"); } - (hir::Unsafety::Normal, hir::Unsafety::Unsafe, _) => { + (Unsafety::Normal, None, Unsafety::Unsafe, _) => { span_err!(self.tcx.sess, item.span, E0199, @@ -63,7 +65,7 @@ impl<'cx, 'tcx, 'v> UnsafetyChecker<'cx, 'tcx> { trait_ref); } - (hir::Unsafety::Unsafe, hir::Unsafety::Normal, hir::ImplPolarity::Positive) => { + (Unsafety::Unsafe, _, Unsafety::Normal, hir::ImplPolarity::Positive) => { span_err!(self.tcx.sess, item.span, E0200, @@ -71,9 +73,19 @@ impl<'cx, 'tcx, 'v> UnsafetyChecker<'cx, 'tcx> { trait_ref); } - (hir::Unsafety::Unsafe, hir::Unsafety::Normal, hir::ImplPolarity::Negative) | - (hir::Unsafety::Unsafe, hir::Unsafety::Unsafe, hir::ImplPolarity::Positive) | - (hir::Unsafety::Normal, hir::Unsafety::Normal, _) => { + (Unsafety::Normal, Some(g), Unsafety::Normal, hir::ImplPolarity::Positive) => + { + span_err!(self.tcx.sess, + item.span, + E0569, + "requires an `unsafe impl` declaration due to `#[{}]` attribute", + g.attr_name()); + } + + (_, _, Unsafety::Normal, hir::ImplPolarity::Negative) | + (Unsafety::Unsafe, _, Unsafety::Unsafe, hir::ImplPolarity::Positive) | + (Unsafety::Normal, Some(_), Unsafety::Unsafe, hir::ImplPolarity::Positive) | + (Unsafety::Normal, None, Unsafety::Normal, _) => { // OK } } @@ -86,10 +98,10 @@ impl<'cx, 'tcx, 'v> intravisit::Visitor<'v> for UnsafetyChecker<'cx, 'tcx> { fn visit_item(&mut self, item: &'v hir::Item) { match item.node { hir::ItemDefaultImpl(unsafety, _) => { - self.check_unsafety_coherence(item, unsafety, hir::ImplPolarity::Positive); + self.check_unsafety_coherence(item, None, unsafety, hir::ImplPolarity::Positive); } - hir::ItemImpl(unsafety, polarity, ..) => { - self.check_unsafety_coherence(item, unsafety, polarity); + hir::ItemImpl(unsafety, polarity, ref generics, ..) => { + self.check_unsafety_coherence(item, Some(generics), unsafety, polarity); } _ => {} } diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 0d6b43b59c6ad..bdd33cb56e0bc 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -2819,6 +2819,23 @@ not a distinct static type. Likewise, it's not legal to attempt to behavior for specific enum variants. "##, +E0569: r##" +If an impl has a generic parameter with the `#[may_dangle]` attribute, then +that impl must be declared as an `unsafe impl. For example: + +```compile_fail,E0569 +struct Foo(X); +impl<#[may_dangle] X> Drop for Foo { + fn drop(&mut self) { } +} +``` + +In this example, we are asserting that the destructor for `Foo` will not +access any data of type `X`, and require this assertion to be true for +overall safety in our program. The compiler does not currently attempt to +verify this assertion; therefore we must tag this `impl` as unsafe. +"##, + E0318: r##" Default impls for a trait must be located in the same crate where the trait was defined. For more information see the [opt-in builtin traits RFC](https://github diff --git a/src/test/compile-fail/dropck-eyepatch-implies-unsafe-impl.rs b/src/test/compile-fail/dropck-eyepatch-implies-unsafe-impl.rs new file mode 100644 index 0000000000000..f92c8703dc927 --- /dev/null +++ b/src/test/compile-fail/dropck-eyepatch-implies-unsafe-impl.rs @@ -0,0 +1,46 @@ +// 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. + +#![feature(generic_param_attrs)] +#![feature(dropck_eyepatch)] + +// This test ensures that a use of `#[may_dangle]` is rejected if +// it is not attached to an `unsafe impl`. + +use std::fmt; + +struct Dt(&'static str, A); +struct Dr<'a, B:'a+fmt::Debug>(&'static str, &'a B); +struct Pt(&'static str, A, B); +struct Pr<'a, 'b, B:'a+'b+fmt::Debug>(&'static str, &'a B, &'b B); +struct St(&'static str, A); +struct Sr<'a, B:'a+fmt::Debug>(&'static str, &'a B); + +impl Drop for Dt { + fn drop(&mut self) { println!("drop {} {:?}", self.0, self.1); } +} +impl<'a, B: fmt::Debug> Drop for Dr<'a, B> { + fn drop(&mut self) { println!("drop {} {:?}", self.0, self.1); } +} +impl<#[may_dangle] A, B: fmt::Debug> Drop for Pt { + //~^ ERROR requires an `unsafe impl` declaration due to `#[may_dangle]` attribute + + // (unsafe to access self.1 due to #[may_dangle] on A) + fn drop(&mut self) { println!("drop {} {:?}", self.0, self.2); } +} +impl<#[may_dangle] 'a, 'b, B: fmt::Debug> Drop for Pr<'a, 'b, B> { + //~^ ERROR requires an `unsafe impl` declaration due to `#[may_dangle]` attribute + + // (unsafe to access self.1 due to #[may_dangle] on 'a) + fn drop(&mut self) { println!("drop {} {:?}", self.0, self.2); } +} + +fn main() { +} From e185cd519058611eac883cde44442f0d48a22de0 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Wed, 12 Oct 2016 16:53:57 +0200 Subject: [PATCH 06/60] Fix bug in test for E0199 and add test for E0198. In particular, as far as I can tell from the error diagnostics, the former test for E0199 was actually a test for E0198, and there was no test for E0198. (I am assuming that one of my previous changes to the `unsafe impl` checking fixed a latent bug in how these two cases were differentiated.) --- src/test/compile-fail/E0198.rs | 18 ++++++++++++++++++ src/test/compile-fail/E0199.rs | 3 ++- 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 src/test/compile-fail/E0198.rs diff --git a/src/test/compile-fail/E0198.rs b/src/test/compile-fail/E0198.rs new file mode 100644 index 0000000000000..892989cc6a080 --- /dev/null +++ b/src/test/compile-fail/E0198.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. + +#![feature(optin_builtin_traits)] + +struct Foo; + +unsafe impl !Clone for Foo { } //~ ERROR negative implementations are not unsafe [E0198] + +fn main() { +} diff --git a/src/test/compile-fail/E0199.rs b/src/test/compile-fail/E0199.rs index 8bd3ffdf6f6ee..1a5cd1941a9d1 100644 --- a/src/test/compile-fail/E0199.rs +++ b/src/test/compile-fail/E0199.rs @@ -12,7 +12,8 @@ struct Foo; -unsafe impl !Clone for Foo { } //~ ERROR E0199 +trait Bar { } +unsafe impl Bar for Foo { } //~ ERROR implementing the trait `Bar` is not unsafe [E0199] fn main() { } From fa7f69cdaaa30a88e928478d7ba05f403f522f54 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 11 Oct 2016 16:03:40 +0200 Subject: [PATCH 07/60] tests for `#[may_dangle]` attribute. --- .../auxiliary/dropck_eyepatch_extern_crate.rs | 46 +++++++ .../dropck-eyepatch-extern-crate.rs | 45 +++++++ src/test/compile-fail/dropck-eyepatch.rs | 96 +++++++++++++++ .../compile-fail/feature-gate-may-dangle.rs | 20 ++++ .../auxiliary/dropck_eyepatch_extern_crate.rs | 61 ++++++++++ .../run-pass/dropck-eyepatch-extern-crate.rs | 48 ++++++++ src/test/run-pass/dropck-eyepatch.rs | 112 ++++++++++++++++++ 7 files changed, 428 insertions(+) create mode 100644 src/test/compile-fail/auxiliary/dropck_eyepatch_extern_crate.rs create mode 100644 src/test/compile-fail/dropck-eyepatch-extern-crate.rs create mode 100644 src/test/compile-fail/dropck-eyepatch.rs create mode 100644 src/test/compile-fail/feature-gate-may-dangle.rs create mode 100644 src/test/run-pass/auxiliary/dropck_eyepatch_extern_crate.rs create mode 100644 src/test/run-pass/dropck-eyepatch-extern-crate.rs create mode 100644 src/test/run-pass/dropck-eyepatch.rs diff --git a/src/test/compile-fail/auxiliary/dropck_eyepatch_extern_crate.rs b/src/test/compile-fail/auxiliary/dropck_eyepatch_extern_crate.rs new file mode 100644 index 0000000000000..15983ada5ea85 --- /dev/null +++ b/src/test/compile-fail/auxiliary/dropck_eyepatch_extern_crate.rs @@ -0,0 +1,46 @@ +// 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. + +#![feature(generic_param_attrs)] +#![feature(dropck_eyepatch)] + +// The point of this test is to illustrate that the `#[may_dangle]` +// attribute specifically allows, in the context of a type +// implementing `Drop`, a generic parameter to be instantiated with a +// lifetime that does not strictly outlive the owning type itself, +// and that this attributes effects are preserved when importing +// the type from another crate. +// +// See also dropck-eyepatch.rs for more information about the general +// structure of the test. + +use std::fmt; + +pub struct Dt(pub &'static str, pub A); +pub struct Dr<'a, B:'a+fmt::Debug>(pub &'static str, pub &'a B); +pub struct Pt(pub &'static str, pub A, pub B); +pub struct Pr<'a, 'b, B:'a+'b+fmt::Debug>(pub &'static str, pub &'a B, pub &'b B); +pub struct St(pub &'static str, pub A); +pub struct Sr<'a, B:'a+fmt::Debug>(pub &'static str, pub &'a B); + +impl Drop for Dt { + fn drop(&mut self) { println!("drop {} {:?}", self.0, self.1); } +} +impl<'a, B: fmt::Debug> Drop for Dr<'a, B> { + fn drop(&mut self) { println!("drop {} {:?}", self.0, self.1); } +} +unsafe impl<#[may_dangle] A, B: fmt::Debug> Drop for Pt { + // (unsafe to access self.1 due to #[may_dangle] on A) + fn drop(&mut self) { println!("drop {} {:?}", self.0, self.2); } +} +unsafe impl<#[may_dangle] 'a, 'b, B: fmt::Debug> Drop for Pr<'a, 'b, B> { + // (unsafe to access self.1 due to #[may_dangle] on 'a) + fn drop(&mut self) { println!("drop {} {:?}", self.0, self.2); } +} diff --git a/src/test/compile-fail/dropck-eyepatch-extern-crate.rs b/src/test/compile-fail/dropck-eyepatch-extern-crate.rs new file mode 100644 index 0000000000000..189340992e920 --- /dev/null +++ b/src/test/compile-fail/dropck-eyepatch-extern-crate.rs @@ -0,0 +1,45 @@ +// 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. + +// aux-build:dropck_eyepatch_extern_crate.rs + +extern crate dropck_eyepatch_extern_crate as other; + +use other::{Dt,Dr,Pt,Pr,St,Sr}; + +fn main() { + use std::cell::Cell; + let c_long; + let (c, mut dt, mut dr, mut pt, mut pr, st, sr) + : (Cell<_>, Dt<_>, Dr<_>, Pt<_, _>, Pr<_>, St<_>, Sr<_>); + c_long = Cell::new(1); + c = Cell::new(1); + + // No error: sufficiently long-lived state can be referenced in dtors + dt = Dt("dt", &c_long); + dr = Dr("dr", &c_long); + // Error: destructor order imprecisely modelled + dt = Dt("dt", &c); //~ ERROR `c` does not live long enough + dr = Dr("dr", &c); //~ ERROR `c` does not live long enough + + // No error: Drop impl asserts .1 (A and &'a _) are not accessed + pt = Pt("pt", &c, &c_long); + pr = Pr("pr", &c, &c_long); + + // Error: Drop impl's assertion does not apply to `B` nor `&'b _` + pt = Pt("pt", &c_long, &c); //~ ERROR `c` does not live long enough + pr = Pr("pr", &c_long, &c); //~ ERROR `c` does not live long enough + + // No error: St and Sr have no destructor. + st = St("st", &c); + sr = Sr("sr", &c); + + println!("{:?}", (dt.0, dr.0, pt.0, pr.0, st.0, sr.0)); +} diff --git a/src/test/compile-fail/dropck-eyepatch.rs b/src/test/compile-fail/dropck-eyepatch.rs new file mode 100644 index 0000000000000..e442fade19730 --- /dev/null +++ b/src/test/compile-fail/dropck-eyepatch.rs @@ -0,0 +1,96 @@ +// 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. + +#![feature(generic_param_attrs)] +#![feature(dropck_eyepatch)] + +// The point of this test is to illustrate that the `#[may_dangle]` +// attribute specifically allows, in the context of a type +// implementing `Drop`, a generic parameter to be instantiated with a +// lifetime that does not strictly outlive the owning type itself. +// +// Here we test that only the expected errors are issued. +// +// The illustration is made concrete by comparison with two variations +// on the type with `#[may_dangle]`: +// +// 1. an analogous type that does not implement `Drop` (and thus +// should exhibit maximal flexibility with respect to dropck), and +// +// 2. an analogous type that does not use `#[may_dangle]` (and thus +// should exhibit the standard limitations imposed by dropck. +// +// The types in this file follow a pattern, {D,P,S}{t,r}, where: +// +// - D means "I implement Drop" +// +// - P means "I implement Drop but guarantee my (first) parameter is +// pure, i.e. not accessed from the destructor"; no other parameters +// are pure. +// +// - S means "I do not implement Drop" +// +// - t suffix is used when the first generic is a type +// +// - r suffix is used when the first generic is a lifetime. + +use std::fmt; + +struct Dt(&'static str, A); +struct Dr<'a, B:'a+fmt::Debug>(&'static str, &'a B); +struct Pt(&'static str, A, B); +struct Pr<'a, 'b, B:'a+'b+fmt::Debug>(&'static str, &'a B, &'b B); +struct St(&'static str, A); +struct Sr<'a, B:'a+fmt::Debug>(&'static str, &'a B); + +impl Drop for Dt { + fn drop(&mut self) { println!("drop {} {:?}", self.0, self.1); } +} +impl<'a, B: fmt::Debug> Drop for Dr<'a, B> { + fn drop(&mut self) { println!("drop {} {:?}", self.0, self.1); } +} +unsafe impl<#[may_dangle] A, B: fmt::Debug> Drop for Pt { + // (unsafe to access self.1 due to #[may_dangle] on A) + fn drop(&mut self) { println!("drop {} {:?}", self.0, self.2); } +} +unsafe impl<#[may_dangle] 'a, 'b, B: fmt::Debug> Drop for Pr<'a, 'b, B> { + // (unsafe to access self.1 due to #[may_dangle] on 'a) + fn drop(&mut self) { println!("drop {} {:?}", self.0, self.2); } +} + +fn main() { + use std::cell::Cell; + let c_long; + let (c, mut dt, mut dr, mut pt, mut pr, st, sr) + : (Cell<_>, Dt<_>, Dr<_>, Pt<_, _>, Pr<_>, St<_>, Sr<_>); + c_long = Cell::new(1); + c = Cell::new(1); + + // No error: sufficiently long-lived state can be referenced in dtors + dt = Dt("dt", &c_long); + dr = Dr("dr", &c_long); + // Error: destructor order imprecisely modelled + dt = Dt("dt", &c); //~ ERROR `c` does not live long enough + dr = Dr("dr", &c); //~ ERROR `c` does not live long enough + + // No error: Drop impl asserts .1 (A and &'a _) are not accessed + pt = Pt("pt", &c, &c_long); + pr = Pr("pr", &c, &c_long); + + // Error: Drop impl's assertion does not apply to `B` nor `&'b _` + pt = Pt("pt", &c_long, &c); //~ ERROR `c` does not live long enough + pr = Pr("pr", &c_long, &c); //~ ERROR `c` does not live long enough + + // No error: St and Sr have no destructor. + st = St("st", &c); + sr = Sr("sr", &c); + + println!("{:?}", (dt.0, dr.0, pt.0, pr.0, st.0, sr.0)); +} diff --git a/src/test/compile-fail/feature-gate-may-dangle.rs b/src/test/compile-fail/feature-gate-may-dangle.rs new file mode 100644 index 0000000000000..23f8ead0ca9dc --- /dev/null +++ b/src/test/compile-fail/feature-gate-may-dangle.rs @@ -0,0 +1,20 @@ +// 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. + +// Check that `may_dangle` is rejected if `dropck_eyepatch` feature gate is absent. + +#![feature(generic_param_attrs)] + +struct Pt(A); +impl<#[may_dangle] A> Drop for Pt { + //~^ ERROR may_dangle has unstable semantics and may be removed in the future + //~| HELP add #![feature(dropck_eyepatch)] to the crate attributes to enable + fn drop(&mut self) { } +} diff --git a/src/test/run-pass/auxiliary/dropck_eyepatch_extern_crate.rs b/src/test/run-pass/auxiliary/dropck_eyepatch_extern_crate.rs new file mode 100644 index 0000000000000..1266e589b127e --- /dev/null +++ b/src/test/run-pass/auxiliary/dropck_eyepatch_extern_crate.rs @@ -0,0 +1,61 @@ +// 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. + +#![feature(generic_param_attrs)] +#![feature(dropck_eyepatch)] + +// The point of this test is to illustrate that the `#[may_dangle]` +// attribute specifically allows, in the context of a type +// implementing `Drop`, a generic parameter to be instantiated with a +// lifetime that does not strictly outlive the owning type itself, +// and that this attributes effects are preserved when importing +// the type from another crate. +// +// See also dropck-eyepatch.rs for more information about the general +// structure of the test. + +use std::cell::RefCell; + +pub trait Foo { fn foo(&self, _: &str); } + +pub struct Dt(pub &'static str, pub A); +pub struct Dr<'a, B:'a+Foo>(pub &'static str, pub &'a B); +pub struct Pt(pub &'static str, pub A, pub B); +pub struct Pr<'a, 'b, B:'a+'b+Foo>(pub &'static str, pub &'a B, pub &'b B); +pub struct St(pub &'static str, pub A); +pub struct Sr<'a, B:'a+Foo>(pub &'static str, pub &'a B); + +impl Drop for Dt { + fn drop(&mut self) { println!("drop {}", self.0); self.1.foo(self.0); } +} +impl<'a, B: Foo> Drop for Dr<'a, B> { + fn drop(&mut self) { println!("drop {}", self.0); self.1.foo(self.0); } +} +unsafe impl<#[may_dangle] A, B: Foo> Drop for Pt { + // (unsafe to access self.1 due to #[may_dangle] on A) + fn drop(&mut self) { println!("drop {}", self.0); self.2.foo(self.0); } +} +unsafe impl<#[may_dangle] 'a, 'b, B: Foo> Drop for Pr<'a, 'b, B> { + // (unsafe to access self.1 due to #[may_dangle] on 'a) + fn drop(&mut self) { println!("drop {}", self.0); self.2.foo(self.0); } +} + +impl Foo for RefCell { + fn foo(&self, s: &str) { + let s2 = format!("{}|{}", *self.borrow(), s); + *self.borrow_mut() = s2; + } +} + +impl<'a, T:Foo> Foo for &'a T { + fn foo(&self, s: &str) { + (*self).foo(s); + } +} diff --git a/src/test/run-pass/dropck-eyepatch-extern-crate.rs b/src/test/run-pass/dropck-eyepatch-extern-crate.rs new file mode 100644 index 0000000000000..20f069f77ea15 --- /dev/null +++ b/src/test/run-pass/dropck-eyepatch-extern-crate.rs @@ -0,0 +1,48 @@ +// 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. + +// aux-build:dropck_eyepatch_extern_crate.rs + +extern crate dropck_eyepatch_extern_crate as other; + +use other::{Dt,Dr,Pt,Pr,St,Sr}; + +fn main() { + use std::cell::RefCell; + + struct CheckOnDrop(RefCell, &'static str); + impl Drop for CheckOnDrop { + fn drop(&mut self) { assert_eq!(*self.0.borrow(), self.1); } + } + + let c_long; + let (c, dt, dr, pt, pr, st, sr) + : (CheckOnDrop, Dt<_>, Dr<_>, Pt<_, _>, Pr<_>, St<_>, Sr<_>); + c_long = CheckOnDrop(RefCell::new("c_long".to_string()), + "c_long|pr|pt|dr|dt"); + c = CheckOnDrop(RefCell::new("c".to_string()), + "c"); + + // No error: sufficiently long-lived state can be referenced in dtors + dt = Dt("dt", &c_long.0); + dr = Dr("dr", &c_long.0); + + // No error: Drop impl asserts .1 (A and &'a _) are not accessed + pt = Pt("pt", &c.0, &c_long.0); + pr = Pr("pr", &c.0, &c_long.0); + + // No error: St and Sr have no destructor. + st = St("st", &c.0); + sr = Sr("sr", &c.0); + + println!("{:?}", (dt.0, dr.0, pt.0, pr.0, st.0, sr.0)); + assert_eq!(*c_long.0.borrow(), "c_long"); + assert_eq!(*c.0.borrow(), "c"); +} diff --git a/src/test/run-pass/dropck-eyepatch.rs b/src/test/run-pass/dropck-eyepatch.rs new file mode 100644 index 0000000000000..4a09ba05dff5e --- /dev/null +++ b/src/test/run-pass/dropck-eyepatch.rs @@ -0,0 +1,112 @@ +// 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. + +#![feature(generic_param_attrs)] +#![feature(dropck_eyepatch)] + +// The point of this test is to illustrate that the `#[may_dangle]` +// attribute specifically allows, in the context of a type +// implementing `Drop`, a generic parameter to be instantiated with a +// lifetime that does not strictly outlive the owning type itself. +// +// Here we test that a model use of `#[may_dangle]` will compile and run. +// +// The illustration is made concrete by comparison with two variations +// on the type with `#[may_dangle]`: +// +// 1. an analogous type that does not implement `Drop` (and thus +// should exhibit maximal flexibility with respect to dropck), and +// +// 2. an analogous type that does not use `#[may_dangle]` (and thus +// should exhibit the standard limitations imposed by dropck. +// +// The types in this file follow a pattern, {D,P,S}{t,r}, where: +// +// - D means "I implement Drop" +// +// - P means "I implement Drop but guarantee my (first) parameter is +// pure, i.e. not accessed from the destructor"; no other parameters +// are pure. +// +// - S means "I do not implement Drop" +// +// - t suffix is used when the first generic is a type +// +// - r suffix is used when the first generic is a lifetime. + +trait Foo { fn foo(&self, _: &str); } + +struct Dt(&'static str, A); +struct Dr<'a, B:'a+Foo>(&'static str, &'a B); +struct Pt(&'static str, A, B); +struct Pr<'a, 'b, B:'a+'b+Foo>(&'static str, &'a B, &'b B); +struct St(&'static str, A); +struct Sr<'a, B:'a+Foo>(&'static str, &'a B); + +impl Drop for Dt { + fn drop(&mut self) { println!("drop {}", self.0); self.1.foo(self.0); } +} +impl<'a, B: Foo> Drop for Dr<'a, B> { + fn drop(&mut self) { println!("drop {}", self.0); self.1.foo(self.0); } +} +unsafe impl<#[may_dangle] A, B: Foo> Drop for Pt { + // (unsafe to access self.1 due to #[may_dangle] on A) + fn drop(&mut self) { println!("drop {}", self.0); self.2.foo(self.0); } +} +unsafe impl<#[may_dangle] 'a, 'b, B: Foo> Drop for Pr<'a, 'b, B> { + // (unsafe to access self.1 due to #[may_dangle] on 'a) + fn drop(&mut self) { println!("drop {}", self.0); self.2.foo(self.0); } +} + +fn main() { + use std::cell::RefCell; + + impl Foo for RefCell { + fn foo(&self, s: &str) { + let s2 = format!("{}|{}", *self.borrow(), s); + *self.borrow_mut() = s2; + } + } + + impl<'a, T:Foo> Foo for &'a T { + fn foo(&self, s: &str) { + (*self).foo(s); + } + } + + struct CheckOnDrop(RefCell, &'static str); + impl Drop for CheckOnDrop { + fn drop(&mut self) { assert_eq!(*self.0.borrow(), self.1); } + } + + let c_long; + let (c, dt, dr, pt, pr, st, sr) + : (CheckOnDrop, Dt<_>, Dr<_>, Pt<_, _>, Pr<_>, St<_>, Sr<_>); + c_long = CheckOnDrop(RefCell::new("c_long".to_string()), + "c_long|pr|pt|dr|dt"); + c = CheckOnDrop(RefCell::new("c".to_string()), + "c"); + + // No error: sufficiently long-lived state can be referenced in dtors + dt = Dt("dt", &c_long.0); + dr = Dr("dr", &c_long.0); + + // No error: Drop impl asserts .1 (A and &'a _) are not accessed + pt = Pt("pt", &c.0, &c_long.0); + pr = Pr("pr", &c.0, &c_long.0); + + // No error: St and Sr have no destructor. + st = St("st", &c.0); + sr = Sr("sr", &c.0); + + println!("{:?}", (dt.0, dr.0, pt.0, pr.0, st.0, sr.0)); + assert_eq!(*c_long.0.borrow(), "c_long"); + assert_eq!(*c.0.borrow(), "c"); +} From b486a8757c6a4885f4e4ba305adbda33a50c5177 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 12 Oct 2016 13:36:23 -0400 Subject: [PATCH 08/60] add test case for changing private methods --- .../struct_point.rs | 114 ++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 src/test/incremental/change_private_impl_method/struct_point.rs diff --git a/src/test/incremental/change_private_impl_method/struct_point.rs b/src/test/incremental/change_private_impl_method/struct_point.rs new file mode 100644 index 0000000000000..43be51143d693 --- /dev/null +++ b/src/test/incremental/change_private_impl_method/struct_point.rs @@ -0,0 +1,114 @@ +// 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. + +// Test where we change the body of a private method in an impl. +// We then test what sort of functions must be rebuilt as a result. + +// revisions:rpass1 rpass2 +// compile-flags: -Z query-dep-graph + +#![feature(rustc_attrs)] +#![feature(stmt_expr_attributes)] +#![allow(dead_code)] + +#![rustc_partition_translated(module="struct_point-point", cfg="rpass2")] + +// FIXME(#37121) -- the following two modules *should* be reused but are not +#![rustc_partition_translated(module="struct_point-fn_calls_methods_in_same_impl", cfg="rpass2")] +#![rustc_partition_translated(module="struct_point-fn_calls_methods_in_another_impl", cfg="rpass2")] +#![rustc_partition_reused(module="struct_point-fn_make_struct", cfg="rpass2")] +#![rustc_partition_reused(module="struct_point-fn_read_field", cfg="rpass2")] +#![rustc_partition_reused(module="struct_point-fn_write_field", cfg="rpass2")] + +mod point { + pub struct Point { + pub x: f32, + pub y: f32, + } + + impl Point { + fn distance_squared(&self) -> f32 { + #[cfg(rpass1)] + return self.x + self.y; + + #[cfg(rpass2)] + return self.x * self.x + self.y * self.y; + } + + pub fn distance_from_origin(&self) -> f32 { + self.distance_squared().sqrt() + } + } + + impl Point { + pub fn translate(&mut self, x: f32, y: f32) { + self.x += x; + self.y += y; + } + } + +} + +/// A fn item that calls (public) methods on `Point` from the same impl which changed +mod fn_calls_methods_in_same_impl { + use point::Point; + + // FIXME(#37121) -- we should not need to typeck this again + #[rustc_dirty(label="TypeckItemBody", cfg="rpass2")] + pub fn check() { + let x = Point { x: 2.0, y: 2.0 }; + x.distance_from_origin(); + } +} + +/// A fn item that calls (public) methods on `Point` from another impl +mod fn_calls_methods_in_another_impl { + use point::Point; + + // FIXME(#37121) -- we should not need to typeck this again + #[rustc_dirty(label="TypeckItemBody", cfg="rpass2")] + pub fn check() { + let mut x = Point { x: 2.0, y: 2.0 }; + x.translate(3.0, 3.0); + } +} + +/// A fn item that makes an instance of `Point` but does not invoke methods +mod fn_make_struct { + use point::Point; + + #[rustc_clean(label="TypeckItemBody", cfg="rpass2")] + pub fn make_origin() -> Point { + Point { x: 2.0, y: 2.0 } + } +} + +/// A fn item that reads fields from `Point` but does not invoke methods +mod fn_read_field { + use point::Point; + + #[rustc_clean(label="TypeckItemBody", cfg="rpass2")] + pub fn get_x(p: Point) -> f32 { + p.x + } +} + +/// A fn item that reads fields from `Point` but does not invoke methods +mod fn_write_field { + use point::Point; + + #[rustc_clean(label="TypeckItemBody", cfg="rpass2")] + pub fn inc_x(p: &mut Point) { + p.x += 1.0; + } +} + +fn main() { +} From 8dd9493cf291b31ebe2e6c3aa18f259156fd9d89 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Wed, 12 Oct 2016 23:39:08 +0200 Subject: [PATCH 09/60] placate diagnostic checking tests by fixing sample code in E0569. --- src/librustc_typeck/diagnostics.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index bdd33cb56e0bc..781991e7bb6ae 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -2824,6 +2824,9 @@ If an impl has a generic parameter with the `#[may_dangle]` attribute, then that impl must be declared as an `unsafe impl. For example: ```compile_fail,E0569 +#![feature(generic_param_attrs)] +#![feature(dropck_eyepatch)] + struct Foo(X); impl<#[may_dangle] X> Drop for Foo { fn drop(&mut self) { } From c239fee2b60c756f88e5dd7abdb945de5b699bea Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Thu, 13 Oct 2016 13:44:57 +0200 Subject: [PATCH 10/60] fix typo in diagnostic sample code --- src/librustc_typeck/diagnostics.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 781991e7bb6ae..16f915c0011cb 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -2828,7 +2828,7 @@ that impl must be declared as an `unsafe impl. For example: #![feature(dropck_eyepatch)] struct Foo(X); -impl<#[may_dangle] X> Drop for Foo { +impl<#[may_dangle] X> Drop for Foo { fn drop(&mut self) { } } ``` From 029dceedb9719ae5dbdbf2c033c920017e3d786e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 14 Oct 2016 09:44:42 +1100 Subject: [PATCH 11/60] Avoid many CrateConfig clones. This commit changes `ExtCtx::cfg()` so it returns a `CrateConfig` reference instead of a clone. As a result, it also changes all of the `cfg()` callsites to explicitly clone... except one, because the commit also changes `macro_parser::parse()` to take `&CrateConfig`. This is good, because that function can be hot, and `CrateConfig` is expensive to clone. This change almost halves the number of heap allocations done by rustc for `html5ever` in rustc-benchmarks suite, which makes compilation 1.20x faster. --- src/libsyntax/ext/base.rs | 4 ++-- src/libsyntax/ext/quote.rs | 14 +++++++++----- src/libsyntax/ext/source_util.rs | 2 +- src/libsyntax/ext/tt/macro_parser.rs | 2 +- src/libsyntax/ext/tt/macro_rules.rs | 4 ++-- src/libsyntax_ext/asm.rs | 2 +- .../auxiliary/macro_crate_test.rs | 2 +- .../auxiliary/macro_crate_test.rs | 2 +- 8 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index f7c88073c9d40..ff1986cb4a81d 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -617,11 +617,11 @@ impl<'a> ExtCtxt<'a> { pub fn new_parser_from_tts(&self, tts: &[tokenstream::TokenTree]) -> parser::Parser<'a> { - parse::tts_to_parser(self.parse_sess, tts.to_vec(), self.cfg()) + parse::tts_to_parser(self.parse_sess, tts.to_vec(), self.cfg().clone()) } pub fn codemap(&self) -> &'a CodeMap { self.parse_sess.codemap() } pub fn parse_sess(&self) -> &'a parse::ParseSess { self.parse_sess } - pub fn cfg(&self) -> ast::CrateConfig { self.cfg.clone() } + pub fn cfg(&self) -> &ast::CrateConfig { &self.cfg } pub fn call_site(&self) -> Span { self.codemap().with_expn_info(self.backtrace(), |ei| match ei { Some(expn_info) => expn_info.call_site, diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs index b70e270df54d2..7f002d2816679 100644 --- a/src/libsyntax/ext/quote.rs +++ b/src/libsyntax/ext/quote.rs @@ -331,7 +331,7 @@ pub mod rt { panictry!(parse::parse_item_from_source_str( "".to_string(), s, - self.cfg(), + self.cfg().clone(), self.parse_sess())).expect("parse error") } @@ -339,7 +339,7 @@ pub mod rt { panictry!(parse::parse_stmt_from_source_str( "".to_string(), s, - self.cfg(), + self.cfg().clone(), self.parse_sess())).expect("parse error") } @@ -347,7 +347,7 @@ pub mod rt { panictry!(parse::parse_expr_from_source_str( "".to_string(), s, - self.cfg(), + self.cfg().clone(), self.parse_sess())) } @@ -355,7 +355,7 @@ pub mod rt { panictry!(parse::parse_tts_from_source_str( "".to_string(), s, - self.cfg(), + self.cfg().clone(), self.parse_sess())) } } @@ -924,6 +924,10 @@ fn expand_parse_call(cx: &ExtCtxt, sp, cx.expr_ident(sp, id_ext("ext_cx")), id_ext("cfg"), Vec::new()); + let cfg_clone_call = || cx.expr_method_call( + sp, cfg_call(), + id_ext("clone"), Vec::new()); + let parse_sess_call = || cx.expr_method_call( sp, cx.expr_ident(sp, id_ext("ext_cx")), id_ext("parse_sess"), Vec::new()); @@ -931,7 +935,7 @@ fn expand_parse_call(cx: &ExtCtxt, let new_parser_call = cx.expr_call(sp, cx.expr_ident(sp, id_ext("new_parser_from_tts")), - vec!(parse_sess_call(), cfg_call(), tts_expr)); + vec!(parse_sess_call(), cfg_clone_call(), tts_expr)); let path = vec![id_ext("syntax"), id_ext("ext"), id_ext("quote"), id_ext(parse_method)]; let mut args = vec![cx.expr_mut_addr_of(sp, new_parser_call)]; diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs index e75e41d0c2d4b..30dc1823b370a 100644 --- a/src/libsyntax/ext/source_util.rs +++ b/src/libsyntax/ext/source_util.rs @@ -94,7 +94,7 @@ pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[tokenstream::T // The file will be added to the code map by the parser let p = parse::new_sub_parser_from_file(cx.parse_sess(), - cx.cfg(), + cx.cfg().clone(), &res_rel_file(cx, sp, Path::new(&file)), diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index b0696a986e3c0..030cb303832af 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -272,7 +272,7 @@ pub fn token_name_eq(t1 : &Token, t2 : &Token) -> bool { } pub fn parse(sess: &ParseSess, - cfg: ast::CrateConfig, + cfg: &ast::CrateConfig, mut rdr: TtReader, ms: &[TokenTree]) -> NamedParseResult { diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 2e0c7ddb540f4..a74d335d6046d 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -120,7 +120,7 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt, Some(named_matches), imported_from, rhs); - let mut p = Parser::new(cx.parse_sess(), cx.cfg(), Box::new(trncbr)); + let mut p = Parser::new(cx.parse_sess(), cx.cfg().clone(), Box::new(trncbr)); p.directory = cx.current_expansion.module.directory.clone(); p.restrictions = match cx.current_expansion.no_noninline_mod { true => Restrictions::NO_NONINLINE_MOD, @@ -225,7 +225,7 @@ pub fn compile(sess: &ParseSess, def: &ast::MacroDef) -> SyntaxExtension { // Parse the macro_rules! invocation (`none` is for no interpolations): let arg_reader = new_tt_reader(&sess.span_diagnostic, None, None, def.body.clone()); - let argument_map = match parse(sess, Vec::new(), arg_reader, &argument_gram) { + let argument_map = match parse(sess, &Vec::new(), arg_reader, &argument_gram) { Success(m) => m, Failure(sp, str) | Error(sp, str) => { panic!(sess.span_diagnostic.span_fatal(sp.substitute_dummy(def.span), &str)); diff --git a/src/libsyntax_ext/asm.rs b/src/libsyntax_ext/asm.rs index cc4fb604d6ccb..af79bdcb61137 100644 --- a/src/libsyntax_ext/asm.rs +++ b/src/libsyntax_ext/asm.rs @@ -107,7 +107,7 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, if p2.token != token::Eof { let mut extra_tts = panictry!(p2.parse_all_token_trees()); extra_tts.extend(tts[first_colon..].iter().cloned()); - p = parse::tts_to_parser(cx.parse_sess, extra_tts, cx.cfg()); + p = parse::tts_to_parser(cx.parse_sess, extra_tts, cx.cfg().clone()); } asm = s; diff --git a/src/test/compile-fail-fulldeps/auxiliary/macro_crate_test.rs b/src/test/compile-fail-fulldeps/auxiliary/macro_crate_test.rs index 5b1ecfed24278..2041abcf82c99 100644 --- a/src/test/compile-fail-fulldeps/auxiliary/macro_crate_test.rs +++ b/src/test/compile-fail-fulldeps/auxiliary/macro_crate_test.rs @@ -57,7 +57,7 @@ fn expand_identity(cx: &mut ExtCtxt, _span: Span, tts: &[TokenTree]) -> Box { // Parse an expression and emit it unchanged. let mut parser = parse::new_parser_from_tts(cx.parse_sess(), - cx.cfg(), tts.to_vec()); + cx.cfg().clone(), tts.to_vec()); let expr = parser.parse_expr().unwrap(); MacEager::expr(quote_expr!(&mut *cx, $expr)) } diff --git a/src/test/run-pass-fulldeps/auxiliary/macro_crate_test.rs b/src/test/run-pass-fulldeps/auxiliary/macro_crate_test.rs index 4885863122c3b..2c814a5433baa 100644 --- a/src/test/run-pass-fulldeps/auxiliary/macro_crate_test.rs +++ b/src/test/run-pass-fulldeps/auxiliary/macro_crate_test.rs @@ -60,7 +60,7 @@ fn expand_make_a_1(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> Box Box { // Parse an expression and emit it unchanged. - let mut parser = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(), tts.to_vec()); + let mut parser = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg().clone(), tts.to_vec()); let expr = parser.parse_expr().unwrap(); MacEager::expr(quote_expr!(&mut *cx, $expr)) } From e25d997cc4a9d99a45af65c80f439a579b43649e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 14 Oct 2016 15:34:51 +0200 Subject: [PATCH 12/60] Add missing urls for io types --- src/libstd/io/cursor.rs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/libstd/io/cursor.rs b/src/libstd/io/cursor.rs index ae0085f1044e4..ca9452ffe3eca 100644 --- a/src/libstd/io/cursor.rs +++ b/src/libstd/io/cursor.rs @@ -15,22 +15,28 @@ use cmp; use io::{self, SeekFrom, Error, ErrorKind}; /// A `Cursor` wraps another type and provides it with a -/// [`Seek`](trait.Seek.html) implementation. +/// [`Seek`] implementation. /// -/// Cursors are typically used with in-memory buffers to allow them to -/// implement `Read` and/or `Write`, allowing these buffers to be used +/// `Cursor`s are typically used with in-memory buffers to allow them to +/// implement [`Read`] and/or [`Write`], allowing these buffers to be used /// anywhere you might use a reader or writer that does actual I/O. /// /// The standard library implements some I/O traits on various types which -/// are commonly used as a buffer, like `Cursor>` and `Cursor<&[u8]>`. +/// are commonly used as a buffer, like `Cursor<`[`Vec`]`>` and +/// `Cursor<`[`&[u8]`]`>`. /// /// # Examples /// -/// We may want to write bytes to a [`File`][file] in our production +/// We may want to write bytes to a [`File`] in our production /// code, but use an in-memory buffer in our tests. We can do this with /// `Cursor`: /// -/// [file]: ../fs/struct.File.html +/// [`Seek`]: trait.Seek.html +/// [`Read`]: ../../std/io/trait.Read.html +/// [`Write`]: ../../std/io/trait.Write.html +/// [`Vec`]: ../../std/vec/struct.Vec.html +/// [`&[u8]`]: ../../std/primitive.slice.html +/// [`File`]: ../fs/struct.File.html /// /// ```no_run /// use std::io::prelude::*; From 094c3a2c785c251dffb9cadbbad02d7b1e4afc4d Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 14 Oct 2016 12:48:53 -0700 Subject: [PATCH 13/60] test: Don't write files into the source tree Tweak a few run-make tests to emit files in the output directories, not directly in the source tree. --- src/test/run-make/dep-info-spaces/Makefile | 7 +++++-- src/test/run-make/dep-info-spaces/Makefile.foo | 4 ++-- src/test/run-make/llvm-phase/test.rs | 5 ++++- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/test/run-make/dep-info-spaces/Makefile b/src/test/run-make/dep-info-spaces/Makefile index eda8cb700810d..82686ffdd9d93 100644 --- a/src/test/run-make/dep-info-spaces/Makefile +++ b/src/test/run-make/dep-info-spaces/Makefile @@ -5,9 +5,12 @@ ifneq ($(shell uname),FreeBSD) ifndef IS_WINDOWS all: - $(RUSTC) --emit link,dep-info --crate-type=lib lib.rs + cp lib.rs $(TMPDIR)/ + cp 'foo foo.rs' $(TMPDIR)/ + cp bar.rs $(TMPDIR)/ + $(RUSTC) --emit link,dep-info --crate-type=lib $(TMPDIR)/lib.rs sleep 1 - touch 'foo foo.rs' + touch $(TMPDIR)/'foo foo.rs' -rm -f $(TMPDIR)/done $(MAKE) -drf Makefile.foo rm $(TMPDIR)/done diff --git a/src/test/run-make/dep-info-spaces/Makefile.foo b/src/test/run-make/dep-info-spaces/Makefile.foo index 2f4cc486d8667..80a5d4333cdc2 100644 --- a/src/test/run-make/dep-info-spaces/Makefile.foo +++ b/src/test/run-make/dep-info-spaces/Makefile.foo @@ -1,7 +1,7 @@ -LIB := $(shell $(RUSTC) --print file-names --crate-type=lib lib.rs) +LIB := $(shell $(RUSTC) --print file-names --crate-type=lib $(TMPDIR)/lib.rs) $(TMPDIR)/$(LIB): - $(RUSTC) --emit link,dep-info --crate-type=lib lib.rs + $(RUSTC) --emit link,dep-info --crate-type=lib $(TMPDIR)/lib.rs touch $(TMPDIR)/done -include $(TMPDIR)/lib.d diff --git a/src/test/run-make/llvm-phase/test.rs b/src/test/run-make/llvm-phase/test.rs index 05c1713561a3e..ca58e007852bd 100644 --- a/src/test/run-make/llvm-phase/test.rs +++ b/src/test/run-make/llvm-phase/test.rs @@ -22,6 +22,7 @@ use rustc_driver::driver::CompileController; use rustc_trans::ModuleSource; use rustc::session::Session; use syntax::codemap::FileLoader; +use std::env; use std::io; use std::path::{PathBuf, Path}; @@ -75,9 +76,11 @@ fn main() { path.pop(); path.pop(); - let args: Vec = + let mut args: Vec = format!("_ _ --sysroot {} --crate-type dylib", path.to_str().unwrap()) .split(' ').map(|s| s.to_string()).collect(); + args.push("--out-dir".to_string()); + args.push(env::var("TMPDIR").unwrap()); let (result, _) = rustc_driver::run_compiler( &args, &mut JitCalls, Some(box JitLoader), None); From 06d173adb76e3f5f30c168a4c48316823b08e650 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 7 Oct 2016 09:43:26 -0700 Subject: [PATCH 14/60] Add AppVeyor configuration to the repo We hope to move to AppVeyor in the near future off of Buildbot + EC2. This adds an `appveyor.yml` configuration file which is ready to run builds on the auto branch. This is also accompanied with a few minor fixes to the build system and such to accomodate AppVeyor. The intention is that we're not switching over to AppVeyor entirely just yet, but rather we'll watch the builds for a week or so. If everything checks out then we'll start gating on AppVeyor instead of Buildbot! --- appveyor.yml | 110 +++++++++++++++++++++++++++ mk/llvm.mk | 32 ++++---- src/bootstrap/config.rs | 2 + src/bootstrap/config.toml.example | 3 + src/bootstrap/native.rs | 25 +++--- src/rustllvm/llvm-auto-clean-trigger | 2 +- src/test/run-make/tools.mk | 3 - src/tools/cargotest/main.rs | 14 ++++ src/tools/compiletest/src/runtest.rs | 5 ++ 9 files changed, 164 insertions(+), 32 deletions(-) create mode 100644 appveyor.yml diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000000000..686c48abb30cd --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,110 @@ +environment: + matrix: + # 32/64 bit MSVC + - MSYS_BITS: 64 + TARGET: x86_64-pc-windows-msvc + CHECK: check + CONFIGURE_ARGS: --enable-llvm-assertions --enable-debug-assertions + - MSYS_BITS: 32 + TARGET: i686-pc-windows-msvc + CHECK: check + CONFIGURE_ARGS: --enable-llvm-assertions --enable-debug-assertions + + # MSVC rustbuild + - MSYS_BITS: 64 + CONFIGURE_ARGS: --enable-rustbuild --enable-llvm-assertions --enable-debug-assertions + TARGET: x86_64-pc-windows-msvc + CHECK: check + + # MSVC cargotest + - MSYS_BITS: 64 + CONFIGURE_ARGS: --enable-rustbuild --enable-llvm-assertions --enable-debug-assertions + TARGET: x86_64-pc-windows-msvc + CHECK: check-cargotest + + # 32/64-bit MinGW builds. + # + # The MinGW builds unfortunately have to both download a custom toolchain and + # avoid the one installed by AppVeyor by default. Interestingly, though, for + # different reasons! + # + # For 32-bit the installed gcc toolchain on AppVeyor uses the pthread + # threading model. This is unfortunately not what we want, and if we compile + # with it then there's lots of link errors in the standard library (undefined + # references to pthread symbols). + # + # For 64-bit the installed gcc toolchain is currently 5.3.0 which + # unfortunately segfaults on Windows with --enable-llvm-assertions (segfaults + # in LLVM). See rust-lang/rust#28445 for more information, but to work around + # this we go back in time to 4.9.2 specifically. + # + # Finally, note that the downloads below are all in the `rust-lang-ci` S3 + # bucket, but they cleraly didn't originate there! The downloads originally + # came from the mingw-w64 SourceForge download site. Unfortunately + # SourceForge is notoriously flaky, so we mirror it on our own infrastructure. + # + # And as a final point of note, the 32-bit MinGW build using the makefiles do + # *not* use debug assertions and llvm assertions. This is because they take + # too long on appveyor and this is tested by rustbuild below. + - MSYS_BITS: 32 + TARGET: i686-pc-windows-gnu + CHECK: check + MINGW_URL: https://s3.amazonaws.com/rust-lang-ci + MINGW_ARCHIVE: i686-4.9.2-release-win32-dwarf-rt_v4-rev4.7z + MINGW_DIR: mingw32 + + - MSYS_BITS: 32 + CONFIGURE_ARGS: --enable-rustbuild --enable-llvm-assertions --enable-debug-assertions + TARGET: i686-pc-windows-gnu + CHECK: check + MINGW_URL: https://s3.amazonaws.com/rust-lang-ci + MINGW_ARCHIVE: i686-4.9.2-release-win32-dwarf-rt_v4-rev4.7z + MINGW_DIR: mingw32 + + - MSYS_BITS: 64 + CONFIGURE_ARGS: --enable-llvm-assertions --enable-debug-assertions + TARGET: x86_64-pc-windows-gnu + CHECK: check + MINGW_URL: https://s3.amazonaws.com/rust-lang-ci + MINGW_ARCHIVE: x86_64-4.9.2-release-win32-seh-rt_v4-rev4.7z + MINGW_DIR: mingw64 + +clone_depth: 1 +build: false + +install: + # If we need to download a custom MinGW, do so here and set the path + # appropriately. + # + # Note that this *also* means that we're not using what is typically + # /mingw32/bin/python2.7.exe, which is a "correct" python interpreter where + # /usr/bin/python2.7.exe is not. To ensure we use the right interpreter we + # move `C:\Python27` ahead in PATH and then also make sure the `python2.7.exe` + # file exists in there (which it doesn't by default). + - if defined MINGW_URL appveyor DownloadFile %MINGW_URL%/%MINGW_ARCHIVE% + - if defined MINGW_URL 7z x -y %MINGW_ARCHIVE% > nul + - if defined MINGW_URL set PATH=C:\Python27;%CD%\%MINGW_DIR%\bin;C:\msys64\usr\bin;%PATH% + - if defined MINGW_URL copy C:\Python27\python.exe C:\Python27\python2.7.exe + + # Otherwise pull in the MinGW installed on appveyor + - if NOT defined MINGW_URL set PATH=C:\msys64\mingw%MSYS_BITS%\bin;C:\msys64\usr\bin;%PATH% + +test_script: + - sh ./configure + %CONFIGURE_ARGS% + --build=%TARGET% + - bash -c "make -j$(nproc)" + - bash -c "make %CHECK% -j$(nproc)" + +cache: + - build/%TARGET%/llvm -> src/rustllvm/llvm-auto-clean-trigger + - "%TARGET%/llvm -> src/rustllvm/llvm-auto-clean-trigger" + +branches: + only: + - auto + +# init: +# - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) +# on_finish: +# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) diff --git a/mk/llvm.mk b/mk/llvm.mk index d6f812049e03c..5a91f5fcaa483 100644 --- a/mk/llvm.mk +++ b/mk/llvm.mk @@ -36,22 +36,27 @@ endif # If CFG_LLVM_ROOT is defined then we don't build LLVM ourselves ifeq ($(CFG_LLVM_ROOT),) -LLVM_STAMP_$(1) = $$(CFG_LLVM_BUILD_DIR_$(1))/llvm-auto-clean-stamp +LLVM_STAMP_$(1) = $(S)src/rustllvm/llvm-auto-clean-trigger LLVM_DONE_$(1) = $$(CFG_LLVM_BUILD_DIR_$(1))/llvm-finished-building $$(LLVM_CONFIG_$(1)): $$(LLVM_DONE_$(1)) -$$(LLVM_DONE_$(1)): $$(LLVM_DEPS_TARGET_$(1)) $$(LLVM_STAMP_$(1)) - @$$(call E, cmake: llvm) ifneq ($$(CFG_NINJA),) - $$(Q)$$(CFG_NINJA) -C $$(CFG_LLVM_BUILD_DIR_$(1)) +BUILD_LLVM_$(1) := $$(CFG_NINJA) -C $$(CFG_LLVM_BUILD_DIR_$(1)) else ifeq ($$(findstring msvc,$(1)),msvc) - $$(Q)$$(CFG_CMAKE) --build $$(CFG_LLVM_BUILD_DIR_$(1)) \ - --config $$(LLVM_BUILD_CONFIG_MODE) +BUILD_LLVM_$(1) := $$(CFG_CMAKE) --build $$(CFG_LLVM_BUILD_DIR_$(1)) \ + --config $$(LLVM_BUILD_CONFIG_MODE) else - $$(Q)$$(MAKE) -C $$(CFG_LLVM_BUILD_DIR_$(1)) +BUILD_LLVM_$(1) := $$(MAKE) -C $$(CFG_LLVM_BUILD_DIR_$(1)) endif - $$(Q)touch $$@ + +$$(LLVM_DONE_$(1)): $$(LLVM_DEPS_TARGET_$(1)) $$(LLVM_STAMP_$(1)) + @$$(call E, cmake: llvm) + $$(Q)if ! cmp $$(LLVM_STAMP_$(1)) $$(LLVM_DONE_$(1)); then \ + $$(MAKE) clean-llvm$(1); \ + $$(BUILD_LLVM_$(1)); \ + fi + $$(Q)cp $$(LLVM_STAMP_$(1)) $$@ ifneq ($$(CFG_NINJA),) clean-llvm$(1): @@ -75,17 +80,6 @@ endif $$(LLVM_AR_$(1)): $$(LLVM_CONFIG_$(1)) -# This is used to independently force an LLVM clean rebuild -# when we changed something not otherwise captured by builtin -# dependencies. In these cases, commit a change that touches -# the stamp in the source dir. -$$(LLVM_STAMP_$(1)): $$(S)src/rustllvm/llvm-auto-clean-trigger - @$$(call E, make: cleaning llvm) - $$(Q)touch $$@.start_time - $$(Q)$$(MAKE) clean-llvm$(1) - @$$(call E, make: done cleaning llvm) - touch -r $$@.start_time $$@ && rm $$@.start_time - ifeq ($$(CFG_ENABLE_LLVM_STATIC_STDCPP),1) LLVM_STDCPP_RUSTFLAGS_$(1) = -L "$$(dir $$(shell $$(CC_$(1)) $$(CFG_GCCISH_CFLAGS_$(1)) \ -print-file-name=lib$(CFG_STDCPP_NAME).a))" diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 6158e94875e95..e4577bfcdfc94 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -120,6 +120,7 @@ struct Build { rustc: Option, compiler_docs: Option, docs: Option, + submodules: Option, } /// TOML representation of how the LLVM build is configured. @@ -225,6 +226,7 @@ impl Config { config.cargo = build.cargo.map(PathBuf::from); set(&mut config.compiler_docs, build.compiler_docs); set(&mut config.docs, build.docs); + set(&mut config.submodules, build.submodules); if let Some(ref llvm) = toml.llvm { set(&mut config.ccache, llvm.ccache); diff --git a/src/bootstrap/config.toml.example b/src/bootstrap/config.toml.example index f054b29d0b140..39c976edc13d1 100644 --- a/src/bootstrap/config.toml.example +++ b/src/bootstrap/config.toml.example @@ -76,6 +76,9 @@ # library and facade crates. #compiler-docs = false +# Indicate whether submodules are managed and updated automatically. +#submodules = true + # ============================================================================= # Options for compiling Rust code itself # ============================================================================= diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 63fc59e43286e..1b4e86fb30f25 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -18,9 +18,10 @@ //! LLVM and compiler-rt are essentially just wired up to everything else to //! ensure that they're always in place if needed. +use std::fs::{self, File}; +use std::io::{Read, Write}; use std::path::Path; use std::process::Command; -use std::fs::{self, File}; use build_helper::output; use cmake; @@ -43,11 +44,17 @@ pub fn llvm(build: &Build, target: &str) { // artifacts are missing) then we keep going, otherwise we bail out. let dst = build.llvm_out(target); let stamp = build.src.join("src/rustllvm/llvm-auto-clean-trigger"); + let mut stamp_contents = String::new(); + t!(t!(File::open(&stamp)).read_to_string(&mut stamp_contents)); let done_stamp = dst.join("llvm-finished-building"); - build.clear_if_dirty(&dst, &stamp); - if fs::metadata(&done_stamp).is_ok() { - return + if done_stamp.exists() { + let mut done_contents = String::new(); + t!(t!(File::open(&done_stamp)).read_to_string(&mut done_contents)); + if done_contents == stamp_contents { + return + } } + drop(fs::remove_dir_all(&dst)); println!("Building LLVM for {}", target); @@ -73,7 +80,9 @@ pub fn llvm(build: &Build, target: &str) { .define("WITH_POLLY", "OFF") .define("LLVM_ENABLE_TERMINFO", "OFF") .define("LLVM_ENABLE_LIBEDIT", "OFF") - .define("LLVM_PARALLEL_COMPILE_JOBS", build.jobs().to_string()); + .define("LLVM_PARALLEL_COMPILE_JOBS", build.jobs().to_string()) + .define("LLVM_TARGET_ARCH", target.split('-').next().unwrap()) + .define("LLVM_DEFAULT_TARGET_TRIPLE", target); if target.starts_with("i686") { cfg.define("LLVM_BUILD_32_BITS", "ON"); @@ -86,9 +95,7 @@ pub fn llvm(build: &Build, target: &str) { // actually exists most of the time in normal installs of LLVM. let host = build.llvm_out(&build.config.build).join("bin/llvm-tblgen"); cfg.define("CMAKE_CROSSCOMPILING", "True") - .define("LLVM_TARGET_ARCH", target.split('-').next().unwrap()) - .define("LLVM_TABLEGEN", &host) - .define("LLVM_DEFAULT_TARGET_TRIPLE", target); + .define("LLVM_TABLEGEN", &host); } // MSVC handles compiler business itself @@ -114,7 +121,7 @@ pub fn llvm(build: &Build, target: &str) { // tools and libs on all platforms. cfg.build(); - t!(File::create(&done_stamp)); + t!(t!(File::create(&done_stamp)).write_all(stamp_contents.as_bytes())); } fn check_llvm_version(build: &Build, llvm_config: &Path) { diff --git a/src/rustllvm/llvm-auto-clean-trigger b/src/rustllvm/llvm-auto-clean-trigger index b12e25bba694f..f4b5ca7a15724 100644 --- a/src/rustllvm/llvm-auto-clean-trigger +++ b/src/rustllvm/llvm-auto-clean-trigger @@ -1,4 +1,4 @@ # If this file is modified, then llvm will be forcibly 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. -2016-10-10 +2016-10-10b diff --git a/src/test/run-make/tools.mk b/src/test/run-make/tools.mk index 38afa42a2935a..1db87d474bd72 100644 --- a/src/test/run-make/tools.mk +++ b/src/test/run-make/tools.mk @@ -22,9 +22,6 @@ RLIB_GLOB = lib$(1)*.rlib BIN = $(1) UNAME = $(shell uname) -ifneq (,$(findstring MINGW,$(UNAME))) -IS_WINDOWS=1 -endif ifeq ($(UNAME),Darwin) RUN = $(TARGET_RPATH_ENV) $(RUN_BINFILE) diff --git a/src/tools/cargotest/main.rs b/src/tools/cargotest/main.rs index 633ff6271b7cc..978e991d50874 100644 --- a/src/tools/cargotest/main.rs +++ b/src/tools/cargotest/main.rs @@ -36,6 +36,20 @@ const TEST_REPOS: &'static [Test] = &[Test { fn main() { + // One of the projects being tested here is Cargo, and when being tested + // Cargo will at some point call `nmake.exe` on Windows MSVC. Unfortunately + // `nmake` will read these two environment variables below and try to + // intepret them. We're likely being run, however, from MSYS `make` which + // uses the same variables. + // + // As a result, to prevent confusion and errors, we remove these variables + // from our environment to prevent passing MSYS make flags to nmake, causing + // it to blow up. + if cfg!(target_env = "msvc") { + env::remove_var("MAKE"); + env::remove_var("MAKEFLAGS"); + } + let args = env::args().collect::>(); let ref cargo = args[1]; let out_dir = Path::new(&args[2]); diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 35b93392baf2c..e10420bf291e7 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2105,12 +2105,17 @@ actual:\n\ .collect::>().join(" "); cmd.env("IS_MSVC", "1") + .env("IS_WINDOWS", "1") .env("MSVC_LIB", format!("'{}' -nologo", lib.display())) .env("CC", format!("'{}' {}", self.config.cc, cflags)) .env("CXX", &self.config.cxx); } else { cmd.env("CC", format!("{} {}", self.config.cc, self.config.cflags)) .env("CXX", format!("{} {}", self.config.cxx, self.config.cflags)); + + if self.config.target.contains("windows") { + cmd.env("IS_WINDOWS", "1"); + } } let output = cmd.output().expect("failed to spawn `make`"); From a8dc2975fd2700e3ed56679ce1bcbd6c2f4c3ab0 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Sat, 15 Oct 2016 00:55:46 -0400 Subject: [PATCH 15/60] Improve doc example for `std::borrow::Cow`. --- src/libcollections/borrow.rs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/libcollections/borrow.rs b/src/libcollections/borrow.rs index 6b45c25eb2139..8f9c357833791 100644 --- a/src/libcollections/borrow.rs +++ b/src/libcollections/borrow.rs @@ -86,16 +86,29 @@ impl ToOwned for T where T: Clone { /// ``` /// use std::borrow::Cow; /// -/// # #[allow(dead_code)] /// fn abs_all(input: &mut Cow<[i32]>) { /// for i in 0..input.len() { /// let v = input[i]; /// if v < 0 { -/// // clones into a vector the first time (if not already owned) +/// // Clones into a vector if not already owned. /// input.to_mut()[i] = -v; /// } /// } /// } +/// +/// // No clone occurs because `input` doesn't need to be mutated. +/// let slice = [0, 1, 2]; +/// let mut input = Cow::from(&slice[..]); +/// abs_all(&mut input); +/// +/// // Clone occurs because `input` needs to be mutated. +/// let slice = [-1, 0, 1]; +/// let mut input = Cow::from(&slice[..]); +/// abs_all(&mut input); +/// +/// // No clone occurs because `input` is already owned. +/// let mut input = Cow::from(vec![-1, 0, 1]); +/// abs_all(&mut input); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub enum Cow<'a, B: ?Sized + 'a> From ac42f3f2064130fa0c841fdf645616e0fa46734a Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Sat, 15 Oct 2016 11:40:12 -0700 Subject: [PATCH 16/60] correct erroneous pluralization of '1 type argument' error messages This is in the matter of #37042. --- src/librustc_typeck/astconv.rs | 7 +++++-- src/test/compile-fail/E0243.rs | 2 +- .../compile-fail/generic-type-less-params-with-defaults.rs | 2 +- src/test/compile-fail/issue-14092.rs | 2 +- .../compile-fail/typeck_type_placeholder_lifetime_1.rs | 2 +- .../compile-fail/typeck_type_placeholder_lifetime_2.rs | 2 +- 6 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index d58b8f083e248..c9ce320988c47 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -2218,10 +2218,12 @@ fn check_type_argument_count(tcx: TyCtxt, span: Span, supplied: usize, } else { "expected" }; + let arguments_plural = if required == 1 { "" } else { "s" }; struct_span_err!(tcx.sess, span, E0243, "wrong number of type arguments") .span_label( span, - &format!("{} {} type arguments, found {}", expected, required, supplied) + &format!("{} {} type argument{}, found {}", + expected, required, arguments_plural, supplied) ) .emit(); } else if supplied > accepted { @@ -2232,11 +2234,12 @@ fn check_type_argument_count(tcx: TyCtxt, span: Span, supplied: usize, } else { format!("expected {}", accepted) }; + let arguments_plural = if accepted == 1 { "" } else { "s" }; struct_span_err!(tcx.sess, span, E0244, "wrong number of type arguments") .span_label( span, - &format!("{} type arguments, found {}", expected, supplied) + &format!("{} type argument{}, found {}", expected, arguments_plural, supplied) ) .emit(); } diff --git a/src/test/compile-fail/E0243.rs b/src/test/compile-fail/E0243.rs index 77c9856c261ff..4434723e12f82 100644 --- a/src/test/compile-fail/E0243.rs +++ b/src/test/compile-fail/E0243.rs @@ -11,7 +11,7 @@ struct Foo { x: T } struct Bar { x: Foo } //~^ ERROR E0243 - //~| NOTE expected 1 type arguments, found 0 + //~| NOTE expected 1 type argument, found 0 fn main() { } diff --git a/src/test/compile-fail/generic-type-less-params-with-defaults.rs b/src/test/compile-fail/generic-type-less-params-with-defaults.rs index d9ac715fa9548..9b1f3e51647cb 100644 --- a/src/test/compile-fail/generic-type-less-params-with-defaults.rs +++ b/src/test/compile-fail/generic-type-less-params-with-defaults.rs @@ -18,5 +18,5 @@ struct Vec( fn main() { let _: Vec; //~^ ERROR E0243 - //~| NOTE expected at least 1 type arguments, found 0 + //~| NOTE expected at least 1 type argument, found 0 } diff --git a/src/test/compile-fail/issue-14092.rs b/src/test/compile-fail/issue-14092.rs index dd02fa7ac151c..df8707ab823e5 100644 --- a/src/test/compile-fail/issue-14092.rs +++ b/src/test/compile-fail/issue-14092.rs @@ -10,6 +10,6 @@ fn fn1(0: Box) {} //~^ ERROR E0243 - //~| NOTE expected 1 type arguments, found 0 + //~| NOTE expected 1 type argument, found 0 fn main() {} diff --git a/src/test/compile-fail/typeck_type_placeholder_lifetime_1.rs b/src/test/compile-fail/typeck_type_placeholder_lifetime_1.rs index f60d925a74864..f40445a030e01 100644 --- a/src/test/compile-fail/typeck_type_placeholder_lifetime_1.rs +++ b/src/test/compile-fail/typeck_type_placeholder_lifetime_1.rs @@ -18,5 +18,5 @@ struct Foo<'a, T:'a> { pub fn main() { let c: Foo<_, _> = Foo { r: &5 }; //~^ ERROR E0244 - //~| NOTE expected 1 type arguments, found 2 + //~| NOTE expected 1 type argument, found 2 } diff --git a/src/test/compile-fail/typeck_type_placeholder_lifetime_2.rs b/src/test/compile-fail/typeck_type_placeholder_lifetime_2.rs index ec2675ece74b0..47898690fcce4 100644 --- a/src/test/compile-fail/typeck_type_placeholder_lifetime_2.rs +++ b/src/test/compile-fail/typeck_type_placeholder_lifetime_2.rs @@ -18,5 +18,5 @@ struct Foo<'a, T:'a> { pub fn main() { let c: Foo<_, usize> = Foo { r: &5 }; //~^ ERROR E0244 - //~| NOTE expected 1 type arguments, found 2 + //~| NOTE expected 1 type argument, found 2 } From d902963b6d58b8b79ec3e29a508b2b9e86716293 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Fri, 14 Oct 2016 23:08:53 +0000 Subject: [PATCH 17/60] Refactor `syntax::ext::base::Resolver::resolve_invoc`. --- src/librustc_resolve/macros.rs | 26 +++++++++----------------- src/libsyntax/ext/base.rs | 6 +++--- src/libsyntax/ext/expand.rs | 12 +++++++++++- 3 files changed, 23 insertions(+), 21 deletions(-) diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 86ab077191eef..6741197b79cd8 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -19,7 +19,7 @@ use syntax::ast; use syntax::errors::DiagnosticBuilder; use syntax::ext::base::{self, Determinacy, MultiModifier, MultiDecorator, MultiItemModifier}; use syntax::ext::base::{NormalTT, SyntaxExtension}; -use syntax::ext::expand::{Expansion, Invocation, InvocationKind}; +use syntax::ext::expand::Expansion; use syntax::ext::hygiene::Mark; use syntax::ext::tt::macro_rules; use syntax::parse::token::intern; @@ -162,21 +162,13 @@ impl<'a> base::Resolver for Resolver<'a> { None } - fn resolve_invoc(&mut self, scope: Mark, invoc: &Invocation, force: bool) + fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, force: bool) -> Result, Determinacy> { - let (name, span) = match invoc.kind { - InvocationKind::Bang { ref mac, .. } => { - let path = &mac.node.path; - if path.segments.len() > 1 || path.global || - !path.segments[0].parameters.is_empty() { - self.session.span_err(path.span, - "expected macro name without module separators"); - return Err(Determinacy::Determined); - } - (path.segments[0].identifier.name, path.span) - } - InvocationKind::Attr { ref attr, .. } => (intern(&*attr.name()), attr.span), - }; + if path.segments.len() > 1 || path.global || !path.segments[0].parameters.is_empty() { + self.session.span_err(path.span, "expected macro name without module separators"); + return Err(Determinacy::Determined); + } + let name = path.segments[0].identifier.name; let invocation = self.invocations[&scope]; if let LegacyScope::Expansion(parent) = invocation.legacy_scope.get() { @@ -184,8 +176,8 @@ impl<'a> base::Resolver for Resolver<'a> { } self.resolve_macro_name(invocation.legacy_scope.get(), name, true).ok_or_else(|| { if force { - let mut err = - self.session.struct_span_err(span, &format!("macro undefined: '{}!'", name)); + let msg = format!("macro undefined: '{}!'", name); + let mut err = self.session.struct_span_err(path.span, &msg); self.suggest_macro_name(&name.as_str(), &mut err); err.emit(); Determinacy::Determined diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index f7c88073c9d40..99b883d26d870 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -15,7 +15,7 @@ use attr::HasAttrs; use codemap::{self, CodeMap, ExpnInfo, Spanned, respan}; use syntax_pos::{Span, ExpnId, NO_EXPANSION}; use errors::DiagnosticBuilder; -use ext::expand::{self, Invocation, Expansion}; +use ext::expand::{self, Expansion}; use ext::hygiene::Mark; use fold::{self, Folder}; use parse::{self, parser}; @@ -522,7 +522,7 @@ pub trait Resolver { fn add_expansions_at_stmt(&mut self, id: ast::NodeId, macros: Vec); fn find_attr_invoc(&mut self, attrs: &mut Vec) -> Option; - fn resolve_invoc(&mut self, scope: Mark, invoc: &Invocation, force: bool) + fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, force: bool) -> Result, Determinacy>; fn resolve_derive_mode(&mut self, ident: ast::Ident) -> Option>; } @@ -546,7 +546,7 @@ impl Resolver for DummyResolver { fn find_attr_invoc(&mut self, _attrs: &mut Vec) -> Option { None } fn resolve_derive_mode(&mut self, _ident: ast::Ident) -> Option> { None } - fn resolve_invoc(&mut self, _scope: Mark, _invoc: &Invocation, _force: bool) + fn resolve_macro(&mut self, _scope: Mark, _path: &ast::Path, _force: bool) -> Result, Determinacy> { Err(Determinacy::Determined) } diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 363ceebf0f475..3a5b3ab832861 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -240,7 +240,17 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let scope = if self.monotonic { invoc.expansion_data.mark } else { orig_expansion_data.mark }; - let ext = match self.cx.resolver.resolve_invoc(scope, &invoc, force) { + let resolution = match invoc.kind { + InvocationKind::Bang { ref mac, .. } => { + self.cx.resolver.resolve_macro(scope, &mac.node.path, force) + } + InvocationKind::Attr { ref attr, .. } => { + let ident = ast::Ident::with_empty_ctxt(intern(&*attr.name())); + let path = ast::Path::from_ident(attr.span, ident); + self.cx.resolver.resolve_macro(scope, &path, force) + } + }; + let ext = match resolution { Ok(ext) => Some(ext), Err(Determinacy::Determined) => None, Err(Determinacy::Undetermined) => { From 33e3da831c8b517c94d85599edf2bcd259128181 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Sat, 15 Oct 2016 20:50:30 +0000 Subject: [PATCH 18/60] Use the macro namespace for custom derives. --- src/librustc/middle/cstore.rs | 3 +- src/librustc_metadata/macro_import.rs | 3 +- src/librustc_resolve/build_reduced_graph.rs | 51 +++++++++++---------- src/librustc_resolve/lib.rs | 3 -- src/librustc_resolve/macros.rs | 6 +-- src/libsyntax/ext/base.rs | 4 +- src/libsyntax/ext/expand.rs | 15 +++++- src/libsyntax_ext/deriving/mod.rs | 24 +++++++--- 8 files changed, 62 insertions(+), 47 deletions(-) diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index dfd6256c35773..b54862ae0ade6 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -35,7 +35,6 @@ use session::Session; use session::search_paths::PathKind; use util::nodemap::{NodeSet, DefIdMap}; use std::path::PathBuf; -use std::rc::Rc; use syntax::ast; use syntax::attr; use syntax::ext::base::MultiItemModifier; @@ -425,7 +424,7 @@ pub struct LoadedMacro { pub enum LoadedMacroKind { Def(ast::MacroDef), - CustomDerive(String, Rc), + CustomDerive(String, Box), } pub trait CrateLoader { diff --git a/src/librustc_metadata/macro_import.rs b/src/librustc_metadata/macro_import.rs index 7cd03b2d5b941..3b1b2a4cd27e4 100644 --- a/src/librustc_metadata/macro_import.rs +++ b/src/librustc_metadata/macro_import.rs @@ -11,7 +11,6 @@ //! Used by `rustc` when loading a crate with exported macros. use std::collections::HashSet; -use std::rc::Rc; use std::env; use std::mem; @@ -212,7 +211,7 @@ impl<'a> CrateLoader<'a> { fn register_custom_derive(&mut self, trait_name: &str, expand: fn(TokenStream) -> TokenStream) { - let derive = Rc::new(CustomDerive::new(expand)); + let derive = Box::new(CustomDerive::new(expand)); self.0.push(LoadedMacro { kind: LoadedMacroKind::CustomDerive(trait_name.to_string(), derive), import_site: self.1, diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 5600669d45fb9..dac9e57be3299 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -36,7 +36,7 @@ use syntax::parse::token; use syntax::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind}; use syntax::ast::{Mutability, StmtKind, TraitItem, TraitItemKind}; use syntax::ast::{Variant, ViewPathGlob, ViewPathList, ViewPathSimple}; -use syntax::ext::base::{MultiItemModifier, Resolver as SyntaxResolver}; +use syntax::ext::base::{SyntaxExtension, Resolver as SyntaxResolver}; use syntax::ext::hygiene::Mark; use syntax::feature_gate::{self, emit_feature_err}; use syntax::ext::tt::macro_rules; @@ -195,22 +195,25 @@ impl<'b> Resolver<'b> { // We need to error on `#[macro_use] extern crate` when it isn't at the // crate root, because `$crate` won't work properly. let is_crate_root = self.current_module.parent.is_none(); + let import_macro = |this: &mut Self, name, ext, span| { + let shadowing = this.builtin_macros.insert(name, Rc::new(ext)).is_some(); + if shadowing && expansion != Mark::root() { + let msg = format!("`{}` is already in scope", name); + this.session.struct_span_err(span, &msg) + .note("macro-expanded `#[macro_use]`s may not shadow \ + existing macros (see RFC 1560)") + .emit(); + } + }; + + let mut custom_derive_crate = false; for loaded_macro in self.crate_loader.load_macros(item, is_crate_root) { match loaded_macro.kind { LoadedMacroKind::Def(mut def) => { - let name = def.ident.name; if def.use_locally { - let ext = - Rc::new(macro_rules::compile(&self.session.parse_sess, &def)); - if self.builtin_macros.insert(name, ext).is_some() && - expansion != Mark::root() { - let msg = format!("`{}` is already in scope", name); - self.session.struct_span_err(loaded_macro.import_site, &msg) - .note("macro-expanded `#[macro_use]`s may not shadow \ - existing macros (see RFC 1560)") - .emit(); - } - self.macro_names.insert(name); + self.macro_names.insert(def.ident.name); + let ext = macro_rules::compile(&self.session.parse_sess, &def); + import_macro(self, def.ident.name, ext, loaded_macro.import_site); } if def.export { def.id = self.next_node_id(); @@ -218,10 +221,19 @@ impl<'b> Resolver<'b> { } } LoadedMacroKind::CustomDerive(name, ext) => { - self.insert_custom_derive(&name, ext, item.span); + custom_derive_crate = true; + let ext = SyntaxExtension::CustomDerive(ext); + import_macro(self, token::intern(&name), ext, loaded_macro.import_site); } } } + + if custom_derive_crate && !self.session.features.borrow().proc_macro { + let issue = feature_gate::GateIssue::Language; + let msg = "loading custom derive macro crates is experimentally supported"; + emit_feature_err(&self.session.parse_sess, "proc_macro", item.span, issue, msg); + } + self.crate_loader.process_item(item, &self.definitions); // n.b. we don't need to look at the path option here, because cstore already did @@ -504,17 +516,6 @@ impl<'b> Resolver<'b> { false } - - fn insert_custom_derive(&mut self, name: &str, ext: Rc, sp: Span) { - if !self.session.features.borrow().proc_macro { - let sess = &self.session.parse_sess; - let msg = "loading custom derive macro crates is experimentally supported"; - emit_feature_err(sess, "proc_macro", sp, feature_gate::GateIssue::Language, msg); - } - if self.derive_modes.insert(token::intern(name), ext).is_some() { - self.session.span_err(sp, &format!("cannot shadow existing derive mode `{}`", name)); - } - } } pub struct BuildReducedGraphVisitor<'a, 'b: 'a> { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 6db844c1d0376..21641a17bbfde 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -53,7 +53,6 @@ use rustc::ty; use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap}; use rustc::util::nodemap::{NodeMap, NodeSet, FnvHashMap, FnvHashSet}; -use syntax::ext::base::MultiItemModifier; use syntax::ext::hygiene::Mark; use syntax::ast::{self, FloatTy}; use syntax::ast::{CRATE_NODE_ID, Name, NodeId, IntTy, UintTy}; @@ -1080,7 +1079,6 @@ pub struct Resolver<'a> { new_import_semantics: bool, // true if `#![feature(item_like_imports)]` pub exported_macros: Vec, - pub derive_modes: FnvHashMap>, crate_loader: &'a mut CrateLoader, macro_names: FnvHashSet, builtin_macros: FnvHashMap>, @@ -1271,7 +1269,6 @@ impl<'a> Resolver<'a> { new_import_semantics: session.features.borrow().item_like_imports, exported_macros: Vec::new(), - derive_modes: FnvHashMap(), crate_loader: crate_loader, macro_names: FnvHashSet(), builtin_macros: FnvHashMap(), diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 6741197b79cd8..cf5ea236b3ec7 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -17,7 +17,7 @@ use std::cell::Cell; use std::rc::Rc; use syntax::ast; use syntax::errors::DiagnosticBuilder; -use syntax::ext::base::{self, Determinacy, MultiModifier, MultiDecorator, MultiItemModifier}; +use syntax::ext::base::{self, Determinacy, MultiModifier, MultiDecorator}; use syntax::ext::base::{NormalTT, SyntaxExtension}; use syntax::ext::expand::Expansion; use syntax::ext::hygiene::Mark; @@ -186,10 +186,6 @@ impl<'a> base::Resolver for Resolver<'a> { } }) } - - fn resolve_derive_mode(&mut self, ident: ast::Ident) -> Option> { - self.derive_modes.get(&ident.name).cloned() - } } impl<'a> Resolver<'a> { diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 99b883d26d870..11c6f87a65529 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -508,6 +508,8 @@ pub enum SyntaxExtension { /// the block. /// IdentTT(Box, Option, bool), + + CustomDerive(Box), } pub type NamedSyntaxExtension = (Name, SyntaxExtension); @@ -524,7 +526,6 @@ pub trait Resolver { fn find_attr_invoc(&mut self, attrs: &mut Vec) -> Option; fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, force: bool) -> Result, Determinacy>; - fn resolve_derive_mode(&mut self, ident: ast::Ident) -> Option>; } #[derive(Copy, Clone, Debug)] @@ -545,7 +546,6 @@ impl Resolver for DummyResolver { fn add_expansions_at_stmt(&mut self, _id: ast::NodeId, _macros: Vec) {} fn find_attr_invoc(&mut self, _attrs: &mut Vec) -> Option { None } - fn resolve_derive_mode(&mut self, _ident: ast::Ident) -> Option> { None } fn resolve_macro(&mut self, _scope: Mark, _path: &ast::Path, _force: bool) -> Result, Determinacy> { Err(Determinacy::Determined) diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 3a5b3ab832861..6aeb46fd52276 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -364,7 +364,15 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let tok_result = mac.expand(self.cx, attr.span, attr_toks, item_toks); self.parse_expansion(tok_result, kind, name, attr.span) } - _ => unreachable!(), + SyntaxExtension::CustomDerive(_) => { + self.cx.span_err(attr.span, &format!("`{}` is a derive mode", name)); + kind.dummy(attr.span) + } + _ => { + let msg = &format!("macro `{}` may not be used in attributes", name); + self.cx.span_err(attr.span, &msg); + kind.dummy(attr.span) + } } } @@ -439,6 +447,11 @@ impl<'a, 'b> MacroExpander<'a, 'b> { return kind.dummy(span); } + SyntaxExtension::CustomDerive(..) => { + self.cx.span_err(path.span, &format!("`{}` is a derive mode", extname)); + return kind.dummy(span); + } + SyntaxExtension::ProcMacro(ref expandfun) => { if ident.name != keywords::Invalid.name() { let msg = diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs index 9f99919c89505..07401d59a15db 100644 --- a/src/libsyntax_ext/deriving/mod.rs +++ b/src/libsyntax_ext/deriving/mod.rs @@ -12,7 +12,7 @@ use syntax::ast::{self, MetaItem}; use syntax::attr::HasAttrs; -use syntax::ext::base::{Annotatable, ExtCtxt}; +use syntax::ext::base::{Annotatable, ExtCtxt, SyntaxExtension}; use syntax::ext::build::AstBuilder; use syntax::feature_gate; use syntax::codemap; @@ -158,10 +158,14 @@ pub fn expand_derive(cx: &mut ExtCtxt, let tword = titem.word().unwrap(); let tname = tword.name(); - let derive_mode = ast::Ident::with_empty_ctxt(intern(&tname)); - let derive_mode = cx.resolver.resolve_derive_mode(derive_mode); - if is_builtin_trait(&tname) || derive_mode.is_some() { - return true + if is_builtin_trait(&tname) || { + let derive_mode = + ast::Path::from_ident(titem.span, ast::Ident::with_empty_ctxt(intern(&tname))); + cx.resolver.resolve_macro(cx.current_expansion.mark, &derive_mode, false).map(|ext| { + if let SyntaxExtension::CustomDerive(_) = *ext { true } else { false } + }).unwrap_or(false) + } { + return true; } if !cx.ecfg.enable_custom_derive() { @@ -216,7 +220,9 @@ pub fn expand_derive(cx: &mut ExtCtxt, .next(); if let Some((i, titem)) = macros_11_derive { let tname = ast::Ident::with_empty_ctxt(intern(&titem.name().unwrap())); - let ext = cx.resolver.resolve_derive_mode(tname).unwrap(); + let path = ast::Path::from_ident(titem.span, tname); + let ext = cx.resolver.resolve_macro(cx.current_expansion.mark, &path, false).unwrap(); + traits.remove(i); if traits.len() > 0 { item = item.map(|mut i| { @@ -232,7 +238,11 @@ pub fn expand_derive(cx: &mut ExtCtxt, intern_and_get_ident("derive"), vec![titem]); let item = Annotatable::Item(item); - return ext.expand(cx, mitem.span, &mitem, item) + if let SyntaxExtension::CustomDerive(ref ext) = *ext { + return ext.expand(cx, mitem.span, &mitem, item); + } else { + unreachable!() + } } // Ok, at this point we know that there are no old-style `#[derive_Foo]` nor From aac6dca21e6a78a8bdf3406f682e2b1a7a7bdc36 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Sat, 15 Oct 2016 07:56:54 +0000 Subject: [PATCH 19/60] Treat custom derive extern crates like empty modules. --- src/librustc_resolve/build_reduced_graph.rs | 6 +++++ .../proc-macro/auxiliary/derive-a-2.rs | 25 ------------------- .../proc-macro/shadow.rs | 3 +-- 3 files changed, 7 insertions(+), 27 deletions(-) delete mode 100644 src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-a-2.rs diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index dac9e57be3299..e0abe8da82b9c 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -250,6 +250,12 @@ impl<'b> Resolver<'b> { self.define(parent, name, TypeNS, (module, sp, vis)); self.populate_module_if_necessary(module); + } else if custom_derive_crate { + // Define an empty module + let def = Def::Mod(self.definitions.local_def_id(item.id)); + let module = ModuleS::new(Some(parent), ModuleKind::Def(def, name)); + let module = self.arenas.alloc_module(module); + self.define(parent, name, TypeNS, (module, sp, vis)); } } diff --git a/src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-a-2.rs b/src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-a-2.rs deleted file mode 100644 index 4aa4238611d89..0000000000000 --- a/src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-a-2.rs +++ /dev/null @@ -1,25 +0,0 @@ -// 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. - -// force-host -// no-prefer-dynamic - -#![feature(proc_macro)] -#![feature(proc_macro_lib)] -#![crate_type = "proc-macro"] - -extern crate proc_macro; - -use proc_macro::TokenStream; - -#[proc_macro_derive(A)] -pub fn derive_a(input: TokenStream) -> TokenStream { - input -} diff --git a/src/test/compile-fail-fulldeps/proc-macro/shadow.rs b/src/test/compile-fail-fulldeps/proc-macro/shadow.rs index 7b1a73d50f6e0..a04756ca19ba7 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/shadow.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/shadow.rs @@ -9,13 +9,12 @@ // except according to those terms. // aux-build:derive-a.rs -// aux-build:derive-a-2.rs #![feature(proc_macro)] #[macro_use] extern crate derive_a; #[macro_use] -extern crate derive_a_2; //~ ERROR: cannot shadow existing derive mode `A` +extern crate derive_a; //~ ERROR `derive_a` has already been defined fn main() {} From 5afd6d8206df0d9bfca5dafbf6b2800fda4a165a Mon Sep 17 00:00:00 2001 From: Srinivas Reddy Thatiparthy Date: Sun, 16 Oct 2016 22:11:01 +0530 Subject: [PATCH 20/60] Run rustfmt on libcore/sync folder --- src/libcore/sync/atomic.rs | 114 +++++++++++++++++++------------------ 1 file changed, 58 insertions(+), 56 deletions(-) diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index c4fe68dfa438c..657f7e7992fee 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -277,7 +277,9 @@ impl AtomicBool { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn store(&self, val: bool, order: Ordering) { - unsafe { atomic_store(self.v.get(), val as u8, order); } + unsafe { + atomic_store(self.v.get(), val as u8, order); + } } /// Stores a value into the bool, returning the old value. @@ -366,9 +368,11 @@ impl AtomicBool { current: bool, new: bool, success: Ordering, - failure: Ordering) -> Result { - match unsafe { atomic_compare_exchange(self.v.get(), current as u8, new as u8, - success, failure) } { + failure: Ordering) + -> Result { + match unsafe { + atomic_compare_exchange(self.v.get(), current as u8, new as u8, success, failure) + } { Ok(x) => Ok(x != 0), Err(x) => Err(x != 0), } @@ -409,9 +413,11 @@ impl AtomicBool { current: bool, new: bool, success: Ordering, - failure: Ordering) -> Result { - match unsafe { atomic_compare_exchange_weak(self.v.get(), current as u8, new as u8, - success, failure) } { + failure: Ordering) + -> Result { + match unsafe { + atomic_compare_exchange_weak(self.v.get(), current as u8, new as u8, success, failure) + } { Ok(x) => Ok(x != 0), Err(x) => Err(x != 0), } @@ -632,9 +638,7 @@ impl AtomicPtr { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn load(&self, order: Ordering) -> *mut T { - unsafe { - atomic_load(self.p.get() as *mut usize, order) as *mut T - } + unsafe { atomic_load(self.p.get() as *mut usize, order) as *mut T } } /// Stores a value into the pointer. @@ -660,7 +664,9 @@ impl AtomicPtr { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn store(&self, ptr: *mut T, order: Ordering) { - unsafe { atomic_store(self.p.get() as *mut usize, ptr as usize, order); } + unsafe { + atomic_store(self.p.get() as *mut usize, ptr as usize, order); + } } /// Stores a value into the pointer, returning the old value. @@ -745,7 +751,8 @@ impl AtomicPtr { current: *mut T, new: *mut T, success: Ordering, - failure: Ordering) -> Result<*mut T, *mut T> { + failure: Ordering) + -> Result<*mut T, *mut T> { unsafe { let res = atomic_compare_exchange(self.p.get() as *mut usize, current as usize, @@ -794,7 +801,8 @@ impl AtomicPtr { current: *mut T, new: *mut T, success: Ordering, - failure: Ordering) -> Result<*mut T, *mut T> { + failure: Ordering) + -> Result<*mut T, *mut T> { unsafe { let res = atomic_compare_exchange_weak(self.p.get() as *mut usize, current as usize, @@ -1266,9 +1274,9 @@ fn strongest_failure_ordering(order: Ordering) -> Ordering { match order { Release => Relaxed, Relaxed => Relaxed, - SeqCst => SeqCst, + SeqCst => SeqCst, Acquire => Acquire, - AcqRel => Acquire, + AcqRel => Acquire, } } @@ -1277,9 +1285,9 @@ unsafe fn atomic_store(dst: *mut T, val: T, order: Ordering) { match order { Release => intrinsics::atomic_store_rel(dst, val), Relaxed => intrinsics::atomic_store_relaxed(dst, val), - SeqCst => intrinsics::atomic_store(dst, val), + SeqCst => intrinsics::atomic_store(dst, val), Acquire => panic!("there is no such thing as an acquire store"), - AcqRel => panic!("there is no such thing as an acquire/release store"), + AcqRel => panic!("there is no such thing as an acquire/release store"), } } @@ -1288,9 +1296,9 @@ unsafe fn atomic_load(dst: *const T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_load_acq(dst), Relaxed => intrinsics::atomic_load_relaxed(dst), - SeqCst => intrinsics::atomic_load(dst), + SeqCst => intrinsics::atomic_load(dst), Release => panic!("there is no such thing as a release load"), - AcqRel => panic!("there is no such thing as an acquire/release load"), + AcqRel => panic!("there is no such thing as an acquire/release load"), } } @@ -1299,9 +1307,9 @@ unsafe fn atomic_swap(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_xchg_acq(dst, val), Release => intrinsics::atomic_xchg_rel(dst, val), - AcqRel => intrinsics::atomic_xchg_acqrel(dst, val), + AcqRel => intrinsics::atomic_xchg_acqrel(dst, val), Relaxed => intrinsics::atomic_xchg_relaxed(dst, val), - SeqCst => intrinsics::atomic_xchg(dst, val) + SeqCst => intrinsics::atomic_xchg(dst, val), } } @@ -1311,9 +1319,9 @@ unsafe fn atomic_add(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_xadd_acq(dst, val), Release => intrinsics::atomic_xadd_rel(dst, val), - AcqRel => intrinsics::atomic_xadd_acqrel(dst, val), + AcqRel => intrinsics::atomic_xadd_acqrel(dst, val), Relaxed => intrinsics::atomic_xadd_relaxed(dst, val), - SeqCst => intrinsics::atomic_xadd(dst, val) + SeqCst => intrinsics::atomic_xadd(dst, val), } } @@ -1323,9 +1331,9 @@ unsafe fn atomic_sub(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_xsub_acq(dst, val), Release => intrinsics::atomic_xsub_rel(dst, val), - AcqRel => intrinsics::atomic_xsub_acqrel(dst, val), + AcqRel => intrinsics::atomic_xsub_acqrel(dst, val), Relaxed => intrinsics::atomic_xsub_relaxed(dst, val), - SeqCst => intrinsics::atomic_xsub(dst, val) + SeqCst => intrinsics::atomic_xsub(dst, val), } } @@ -1334,26 +1342,23 @@ unsafe fn atomic_compare_exchange(dst: *mut T, old: T, new: T, success: Ordering, - failure: Ordering) -> Result { + failure: Ordering) + -> Result { let (val, ok) = match (success, failure) { (Acquire, Acquire) => intrinsics::atomic_cxchg_acq(dst, old, new), (Release, Relaxed) => intrinsics::atomic_cxchg_rel(dst, old, new), - (AcqRel, Acquire) => intrinsics::atomic_cxchg_acqrel(dst, old, new), + (AcqRel, Acquire) => intrinsics::atomic_cxchg_acqrel(dst, old, new), (Relaxed, Relaxed) => intrinsics::atomic_cxchg_relaxed(dst, old, new), - (SeqCst, SeqCst) => intrinsics::atomic_cxchg(dst, old, new), + (SeqCst, SeqCst) => intrinsics::atomic_cxchg(dst, old, new), (Acquire, Relaxed) => intrinsics::atomic_cxchg_acq_failrelaxed(dst, old, new), - (AcqRel, Relaxed) => intrinsics::atomic_cxchg_acqrel_failrelaxed(dst, old, new), - (SeqCst, Relaxed) => intrinsics::atomic_cxchg_failrelaxed(dst, old, new), - (SeqCst, Acquire) => intrinsics::atomic_cxchg_failacq(dst, old, new), + (AcqRel, Relaxed) => intrinsics::atomic_cxchg_acqrel_failrelaxed(dst, old, new), + (SeqCst, Relaxed) => intrinsics::atomic_cxchg_failrelaxed(dst, old, new), + (SeqCst, Acquire) => intrinsics::atomic_cxchg_failacq(dst, old, new), (_, AcqRel) => panic!("there is no such thing as an acquire/release failure ordering"), (_, Release) => panic!("there is no such thing as a release failure ordering"), _ => panic!("a failure ordering can't be stronger than a success ordering"), }; - if ok { - Ok(val) - } else { - Err(val) - } + if ok { Ok(val) } else { Err(val) } } #[inline] @@ -1361,26 +1366,23 @@ unsafe fn atomic_compare_exchange_weak(dst: *mut T, old: T, new: T, success: Ordering, - failure: Ordering) -> Result { + failure: Ordering) + -> Result { let (val, ok) = match (success, failure) { (Acquire, Acquire) => intrinsics::atomic_cxchgweak_acq(dst, old, new), (Release, Relaxed) => intrinsics::atomic_cxchgweak_rel(dst, old, new), - (AcqRel, Acquire) => intrinsics::atomic_cxchgweak_acqrel(dst, old, new), + (AcqRel, Acquire) => intrinsics::atomic_cxchgweak_acqrel(dst, old, new), (Relaxed, Relaxed) => intrinsics::atomic_cxchgweak_relaxed(dst, old, new), - (SeqCst, SeqCst) => intrinsics::atomic_cxchgweak(dst, old, new), + (SeqCst, SeqCst) => intrinsics::atomic_cxchgweak(dst, old, new), (Acquire, Relaxed) => intrinsics::atomic_cxchgweak_acq_failrelaxed(dst, old, new), - (AcqRel, Relaxed) => intrinsics::atomic_cxchgweak_acqrel_failrelaxed(dst, old, new), - (SeqCst, Relaxed) => intrinsics::atomic_cxchgweak_failrelaxed(dst, old, new), - (SeqCst, Acquire) => intrinsics::atomic_cxchgweak_failacq(dst, old, new), + (AcqRel, Relaxed) => intrinsics::atomic_cxchgweak_acqrel_failrelaxed(dst, old, new), + (SeqCst, Relaxed) => intrinsics::atomic_cxchgweak_failrelaxed(dst, old, new), + (SeqCst, Acquire) => intrinsics::atomic_cxchgweak_failacq(dst, old, new), (_, AcqRel) => panic!("there is no such thing as an acquire/release failure ordering"), (_, Release) => panic!("there is no such thing as a release failure ordering"), _ => panic!("a failure ordering can't be stronger than a success ordering"), }; - if ok { - Ok(val) - } else { - Err(val) - } + if ok { Ok(val) } else { Err(val) } } #[inline] @@ -1388,9 +1390,9 @@ unsafe fn atomic_and(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_and_acq(dst, val), Release => intrinsics::atomic_and_rel(dst, val), - AcqRel => intrinsics::atomic_and_acqrel(dst, val), + AcqRel => intrinsics::atomic_and_acqrel(dst, val), Relaxed => intrinsics::atomic_and_relaxed(dst, val), - SeqCst => intrinsics::atomic_and(dst, val) + SeqCst => intrinsics::atomic_and(dst, val), } } @@ -1399,9 +1401,9 @@ unsafe fn atomic_or(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_or_acq(dst, val), Release => intrinsics::atomic_or_rel(dst, val), - AcqRel => intrinsics::atomic_or_acqrel(dst, val), + AcqRel => intrinsics::atomic_or_acqrel(dst, val), Relaxed => intrinsics::atomic_or_relaxed(dst, val), - SeqCst => intrinsics::atomic_or(dst, val) + SeqCst => intrinsics::atomic_or(dst, val), } } @@ -1410,9 +1412,9 @@ unsafe fn atomic_xor(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_xor_acq(dst, val), Release => intrinsics::atomic_xor_rel(dst, val), - AcqRel => intrinsics::atomic_xor_acqrel(dst, val), + AcqRel => intrinsics::atomic_xor_acqrel(dst, val), Relaxed => intrinsics::atomic_xor_relaxed(dst, val), - SeqCst => intrinsics::atomic_xor(dst, val) + SeqCst => intrinsics::atomic_xor(dst, val), } } @@ -1443,9 +1445,9 @@ pub fn fence(order: Ordering) { match order { Acquire => intrinsics::atomic_fence_acq(), Release => intrinsics::atomic_fence_rel(), - AcqRel => intrinsics::atomic_fence_acqrel(), - SeqCst => intrinsics::atomic_fence(), - Relaxed => panic!("there is no such thing as a relaxed fence") + AcqRel => intrinsics::atomic_fence_acqrel(), + SeqCst => intrinsics::atomic_fence(), + Relaxed => panic!("there is no such thing as a relaxed fence"), } } } From e4ed345b2ca84db1b3300661aa3940afc0c0cbf0 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Sun, 16 Oct 2016 20:38:56 +0200 Subject: [PATCH 21/60] impl Debug for ReadDir It is good practice to implement Debug for public types, and indicating what directory you're reading seems useful. Signed-off-by: David Henningsson --- src/libstd/fs.rs | 1 + src/libstd/sys/unix/fs.rs | 8 ++++++++ src/libstd/sys/windows/fs.rs | 8 ++++++++ 3 files changed, 17 insertions(+) diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index 5bb5183fd6a93..df5741d00a2c1 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -83,6 +83,7 @@ pub struct Metadata(fs_imp::FileAttr); /// /// [`io::Result`]: ../io/type.Result.html #[stable(feature = "rust1", since = "1.0.0")] +#[derive(Debug)] pub struct ReadDir(fs_imp::ReadDir); /// Entries returned by the [`ReadDir`] iterator. diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index fe8cbc8421572..b77008676b16f 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -193,6 +193,14 @@ impl FromInner for FilePermissions { } } +impl fmt::Debug for ReadDir { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + // This will only be called from std::fs::ReadDir, which will add a "ReadDir()" frame. + // Thus the result will be e g 'ReadDir("/home")' + fmt::Debug::fmt(&*self.root, f) + } +} + impl Iterator for ReadDir { type Item = io::Result; diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index a927eae020dcf..98fd15f863ba1 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -81,6 +81,14 @@ pub struct FilePermissions { attrs: c::DWORD } pub struct DirBuilder; +impl fmt::Debug for ReadDir { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + // This will only be called from std::fs::ReadDir, which will add a "ReadDir()" frame. + // Thus the result will be e g 'ReadDir("C:\")' + fmt::Debug::fmt(&*self.root, f) + } +} + impl Iterator for ReadDir { type Item = io::Result; fn next(&mut self) -> Option> { From 49e6b466e953e5cb56e29cf546204a004f26a985 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 12 Oct 2016 20:54:41 +0300 Subject: [PATCH 22/60] Mark enums with non-zero discriminant as non-zero --- src/librustc/ty/layout.rs | 32 +++++++++++++------------ src/test/run-pass/nonzero-enum.rs | 39 +++++++++++++++++++++++++++++++ src/tools/compiletest/src/main.rs | 2 ++ 3 files changed, 58 insertions(+), 15 deletions(-) create mode 100644 src/test/run-pass/nonzero-enum.rs diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index ec6843eb75d1f..5ce43d905ec71 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -597,7 +597,8 @@ impl<'a, 'gcx, 'tcx> Struct { -> Result, LayoutError<'gcx>> { let tcx = infcx.tcx.global_tcx(); match (ty.layout(infcx)?, &ty.sty) { - (&Scalar { non_zero: true, .. }, _) => Ok(Some(vec![])), + (&Scalar { non_zero: true, .. }, _) | + (&CEnum { non_zero: true, .. }, _) => Ok(Some(vec![])), (&FatPointer { non_zero: true, .. }, _) => { Ok(Some(vec![FAT_PTR_ADDR as u32])) } @@ -769,6 +770,7 @@ pub enum Layout { CEnum { discr: Integer, signed: bool, + non_zero: bool, // Inclusive discriminant range. // If min > max, it represents min...u64::MAX followed by 0...max. // FIXME(eddyb) always use the shortest range, e.g. by finding @@ -1002,9 +1004,10 @@ impl<'a, 'gcx, 'tcx> Layout { if def.is_enum() && def.variants.iter().all(|v| v.fields.is_empty()) { // All bodies empty -> intlike - let (mut min, mut max) = (i64::MAX, i64::MIN); + let (mut min, mut max, mut non_zero) = (i64::MAX, i64::MIN, true); for v in &def.variants { let x = v.disr_val.to_u64_unchecked() as i64; + if x == 0 { non_zero = false; } if x < min { min = x; } if x > max { max = x; } } @@ -1013,6 +1016,7 @@ impl<'a, 'gcx, 'tcx> Layout { return success(CEnum { discr: discr, signed: signed, + non_zero: non_zero, min: min as u64, max: max as u64 }); @@ -1069,19 +1073,17 @@ impl<'a, 'gcx, 'tcx> Layout { // FIXME(eddyb) should take advantage of a newtype. if path == &[0] && variants[discr].len() == 1 { - match *variants[discr][0].layout(infcx)? { - Scalar { value, .. } => { - return success(RawNullablePointer { - nndiscr: discr as u64, - value: value - }); - } - _ => { - bug!("Layout::compute: `{}`'s non-zero \ - `{}` field not scalar?!", - ty, variants[discr][0]) - } - } + let value = match *variants[discr][0].layout(infcx)? { + Scalar { value, .. } => value, + CEnum { discr, .. } => Int(discr), + _ => bug!("Layout::compute: `{}`'s non-zero \ + `{}` field not scalar?!", + ty, variants[discr][0]) + }; + return success(RawNullablePointer { + nndiscr: discr as u64, + value: value, + }); } path.push(0); // For GEP through a pointer. diff --git a/src/test/run-pass/nonzero-enum.rs b/src/test/run-pass/nonzero-enum.rs new file mode 100644 index 0000000000000..266506e04b74d --- /dev/null +++ b/src/test/run-pass/nonzero-enum.rs @@ -0,0 +1,39 @@ +// 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. + +use std::mem::size_of; + +enum E { + A = 1, + B = 2, + C = 3, +} + +struct S { + a: u16, + b: u8, + e: E, +} + +fn main() { + assert_eq!(size_of::(), 1); + assert_eq!(size_of::>(), 1); + assert_eq!(size_of::>(), 1); + assert_eq!(size_of::(), 4); + assert_eq!(size_of::>(), 4); + let enone = None::; + let esome = Some(E::A); + if let Some(..) = enone { + panic!(); + } + if let None = esome { + panic!(); + } +} diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 81478c18d7b24..e6efd45cad186 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -15,6 +15,8 @@ #![feature(test)] #![feature(libc)] +#![cfg_attr(stage0, feature(question_mark))] + #![deny(warnings)] extern crate libc; From 88fde7f728612252eef9624a40b3b3f7868309f1 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Mon, 17 Oct 2016 02:28:31 +0200 Subject: [PATCH 23/60] Don't process cycles when stalled This improves the `inflate-0.1.0` benchmark by about 10% for me. --- src/librustc_data_structures/obligation_forest/mod.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/librustc_data_structures/obligation_forest/mod.rs b/src/librustc_data_structures/obligation_forest/mod.rs index c079146edbf42..fb2d3291a601b 100644 --- a/src/librustc_data_structures/obligation_forest/mod.rs +++ b/src/librustc_data_structures/obligation_forest/mod.rs @@ -342,6 +342,16 @@ impl ObligationForest { } } + if stalled { + // There's no need to perform marking, cycle processing and compression when nothing + // changed. + return Outcome { + completed: vec![], + errors: errors, + stalled: stalled, + }; + } + self.mark_as_waiting(); self.process_cycles(processor); From ed5015939f02ce340bf3581c866f7b6ddabb6daf Mon Sep 17 00:00:00 2001 From: Ulrik Sverdrup Date: Mon, 17 Oct 2016 10:58:21 +0200 Subject: [PATCH 24/60] Expand .zip() specialization to .map() and .cloned() Implement .zip() specialization for Map and Cloned. The crucial thing for transparent specialization is that we want to preserve the potential side effects. The simplest example is that in this code snippet: `(0..6).map(f).zip((0..4).map(g)).count()` `f` will be called five times, and `g` four times. The last time for `f` is when the other iterator is at its end, so this element is unused. This side effect can be preserved without disturbing code generation for simple uses of `.map()`. The `Zip::next_back()` case is even more complicated, unfortunately. --- src/libcore/iter/mod.rs | 59 ++++++++++++++++++ src/libcore/iter_private.rs | 5 +- src/libcore/slice.rs | 2 + src/test/codegen/zip.rs | 9 +++ src/test/run-pass/iter-zip.rs | 112 ++++++++++++++++++++++++++++++++++ 5 files changed, 186 insertions(+), 1 deletion(-) create mode 100644 src/test/run-pass/iter-zip.rs diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index 035418570a019..9eeb2608071c2 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -420,6 +420,18 @@ impl<'a, I, T: 'a> FusedIterator for Cloned where I: FusedIterator, T: Clone {} +#[doc(hidden)] +unsafe impl<'a, I, T: 'a> TrustedRandomAccess for Cloned + where I: TrustedRandomAccess, T: Clone +{ + unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item { + self.it.get_unchecked(i).clone() + } + + #[inline] + fn may_have_side_effect() -> bool { true } +} + /// An iterator that repeats endlessly. /// /// This `struct` is created by the [`cycle()`] method on [`Iterator`]. See its @@ -773,6 +785,13 @@ impl ZipImpl for Zip unsafe { Some((self.a.get_unchecked(i), self.b.get_unchecked(i))) } + } else if A::may_have_side_effect() && self.index < self.a.len() { + // match the base implementation's potential side effects + unsafe { + self.a.get_unchecked(self.index); + } + self.index += 1; + None } else { None } @@ -789,6 +808,23 @@ impl ZipImpl for Zip where A: DoubleEndedIterator + ExactSizeIterator, B: DoubleEndedIterator + ExactSizeIterator { + // Adjust a, b to equal length + if A::may_have_side_effect() { + let sz = self.a.len(); + if sz > self.len { + for _ in 0..sz - cmp::max(self.len, self.index) { + self.a.next_back(); + } + } + } + if B::may_have_side_effect() { + let sz = self.b.len(); + if sz > self.len { + for _ in 0..sz - self.len { + self.b.next_back(); + } + } + } if self.index < self.len { self.len -= 1; let i = self.len; @@ -814,6 +850,9 @@ unsafe impl TrustedRandomAccess for Zip (self.a.get_unchecked(i), self.b.get_unchecked(i)) } + fn may_have_side_effect() -> bool { + A::may_have_side_effect() || B::may_have_side_effect() + } } #[unstable(feature = "fused", issue = "35602")] @@ -920,6 +959,18 @@ impl ExactSizeIterator for Map impl FusedIterator for Map where F: FnMut(I::Item) -> B {} +#[doc(hidden)] +unsafe impl TrustedRandomAccess for Map + where I: TrustedRandomAccess, + F: FnMut(I::Item) -> B, +{ + unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item { + (self.f)(self.iter.get_unchecked(i)) + } + #[inline] + fn may_have_side_effect() -> bool { true } +} + /// An iterator that filters the elements of `iter` with `predicate`. /// /// This `struct` is created by the [`filter()`] method on [`Iterator`]. See its @@ -1135,6 +1186,10 @@ unsafe impl TrustedRandomAccess for Enumerate unsafe fn get_unchecked(&mut self, i: usize) -> (usize, I::Item) { (self.count + i, self.iter.get_unchecked(i)) } + + fn may_have_side_effect() -> bool { + I::may_have_side_effect() + } } #[unstable(feature = "fused", issue = "35602")] @@ -1764,6 +1819,10 @@ unsafe impl TrustedRandomAccess for Fuse unsafe fn get_unchecked(&mut self, i: usize) -> I::Item { self.iter.get_unchecked(i) } + + fn may_have_side_effect() -> bool { + I::may_have_side_effect() + } } #[unstable(feature = "fused", issue = "35602")] diff --git a/src/libcore/iter_private.rs b/src/libcore/iter_private.rs index 83eeef31ab054..bc1aaa09f3dbd 100644 --- a/src/libcore/iter_private.rs +++ b/src/libcore/iter_private.rs @@ -14,6 +14,7 @@ /// # Safety /// /// The iterator's .len() and size_hint() must be exact. +/// `.len()` must be cheap to call. /// /// .get_unchecked() must return distinct mutable references for distinct /// indices (if applicable), and must return a valid reference if index is in @@ -21,5 +22,7 @@ #[doc(hidden)] pub unsafe trait TrustedRandomAccess : ExactSizeIterator { unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item; + /// Return `true` if getting an iterator element may have + /// side effects. Remember to take inner iterators into account. + fn may_have_side_effect() -> bool; } - diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index d1df56905df24..31be404ba905a 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -1968,6 +1968,7 @@ unsafe impl<'a, T> TrustedRandomAccess for Iter<'a, T> { unsafe fn get_unchecked(&mut self, i: usize) -> &'a T { &*self.ptr.offset(i as isize) } + fn may_have_side_effect() -> bool { false } } #[doc(hidden)] @@ -1975,4 +1976,5 @@ unsafe impl<'a, T> TrustedRandomAccess for IterMut<'a, T> { unsafe fn get_unchecked(&mut self, i: usize) -> &'a mut T { &mut *self.ptr.offset(i as isize) } + fn may_have_side_effect() -> bool { false } } diff --git a/src/test/codegen/zip.rs b/src/test/codegen/zip.rs index 6c956364bf80f..d0051c5165fe1 100644 --- a/src/test/codegen/zip.rs +++ b/src/test/codegen/zip.rs @@ -20,3 +20,12 @@ pub fn zip_copy(xs: &[u8], ys: &mut [u8]) { *y = *x; } } + +// CHECK-LABEL: @zip_copy_mapped +#[no_mangle] +pub fn zip_copy_mapped(xs: &[u8], ys: &mut [u8]) { +// CHECK: memcpy + for (x, y) in xs.iter().map(|&x| x).zip(ys) { + *y = x; + } +} diff --git a/src/test/run-pass/iter-zip.rs b/src/test/run-pass/iter-zip.rs new file mode 100644 index 0000000000000..b0503bc2048e7 --- /dev/null +++ b/src/test/run-pass/iter-zip.rs @@ -0,0 +1,112 @@ +// 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. + +// Test that .zip() specialization preserves side effects +// in sideeffectful iterator adaptors. + +use std::cell::Cell; + +#[derive(Debug)] +struct CountClone(Cell); + +fn count_clone() -> CountClone { CountClone(Cell::new(0)) } + +impl PartialEq for CountClone { + fn eq(&self, rhs: &i32) -> bool { + self.0.get() == *rhs + } +} + +impl Clone for CountClone { + fn clone(&self) -> Self { + let ret = CountClone(self.0.clone()); + let n = self.0.get(); + self.0.set(n + 1); + ret + } +} + +fn test_zip_cloned_sideffectful() { + let xs = [count_clone(), count_clone(), count_clone(), count_clone()]; + let ys = [count_clone(), count_clone()]; + + for _ in xs.iter().cloned().zip(ys.iter().cloned()) { } + + assert_eq!(&xs, &[1, 1, 1, 0][..]); + assert_eq!(&ys, &[1, 1][..]); + + let xs = [count_clone(), count_clone()]; + let ys = [count_clone(), count_clone(), count_clone(), count_clone()]; + + for _ in xs.iter().cloned().zip(ys.iter().cloned()) { } + + assert_eq!(&xs, &[1, 1][..]); + assert_eq!(&ys, &[1, 1, 0, 0][..]); +} + +fn test_zip_map_sideffectful() { + let mut xs = [0; 6]; + let mut ys = [0; 4]; + + for _ in xs.iter_mut().map(|x| *x += 1).zip(ys.iter_mut().map(|y| *y += 1)) { } + + assert_eq!(&xs, &[1, 1, 1, 1, 1, 0]); + assert_eq!(&ys, &[1, 1, 1, 1]); + + let mut xs = [0; 4]; + let mut ys = [0; 6]; + + for _ in xs.iter_mut().map(|x| *x += 1).zip(ys.iter_mut().map(|y| *y += 1)) { } + + assert_eq!(&xs, &[1, 1, 1, 1]); + assert_eq!(&ys, &[1, 1, 1, 1, 0, 0]); +} + +fn test_zip_map_rev_sideffectful() { + let mut xs = [0; 6]; + let mut ys = [0; 4]; + + { + let mut it = xs.iter_mut().map(|x| *x += 1).zip(ys.iter_mut().map(|y| *y += 1)); + it.next_back(); + } + assert_eq!(&xs, &[0, 0, 0, 1, 1, 1]); + assert_eq!(&ys, &[0, 0, 0, 1]); + + let mut xs = [0; 6]; + let mut ys = [0; 4]; + + { + let mut it = xs.iter_mut().map(|x| *x += 1).zip(ys.iter_mut().map(|y| *y += 1)); + (&mut it).take(5).count(); + it.next_back(); + } + assert_eq!(&xs, &[1, 1, 1, 1, 1, 1]); + assert_eq!(&ys, &[1, 1, 1, 1]); +} + +fn test_zip_nested_sideffectful() { + let mut xs = [0; 6]; + let ys = [0; 4]; + + { + // test that it has the side effect nested inside enumerate + let it = xs.iter_mut().map(|x| *x = 1).enumerate().zip(&ys); + it.count(); + } + assert_eq!(&xs, &[1, 1, 1, 1, 1, 0]); +} + +fn main() { + test_zip_cloned_sideffectful(); + test_zip_map_sideffectful(); + test_zip_map_rev_sideffectful(); + test_zip_nested_sideffectful(); +} From 0271a9a60a5b1ba5e1b51aa9ac73321bf699c3df Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Mon, 17 Oct 2016 16:14:25 +0200 Subject: [PATCH 25/60] Fix Subst construction: use subst from adt_def rather than Drop impl's subst. This addresses issue pointed out by niko that prior code would break if the declaration order for generics does not match how they are fed into the instantiation of the type itself. (Added some tests exercising this scenario.) --- src/librustc/ty/mod.rs | 8 ++ src/librustc_typeck/check/dropck.rs | 90 ++++++++++++++++--- .../compile-fail/dropck-eyepatch-reorder.rs | 73 +++++++++++++++ src/test/run-pass/dropck-eyepatch-reorder.rs | 89 ++++++++++++++++++ 4 files changed, 247 insertions(+), 13 deletions(-) create mode 100644 src/test/compile-fail/dropck-eyepatch-reorder.rs create mode 100644 src/test/run-pass/dropck-eyepatch-reorder.rs diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index e1d8839bb37d8..7a22ef3c81edc 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -742,6 +742,14 @@ impl<'tcx> Generics<'tcx> { pub fn count(&self) -> usize { self.parent_count() + self.own_count() } + + pub fn region_param(&self, param: &EarlyBoundRegion) -> &RegionParameterDef<'tcx> { + &self.regions[param.index as usize - self.has_self as usize] + } + + pub fn type_param(&self, param: &ParamTy) -> &TypeParameterDef<'tcx> { + &self.types[param.idx as usize - self.has_self as usize - self.regions.len()] + } } /// Bounds on generics. diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index b48c37b2fc9f3..607b32fd14021 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -556,20 +556,10 @@ fn has_dtor_of_interest<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, } else { return DropckKind::BorrowedDataMustStrictlyOutliveSelf; }; + let method = tcx.impl_or_trait_item(dtor_method); - let substs = Substs::for_item(tcx, - method.container().id(), - |def, _| if def.pure_wrt_drop { - tcx.mk_region(ty::ReStatic) - } else { - substs.region_for_def(def) - }, - |def, _| if def.pure_wrt_drop { - tcx.mk_nil() - } else { - substs.type_for_def(def) - }); - let revised_ty = tcx.mk_adt(adt_def, &substs); + let impl_id: DefId = method.container().id(); + let revised_ty = revise_self_ty(tcx, adt_def, impl_id, substs); return DropckKind::RevisedSelf(revised_ty); } ty::TyTrait(..) | ty::TyProjection(..) | ty::TyAnon(..) => { @@ -581,3 +571,77 @@ fn has_dtor_of_interest<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, } } } + +// Constructs new Ty just like the type defined by `adt_def` coupled +// with `substs`, except each type and lifetime parameter marked as +// `#[may_dangle]` in the Drop impl (identified by `impl_id`) is +// respectively mapped to `()` or `'static`. +// +// For example: If the `adt_def` maps to: +// +// enum Foo<'a, X, Y> { ... } +// +// and the `impl_id` maps to: +// +// impl<#[may_dangle] 'a, X, #[may_dangle] Y> Drop for Foo<'a, X, Y> { ... } +// +// then revises input: `Foo<'r,i64,&'r i64>` to: `Foo<'static,i64,()>` +fn revise_self_ty<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, + adt_def: ty::AdtDef<'tcx>, + impl_id: DefId, + substs: &Substs<'tcx>) -> Ty<'tcx> { + // Get generics for `impl Drop` to query for `#[may_dangle]` attr. + let impl_bindings = tcx.lookup_generics(impl_id); + + // Get Substs attached to Self on `impl Drop`; process in parallel + // with `substs`, replacing dangling entries as appropriate. + let self_substs = { + let impl_self_ty: Ty<'tcx> = tcx.lookup_item_type(impl_id).ty; + if let ty::TyAdt(self_adt_def, self_substs) = impl_self_ty.sty { + assert_eq!(adt_def, self_adt_def); + self_substs + } else { + bug!("Self in `impl Drop for _` must be an Adt."); + } + }; + + // Walk `substs` + `self_substs`, build new substs appropriate for + // `adt_def`; each non-dangling param reuses entry from `substs`. + let substs = Substs::for_item( + tcx, + adt_def.did, + |def, _| { + let r_orig = substs.region_for_def(def); + let impl_self_orig = self_substs.region_for_def(def); + let r = if let ty::Region::ReEarlyBound(ref ebr) = *impl_self_orig { + if impl_bindings.region_param(ebr).pure_wrt_drop { + tcx.mk_region(ty::ReStatic) + } else { + r_orig + } + } else { + bug!("substs for an impl must map regions to ReEarlyBound"); + }; + debug!("has_dtor_of_interest mapping def {:?} orig {:?} to {:?}", + def, r_orig, r); + r + }, + |def, _| { + let t_orig = substs.type_for_def(def); + let impl_self_orig = self_substs.type_for_def(def); + let t = if let ty::TypeVariants::TyParam(ref pt) = impl_self_orig.sty { + if impl_bindings.type_param(pt).pure_wrt_drop { + tcx.mk_nil() + } else { + t_orig + } + } else { + bug!("substs for an impl must map types to TyParam"); + }; + debug!("has_dtor_of_interest mapping def {:?} orig {:?} {:?} to {:?} {:?}", + def, t_orig, t_orig.sty, t, t.sty); + t + }); + + return tcx.mk_adt(adt_def, &substs); +} diff --git a/src/test/compile-fail/dropck-eyepatch-reorder.rs b/src/test/compile-fail/dropck-eyepatch-reorder.rs new file mode 100644 index 0000000000000..68b0ff3b5f096 --- /dev/null +++ b/src/test/compile-fail/dropck-eyepatch-reorder.rs @@ -0,0 +1,73 @@ +// 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. + +#![feature(generic_param_attrs)] +#![feature(dropck_eyepatch)] + +// The point of this test is to test uses of `#[may_dangle]` attribute +// where the formal declaration order (in the impl generics) does not +// match the actual usage order (in the type instantiation). +// +// See also dropck-eyepatch.rs for more information about the general +// structure of the test. + +use std::fmt; + +struct Dt(&'static str, A); +struct Dr<'a, B:'a+fmt::Debug>(&'static str, &'a B); +struct Pt(&'static str, A, B); +struct Pr<'a, 'b, B:'a+'b+fmt::Debug>(&'static str, &'a B, &'b B); +struct St(&'static str, A); +struct Sr<'a, B:'a+fmt::Debug>(&'static str, &'a B); + +impl Drop for Dt { + fn drop(&mut self) { println!("drop {} {:?}", self.0, self.1); } +} +impl<'a, B: fmt::Debug> Drop for Dr<'a, B> { + fn drop(&mut self) { println!("drop {} {:?}", self.0, self.1); } +} +unsafe impl Drop for Pt { + // (unsafe to access self.1 due to #[may_dangle] on A) + fn drop(&mut self) { println!("drop {} {:?}", self.0, self.2); } +} +unsafe impl<'b, #[may_dangle] 'a, B: fmt::Debug> Drop for Pr<'a, 'b, B> { + // (unsafe to access self.1 due to #[may_dangle] on 'a) + fn drop(&mut self) { println!("drop {} {:?}", self.0, self.2); } +} + +fn main() { + use std::cell::Cell; + let c_long; + let (c, mut dt, mut dr, mut pt, mut pr, st, sr) + : (Cell<_>, Dt<_>, Dr<_>, Pt<_, _>, Pr<_>, St<_>, Sr<_>); + c_long = Cell::new(1); + c = Cell::new(1); + + // No error: sufficiently long-lived state can be referenced in dtors + dt = Dt("dt", &c_long); + dr = Dr("dr", &c_long); + // Error: destructor order imprecisely modelled + dt = Dt("dt", &c); //~ ERROR `c` does not live long enough + dr = Dr("dr", &c); //~ ERROR `c` does not live long enough + + // No error: Drop impl asserts .1 (A and &'a _) are not accessed + pt = Pt("pt", &c, &c_long); + pr = Pr("pr", &c, &c_long); + + // Error: Drop impl's assertion does not apply to `B` nor `&'b _` + pt = Pt("pt", &c_long, &c); //~ ERROR `c` does not live long enough + pr = Pr("pr", &c_long, &c); //~ ERROR `c` does not live long enough + + // No error: St and Sr have no destructor. + st = St("st", &c); + sr = Sr("sr", &c); + + println!("{:?}", (dt.0, dr.0, pt.0, pr.0, st.0, sr.0)); +} diff --git a/src/test/run-pass/dropck-eyepatch-reorder.rs b/src/test/run-pass/dropck-eyepatch-reorder.rs new file mode 100644 index 0000000000000..bbf8bb8c35238 --- /dev/null +++ b/src/test/run-pass/dropck-eyepatch-reorder.rs @@ -0,0 +1,89 @@ +// 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. + +#![feature(generic_param_attrs)] +#![feature(dropck_eyepatch)] + +// The point of this test is to test uses of `#[may_dangle]` attribute +// where the formal declaration order (in the impl generics) does not +// match the actual usage order (in the type instantiation). +// +// See also dropck-eyepatch.rs for more information about the general +// structure of the test. + +trait Foo { fn foo(&self, _: &str); } + +struct Dt(&'static str, A); +struct Dr<'a, B:'a+Foo>(&'static str, &'a B); +struct Pt(&'static str, A, B); +struct Pr<'a, 'b, B:'a+'b+Foo>(&'static str, &'a B, &'b B); +struct St(&'static str, A); +struct Sr<'a, B:'a+Foo>(&'static str, &'a B); + +impl Drop for Dt { + fn drop(&mut self) { println!("drop {}", self.0); self.1.foo(self.0); } +} +impl<'a, B: Foo> Drop for Dr<'a, B> { + fn drop(&mut self) { println!("drop {}", self.0); self.1.foo(self.0); } +} +unsafe impl Drop for Pt { + // (unsafe to access self.1 due to #[may_dangle] on A) + fn drop(&mut self) { println!("drop {}", self.0); self.2.foo(self.0); } +} +unsafe impl<'b, #[may_dangle] 'a, B: Foo> Drop for Pr<'a, 'b, B> { + // (unsafe to access self.1 due to #[may_dangle] on 'a) + fn drop(&mut self) { println!("drop {}", self.0); self.2.foo(self.0); } +} + +fn main() { + use std::cell::RefCell; + + impl Foo for RefCell { + fn foo(&self, s: &str) { + let s2 = format!("{}|{}", *self.borrow(), s); + *self.borrow_mut() = s2; + } + } + + impl<'a, T:Foo> Foo for &'a T { + fn foo(&self, s: &str) { + (*self).foo(s); + } + } + + struct CheckOnDrop(RefCell, &'static str); + impl Drop for CheckOnDrop { + fn drop(&mut self) { assert_eq!(*self.0.borrow(), self.1); } + } + + let c_long; + let (c, dt, dr, pt, pr, st, sr) + : (CheckOnDrop, Dt<_>, Dr<_>, Pt<_, _>, Pr<_>, St<_>, Sr<_>); + c_long = CheckOnDrop(RefCell::new("c_long".to_string()), + "c_long|pr|pt|dr|dt"); + c = CheckOnDrop(RefCell::new("c".to_string()), + "c"); + + // No error: sufficiently long-lived state can be referenced in dtors + dt = Dt("dt", &c_long.0); + dr = Dr("dr", &c_long.0); + + // No error: Drop impl asserts .1 (A and &'a _) are not accessed + pt = Pt("pt", &c.0, &c_long.0); + pr = Pr("pr", &c.0, &c_long.0); + + // No error: St and Sr have no destructor. + st = St("st", &c.0); + sr = Sr("sr", &c.0); + + println!("{:?}", (dt.0, dr.0, pt.0, pr.0, st.0, sr.0)); + assert_eq!(*c_long.0.borrow(), "c_long"); + assert_eq!(*c.0.borrow(), "c"); +} From 818ac082d211128d399b51f1466f9fac1bbe4b43 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Mon, 17 Oct 2016 16:17:54 +0200 Subject: [PATCH 26/60] remove fixme that i no longer think appropriate. --- src/librustc_typeck/check/dropck.rs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index 607b32fd14021..03842f3a0a05d 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -510,17 +510,6 @@ enum DropckKind<'tcx> { /// outlive self. /// /// Equivalent to RevisedTy with no change to the self type. - /// - /// FIXME: this name may not be general enough; it should be - /// talking about Phantom lifetimes rather than just borrows. - /// - /// (actually, pnkfelix is not 100% sure that's the right - /// viewpoint. If I'm holding a phantom lifetime just to - /// constrain a reference type that occurs solely in *negative* - /// type positions, then my destructor cannot itself ever actually - /// access such references, right? And don't we end up essentially - /// requring people to put a fake borrow inside a PhantomData in - /// order to make phantom lifetimes work anyway?) BorrowedDataMustStrictlyOutliveSelf, /// The nearly completely-unsafe kind. From 85d2e4d1d6c78f885d010284a439041aa6f2bc80 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Mon, 17 Oct 2016 16:22:24 +0200 Subject: [PATCH 27/60] Review feedback: add linebreak and reindent to make braces match better. --- src/librustc/infer/error_reporting.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/librustc/infer/error_reporting.rs b/src/librustc/infer/error_reporting.rs index f4b19cdc8ad12..ddb43702ef36c 100644 --- a/src/librustc/infer/error_reporting.rs +++ b/src/librustc/infer/error_reporting.rs @@ -1295,9 +1295,10 @@ impl<'a, 'gcx, 'tcx> Rebuilder<'a, 'gcx, 'tcx> { -> hir::Generics { let mut lifetimes = Vec::new(); for lt in add { - lifetimes.push(hir::LifetimeDef { lifetime: *lt, - bounds: hir::HirVec::new(), - pure_wrt_drop: false, + lifetimes.push(hir::LifetimeDef { + lifetime: *lt, + bounds: hir::HirVec::new(), + pure_wrt_drop: false, }); } for lt in &generics.lifetimes { From 0d8f7164bb2a5b949e8b34e8bf08b19eb32b1144 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Mon, 17 Oct 2016 16:22:42 +0200 Subject: [PATCH 28/60] Review feedback: expand comment and simplify some code. --- src/librustc_typeck/check/dropck.rs | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index 03842f3a0a05d..665931ec324ca 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -520,8 +520,9 @@ enum DropckKind<'tcx> { /// Assume all borrowed data access by dtor occurs as if Self has the /// type carried by this variant. In practice this means that some - /// of the type parameters are remapped to `()`, because the developer - /// has asserted that the destructor will not access their contents. + /// of the type parameters are remapped to `()` (and some lifetime + /// parameters remapped to `'static`), because the developer has asserted + /// that the destructor will not access their contents. RevisedSelf(Ty<'tcx>), } @@ -539,13 +540,8 @@ fn has_dtor_of_interest<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, // Find the `impl<..> Drop for _` to inspect any // attributes attached to the impl's generics. - let opt_dtor_method = adt_def.destructor(); - let dtor_method = if let Some(dtor_method) = opt_dtor_method { - dtor_method - } else { - return DropckKind::BorrowedDataMustStrictlyOutliveSelf; - }; - + let dtor_method = adt_def.destructor() + .expect("dtorck type without destructor impossible"); let method = tcx.impl_or_trait_item(dtor_method); let impl_id: DefId = method.container().id(); let revised_ty = revise_self_ty(tcx, adt_def, impl_id, substs); From 4124d8e48b9ffbd9f33819eba74baadf6cfdbe6c Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Mon, 17 Oct 2016 18:02:23 +0200 Subject: [PATCH 29/60] Moved new dropck-eyepatch compile-fail tests to the `ui/` subtree. --- .../auxiliary/dropck_eyepatch_extern_crate.rs | 6 ++- .../dropck}/dropck-eyepatch-extern-crate.rs | 10 ++++ .../dropck-eyepatch-extern-crate.stderr | 46 +++++++++++++++++++ .../dropck-eyepatch-implies-unsafe-impl.rs | 0 ...dropck-eyepatch-implies-unsafe-impl.stderr | 14 ++++++ .../dropck}/dropck-eyepatch-reorder.rs | 0 .../ui/dropck/dropck-eyepatch-reorder.stderr | 46 +++++++++++++++++++ .../dropck}/dropck-eyepatch.rs | 0 src/test/ui/dropck/dropck-eyepatch.stderr | 46 +++++++++++++++++++ 9 files changed, 166 insertions(+), 2 deletions(-) rename src/test/{compile-fail => ui/dropck}/auxiliary/dropck_eyepatch_extern_crate.rs (90%) rename src/test/{compile-fail => ui/dropck}/dropck-eyepatch-extern-crate.rs (77%) create mode 100644 src/test/ui/dropck/dropck-eyepatch-extern-crate.stderr rename src/test/{compile-fail => ui/dropck}/dropck-eyepatch-implies-unsafe-impl.rs (100%) create mode 100644 src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr rename src/test/{compile-fail => ui/dropck}/dropck-eyepatch-reorder.rs (100%) create mode 100644 src/test/ui/dropck/dropck-eyepatch-reorder.stderr rename src/test/{compile-fail => ui/dropck}/dropck-eyepatch.rs (100%) create mode 100644 src/test/ui/dropck/dropck-eyepatch.stderr diff --git a/src/test/compile-fail/auxiliary/dropck_eyepatch_extern_crate.rs b/src/test/ui/dropck/auxiliary/dropck_eyepatch_extern_crate.rs similarity index 90% rename from src/test/compile-fail/auxiliary/dropck_eyepatch_extern_crate.rs rename to src/test/ui/dropck/auxiliary/dropck_eyepatch_extern_crate.rs index 15983ada5ea85..1b00d88dcb3df 100644 --- a/src/test/compile-fail/auxiliary/dropck_eyepatch_extern_crate.rs +++ b/src/test/ui/dropck/auxiliary/dropck_eyepatch_extern_crate.rs @@ -11,14 +11,16 @@ #![feature(generic_param_attrs)] #![feature(dropck_eyepatch)] +// This is a support file for ../dropck-eyepatch-extern-crate.rs +// // The point of this test is to illustrate that the `#[may_dangle]` // attribute specifically allows, in the context of a type // implementing `Drop`, a generic parameter to be instantiated with a // lifetime that does not strictly outlive the owning type itself, -// and that this attributes effects are preserved when importing +// and that this attribute's effects are preserved when importing // the type from another crate. // -// See also dropck-eyepatch.rs for more information about the general +// See also ../dropck-eyepatch.rs for more information about the general // structure of the test. use std::fmt; diff --git a/src/test/compile-fail/dropck-eyepatch-extern-crate.rs b/src/test/ui/dropck/dropck-eyepatch-extern-crate.rs similarity index 77% rename from src/test/compile-fail/dropck-eyepatch-extern-crate.rs rename to src/test/ui/dropck/dropck-eyepatch-extern-crate.rs index 189340992e920..5e200dbdbfa01 100644 --- a/src/test/compile-fail/dropck-eyepatch-extern-crate.rs +++ b/src/test/ui/dropck/dropck-eyepatch-extern-crate.rs @@ -10,6 +10,16 @@ // aux-build:dropck_eyepatch_extern_crate.rs +// The point of this test is to illustrate that the `#[may_dangle]` +// attribute specifically allows, in the context of a type +// implementing `Drop`, a generic parameter to be instantiated with a +// lifetime that does not strictly outlive the owning type itself, +// and that this attribute's effects are preserved when importing +// the type from another crate. +// +// See also dropck-eyepatch.rs for more information about the general +// structure of the test. + extern crate dropck_eyepatch_extern_crate as other; use other::{Dt,Dr,Pt,Pr,St,Sr}; diff --git a/src/test/ui/dropck/dropck-eyepatch-extern-crate.stderr b/src/test/ui/dropck/dropck-eyepatch-extern-crate.stderr new file mode 100644 index 0000000000000..5d2096e8b07a4 --- /dev/null +++ b/src/test/ui/dropck/dropck-eyepatch-extern-crate.stderr @@ -0,0 +1,46 @@ +error: `c` does not live long enough + --> $DIR/dropck-eyepatch-extern-crate.rs:39:20 + | +39 | dt = Dt("dt", &c); //~ ERROR `c` does not live long enough + | ^ does not live long enough +... +55 | } + | - borrowed value dropped before borrower + | + = note: values in a scope are dropped in the opposite order they are created + +error: `c` does not live long enough + --> $DIR/dropck-eyepatch-extern-crate.rs:40:20 + | +40 | dr = Dr("dr", &c); //~ ERROR `c` does not live long enough + | ^ does not live long enough +... +55 | } + | - borrowed value dropped before borrower + | + = note: values in a scope are dropped in the opposite order they are created + +error: `c` does not live long enough + --> $DIR/dropck-eyepatch-extern-crate.rs:47:29 + | +47 | pt = Pt("pt", &c_long, &c); //~ ERROR `c` does not live long enough + | ^ does not live long enough +... +55 | } + | - borrowed value dropped before borrower + | + = note: values in a scope are dropped in the opposite order they are created + +error: `c` does not live long enough + --> $DIR/dropck-eyepatch-extern-crate.rs:48:29 + | +48 | pr = Pr("pr", &c_long, &c); //~ ERROR `c` does not live long enough + | ^ does not live long enough +... +55 | } + | - borrowed value dropped before borrower + | + = note: values in a scope are dropped in the opposite order they are created + +error: aborting due to 4 previous errors + diff --git a/src/test/compile-fail/dropck-eyepatch-implies-unsafe-impl.rs b/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.rs similarity index 100% rename from src/test/compile-fail/dropck-eyepatch-implies-unsafe-impl.rs rename to src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.rs diff --git a/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr b/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr new file mode 100644 index 0000000000000..c53cf020a9bc5 --- /dev/null +++ b/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr @@ -0,0 +1,14 @@ +error[E0569]: requires an `unsafe impl` declaration due to `#[may_dangle]` attribute + --> $DIR/dropck-eyepatch-implies-unsafe-impl.rs:32:1 + | +32 | impl<#[may_dangle] A, B: fmt::Debug> Drop for Pt { + | ^ + +error[E0569]: requires an `unsafe impl` declaration due to `#[may_dangle]` attribute + --> $DIR/dropck-eyepatch-implies-unsafe-impl.rs:38:1 + | +38 | impl<#[may_dangle] 'a, 'b, B: fmt::Debug> Drop for Pr<'a, 'b, B> { + | ^ + +error: aborting due to 2 previous errors + diff --git a/src/test/compile-fail/dropck-eyepatch-reorder.rs b/src/test/ui/dropck/dropck-eyepatch-reorder.rs similarity index 100% rename from src/test/compile-fail/dropck-eyepatch-reorder.rs rename to src/test/ui/dropck/dropck-eyepatch-reorder.rs diff --git a/src/test/ui/dropck/dropck-eyepatch-reorder.stderr b/src/test/ui/dropck/dropck-eyepatch-reorder.stderr new file mode 100644 index 0000000000000..33b18f6f02e0f --- /dev/null +++ b/src/test/ui/dropck/dropck-eyepatch-reorder.stderr @@ -0,0 +1,46 @@ +error: `c` does not live long enough + --> $DIR/dropck-eyepatch-reorder.rs:57:20 + | +57 | dt = Dt("dt", &c); //~ ERROR `c` does not live long enough + | ^ does not live long enough +... +73 | } + | - borrowed value dropped before borrower + | + = note: values in a scope are dropped in the opposite order they are created + +error: `c` does not live long enough + --> $DIR/dropck-eyepatch-reorder.rs:58:20 + | +58 | dr = Dr("dr", &c); //~ ERROR `c` does not live long enough + | ^ does not live long enough +... +73 | } + | - borrowed value dropped before borrower + | + = note: values in a scope are dropped in the opposite order they are created + +error: `c` does not live long enough + --> $DIR/dropck-eyepatch-reorder.rs:65:29 + | +65 | pt = Pt("pt", &c_long, &c); //~ ERROR `c` does not live long enough + | ^ does not live long enough +... +73 | } + | - borrowed value dropped before borrower + | + = note: values in a scope are dropped in the opposite order they are created + +error: `c` does not live long enough + --> $DIR/dropck-eyepatch-reorder.rs:66:29 + | +66 | pr = Pr("pr", &c_long, &c); //~ ERROR `c` does not live long enough + | ^ does not live long enough +... +73 | } + | - borrowed value dropped before borrower + | + = note: values in a scope are dropped in the opposite order they are created + +error: aborting due to 4 previous errors + diff --git a/src/test/compile-fail/dropck-eyepatch.rs b/src/test/ui/dropck/dropck-eyepatch.rs similarity index 100% rename from src/test/compile-fail/dropck-eyepatch.rs rename to src/test/ui/dropck/dropck-eyepatch.rs diff --git a/src/test/ui/dropck/dropck-eyepatch.stderr b/src/test/ui/dropck/dropck-eyepatch.stderr new file mode 100644 index 0000000000000..75e612ca9c8f1 --- /dev/null +++ b/src/test/ui/dropck/dropck-eyepatch.stderr @@ -0,0 +1,46 @@ +error: `c` does not live long enough + --> $DIR/dropck-eyepatch.rs:80:20 + | +80 | dt = Dt("dt", &c); //~ ERROR `c` does not live long enough + | ^ does not live long enough +... +96 | } + | - borrowed value dropped before borrower + | + = note: values in a scope are dropped in the opposite order they are created + +error: `c` does not live long enough + --> $DIR/dropck-eyepatch.rs:81:20 + | +81 | dr = Dr("dr", &c); //~ ERROR `c` does not live long enough + | ^ does not live long enough +... +96 | } + | - borrowed value dropped before borrower + | + = note: values in a scope are dropped in the opposite order they are created + +error: `c` does not live long enough + --> $DIR/dropck-eyepatch.rs:88:29 + | +88 | pt = Pt("pt", &c_long, &c); //~ ERROR `c` does not live long enough + | ^ does not live long enough +... +96 | } + | - borrowed value dropped before borrower + | + = note: values in a scope are dropped in the opposite order they are created + +error: `c` does not live long enough + --> $DIR/dropck-eyepatch.rs:89:29 + | +89 | pr = Pr("pr", &c_long, &c); //~ ERROR `c` does not live long enough + | ^ does not live long enough +... +96 | } + | - borrowed value dropped before borrower + | + = note: values in a scope are dropped in the opposite order they are created + +error: aborting due to 4 previous errors + From d07523c716cd384b257baca48046db1264aab7f6 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Fri, 7 Oct 2016 09:13:11 -0400 Subject: [PATCH 30/60] ICH: Use 128-bit Blake2b hash instead of 64-bit SipHash for incr. comp. fingerprints. --- src/librustc_data_structures/blake2b.rs | 286 ++++++++++++++++++ src/librustc_data_structures/lib.rs | 1 + .../calculate_svh/hasher.rs | 42 ++- src/librustc_incremental/calculate_svh/mod.rs | 21 +- src/librustc_incremental/ich/fingerprint.rs | 81 +++++ src/librustc_incremental/ich/mod.rs | 13 + src/librustc_incremental/lib.rs | 1 + src/librustc_incremental/persist/data.rs | 5 +- .../persist/dirty_clean.rs | 9 +- src/librustc_incremental/persist/hash.rs | 20 +- src/librustc_incremental/persist/load.rs | 3 +- src/librustc_incremental/persist/preds.rs | 3 +- src/librustc_incremental/persist/save.rs | 11 +- src/librustc_trans/back/link.rs | 2 +- 14 files changed, 460 insertions(+), 38 deletions(-) create mode 100644 src/librustc_data_structures/blake2b.rs create mode 100644 src/librustc_incremental/ich/fingerprint.rs create mode 100644 src/librustc_incremental/ich/mod.rs diff --git a/src/librustc_data_structures/blake2b.rs b/src/librustc_data_structures/blake2b.rs new file mode 100644 index 0000000000000..996df2e7fcfca --- /dev/null +++ b/src/librustc_data_structures/blake2b.rs @@ -0,0 +1,286 @@ +// 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. + + +// An implementation of the Blake2b cryptographic hash function. +// The implementation closely follows: https://tools.ietf.org/html/rfc7693 +// +// "BLAKE2 is a cryptographic hash function faster than MD5, SHA-1, SHA-2, and +// SHA-3, yet is at least as secure as the latest standard SHA-3." +// according to their own website :) +// +// Indeed this implementation is two to three times as fast as our SHA-256 +// implementation. If you have the luxury of being able to use crates from +// crates.io, you can go there and find still faster implementations. + +pub struct Blake2bCtx { + b: [u8; 128], + h: [u64; 8], + t: [u64; 2], + c: usize, + outlen: usize, +} + +impl ::std::fmt::Debug for Blake2bCtx { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { + write!(fmt, "{:?}", self.h) + } +} + +#[inline(always)] +fn b2b_g(v: &mut [u64; 16], + a: usize, + b: usize, + c: usize, + d: usize, + x: u64, + y: u64) +{ + v[a] = v[a].wrapping_add(v[b]).wrapping_add(x); + v[d] = (v[d] ^ v[a]).rotate_right(32); + v[c] = v[c].wrapping_add(v[d]); + v[b] = (v[b] ^ v[c]).rotate_right(24); + v[a] = v[a].wrapping_add(v[b]).wrapping_add(y); + v[d] = (v[d] ^ v[a]).rotate_right(16); + v[c] = v[c].wrapping_add(v[d]); + v[b] = (v[b] ^ v[c]).rotate_right(63); +} + +// Initialization vector +const BLAKE2B_IV: [u64; 8] = [ + 0x6A09E667F3BCC908, 0xBB67AE8584CAA73B, + 0x3C6EF372FE94F82B, 0xA54FF53A5F1D36F1, + 0x510E527FADE682D1, 0x9B05688C2B3E6C1F, + 0x1F83D9ABFB41BD6B, 0x5BE0CD19137E2179 +]; + +fn blake2b_compress(ctx: &mut Blake2bCtx, last: bool) { + + const SIGMA: [[usize; 16]; 12] = [ + [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], + [14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 ], + [11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 ], + [7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 ], + [9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 ], + [2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 ], + [12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 ], + [13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 ], + [6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 ], + [10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 ], + [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], + [14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 ] + ]; + + let mut v: [u64; 16] = [ + ctx.h[0], + ctx.h[1], + ctx.h[2], + ctx.h[3], + ctx.h[4], + ctx.h[5], + ctx.h[6], + ctx.h[7], + + BLAKE2B_IV[0], + BLAKE2B_IV[1], + BLAKE2B_IV[2], + BLAKE2B_IV[3], + BLAKE2B_IV[4], + BLAKE2B_IV[5], + BLAKE2B_IV[6], + BLAKE2B_IV[7], + ]; + + v[12] ^= ctx.t[0]; // low 64 bits of offset + v[13] ^= ctx.t[1]; // high 64 bits + if last { + v[14] = !v[14]; + } + + { + // Re-interpret the input buffer in the state as u64s + let m: &mut [u64; 16] = unsafe { + let b: &mut [u8; 128] = &mut ctx.b; + ::std::mem::transmute(b) + }; + + // It's OK to modify the buffer in place since this is the last time + // this data will be accessed before it's overwritten + if cfg!(target_endian = "big") { + for word in &mut m[..] { + *word = word.to_be(); + } + } + + for i in 0 .. 12 { + b2b_g(&mut v, 0, 4, 8, 12, m[SIGMA[i][ 0]], m[SIGMA[i][ 1]]); + b2b_g(&mut v, 1, 5, 9, 13, m[SIGMA[i][ 2]], m[SIGMA[i][ 3]]); + b2b_g(&mut v, 2, 6, 10, 14, m[SIGMA[i][ 4]], m[SIGMA[i][ 5]]); + b2b_g(&mut v, 3, 7, 11, 15, m[SIGMA[i][ 6]], m[SIGMA[i][ 7]]); + b2b_g(&mut v, 0, 5, 10, 15, m[SIGMA[i][ 8]], m[SIGMA[i][ 9]]); + b2b_g(&mut v, 1, 6, 11, 12, m[SIGMA[i][10]], m[SIGMA[i][11]]); + b2b_g(&mut v, 2, 7, 8, 13, m[SIGMA[i][12]], m[SIGMA[i][13]]); + b2b_g(&mut v, 3, 4, 9, 14, m[SIGMA[i][14]], m[SIGMA[i][15]]); + } + } + + for i in 0 .. 8 { + ctx.h[i] ^= v[i] ^ v[i + 8]; + } +} + +pub fn blake2b_new(outlen: usize, key: &[u8]) -> Blake2bCtx { + assert!(outlen > 0 && outlen <= 64 && key.len() <= 64); + + let mut ctx = Blake2bCtx { + b: [0; 128], + h: BLAKE2B_IV, + t: [0; 2], + c: 0, + outlen: outlen, + }; + + ctx.h[0] ^= 0x01010000 ^ ((key.len() << 8) as u64) ^ (outlen as u64); + + if key.len() > 0 { + blake2b_update(&mut ctx, key); + ctx.c = ctx.b.len(); + } + + ctx +} + +pub fn blake2b_update(ctx: &mut Blake2bCtx, mut data: &[u8]) +{ + let mut bytes_to_copy = data.len(); + let mut space_in_buffer = ctx.b.len() - ctx.c; + + while bytes_to_copy > space_in_buffer { + checked_mem_copy(data, &mut ctx.b[ctx.c .. ], space_in_buffer); + + ctx.t[0] = ctx.t[0].wrapping_add(ctx.b.len() as u64); + if ctx.t[0] < (ctx.b.len() as u64) { + ctx.t[1] += 1; + } + blake2b_compress(ctx, false); + ctx.c = 0; + + data = &data[space_in_buffer .. ]; + bytes_to_copy -= space_in_buffer; + space_in_buffer = ctx.b.len(); + } + + if bytes_to_copy > 0 { + checked_mem_copy(data, &mut ctx.b[ctx.c .. ], bytes_to_copy); + ctx.c += bytes_to_copy; + } +} + +pub fn blake2b_final(mut ctx: Blake2bCtx, out: &mut [u8]) +{ + ctx.t[0] = ctx.t[0].wrapping_add(ctx.c as u64); + if ctx.t[0] < ctx.c as u64 { + ctx.t[1] += 1; + } + + while ctx.c < 128 { + ctx.b[ctx.c] = 0; + ctx.c += 1; + } + + blake2b_compress(&mut ctx, true); + + if cfg!(target_endian = "big") { + // Make sure that the data is in memory in little endian format, as is + // demanded by BLAKE2 + for word in &mut ctx.h { + *word = word.to_le(); + } + } + + checked_mem_copy(&ctx.h, out, ctx.outlen); +} + +#[inline(always)] +fn checked_mem_copy(from: &[T1], to: &mut [T2], byte_count: usize) { + let from_size = from.len() * ::std::mem::size_of::(); + let to_size = to.len() * ::std::mem::size_of::(); + assert!(from_size >= byte_count); + assert!(to_size >= byte_count); + let from_byte_ptr = from.as_ptr() as * const u8; + let to_byte_ptr = to.as_mut_ptr() as * mut u8; + unsafe { + ::std::ptr::copy_nonoverlapping(from_byte_ptr, to_byte_ptr, byte_count); + } +} + +pub fn blake2b(out: &mut [u8], key: &[u8], data: &[u8]) +{ + let mut ctx = blake2b_new(out.len(), key); + blake2b_update(&mut ctx, data); + blake2b_final(ctx, out); +} + +#[cfg(test)] +fn selftest_seq(out: &mut [u8], seed: u32) +{ + let mut a: u32 = 0xDEAD4BADu32.wrapping_mul(seed); + let mut b: u32 = 1; + + for i in 0 .. out.len() { + let t: u32 = a.wrapping_add(b); + a = b; + b = t; + out[i] = ((t >> 24) & 0xFF) as u8; + } +} + +#[test] +fn blake2b_selftest() +{ + // grand hash of hash results + const BLAKE2B_RES: [u8; 32] = [ + 0xC2, 0x3A, 0x78, 0x00, 0xD9, 0x81, 0x23, 0xBD, + 0x10, 0xF5, 0x06, 0xC6, 0x1E, 0x29, 0xDA, 0x56, + 0x03, 0xD7, 0x63, 0xB8, 0xBB, 0xAD, 0x2E, 0x73, + 0x7F, 0x5E, 0x76, 0x5A, 0x7B, 0xCC, 0xD4, 0x75 + ]; + + // parameter sets + const B2B_MD_LEN: [usize; 4] = [20, 32, 48, 64]; + const B2B_IN_LEN: [usize; 6] = [0, 3, 128, 129, 255, 1024]; + + let mut data = [0u8; 1024]; + let mut md = [0u8; 64]; + let mut key = [0u8; 64]; + + let mut ctx = blake2b_new(32, &[]); + + for i in 0 .. 4 { + let outlen = B2B_MD_LEN[i]; + for j in 0 .. 6 { + let inlen = B2B_IN_LEN[j]; + + selftest_seq(&mut data[.. inlen], inlen as u32); // unkeyed hash + blake2b(&mut md[.. outlen], &[], &data[.. inlen]); + blake2b_update(&mut ctx, &md[.. outlen]); // hash the hash + + selftest_seq(&mut key[0 .. outlen], outlen as u32); // keyed hash + blake2b(&mut md[.. outlen], &key[.. outlen], &data[.. inlen]); + blake2b_update(&mut ctx, &md[.. outlen]); // hash the hash + } + } + + // compute and compare the hash of hashes + blake2b_final(ctx, &mut md[..]); + for i in 0 .. 32 { + assert_eq!(md[i], BLAKE2B_RES[i]); + } +} diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index c8f4d766153cf..26b9f48ad04dd 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -42,6 +42,7 @@ extern crate serialize as rustc_serialize; // used by deriving extern crate libc; pub mod bitslice; +pub mod blake2b; pub mod bitvec; pub mod graph; pub mod ivar; diff --git a/src/librustc_incremental/calculate_svh/hasher.rs b/src/librustc_incremental/calculate_svh/hasher.rs index 28db39d667c4c..d92a8d375e0d3 100644 --- a/src/librustc_incremental/calculate_svh/hasher.rs +++ b/src/librustc_incremental/calculate_svh/hasher.rs @@ -9,20 +9,20 @@ // except according to those terms. use std::hash::Hasher; -use std::collections::hash_map::DefaultHasher; +use std::mem; +use rustc_data_structures::blake2b; +use ich::Fingerprint; #[derive(Debug)] pub struct IchHasher { - // FIXME: this should use SHA1, not DefaultHasher. DefaultHasher is not - // built to avoid collisions. - state: DefaultHasher, + state: blake2b::Blake2bCtx, bytes_hashed: u64, } impl IchHasher { pub fn new() -> IchHasher { IchHasher { - state: DefaultHasher::new(), + state: blake2b::blake2b_new(mem::size_of::(), &[]), bytes_hashed: 0 } } @@ -30,17 +30,43 @@ impl IchHasher { pub fn bytes_hashed(&self) -> u64 { self.bytes_hashed } + + pub fn finish(self) -> Fingerprint { + let mut fingerprint = Fingerprint::zero(); + blake2b::blake2b_final(self.state, &mut fingerprint.0); + fingerprint + } } impl Hasher for IchHasher { - #[inline] fn finish(&self) -> u64 { - self.state.finish() + bug!("Use other finish() implementation to get the full 128-bit hash."); } #[inline] fn write(&mut self, bytes: &[u8]) { - self.state.write(bytes); + blake2b::blake2b_update(&mut self.state, bytes); self.bytes_hashed += bytes.len() as u64; } + + #[inline] + fn write_u16(&mut self, i: u16) { + self.write(&unsafe { mem::transmute::<_, [u8; 2]>(i.to_le()) }) + } + + #[inline] + fn write_u32(&mut self, i: u32) { + self.write(&unsafe { mem::transmute::<_, [u8; 4]>(i.to_le()) }) + } + + #[inline] + fn write_u64(&mut self, i: u64) { + self.write(&unsafe { mem::transmute::<_, [u8; 8]>(i.to_le()) }) + } + + #[inline] + fn write_usize(&mut self, i: usize) { + // always hash as u64, so we don't depend on the size of `usize` + self.write_u64(i as u64); + } } diff --git a/src/librustc_incremental/calculate_svh/mod.rs b/src/librustc_incremental/calculate_svh/mod.rs index 12627e02debd0..3b0b37bb01ce3 100644 --- a/src/librustc_incremental/calculate_svh/mod.rs +++ b/src/librustc_incremental/calculate_svh/mod.rs @@ -29,7 +29,7 @@ use syntax::ast; use std::cell::RefCell; -use std::hash::{Hash, Hasher}; +use std::hash::Hash; use rustc::dep_graph::DepNode; use rustc::hir; use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId}; @@ -43,21 +43,22 @@ use self::def_path_hash::DefPathHashes; use self::svh_visitor::StrictVersionHashVisitor; use self::caching_codemap_view::CachingCodemapView; use self::hasher::IchHasher; +use ich::Fingerprint; mod def_path_hash; mod svh_visitor; mod caching_codemap_view; -mod hasher; +pub mod hasher; pub struct IncrementalHashesMap { - hashes: FnvHashMap, u64>, + hashes: FnvHashMap, Fingerprint>, // These are the metadata hashes for the current crate as they were stored // during the last compilation session. They are only loaded if // -Z query-dep-graph was specified and are needed for auto-tests using // the #[rustc_metadata_dirty] and #[rustc_metadata_clean] attributes to // check whether some metadata hash has changed in between two revisions. - pub prev_metadata_hashes: RefCell>, + pub prev_metadata_hashes: RefCell>, } impl IncrementalHashesMap { @@ -68,11 +69,12 @@ impl IncrementalHashesMap { } } - pub fn insert(&mut self, k: DepNode, v: u64) -> Option { + pub fn insert(&mut self, k: DepNode, v: Fingerprint) -> Option { self.hashes.insert(k, v) } - pub fn iter<'a>(&'a self) -> ::std::collections::hash_map::Iter<'a, DepNode, u64> { + pub fn iter<'a>(&'a self) + -> ::std::collections::hash_map::Iter<'a, DepNode, Fingerprint> { self.hashes.iter() } @@ -82,9 +84,9 @@ impl IncrementalHashesMap { } impl<'a> ::std::ops::Index<&'a DepNode> for IncrementalHashesMap { - type Output = u64; + type Output = Fingerprint; - fn index(&self, index: &'a DepNode) -> &u64 { + fn index(&self, index: &'a DepNode) -> &Fingerprint { &self.hashes[index] } } @@ -141,12 +143,13 @@ impl<'a, 'tcx> HashItemsVisitor<'a, 'tcx> { &mut self.def_path_hashes, &mut self.codemap, self.hash_spans)); + let bytes_hashed = state.bytes_hashed(); let item_hash = state.finish(); self.hashes.insert(DepNode::Hir(def_id), item_hash); debug!("calculate_item_hash: def_id={:?} hash={:?}", def_id, item_hash); let bytes_hashed = self.tcx.sess.perf_stats.incr_comp_bytes_hashed.get() + - state.bytes_hashed(); + bytes_hashed; self.tcx.sess.perf_stats.incr_comp_bytes_hashed.set(bytes_hashed); } diff --git a/src/librustc_incremental/ich/fingerprint.rs b/src/librustc_incremental/ich/fingerprint.rs new file mode 100644 index 0000000000000..005ac3896ce4c --- /dev/null +++ b/src/librustc_incremental/ich/fingerprint.rs @@ -0,0 +1,81 @@ +// 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. + +use rustc_serialize::{Encodable, Decodable, Encoder, Decoder}; + +const FINGERPRINT_LENGTH: usize = 16; + +#[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Clone, Copy)] +pub struct Fingerprint(pub [u8; FINGERPRINT_LENGTH]); + +impl Fingerprint { + #[inline] + pub fn zero() -> Fingerprint { + Fingerprint([0; FINGERPRINT_LENGTH]) + } + + pub fn from_smaller_hash(hash: u64) -> Fingerprint { + let mut result = Fingerprint::zero(); + result.0[0] = (hash >> 0) as u8; + result.0[1] = (hash >> 8) as u8; + result.0[2] = (hash >> 16) as u8; + result.0[3] = (hash >> 24) as u8; + result.0[4] = (hash >> 32) as u8; + result.0[5] = (hash >> 40) as u8; + result.0[6] = (hash >> 48) as u8; + result.0[7] = (hash >> 56) as u8; + result + } + + pub fn to_smaller_hash(&self) -> u64 { + ((self.0[0] as u64) << 0) | + ((self.0[1] as u64) << 8) | + ((self.0[2] as u64) << 16) | + ((self.0[3] as u64) << 24) | + ((self.0[4] as u64) << 32) | + ((self.0[5] as u64) << 40) | + ((self.0[6] as u64) << 48) | + ((self.0[7] as u64) << 56) + } +} + +impl Encodable for Fingerprint { + #[inline] + fn encode(&self, s: &mut S) -> Result<(), S::Error> { + for &byte in &self.0[..] { + s.emit_u8(byte)?; + } + Ok(()) + } +} + +impl Decodable for Fingerprint { + #[inline] + fn decode(d: &mut D) -> Result { + let mut result = Fingerprint([0u8; FINGERPRINT_LENGTH]); + for byte in &mut result.0[..] { + *byte = d.read_u8()?; + } + Ok(result) + } +} + +impl ::std::fmt::Display for Fingerprint { + fn fmt(&self, formatter: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { + for i in 0 .. self.0.len() { + if i > 0 { + write!(formatter, "::")?; + } + + write!(formatter, "{}", self.0[i])?; + } + Ok(()) + } +} diff --git a/src/librustc_incremental/ich/mod.rs b/src/librustc_incremental/ich/mod.rs new file mode 100644 index 0000000000000..8edd04322d7f6 --- /dev/null +++ b/src/librustc_incremental/ich/mod.rs @@ -0,0 +1,13 @@ +// 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 use self::fingerprint::Fingerprint; + +mod fingerprint; diff --git a/src/librustc_incremental/lib.rs b/src/librustc_incremental/lib.rs index 67104e912f90e..577e50699bffd 100644 --- a/src/librustc_incremental/lib.rs +++ b/src/librustc_incremental/lib.rs @@ -45,6 +45,7 @@ const ATTR_THEN_THIS_WOULD_NEED: &'static str = "rustc_then_this_would_need"; mod assert_dep_graph; mod calculate_svh; mod persist; +pub mod ich; pub use assert_dep_graph::assert_dep_graph; pub use calculate_svh::compute_incremental_hashes_map; diff --git a/src/librustc_incremental/persist/data.rs b/src/librustc_incremental/persist/data.rs index 57e7a0bc21a4e..734ffe6a94412 100644 --- a/src/librustc_incremental/persist/data.rs +++ b/src/librustc_incremental/persist/data.rs @@ -14,6 +14,7 @@ use rustc::dep_graph::{DepNode, WorkProduct, WorkProductId}; use rustc::hir::def_id::DefIndex; use std::sync::Arc; use rustc_data_structures::fnv::FnvHashMap; +use ich::Fingerprint; use super::directory::DefPathIndex; @@ -60,7 +61,7 @@ pub struct SerializedHash { /// the hash as of previous compilation, computed by code in /// `hash` module - pub hash: u64, + pub hash: Fingerprint, } #[derive(Debug, RustcEncodable, RustcDecodable)] @@ -116,5 +117,5 @@ pub struct SerializedMetadataHash { pub def_index: DefIndex, /// the hash itself, computed by `calculate_item_hash` - pub hash: u64, + pub hash: Fingerprint, } diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs index 95452021d8784..0418148ffc7df 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -51,6 +51,7 @@ use rustc_data_structures::fnv::{FnvHashSet, FnvHashMap}; use syntax::parse::token::InternedString; use syntax_pos::Span; use rustc::ty::TyCtxt; +use ich::Fingerprint; use {ATTR_DIRTY, ATTR_CLEAN, ATTR_DIRTY_METADATA, ATTR_CLEAN_METADATA}; @@ -186,8 +187,8 @@ impl<'a, 'tcx> Visitor<'tcx> for DirtyCleanVisitor<'a, 'tcx> { } pub fn check_dirty_clean_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - prev_metadata_hashes: &FnvHashMap, - current_metadata_hashes: &FnvHashMap) { + prev_metadata_hashes: &FnvHashMap, + current_metadata_hashes: &FnvHashMap) { if !tcx.sess.opts.debugging_opts.query_dep_graph { return; } @@ -204,8 +205,8 @@ pub fn check_dirty_clean_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pub struct DirtyCleanMetadataVisitor<'a, 'tcx:'a, 'm> { tcx: TyCtxt<'a, 'tcx, 'tcx>, - prev_metadata_hashes: &'m FnvHashMap, - current_metadata_hashes: &'m FnvHashMap, + prev_metadata_hashes: &'m FnvHashMap, + current_metadata_hashes: &'m FnvHashMap, } impl<'a, 'tcx, 'm> Visitor<'tcx> for DirtyCleanMetadataVisitor<'a, 'tcx, 'm> { diff --git a/src/librustc_incremental/persist/hash.rs b/src/librustc_incremental/persist/hash.rs index ca173db15fcac..e365cbbd3a9a1 100644 --- a/src/librustc_incremental/persist/hash.rs +++ b/src/librustc_incremental/persist/hash.rs @@ -18,6 +18,7 @@ use rustc_serialize::Decodable; use rustc_serialize::opaque::Decoder; use IncrementalHashesMap; +use ich::Fingerprint; use super::data::*; use super::fs::*; use super::file_format; @@ -25,7 +26,7 @@ use super::file_format; pub struct HashContext<'a, 'tcx: 'a> { pub tcx: TyCtxt<'a, 'tcx, 'tcx>, incremental_hashes_map: &'a IncrementalHashesMap, - item_metadata_hashes: FnvHashMap, + item_metadata_hashes: FnvHashMap, crate_hashes: FnvHashMap, } @@ -50,7 +51,7 @@ impl<'a, 'tcx> HashContext<'a, 'tcx> { } } - pub fn hash(&mut self, dep_node: &DepNode) -> Option { + pub fn hash(&mut self, dep_node: &DepNode) -> Option { match *dep_node { DepNode::Krate => { Some(self.incremental_hashes_map[dep_node]) @@ -89,7 +90,7 @@ impl<'a, 'tcx> HashContext<'a, 'tcx> { } } - fn metadata_hash(&mut self, def_id: DefId) -> u64 { + fn metadata_hash(&mut self, def_id: DefId) -> Fingerprint { debug!("metadata_hash(def_id={:?})", def_id); assert!(!def_id.is_local()); @@ -102,14 +103,15 @@ impl<'a, 'tcx> HashContext<'a, 'tcx> { // check whether we did not find detailed metadata for this // krate; in that case, we just use the krate's overall hash - if let Some(&hash) = self.crate_hashes.get(&def_id.krate) { - debug!("metadata_hash: def_id={:?} crate_hash={:?}", def_id, hash); + if let Some(&svh) = self.crate_hashes.get(&def_id.krate) { + debug!("metadata_hash: def_id={:?} crate_hash={:?}", def_id, svh); // micro-"optimization": avoid a cache miss if we ask // for metadata from this particular def-id again. - self.item_metadata_hashes.insert(def_id, hash.as_u64()); + let fingerprint = svh_to_fingerprint(svh); + self.item_metadata_hashes.insert(def_id, fingerprint); - return hash.as_u64(); + return fingerprint; } // otherwise, load the data and repeat. @@ -206,3 +208,7 @@ impl<'a, 'tcx> HashContext<'a, 'tcx> { Ok(()) } } + +fn svh_to_fingerprint(svh: Svh) -> Fingerprint { + Fingerprint::from_smaller_hash(svh.as_u64()) +} diff --git a/src/librustc_incremental/persist/load.rs b/src/librustc_incremental/persist/load.rs index db8d3125e510b..1f43e79ace3ae 100644 --- a/src/librustc_incremental/persist/load.rs +++ b/src/librustc_incremental/persist/load.rs @@ -22,6 +22,7 @@ use std::fs; use std::path::{Path}; use IncrementalHashesMap; +use ich::Fingerprint; use super::data::*; use super::directory::*; use super::dirty_clean; @@ -315,7 +316,7 @@ fn delete_dirty_work_product(tcx: TyCtxt, fn load_prev_metadata_hashes(tcx: TyCtxt, retraced: &RetracedDefIdDirectory, - output: &mut FnvHashMap) { + output: &mut FnvHashMap) { if !tcx.sess.opts.debugging_opts.query_dep_graph { return } diff --git a/src/librustc_incremental/persist/preds.rs b/src/librustc_incremental/persist/preds.rs index af13484e4288d..fe1d627253f28 100644 --- a/src/librustc_incremental/persist/preds.rs +++ b/src/librustc_incremental/persist/preds.rs @@ -14,6 +14,7 @@ use rustc_data_structures::fnv::FnvHashMap; use rustc_data_structures::graph::{DepthFirstTraversal, INCOMING, NodeIndex}; use super::hash::*; +use ich::Fingerprint; /// A data-structure that makes it easy to enumerate the hashable /// predecessors of any given dep-node. @@ -26,7 +27,7 @@ pub struct Predecessors<'query> { // - Keys: some hashable node // - Values: the hash thereof - pub hashes: FnvHashMap<&'query DepNode, u64>, + pub hashes: FnvHashMap<&'query DepNode, Fingerprint>, } impl<'q> Predecessors<'q> { diff --git a/src/librustc_incremental/persist/save.rs b/src/librustc_incremental/persist/save.rs index bc542b71ac670..bc156b0e8913b 100644 --- a/src/librustc_incremental/persist/save.rs +++ b/src/librustc_incremental/persist/save.rs @@ -16,13 +16,13 @@ use rustc::ty::TyCtxt; use rustc_data_structures::fnv::FnvHashMap; use rustc_serialize::Encodable as RustcEncodable; use rustc_serialize::opaque::Encoder; -use std::hash::{Hash, Hasher}; +use std::hash::Hash; use std::io::{self, Cursor, Write}; use std::fs::{self, File}; use std::path::PathBuf; -use std::collections::hash_map::DefaultHasher; use IncrementalHashesMap; +use ich::Fingerprint; use super::data::*; use super::directory::*; use super::hash::*; @@ -30,6 +30,7 @@ use super::preds::*; use super::fs::*; use super::dirty_clean; use super::file_format; +use calculate_svh::hasher::IchHasher; pub fn save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, incremental_hashes_map: &IncrementalHashesMap, @@ -185,7 +186,7 @@ pub fn encode_metadata_hashes(tcx: TyCtxt, svh: Svh, preds: &Predecessors, builder: &mut DefIdDirectoryBuilder, - current_metadata_hashes: &mut FnvHashMap, + current_metadata_hashes: &mut FnvHashMap, encoder: &mut Encoder) -> io::Result<()> { // For each `MetaData(X)` node where `X` is local, accumulate a @@ -233,7 +234,7 @@ pub fn encode_metadata_hashes(tcx: TyCtxt, // is the det. hash of the def-path. This is convenient // because we can sort this to get a stable ordering across // compilations, even if the def-ids themselves have changed. - let mut hashes: Vec<(DepNode, u64)> = sources.iter() + let mut hashes: Vec<(DepNode, Fingerprint)> = sources.iter() .map(|dep_node| { let hash_dep_node = dep_node.map_def(|&def_id| Some(def_id_hash(def_id))).unwrap(); let hash = preds.hashes[dep_node]; @@ -242,7 +243,7 @@ pub fn encode_metadata_hashes(tcx: TyCtxt, .collect(); hashes.sort(); - let mut state = DefaultHasher::new(); + let mut state = IchHasher::new(); hashes.hash(&mut state); let hash = state.finish(); diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index 5a8c5cb4b82c6..e46bdbb5ccf4a 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -130,7 +130,7 @@ pub fn build_link_meta(incremental_hashes_map: &IncrementalHashesMap, -> LinkMeta { let r = LinkMeta { crate_name: name.to_owned(), - crate_hash: Svh::new(incremental_hashes_map[&DepNode::Krate]), + crate_hash: Svh::new(incremental_hashes_map[&DepNode::Krate].to_smaller_hash()), }; info!("{:?}", r); return r; From 0a0efcbebf385d70404425ac9be0d52e933640c5 Mon Sep 17 00:00:00 2001 From: Ulrik Sverdrup Date: Mon, 17 Oct 2016 21:26:29 +0200 Subject: [PATCH 31/60] std::collections: Reexport libcollections's range module This is overdue, even if range and RangeArgument is still unstable. The stability attributes are the same ones as the other unstable item (Bound) here, they don't seem to matter. --- src/libstd/collections/mod.rs | 3 +++ src/libstd/lib.rs | 1 + 2 files changed, 4 insertions(+) diff --git a/src/libstd/collections/mod.rs b/src/libstd/collections/mod.rs index 9b13d54230078..504b3a76bd295 100644 --- a/src/libstd/collections/mod.rs +++ b/src/libstd/collections/mod.rs @@ -425,6 +425,9 @@ pub use self::hash_map::HashMap; #[stable(feature = "rust1", since = "1.0.0")] pub use self::hash_set::HashSet; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core_collections::range; + mod hash; #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index c2f6a6f660c48..71e0ab0388f5b 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -224,6 +224,7 @@ #![feature(char_internals)] #![feature(collections)] #![feature(collections_bound)] +#![feature(collections_range)] #![feature(compiler_builtins_lib)] #![feature(const_fn)] #![feature(core_float)] From 0c844d23046161e831a2c265e5b733674cb89655 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Mon, 17 Oct 2016 21:53:27 +0200 Subject: [PATCH 32/60] Set stalled=false when encountering an error --- src/librustc_data_structures/obligation_forest/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/librustc_data_structures/obligation_forest/mod.rs b/src/librustc_data_structures/obligation_forest/mod.rs index fb2d3291a601b..5e590cb445f79 100644 --- a/src/librustc_data_structures/obligation_forest/mod.rs +++ b/src/librustc_data_structures/obligation_forest/mod.rs @@ -333,6 +333,7 @@ impl ObligationForest { } } Err(err) => { + stalled = false; let backtrace = self.error_at(index); errors.push(Error { error: err, From c560ca4513fbf19c54fcfb7bf15271be41424377 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Mon, 17 Oct 2016 17:47:48 -0400 Subject: [PATCH 33/60] Fix typo --- src/test/incremental/change_private_impl_method/struct_point.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/incremental/change_private_impl_method/struct_point.rs b/src/test/incremental/change_private_impl_method/struct_point.rs index 43be51143d693..8fa34bde17053 100644 --- a/src/test/incremental/change_private_impl_method/struct_point.rs +++ b/src/test/incremental/change_private_impl_method/struct_point.rs @@ -100,7 +100,7 @@ mod fn_read_field { } } -/// A fn item that reads fields from `Point` but does not invoke methods +/// A fn item that writes to a field of `Point` but does not invoke methods mod fn_write_field { use point::Point; From 9578e1a2519e20b61a1ba4a1451229d24c7b37a7 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Sun, 16 Oct 2016 05:19:02 +0000 Subject: [PATCH 34/60] Fix partially consumed tokens in macro matchers. --- src/libsyntax/ext/tt/macro_parser.rs | 21 +++++++++------------ src/libsyntax/ext/tt/transcribe.rs | 5 +++++ src/libsyntax/parse/lexer/mod.rs | 27 ++++++++++++++++++++++++--- 3 files changed, 38 insertions(+), 15 deletions(-) diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index b0696a986e3c0..d7a5d04bda586 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -476,24 +476,21 @@ pub fn parse(sess: &ParseSess, } rdr.next_token(); } else /* bb_eis.len() == 1 */ { - let mut rust_parser = Parser::new(sess, cfg.clone(), Box::new(rdr.clone())); - - let mut ei = bb_eis.pop().unwrap(); - match ei.top_elts.get_tt(ei.idx) { - TokenTree::Token(span, MatchNt(_, ident)) => { + rdr.next_tok = { + let mut rust_parser = Parser::new(sess, cfg.clone(), Box::new(&mut rdr)); + let mut ei = bb_eis.pop().unwrap(); + if let TokenTree::Token(span, MatchNt(_, ident)) = ei.top_elts.get_tt(ei.idx) { let match_cur = ei.match_cur; (&mut ei.matches[match_cur]).push(Rc::new(MatchedNonterminal( parse_nt(&mut rust_parser, span, &ident.name.as_str())))); ei.idx += 1; ei.match_cur += 1; + } else { + unreachable!() } - _ => panic!() - } - cur_eis.push(ei); - - for _ in 0..rust_parser.tokens_consumed { - let _ = rdr.next_token(); - } + cur_eis.push(ei); + Some(TokenAndSpan { tok: rust_parser.token, sp: rust_parser.span }) + }; } } diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index 939425378def6..205c709d6cb40 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -48,6 +48,7 @@ pub struct TtReader<'a> { /* cached: */ pub cur_tok: Token, pub cur_span: Span, + pub next_tok: Option, /// Transform doc comments. Only useful in macro invocations pub desugar_doc_comments: bool, pub fatal_errs: Vec>, @@ -100,6 +101,7 @@ pub fn new_tt_reader_with_doc_flag(sp_diag: &Handler, /* dummy values, never read: */ cur_tok: token::Eof, cur_span: DUMMY_SP, + next_tok: None, fatal_errs: Vec::new(), }; tt_next_token(&mut r); /* get cur_tok and cur_span set up */ @@ -178,6 +180,9 @@ fn lockstep_iter_size(t: &TokenTree, r: &TtReader) -> LockstepIterSize { /// Return the next token from the TtReader. /// EFFECT: advances the reader's token field pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan { + if let Some(tok) = r.next_tok.take() { + return tok; + } // FIXME(pcwalton): Bad copy? let ret_val = TokenAndSpan { tok: r.cur_tok.clone(), diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index 0ba2db3310cda..6dd45a08785af 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -144,7 +144,7 @@ impl<'a> Reader for StringReader<'a> { impl<'a> Reader for TtReader<'a> { fn is_eof(&self) -> bool { - self.cur_tok == token::Eof + self.peek().tok == token::Eof } fn try_next_token(&mut self) -> Result { assert!(self.fatal_errs.is_empty()); @@ -165,10 +165,31 @@ impl<'a> Reader for TtReader<'a> { self.fatal_errs.clear(); } fn peek(&self) -> TokenAndSpan { - TokenAndSpan { + self.next_tok.clone().unwrap_or(TokenAndSpan { tok: self.cur_tok.clone(), sp: self.cur_span, - } + }) + } +} + +impl<'a, 'b> Reader for &'b mut TtReader<'a> { + fn is_eof(&self) -> bool { + (**self).is_eof() + } + fn try_next_token(&mut self) -> Result { + (**self).try_next_token() + } + fn fatal(&self, m: &str) -> FatalError { + (**self).fatal(m) + } + fn err(&self, m: &str) { + (**self).err(m) + } + fn emit_fatal_errors(&mut self) { + (**self).emit_fatal_errors() + } + fn peek(&self) -> TokenAndSpan { + (**self).peek() } } From 95a9e2a724019c11c9b69a45e7953f8ba1225df9 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Sun, 16 Oct 2016 09:13:15 +0000 Subject: [PATCH 35/60] Add regression test. --- src/test/run-pass/issue-37175.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 src/test/run-pass/issue-37175.rs diff --git a/src/test/run-pass/issue-37175.rs b/src/test/run-pass/issue-37175.rs new file mode 100644 index 0000000000000..0d3613b573e12 --- /dev/null +++ b/src/test/run-pass/issue-37175.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. + +macro_rules! m { (<$t:ty>) => { stringify!($t) } } +fn main() { + println!("{}", m!(>)); +} From a29b50303325cab60a6e4db0cbba434b2fe243a2 Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Mon, 17 Oct 2016 17:49:07 -0700 Subject: [PATCH 36/60] Add stable example to TypeId --- src/libcore/any.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/libcore/any.rs b/src/libcore/any.rs index f7edcb998a927..eb0636e8576be 100644 --- a/src/libcore/any.rs +++ b/src/libcore/any.rs @@ -351,12 +351,10 @@ impl TypeId { /// # Examples /// /// ``` - /// #![feature(get_type_id)] - /// /// use std::any::{Any, TypeId}; /// - /// fn is_string(s: &Any) -> bool { - /// TypeId::of::() == s.get_type_id() + /// fn is_string(_s: &T) -> bool { + /// TypeId::of::() == TypeId::of::() /// } /// /// fn main() { From 1e7cd5edcca6598720e6a6cb7b7a2c103018028d Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Mon, 17 Oct 2016 19:00:20 -0700 Subject: [PATCH 37/60] prefer `if let` to match with `None => { }` arm in some places In #34268 (8531d581), we replaced matches of None to the unit value `()` with `if let`s in places where it was deemed that this made the code unambiguously clearer and more idiomatic. In #34638 (d37edef9), we did the same for matches of None to the empty block `{}`. A casual observer, upon seeing these commits fly by, might suppose that the matter was then settled, that no further pull requests on this utterly trivial point of style could or would be made. Unless ... It turns out that sometimes people write the empty block with a space in between the braces. Who knew? --- src/librustc/infer/freshen.rs | 5 +- src/librustc/middle/region.rs | 37 ++---- src/librustc/traits/project.rs | 5 +- src/librustc/traits/select.rs | 13 +- src/librustc_borrowck/borrowck/check_loans.rs | 112 ++++++++---------- src/librustc_trans/callee.rs | 5 +- src/librustc_trans/meth.rs | 5 +- src/librustc_typeck/astconv.rs | 5 +- src/librustc_typeck/check/mod.rs | 24 ++-- src/librustc_typeck/collect.rs | 11 +- src/libsyntax/print/pprust.rs | 11 +- 11 files changed, 97 insertions(+), 136 deletions(-) diff --git a/src/librustc/infer/freshen.rs b/src/librustc/infer/freshen.rs index eea12b7f19712..828f9f32baac8 100644 --- a/src/librustc/infer/freshen.rs +++ b/src/librustc/infer/freshen.rs @@ -61,9 +61,8 @@ impl<'a, 'gcx, 'tcx> TypeFreshener<'a, 'gcx, 'tcx> { -> Ty<'tcx> where F: FnOnce(u32) -> ty::InferTy, { - match opt_ty { - Some(ty) => { return ty.fold_with(self); } - None => { } + if let Some(ty) = opt_ty { + return ty.fold_with(self); } match self.freshen_map.entry(key) { diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 90b6cbad3d9ae..30b735b9c24e3 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -478,12 +478,9 @@ impl RegionMaps { //! Returns the scope when temp created by expr_id will be cleaned up // check for a designated rvalue scope - match self.rvalue_scopes.borrow().get(&expr_id) { - Some(&s) => { - debug!("temporary_scope({:?}) = {:?} [custom]", expr_id, s); - return Some(s); - } - None => { } + if let Some(&s) = self.rvalue_scopes.borrow().get(&expr_id) { + debug!("temporary_scope({:?}) = {:?} [custom]", expr_id, s); + return Some(s); } let scope_map : &[CodeExtent] = &self.scope_map.borrow(); @@ -928,19 +925,15 @@ fn resolve_local(visitor: &mut RegionResolutionVisitor, local: &hir::Local) { // // FIXME(#6308) -- Note that `[]` patterns work more smoothly post-DST. - match local.init { - Some(ref expr) => { - record_rvalue_scope_if_borrow_expr(visitor, &expr, blk_scope); + if let Some(ref expr) = local.init { + record_rvalue_scope_if_borrow_expr(visitor, &expr, blk_scope); - let is_borrow = - if let Some(ref ty) = local.ty { is_borrowed_ty(&ty) } else { false }; + let is_borrow = + if let Some(ref ty) = local.ty { is_borrowed_ty(&ty) } else { false }; - if is_binding_pat(&local.pat) || is_borrow { - record_rvalue_scope(visitor, &expr, blk_scope); - } + if is_binding_pat(&local.pat) || is_borrow { + record_rvalue_scope(visitor, &expr, blk_scope); } - - None => { } } intravisit::walk_local(visitor, local); @@ -1023,16 +1016,12 @@ fn resolve_local(visitor: &mut RegionResolutionVisitor, local: &hir::Local) { record_rvalue_scope_if_borrow_expr(visitor, &subexpr, blk_id) } hir::ExprBlock(ref block) => { - match block.expr { - Some(ref subexpr) => { - record_rvalue_scope_if_borrow_expr( - visitor, &subexpr, blk_id); - } - None => { } + if let Some(ref subexpr) = block.expr { + record_rvalue_scope_if_borrow_expr( + visitor, &subexpr, blk_id); } } - _ => { - } + _ => {} } } diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index ddabc53a89a81..27554c0d2a44d 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -1405,9 +1405,8 @@ impl<'tcx> ProjectionCache<'tcx> { /// cache hit, so it's actually a good thing). fn try_start(&mut self, key: ty::ProjectionTy<'tcx>) -> Result<(), ProjectionCacheEntry<'tcx>> { - match self.map.get(&key) { - Some(entry) => return Err(entry.clone()), - None => { } + if let Some(entry) = self.map.get(&key) { + return Err(entry.clone()); } self.map.insert(key, ProjectionCacheEntry::InProgress); diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index dbaa8db3e8971..f4747b5b108a1 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -788,14 +788,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { stack); assert!(!stack.obligation.predicate.has_escaping_regions()); - match self.check_candidate_cache(&cache_fresh_trait_pred) { - Some(c) => { - debug!("CACHE HIT: SELECT({:?})={:?}", - cache_fresh_trait_pred, - c); - return c; - } - None => { } + if let Some(c) = self.check_candidate_cache(&cache_fresh_trait_pred) { + debug!("CACHE HIT: SELECT({:?})={:?}", + cache_fresh_trait_pred, + c); + return c; } // If no match, compute result and insert into cache. diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs index 089733da536d8..b2032e6a1bf9f 100644 --- a/src/librustc_borrowck/borrowck/check_loans.rs +++ b/src/librustc_borrowck/borrowck/check_loans.rs @@ -135,15 +135,12 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for CheckLoanCtxt<'a, 'tcx> { borrow_id, cmt, loan_region, bk, loan_cause); - match opt_loan_path(&cmt) { - Some(lp) => { - let moved_value_use_kind = match loan_cause { - euv::ClosureCapture(_) => MovedInCapture, - _ => MovedInUse, - }; - self.check_if_path_is_moved(borrow_id, borrow_span, moved_value_use_kind, &lp); - } - None => { } + if let Some(lp) = opt_loan_path(&cmt) { + let moved_value_use_kind = match loan_cause { + euv::ClosureCapture(_) => MovedInCapture, + _ => MovedInUse, + }; + self.check_if_path_is_moved(borrow_id, borrow_span, moved_value_use_kind, &lp); } self.check_for_conflicting_loans(borrow_id); @@ -158,33 +155,29 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for CheckLoanCtxt<'a, 'tcx> { debug!("mutate(assignment_id={}, assignee_cmt={:?})", assignment_id, assignee_cmt); - match opt_loan_path(&assignee_cmt) { - Some(lp) => { - match mode { - MutateMode::Init | MutateMode::JustWrite => { - // In a case like `path = 1`, then path does not - // have to be *FULLY* initialized, but we still - // must be careful lest it contains derefs of - // pointers. - self.check_if_assigned_path_is_moved(assignee_cmt.id, - assignment_span, - MovedInUse, - &lp); - } - MutateMode::WriteAndRead => { - // In a case like `path += 1`, then path must be - // fully initialized, since we will read it before - // we write it. - self.check_if_path_is_moved(assignee_cmt.id, - assignment_span, - MovedInUse, - &lp); - } + if let Some(lp) = opt_loan_path(&assignee_cmt) { + match mode { + MutateMode::Init | MutateMode::JustWrite => { + // In a case like `path = 1`, then path does not + // have to be *FULLY* initialized, but we still + // must be careful lest it contains derefs of + // pointers. + self.check_if_assigned_path_is_moved(assignee_cmt.id, + assignment_span, + MovedInUse, + &lp); + } + MutateMode::WriteAndRead => { + // In a case like `path += 1`, then path must be + // fully initialized, since we will read it before + // we write it. + self.check_if_path_is_moved(assignee_cmt.id, + assignment_span, + MovedInUse, + &lp); } } - None => { } } - self.check_assignment(assignment_id, assignment_span, assignee_cmt); } @@ -601,39 +594,36 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { span: Span, cmt: mc::cmt<'tcx>, mode: euv::ConsumeMode) { - match opt_loan_path(&cmt) { - Some(lp) => { - let moved_value_use_kind = match mode { - euv::Copy => { - self.check_for_copy_of_frozen_path(id, span, &lp); - MovedInUse - } - euv::Move(_) => { - match self.move_data.kind_of_move_of_path(id, &lp) { - None => { - // Sometimes moves don't have a move kind; - // this either means that the original move - // was from something illegal to move, - // or was moved from referent of an unsafe - // pointer or something like that. + if let Some(lp) = opt_loan_path(&cmt) { + let moved_value_use_kind = match mode { + euv::Copy => { + self.check_for_copy_of_frozen_path(id, span, &lp); + MovedInUse + } + euv::Move(_) => { + match self.move_data.kind_of_move_of_path(id, &lp) { + None => { + // Sometimes moves don't have a move kind; + // this either means that the original move + // was from something illegal to move, + // or was moved from referent of an unsafe + // pointer or something like that. + MovedInUse + } + Some(move_kind) => { + self.check_for_move_of_borrowed_path(id, span, + &lp, move_kind); + if move_kind == move_data::Captured { + MovedInCapture + } else { MovedInUse } - Some(move_kind) => { - self.check_for_move_of_borrowed_path(id, span, - &lp, move_kind); - if move_kind == move_data::Captured { - MovedInCapture - } else { - MovedInUse - } - } } } - }; + } + }; - self.check_if_path_is_moved(id, span, moved_value_use_kind, &lp); - } - None => { } + self.check_if_path_is_moved(id, span, moved_value_use_kind, &lp); } } diff --git a/src/librustc_trans/callee.rs b/src/librustc_trans/callee.rs index 05e22896c4006..12d1a28b2ea3e 100644 --- a/src/librustc_trans/callee.rs +++ b/src/librustc_trans/callee.rs @@ -302,9 +302,8 @@ fn trans_fn_pointer_shim<'a, 'tcx>( }; // Check if we already trans'd this shim. - match ccx.fn_pointer_shims().borrow().get(&bare_fn_ty_maybe_ref) { - Some(&llval) => { return llval; } - None => { } + if let Some(&llval) = ccx.fn_pointer_shims().borrow().get(&bare_fn_ty_maybe_ref) { + return llval; } debug!("trans_fn_pointer_shim(bare_fn_ty={:?})", diff --git a/src/librustc_trans/meth.rs b/src/librustc_trans/meth.rs index dac70d4a1de70..1e687f5ff6e3a 100644 --- a/src/librustc_trans/meth.rs +++ b/src/librustc_trans/meth.rs @@ -119,9 +119,8 @@ pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, debug!("get_vtable(trait_ref={:?})", trait_ref); // Check the cache. - match ccx.vtables().borrow().get(&trait_ref) { - Some(&val) => { return val } - None => { } + if let Some(&val) = ccx.vtables().borrow().get(&trait_ref) { + return val; } // Not in the cache. Build it. diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index d58b8f083e248..431aaf99a3e50 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1629,9 +1629,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let tcx = self.tcx(); let cache = self.ast_ty_to_ty_cache(); - match cache.borrow().get(&ast_ty.id) { - Some(ty) => { return ty; } - None => { } + if let Some(ty) = cache.borrow().get(&ast_ty.id) { + return ty; } let result_ty = match ast_ty.node { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 2224b747210a6..f06a48dcf3f0d 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -742,17 +742,14 @@ pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) { hir::ItemImpl(.., ref impl_items) => { debug!("ItemImpl {} with id {}", it.name, it.id); let impl_def_id = ccx.tcx.map.local_def_id(it.id); - match ccx.tcx.impl_trait_ref(impl_def_id) { - Some(impl_trait_ref) => { - check_impl_items_against_trait(ccx, - it.span, - impl_def_id, - &impl_trait_ref, - impl_items); - let trait_def_id = impl_trait_ref.def_id; - check_on_unimplemented(ccx, trait_def_id, it); - } - None => { } + if let Some(impl_trait_ref) = ccx.tcx.impl_trait_ref(impl_def_id) { + check_impl_items_against_trait(ccx, + it.span, + impl_def_id, + &impl_trait_ref, + impl_items); + let trait_def_id = impl_trait_ref.def_id; + check_on_unimplemented(ccx, trait_def_id, it); } } hir::ItemTrait(..) => { @@ -1812,9 +1809,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { f: F) where F: FnOnce(&ty::ItemSubsts<'tcx>), { - match self.tables.borrow().item_substs.get(&id) { - Some(s) => { f(s) } - None => { } + if let Some(s) = self.tables.borrow().item_substs.get(&id) { + f(s); } } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 128db6ef5848a..891098b85f4eb 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -156,13 +156,10 @@ impl<'a,'tcx> CrateCtxt<'a,'tcx> { { { let mut stack = self.stack.borrow_mut(); - match stack.iter().enumerate().rev().find(|&(_, r)| *r == request) { - None => { } - Some((i, _)) => { - let cycle = &stack[i..]; - self.report_cycle(span, cycle); - return Err(ErrorReported); - } + if let Some((i, _)) = stack.iter().enumerate().rev().find(|&(_, r)| *r == request) { + let cycle = &stack[i..]; + self.report_cycle(span, cycle); + return Err(ErrorReported); } stack.push(request); } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index ecb437f31a5ad..a6aed0f7178e5 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -2450,13 +2450,10 @@ impl<'a> State<'a> { |s, ty| s.print_type(&ty))); try!(word(&mut self.s, ")")); - match data.output { - None => { } - Some(ref ty) => { - try!(self.space_if_not_bol()); - try!(self.word_space("->")); - try!(self.print_type(&ty)); - } + if let Some(ref ty) = data.output { + try!(self.space_if_not_bol()); + try!(self.word_space("->")); + try!(self.print_type(&ty)); } } } From cde42cd7803308793a9902022413a5e34557f9a9 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 18 Oct 2016 14:46:41 +1100 Subject: [PATCH 38/60] Don't enqueue onto a disabled dep_graph. This commit guards all calls to `DepGraphThreadData::enqueue` with a check to make sure it is enabled. This requires distinguishing between a "fully enabled" and an "enqueue-enabled" graph. This change avoids some useless allocation and vector manipulations when the graph is disabled (i.e. when incremental compilation is off) which improves speed by ~1% on some of the rustc-benchmarks. --- src/librustc/dep_graph/graph.rs | 19 ++++++++----------- src/librustc/dep_graph/raii.rs | 28 ++++++++++++++++++++-------- src/librustc/dep_graph/shadow.rs | 5 +++++ src/librustc/dep_graph/thread.rs | 19 ++++++++++++++----- 4 files changed, 47 insertions(+), 24 deletions(-) diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index c42eeead69ec1..fac3586afc7b9 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -51,22 +51,15 @@ impl DepGraph { } } - /// True if we are actually building a dep-graph. If this returns false, - /// then the other methods on this `DepGraph` will have no net effect. - #[inline] - pub fn enabled(&self) -> bool { - self.data.thread.enabled() - } - pub fn query(&self) -> DepGraphQuery { self.data.thread.query() } - pub fn in_ignore<'graph>(&'graph self) -> raii::IgnoreTask<'graph> { + pub fn in_ignore<'graph>(&'graph self) -> Option> { raii::IgnoreTask::new(&self.data.thread) } - pub fn in_task<'graph>(&'graph self, key: DepNode) -> raii::DepTask<'graph> { + pub fn in_task<'graph>(&'graph self, key: DepNode) -> Option> { raii::DepTask::new(&self.data.thread, key) } @@ -85,11 +78,15 @@ impl DepGraph { } pub fn read(&self, v: DepNode) { - self.data.thread.enqueue(DepMessage::Read(v)); + if self.data.thread.is_enqueue_enabled() { + self.data.thread.enqueue(DepMessage::Read(v)); + } } pub fn write(&self, v: DepNode) { - self.data.thread.enqueue(DepMessage::Write(v)); + if self.data.thread.is_enqueue_enabled() { + self.data.thread.enqueue(DepMessage::Write(v)); + } } /// Indicates that a previous work product exists for `v`. This is diff --git a/src/librustc/dep_graph/raii.rs b/src/librustc/dep_graph/raii.rs index e4f572902f9e5..e39797599acfd 100644 --- a/src/librustc/dep_graph/raii.rs +++ b/src/librustc/dep_graph/raii.rs @@ -19,15 +19,21 @@ pub struct DepTask<'graph> { impl<'graph> DepTask<'graph> { pub fn new(data: &'graph DepGraphThreadData, key: DepNode) - -> DepTask<'graph> { - data.enqueue(DepMessage::PushTask(key.clone())); - DepTask { data: data, key: Some(key) } + -> Option> { + if data.is_enqueue_enabled() { + data.enqueue(DepMessage::PushTask(key.clone())); + Some(DepTask { data: data, key: Some(key) }) + } else { + None + } } } impl<'graph> Drop for DepTask<'graph> { fn drop(&mut self) { - self.data.enqueue(DepMessage::PopTask(self.key.take().unwrap())); + if self.data.is_enqueue_enabled() { + self.data.enqueue(DepMessage::PopTask(self.key.take().unwrap())); + } } } @@ -36,15 +42,21 @@ pub struct IgnoreTask<'graph> { } impl<'graph> IgnoreTask<'graph> { - pub fn new(data: &'graph DepGraphThreadData) -> IgnoreTask<'graph> { - data.enqueue(DepMessage::PushIgnore); - IgnoreTask { data: data } + pub fn new(data: &'graph DepGraphThreadData) -> Option> { + if data.is_enqueue_enabled() { + data.enqueue(DepMessage::PushIgnore); + Some(IgnoreTask { data: data }) + } else { + None + } } } impl<'graph> Drop for IgnoreTask<'graph> { fn drop(&mut self) { - self.data.enqueue(DepMessage::PopIgnore); + if self.data.is_enqueue_enabled() { + self.data.enqueue(DepMessage::PopIgnore); + } } } diff --git a/src/librustc/dep_graph/shadow.rs b/src/librustc/dep_graph/shadow.rs index 72a321425ef06..06def4bf19af3 100644 --- a/src/librustc/dep_graph/shadow.rs +++ b/src/librustc/dep_graph/shadow.rs @@ -64,6 +64,11 @@ impl ShadowGraph { } } + #[inline] + pub fn enabled(&self) -> bool { + ENABLED + } + pub fn enqueue(&self, message: &DepMessage) { if ENABLED { match self.stack.borrow_state() { diff --git a/src/librustc/dep_graph/thread.rs b/src/librustc/dep_graph/thread.rs index 90c42d66b7adf..9f755cf86e4e4 100644 --- a/src/librustc/dep_graph/thread.rs +++ b/src/librustc/dep_graph/thread.rs @@ -88,15 +88,24 @@ impl DepGraphThreadData { } } + /// True if we are actually building the full dep-graph. #[inline] - pub fn enabled(&self) -> bool { + pub fn is_fully_enabled(&self) -> bool { self.enabled } + /// True if (a) we are actually building the full dep-graph, or (b) we are + /// only enqueuing messages in order to sanity-check them (which happens + /// when debug assertions are enabled). + #[inline] + pub fn is_enqueue_enabled(&self) -> bool { + self.is_fully_enabled() || self.shadow_graph.enabled() + } + /// Sends the current batch of messages to the thread. Installs a /// new vector of messages. fn swap(&self) { - assert!(self.enabled, "should never swap if not enabled"); + assert!(self.is_fully_enabled(), "should never swap if not fully enabled"); // should be a buffer waiting for us (though of course we may // have to wait for depgraph thread to finish processing the @@ -112,7 +121,7 @@ impl DepGraphThreadData { } pub fn query(&self) -> DepGraphQuery { - assert!(self.enabled, "cannot query if dep graph construction not enabled"); + assert!(self.is_fully_enabled(), "should never query if not fully enabled"); self.enqueue(DepMessage::Query); self.swap(); self.query_in.recv().unwrap() @@ -122,9 +131,9 @@ impl DepGraphThreadData { /// the buffer is full, this may swap.) #[inline] pub fn enqueue(&self, message: DepMessage) { + assert!(self.is_enqueue_enabled(), "should never enqueue if not enqueue-enabled"); self.shadow_graph.enqueue(&message); - - if self.enabled { + if self.is_fully_enabled() { self.enqueue_enabled(message); } } From 1e4241ab31372c7efb5d59b6b6a6711bcbae0e59 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 12 Oct 2016 16:59:53 +1100 Subject: [PATCH 39/60] Optimize `Substs::super_fold_with`. This speeds up several rustc-benchmarks by 1--4%. --- src/librustc/ty/subst.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index 7d7bbd931225f..6beb2b968e2b5 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -304,8 +304,15 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> { impl<'tcx> TypeFoldable<'tcx> for &'tcx Substs<'tcx> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - let params = self.iter().map(|k| k.fold_with(folder)).collect(); - folder.tcx().mk_substs(params) + let params: Vec<_> = self.iter().map(|k| k.fold_with(folder)).collect(); + + // If folding doesn't change the substs, it's faster to avoid calling + // `mk_substs` and instead reuse the existing substs. + if params[..] == self[..] { + self + } else { + folder.tcx().mk_substs(params) + } } fn fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { From 10a58ac49b7529e39fc2ad823204853f3538d90b Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 18 Oct 2016 14:46:55 +0200 Subject: [PATCH 40/60] Incorporate review feedback: code formatting fixes, expand a comment. --- src/librustc_typeck/check/dropck.rs | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index 665931ec324ca..5e2b49bac1b2f 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -71,7 +71,8 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>( ccx: &CrateCtxt<'a, 'tcx>, drop_impl_did: DefId, drop_impl_ty: Ty<'tcx>, - self_type_did: DefId) -> Result<(), ()> + self_type_did: DefId) + -> Result<(), ()> { let tcx = ccx.tcx; let drop_impl_node_id = tcx.map.as_local_node_id(drop_impl_did).unwrap(); @@ -123,7 +124,9 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'a, 'tcx>( drop_impl_did: DefId, dtor_predicates: &ty::GenericPredicates<'tcx>, self_type_did: DefId, - self_to_impl_substs: &Substs<'tcx>) -> Result<(), ()> { + self_to_impl_substs: &Substs<'tcx>) + -> Result<(), ()> +{ // Here is an example, analogous to that from // `compare_impl_method`. @@ -350,7 +353,8 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'b, 'gcx, 'tcx>( cx: &mut DropckContext<'a, 'b, 'gcx, 'tcx>, context: TypeContext, ty: Ty<'tcx>, - depth: usize) -> Result<(), Error<'tcx>> + depth: usize) + -> Result<(), Error<'tcx>> { let tcx = cx.rcx.tcx; // Issue #22443: Watch out for overflow. While we are careful to @@ -531,7 +535,8 @@ enum DropckKind<'tcx> { /// parameters are re-mapped to `()` to reflect the destructor's /// "purity" with respect to their actual contents. fn has_dtor_of_interest<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, - ty: Ty<'tcx>) -> DropckKind<'tcx> { + ty: Ty<'tcx>) + -> DropckKind<'tcx> { match ty.sty { ty::TyAdt(adt_def, substs) => { if !adt_def.is_dtorck(tcx) { @@ -574,7 +579,8 @@ fn has_dtor_of_interest<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, fn revise_self_ty<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, adt_def: ty::AdtDef<'tcx>, impl_id: DefId, - substs: &Substs<'tcx>) -> Ty<'tcx> { + substs: &Substs<'tcx>) + -> Ty<'tcx> { // Get generics for `impl Drop` to query for `#[may_dangle]` attr. let impl_bindings = tcx.lookup_generics(impl_id); @@ -592,6 +598,14 @@ fn revise_self_ty<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, // Walk `substs` + `self_substs`, build new substs appropriate for // `adt_def`; each non-dangling param reuses entry from `substs`. + // + // Note: The manner we map from a right-hand side (i.e. Region or + // Ty) for a given `def` to generic parameter associated with that + // right-hand side is tightly coupled to `Drop` impl constraints. + // + // E.g. we know such a Ty must be `TyParam`, because a destructor + // for `struct Foo` is defined via `impl Drop for Foo`, + // and never by (for example) `impl Drop for Foo>`. let substs = Substs::for_item( tcx, adt_def.did, From 1cc1dcce7d7e934817c3bf3543ca8e7753960d0b Mon Sep 17 00:00:00 2001 From: Srinivas Reddy Thatiparthy Date: Tue, 18 Oct 2016 23:09:47 +0530 Subject: [PATCH 41/60] run rustfmt on libpanic_unwind --- src/libpanic_unwind/dwarf/eh.rs | 10 +++------- src/libpanic_unwind/emcc.rs | 7 ++----- src/libpanic_unwind/gcc.rs | 21 +++++++++++++-------- src/libpanic_unwind/seh64_gnu.rs | 3 ++- 4 files changed, 20 insertions(+), 21 deletions(-) diff --git a/src/libpanic_unwind/dwarf/eh.rs b/src/libpanic_unwind/dwarf/eh.rs index 2284a9bbb73e1..e7994f4e0ef0a 100644 --- a/src/libpanic_unwind/dwarf/eh.rs +++ b/src/libpanic_unwind/dwarf/eh.rs @@ -116,7 +116,7 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext) -> EHAction { // The "IP" is an index into the call-site table, with two exceptions: // -1 means 'no-action', and 0 means 'terminate'. match ip as isize { - -1 => return EHAction::None, + -1 => return EHAction::None, 0 => return EHAction::Terminate, _ => (), } @@ -182,12 +182,8 @@ unsafe fn read_encoded_pointer(reader: &mut DwarfReader, assert!(context.func_start != 0); context.func_start } - DW_EH_PE_textrel => { - (*context.get_text_start)() - } - DW_EH_PE_datarel => { - (*context.get_data_start)() - } + DW_EH_PE_textrel => (*context.get_text_start)(), + DW_EH_PE_datarel => (*context.get_data_start)(), _ => panic!(), }; diff --git a/src/libpanic_unwind/emcc.rs b/src/libpanic_unwind/emcc.rs index b3ab1117674ca..0e48e37c92358 100644 --- a/src/libpanic_unwind/emcc.rs +++ b/src/libpanic_unwind/emcc.rs @@ -57,13 +57,10 @@ unsafe extern "C" fn rust_eh_personality(version: c_int, exception_object: *mut uw::_Unwind_Exception, context: *mut uw::_Unwind_Context) -> uw::_Unwind_Reason_Code { - __gxx_personality_v0(version, actions, - exception_class, - exception_object, - context) + __gxx_personality_v0(version, actions, exception_class, exception_object, context) } -extern { +extern "C" { fn __cxa_allocate_exception(thrown_size: libc::size_t) -> *mut libc::c_void; fn __cxa_free_exception(thrown_exception: *mut libc::c_void); fn __cxa_throw(thrown_exception: *mut libc::c_void, diff --git a/src/libpanic_unwind/gcc.rs b/src/libpanic_unwind/gcc.rs index b0e05ff205866..f0f19be3366bd 100644 --- a/src/libpanic_unwind/gcc.rs +++ b/src/libpanic_unwind/gcc.rs @@ -156,14 +156,16 @@ unsafe extern "C" fn rust_eh_personality(version: c_int, let eh_action = find_eh_action(context); if actions as i32 & uw::_UA_SEARCH_PHASE as i32 != 0 { match eh_action { - EHAction::None | EHAction::Cleanup(_) => return uw::_URC_CONTINUE_UNWIND, + EHAction::None | + EHAction::Cleanup(_) => return uw::_URC_CONTINUE_UNWIND, EHAction::Catch(_) => return uw::_URC_HANDLER_FOUND, EHAction::Terminate => return uw::_URC_FATAL_PHASE1_ERROR, } } else { match eh_action { EHAction::None => return uw::_URC_CONTINUE_UNWIND, - EHAction::Cleanup(lpad) | EHAction::Catch(lpad) => { + EHAction::Cleanup(lpad) | + EHAction::Catch(lpad) => { uw::_Unwind_SetGR(context, UNWIND_DATA_REG.0, exception_object as uintptr_t); uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, 0); uw::_Unwind_SetIP(context, lpad); @@ -182,7 +184,7 @@ unsafe extern "C" fn rust_eh_personality(version: c_int, unsafe extern "C" fn rust_eh_personality(state: uw::_Unwind_State, exception_object: *mut uw::_Unwind_Exception, context: *mut uw::_Unwind_Context) - -> uw::_Unwind_Reason_Code { + -> uw::_Unwind_Reason_Code { let state = state as c_int; let action = state & uw::_US_ACTION_MASK as c_int; let search_phase = if action == uw::_US_VIRTUAL_UNWIND_FRAME as c_int { @@ -191,7 +193,7 @@ unsafe extern "C" fn rust_eh_personality(state: uw::_Unwind_State, // we want to continue unwinding the stack, otherwise all our backtraces // would end at __rust_try if state & uw::_US_FORCE_UNWIND as c_int != 0 { - return continue_unwind(exception_object, context) + return continue_unwind(exception_object, context); } true } else if action == uw::_US_UNWIND_FRAME_STARTING as c_int { @@ -207,7 +209,9 @@ unsafe extern "C" fn rust_eh_personality(state: uw::_Unwind_State, // To preserve signatures of functions like _Unwind_GetLanguageSpecificData(), which // take only the context pointer, GCC personality routines stash a pointer to exception_object // in the context, using location reserved for ARM's "scratch register" (r12). - uw::_Unwind_SetGR(context, uw::UNWIND_POINTER_REG, exception_object as uw::_Unwind_Ptr); + uw::_Unwind_SetGR(context, + uw::UNWIND_POINTER_REG, + exception_object as uw::_Unwind_Ptr); // ...A more principled approach would be to provide the full definition of ARM's // _Unwind_Context in our libunwind bindings and fetch the required data from there directly, // bypassing DWARF compatibility functions. @@ -223,7 +227,8 @@ unsafe extern "C" fn rust_eh_personality(state: uw::_Unwind_State, } else { match eh_action { EHAction::None => return continue_unwind(exception_object, context), - EHAction::Cleanup(lpad) | EHAction::Catch(lpad) => { + EHAction::Cleanup(lpad) | + EHAction::Catch(lpad) => { uw::_Unwind_SetGR(context, UNWIND_DATA_REG.0, exception_object as uintptr_t); uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, 0); uw::_Unwind_SetIP(context, lpad); @@ -247,8 +252,8 @@ unsafe extern "C" fn rust_eh_personality(state: uw::_Unwind_State, // defined in libgcc extern "C" { fn __gnu_unwind_frame(exception_object: *mut uw::_Unwind_Exception, - context: *mut uw::_Unwind_Context) - -> uw::_Unwind_Reason_Code; + context: *mut uw::_Unwind_Context) + -> uw::_Unwind_Reason_Code; } } diff --git a/src/libpanic_unwind/seh64_gnu.rs b/src/libpanic_unwind/seh64_gnu.rs index e6d3920b29cb0..d4906b556b31a 100644 --- a/src/libpanic_unwind/seh64_gnu.rs +++ b/src/libpanic_unwind/seh64_gnu.rs @@ -129,7 +129,8 @@ unsafe fn find_landing_pad(dc: &c::DISPATCHER_CONTEXT) -> Option { }; match find_eh_action(dc.HandlerData, &eh_ctx) { EHAction::None => None, - EHAction::Cleanup(lpad) | EHAction::Catch(lpad) => Some(lpad), + EHAction::Cleanup(lpad) | + EHAction::Catch(lpad) => Some(lpad), EHAction::Terminate => intrinsics::abort(), } } From b2606173450b7842a59b23f8167eb6832d9c3305 Mon Sep 17 00:00:00 2001 From: Srinivas Reddy Thatiparthy Date: Tue, 18 Oct 2016 23:13:02 +0530 Subject: [PATCH 42/60] run rustfmt on librustc_errors folder --- src/librustc_errors/emitter.rs | 174 +++++++++++++-------------- src/librustc_errors/lib.rs | 150 +++++++++++------------ src/librustc_errors/lock.rs | 15 ++- src/librustc_errors/registry.rs | 2 +- src/librustc_errors/snippet.rs | 6 +- src/librustc_errors/styled_buffer.rs | 7 +- 6 files changed, 173 insertions(+), 181 deletions(-) diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 1d7ff45b3b8a0..a307e9b696def 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -51,8 +51,8 @@ impl ColorConfig { fn use_color(&self) -> bool { match *self { ColorConfig::Always => true, - ColorConfig::Never => false, - ColorConfig::Auto => stderr_isatty(), + ColorConfig::Never => false, + ColorConfig::Auto => stderr_isatty(), } } } @@ -83,22 +83,22 @@ macro_rules! println_maybe_styled { } impl EmitterWriter { - pub fn stderr(color_config: ColorConfig, - code_map: Option>) - -> EmitterWriter { + pub fn stderr(color_config: ColorConfig, code_map: Option>) -> EmitterWriter { if color_config.use_color() { let dst = Destination::from_stderr(); - EmitterWriter { dst: dst, - cm: code_map} + EmitterWriter { + dst: dst, + cm: code_map, + } } else { - EmitterWriter { dst: Raw(Box::new(io::stderr())), - cm: code_map} + EmitterWriter { + dst: Raw(Box::new(io::stderr())), + cm: code_map, + } } } - pub fn new(dst: Box, - code_map: Option>) - -> EmitterWriter { + pub fn new(dst: Box, code_map: Option>) -> EmitterWriter { EmitterWriter { dst: Raw(dst), cm: code_map, @@ -107,9 +107,9 @@ impl EmitterWriter { fn preprocess_annotations(&self, msp: &MultiSpan) -> Vec { fn add_annotation_to_file(file_vec: &mut Vec, - file: Rc, - line_index: usize, - ann: Annotation) { + file: Rc, + line_index: usize, + ann: Annotation) { for slot in file_vec.iter_mut() { // Look through each of our files for the one we're adding to @@ -168,15 +168,15 @@ impl EmitterWriter { } add_annotation_to_file(&mut output, - lo.file, - lo.line, - Annotation { - start_col: lo.col.0, - end_col: hi.col.0, - is_primary: span_label.is_primary, - is_minimized: is_minimized, - label: span_label.label.clone(), - }); + lo.file, + lo.line, + Annotation { + start_col: lo.col.0, + end_col: hi.col.0, + is_primary: span_label.is_primary, + is_minimized: is_minimized, + label: span_label.label.clone(), + }); } } output @@ -237,9 +237,7 @@ impl EmitterWriter { '^', Style::UnderlinePrimary); if !annotation.is_minimized { - buffer.set_style(line_offset, - width_offset + p, - Style::UnderlinePrimary); + buffer.set_style(line_offset, width_offset + p, Style::UnderlinePrimary); } } else { buffer.putc(line_offset + 1, @@ -247,9 +245,7 @@ impl EmitterWriter { '-', Style::UnderlineSecondary); if !annotation.is_minimized { - buffer.set_style(line_offset, - width_offset + p, - Style::UnderlineSecondary); + buffer.set_style(line_offset, width_offset + p, Style::UnderlineSecondary); } } } @@ -429,8 +425,7 @@ impl EmitterWriter { } // Check to make sure we're not in any <*macros> if !cm.span_to_filename(def_site).contains("macros>") && - !trace.macro_decl_name.starts_with("#[") - { + !trace.macro_decl_name.starts_with("#[") { new_labels.push((trace.call_site, "in this macro invocation".to_string())); break; @@ -475,10 +470,10 @@ impl EmitterWriter { if spans_updated { children.push(SubDiagnostic { level: Level::Note, - message:"this error originates in a macro outside of the current \ - crate".to_string(), + message: "this error originates in a macro outside of the current crate" + .to_string(), span: MultiSpan::new(), - render_span: None + render_span: None, }); } } @@ -502,8 +497,7 @@ impl EmitterWriter { buffer.append(0, &level.to_string(), Style::HeaderMsg); buffer.append(0, ": ", Style::NoStyle); buffer.append(0, msg, Style::NoStyle); - } - else { + } else { buffer.append(0, &level.to_string(), Style::Level(level.clone())); match code { &Some(ref code) => { @@ -522,23 +516,21 @@ impl EmitterWriter { let mut annotated_files = self.preprocess_annotations(msp); // Make sure our primary file comes first - let primary_lo = - if let (Some(ref cm), Some(ref primary_span)) = (self.cm.as_ref(), - msp.primary_span().as_ref()) { - if primary_span != &&DUMMY_SP && primary_span != &&COMMAND_LINE_SP { - cm.lookup_char_pos(primary_span.lo) - } - else { - emit_to_destination(&buffer.render(), level, &mut self.dst)?; - return Ok(()); - } + let primary_lo = if let (Some(ref cm), Some(ref primary_span)) = + (self.cm.as_ref(), msp.primary_span().as_ref()) { + if primary_span != &&DUMMY_SP && primary_span != &&COMMAND_LINE_SP { + cm.lookup_char_pos(primary_span.lo) } else { - // If we don't have span information, emit and exit emit_to_destination(&buffer.render(), level, &mut self.dst)?; return Ok(()); - }; + } + } else { + // If we don't have span information, emit and exit + emit_to_destination(&buffer.render(), level, &mut self.dst)?; + return Ok(()); + }; if let Ok(pos) = - annotated_files.binary_search_by(|x| x.file.name.cmp(&primary_lo.file.name)) { + annotated_files.binary_search_by(|x| x.file.name.cmp(&primary_lo.file.name)) { annotated_files.swap(0, pos); } @@ -554,8 +546,8 @@ impl EmitterWriter { buffer.prepend(buffer_msg_line_offset, "--> ", Style::LineNumber); let loc = primary_lo.clone(); buffer.append(buffer_msg_line_offset, - &format!("{}:{}:{}", loc.file.name, loc.line, loc.col.0 + 1), - Style::LineAndColumn); + &format!("{}:{}:{}", loc.file.name, loc.line, loc.col.0 + 1), + Style::LineAndColumn); for _ in 0..max_line_num_len { buffer.prepend(buffer_msg_line_offset, " ", Style::NoStyle); } @@ -569,8 +561,8 @@ impl EmitterWriter { // Then, the secondary file indicator buffer.prepend(buffer_msg_line_offset + 1, "::: ", Style::LineNumber); buffer.append(buffer_msg_line_offset + 1, - &annotated_file.file.name, - Style::LineAndColumn); + &annotated_file.file.name, + Style::LineAndColumn); for _ in 0..max_line_num_len { buffer.prepend(buffer_msg_line_offset + 1, " ", Style::NoStyle); } @@ -591,7 +583,7 @@ impl EmitterWriter { // this annotated line and the next one if line_idx < (annotated_file.lines.len() - 1) { let line_idx_delta = annotated_file.lines[line_idx + 1].line_index - - annotated_file.lines[line_idx].line_index; + annotated_file.lines[line_idx].line_index; if line_idx_delta > 2 { let last_buffer_line_num = buffer.num_lines(); buffer.puts(last_buffer_line_num, 0, "...", Style::LineNumber); @@ -672,12 +664,7 @@ impl EmitterWriter { let max_line_num = self.get_max_line_num(span, children); let max_line_num_len = max_line_num.to_string().len(); - match self.emit_message_default(span, - message, - code, - level, - max_line_num_len, - false) { + match self.emit_message_default(span, message, code, level, max_line_num_len, false) { Ok(()) => { if !children.is_empty() { let mut buffer = StyledBuffer::new(); @@ -723,13 +710,15 @@ impl EmitterWriter { } } } - Err(e) => panic!("failed to emit error: {}", e) + Err(e) => panic!("failed to emit error: {}", e), } match write!(&mut self.dst, "\n") { Err(e) => panic!("failed to emit error: {}", e), - _ => match self.dst.flush() { - Err(e) => panic!("failed to emit error: {}", e), - _ => () + _ => { + match self.dst.flush() { + Err(e) => panic!("failed to emit error: {}", e), + _ => (), + } } } } @@ -753,8 +742,9 @@ fn overlaps(a1: &Annotation, a2: &Annotation) -> bool { } fn emit_to_destination(rendered_buffer: &Vec>, - lvl: &Level, - dst: &mut Destination) -> io::Result<()> { + lvl: &Level, + dst: &mut Destination) + -> io::Result<()> { use lock; // In order to prevent error message interleaving, where multiple error lines get intermixed @@ -795,8 +785,7 @@ fn stderr_isatty() -> bool { const STD_ERROR_HANDLE: DWORD = -12i32 as DWORD; extern "system" { fn GetStdHandle(which: DWORD) -> HANDLE; - fn GetConsoleMode(hConsoleHandle: HANDLE, - lpMode: *mut DWORD) -> BOOL; + fn GetConsoleMode(hConsoleHandle: HANDLE, lpMode: *mut DWORD) -> BOOL; } unsafe { let handle = GetStdHandle(STD_ERROR_HANDLE); @@ -824,9 +813,7 @@ impl BufferedWriter { // note: we use _new because the conditional compilation at its use site may make this // this function unused on some platforms fn _new() -> BufferedWriter { - BufferedWriter { - buffer: vec![] - } + BufferedWriter { buffer: vec![] } } } @@ -853,35 +840,34 @@ impl Destination { /// When not on Windows, prefer the buffered terminal so that we can buffer an entire error /// to be emitted at one time. fn from_stderr() -> Destination { - let stderr: Option> = + let stderr: Option> = term::TerminfoTerminal::new(BufferedWriter::_new()) .map(|t| Box::new(t) as Box); match stderr { Some(t) => BufferedTerminal(t), - None => Raw(Box::new(io::stderr())), + None => Raw(Box::new(io::stderr())), } } #[cfg(windows)] /// Return a normal, unbuffered terminal when on Windows. fn from_stderr() -> Destination { - let stderr: Option> = - term::TerminfoTerminal::new(io::stderr()) - .map(|t| Box::new(t) as Box) - .or_else(|| term::WinConsole::new(io::stderr()).ok() - .map(|t| Box::new(t) as Box)); + let stderr: Option> = term::TerminfoTerminal::new(io::stderr()) + .map(|t| Box::new(t) as Box) + .or_else(|| { + term::WinConsole::new(io::stderr()) + .ok() + .map(|t| Box::new(t) as Box) + }); match stderr { Some(t) => Terminal(t), - None => Raw(Box::new(io::stderr())), + None => Raw(Box::new(io::stderr())), } } - fn apply_style(&mut self, - lvl: Level, - style: Style) - -> io::Result<()> { + fn apply_style(&mut self, lvl: Level, style: Style) -> io::Result<()> { match style { Style::FileNameStyle | Style::LineAndColumn => {} Style::LineNumber => { @@ -931,18 +917,26 @@ impl Destination { fn start_attr(&mut self, attr: term::Attr) -> io::Result<()> { match *self { - Terminal(ref mut t) => { t.attr(attr)?; } - BufferedTerminal(ref mut t) => { t.attr(attr)?; } - Raw(_) => { } + Terminal(ref mut t) => { + t.attr(attr)?; + } + BufferedTerminal(ref mut t) => { + t.attr(attr)?; + } + Raw(_) => {} } Ok(()) } fn reset_attrs(&mut self) -> io::Result<()> { match *self { - Terminal(ref mut t) => { t.reset()?; } - BufferedTerminal(ref mut t) => { t.reset()?; } - Raw(_) => { } + Terminal(ref mut t) => { + t.reset()?; + } + BufferedTerminal(ref mut t) => { + t.reset()?; + } + Raw(_) => {} } Ok(()) } diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index af8ac81b4fbb1..25b314256b092 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -28,8 +28,10 @@ extern crate serialize; extern crate term; -#[macro_use] extern crate log; -#[macro_use] extern crate libc; +#[macro_use] +extern crate log; +#[macro_use] +extern crate libc; extern crate rustc_unicode; extern crate serialize as rustc_serialize; // used by deriving extern crate syntax_pos; @@ -52,8 +54,8 @@ pub mod registry; pub mod styled_buffer; mod lock; -use syntax_pos::{BytePos, Loc, FileLinesResult, FileName, MultiSpan, Span, NO_EXPANSION }; -use syntax_pos::{MacroBacktrace}; +use syntax_pos::{BytePos, Loc, FileLinesResult, FileName, MultiSpan, Span, NO_EXPANSION}; +use syntax_pos::MacroBacktrace; #[derive(Clone)] pub enum RenderSpan { @@ -89,9 +91,11 @@ impl CodeSuggestion { pub fn splice_lines(&self, cm: &CodeMapper) -> String { use syntax_pos::{CharPos, Loc, Pos}; - fn push_trailing(buf: &mut String, line_opt: Option<&str>, - lo: &Loc, hi_opt: Option<&Loc>) { - let (lo, hi_opt) = (lo.col.to_usize(), hi_opt.map(|hi|hi.col.to_usize())); + fn push_trailing(buf: &mut String, + line_opt: Option<&str>, + lo: &Loc, + hi_opt: Option<&Loc>) { + let (lo, hi_opt) = (lo.col.to_usize(), hi_opt.map(|hi| hi.col.to_usize())); if let Some(line) = line_opt { if line.len() > lo { buf.push_str(match hi_opt { @@ -119,7 +123,11 @@ impl CodeSuggestion { // Find the bounding span. let lo = primary_spans.iter().map(|sp| sp.lo).min().unwrap(); let hi = primary_spans.iter().map(|sp| sp.hi).min().unwrap(); - let bounding_span = Span { lo: lo, hi: hi, expn_id: NO_EXPANSION }; + let bounding_span = Span { + lo: lo, + hi: hi, + expn_id: NO_EXPANSION, + }; let lines = cm.span_to_lines(bounding_span).unwrap(); assert!(!lines.lines.is_empty()); @@ -153,7 +161,7 @@ impl CodeSuggestion { } } if let Some(cur_line) = fm.get_line(cur_lo.line - 1) { - buf.push_str(&cur_line[.. cur_lo.col.to_usize()]); + buf.push_str(&cur_line[..cur_lo.col.to_usize()]); } } buf.push_str(substitute); @@ -263,8 +271,7 @@ impl<'a> DiagnosticBuilder<'a> { /// all, and you just supplied a `Span` to create the diagnostic, /// then the snippet will just include that `Span`, which is /// called the primary span. - pub fn span_label(&mut self, span: Span, label: &fmt::Display) - -> &mut DiagnosticBuilder<'a> { + pub fn span_label(&mut self, span: Span, label: &fmt::Display) -> &mut DiagnosticBuilder<'a> { self.span.push_span_label(span, format!("{}", label)); self } @@ -273,8 +280,7 @@ impl<'a> DiagnosticBuilder<'a> { label: &fmt::Display, expected: &fmt::Display, found: &fmt::Display) - -> &mut DiagnosticBuilder<'a> - { + -> &mut DiagnosticBuilder<'a> { self.note_expected_found_extra(label, expected, found, &"", &"") } @@ -284,8 +290,7 @@ impl<'a> DiagnosticBuilder<'a> { found: &fmt::Display, expected_extra: &fmt::Display, found_extra: &fmt::Display) - -> &mut DiagnosticBuilder<'a> - { + -> &mut DiagnosticBuilder<'a> { // For now, just attach these as notes self.note(&format!("expected {} `{}`{}", label, expected, expected_extra)); self.note(&format!(" found {} `{}`{}", label, found, found_extra)); @@ -314,7 +319,7 @@ impl<'a> DiagnosticBuilder<'a> { self.sub(Level::Warning, msg, sp.into(), None); self } - pub fn help(&mut self , msg: &str) -> &mut DiagnosticBuilder<'a> { + pub fn help(&mut self, msg: &str) -> &mut DiagnosticBuilder<'a> { self.sub(Level::Help, msg, MultiSpan::new(), None); self } @@ -333,10 +338,13 @@ impl<'a> DiagnosticBuilder<'a> { msg: &str, suggestion: String) -> &mut DiagnosticBuilder<'a> { - self.sub(Level::Help, msg, MultiSpan::new(), Some(Suggestion(CodeSuggestion { - msp: sp.into(), - substitutes: vec![suggestion], - }))); + self.sub(Level::Help, + msg, + MultiSpan::new(), + Some(Suggestion(CodeSuggestion { + msp: sp.into(), + substitutes: vec![suggestion], + }))); self } @@ -360,18 +368,17 @@ impl<'a> DiagnosticBuilder<'a> { /// Convenience function for internal use, clients should use one of the /// struct_* methods on Handler. - fn new(handler: &'a Handler, - level: Level, - message: &str) -> DiagnosticBuilder<'a> { + fn new(handler: &'a Handler, level: Level, message: &str) -> DiagnosticBuilder<'a> { DiagnosticBuilder::new_with_code(handler, level, None, message) } /// Convenience function for internal use, clients should use one of the /// struct_* methods on Handler. fn new_with_code(handler: &'a Handler, - level: Level, - code: Option, - message: &str) -> DiagnosticBuilder<'a> { + level: Level, + code: Option, + message: &str) + -> DiagnosticBuilder<'a> { DiagnosticBuilder { handler: handler, level: level, @@ -410,9 +417,8 @@ impl<'a> fmt::Debug for DiagnosticBuilder<'a> { impl<'a> Drop for DiagnosticBuilder<'a> { fn drop(&mut self) { if !panicking() && !self.cancelled() { - let mut db = DiagnosticBuilder::new(self.handler, - Bug, - "Error constructed but not emitted"); + let mut db = + DiagnosticBuilder::new(self.handler, Bug, "Error constructed but not emitted"); db.emit(); panic!(); } @@ -443,7 +449,8 @@ impl Handler { pub fn with_emitter(can_emit_warnings: bool, treat_err_as_bug: bool, - e: Box) -> Handler { + e: Box) + -> Handler { Handler { err_count: Cell::new(0), emitter: RefCell::new(e), @@ -544,10 +551,10 @@ impl Handler { pub fn cancel(&self, err: &mut DiagnosticBuilder) { if err.level == Level::Error || err.level == Level::Fatal { - self.err_count.set( - self.err_count.get().checked_sub(1) - .expect("cancelled an error but err_count is 0") - ); + self.err_count.set(self.err_count + .get() + .checked_sub(1) + .expect("cancelled an error but err_count is 0")); } err.cancel(); } @@ -558,14 +565,16 @@ impl Handler { } } - pub fn span_fatal>(&self, sp: S, msg: &str) - -> FatalError { + pub fn span_fatal>(&self, sp: S, msg: &str) -> FatalError { self.emit(&sp.into(), msg, Fatal); self.bump_err_count(); self.panic_if_treat_err_as_bug(); return FatalError; } - pub fn span_fatal_with_code>(&self, sp: S, msg: &str, code: &str) + pub fn span_fatal_with_code>(&self, + sp: S, + msg: &str, + code: &str) -> FatalError { self.emit_with_code(&sp.into(), msg, code, Fatal); self.bump_err_count(); @@ -619,9 +628,7 @@ impl Handler { if self.treat_err_as_bug { self.bug(msg); } - let mut db = DiagnosticBuilder::new(self, - Fatal, - msg); + let mut db = DiagnosticBuilder::new(self, Fatal, msg); db.emit(); self.bump_err_count(); FatalError @@ -630,28 +637,20 @@ impl Handler { if self.treat_err_as_bug { self.bug(msg); } - let mut db = DiagnosticBuilder::new(self, - Error, - msg); + let mut db = DiagnosticBuilder::new(self, Error, msg); db.emit(); self.bump_err_count(); } pub fn warn(&self, msg: &str) { - let mut db = DiagnosticBuilder::new(self, - Warning, - msg); + let mut db = DiagnosticBuilder::new(self, Warning, msg); db.emit(); } pub fn note_without_error(&self, msg: &str) { - let mut db = DiagnosticBuilder::new(self, - Note, - msg); + let mut db = DiagnosticBuilder::new(self, Note, msg); db.emit(); } pub fn bug(&self, msg: &str) -> ! { - let mut db = DiagnosticBuilder::new(self, - Bug, - msg); + let mut db = DiagnosticBuilder::new(self, Bug, msg); db.emit(); panic!(ExplicitBug); } @@ -678,44 +677,41 @@ impl Handler { match *delayed_bug { Some((ref span, ref errmsg)) => { self.span_bug(span.clone(), errmsg); - }, + } _ => {} } return; } 1 => s = "aborting due to previous error".to_string(), - _ => { - s = format!("aborting due to {} previous errors", - self.err_count.get()); + _ => { + s = format!("aborting due to {} previous errors", self.err_count.get()); } } panic!(self.fatal(&s)); } - pub fn emit(&self, - msp: &MultiSpan, - msg: &str, - lvl: Level) { - if lvl == Warning && !self.can_emit_warnings { return } + pub fn emit(&self, msp: &MultiSpan, msg: &str, lvl: Level) { + if lvl == Warning && !self.can_emit_warnings { + return; + } let mut db = DiagnosticBuilder::new(self, lvl, msg); db.set_span(msp.clone()); db.emit(); - if !self.continue_after_error.get() { self.abort_if_errors(); } - } - pub fn emit_with_code(&self, - msp: &MultiSpan, - msg: &str, - code: &str, - lvl: Level) { - if lvl == Warning && !self.can_emit_warnings { return } - let mut db = DiagnosticBuilder::new_with_code(self, - lvl, - Some(code.to_owned()), - msg); + if !self.continue_after_error.get() { + self.abort_if_errors(); + } + } + pub fn emit_with_code(&self, msp: &MultiSpan, msg: &str, code: &str, lvl: Level) { + if lvl == Warning && !self.can_emit_warnings { + return; + } + let mut db = DiagnosticBuilder::new_with_code(self, lvl, Some(code.to_owned()), msg); db.set_span(msp.clone()); db.emit(); - if !self.continue_after_error.get() { self.abort_if_errors(); } + if !self.continue_after_error.get() { + self.abort_if_errors(); + } } } @@ -750,7 +746,7 @@ impl Level { } else { term::color::YELLOW } - }, + } Note => term::color::BRIGHT_GREEN, Help => term::color::BRIGHT_CYAN, Cancelled => unreachable!(), @@ -769,8 +765,8 @@ impl Level { } } -pub fn expect(diag: &Handler, opt: Option, msg: M) -> T where - M: FnOnce() -> String, +pub fn expect(diag: &Handler, opt: Option, msg: M) -> T + where M: FnOnce() -> String { match opt { Some(t) => t, diff --git a/src/librustc_errors/lock.rs b/src/librustc_errors/lock.rs index 0a9e0c4bbefb3..4c298228c37c7 100644 --- a/src/librustc_errors/lock.rs +++ b/src/librustc_errors/lock.rs @@ -40,9 +40,9 @@ pub fn acquire_global_lock(name: &str) -> Box { extern "system" { fn CreateMutexA(lpMutexAttributes: LPSECURITY_ATTRIBUTES, bInitialOwner: BOOL, - lpName: LPCSTR) -> HANDLE; - fn WaitForSingleObject(hHandle: HANDLE, - dwMilliseconds: DWORD) -> DWORD; + lpName: LPCSTR) + -> HANDLE; + fn WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: DWORD) -> DWORD; fn ReleaseMutex(hMutex: HANDLE) -> BOOL; fn CloseHandle(hObject: HANDLE) -> BOOL; } @@ -76,7 +76,8 @@ pub fn acquire_global_lock(name: &str) -> Box { // open up a handle to one if it already exists. let mutex = CreateMutexA(0 as *mut _, 0, cname.as_ptr() as *const u8); if mutex.is_null() { - panic!("failed to create global mutex named `{}`: {}", name, + panic!("failed to create global mutex named `{}`: {}", + name, io::Error::last_os_error()); } let mutex = Handle(mutex); @@ -96,8 +97,10 @@ pub fn acquire_global_lock(name: &str) -> Box { WAIT_OBJECT_0 | WAIT_ABANDONED => {} code => { panic!("WaitForSingleObject failed on global mutex named \ - `{}`: {} (ret={:x})", name, - io::Error::last_os_error(), code); + `{}`: {} (ret={:x})", + name, + io::Error::last_os_error(), + code); } } diff --git a/src/librustc_errors/registry.rs b/src/librustc_errors/registry.rs index a6cfd1a5a9ac3..83737681471e2 100644 --- a/src/librustc_errors/registry.rs +++ b/src/librustc_errors/registry.rs @@ -12,7 +12,7 @@ use std::collections::HashMap; #[derive(Clone)] pub struct Registry { - descriptions: HashMap<&'static str, &'static str> + descriptions: HashMap<&'static str, &'static str>, } impl Registry { diff --git a/src/librustc_errors/snippet.rs b/src/librustc_errors/snippet.rs index 5ade8cd9bad82..abfb71c861b25 100644 --- a/src/librustc_errors/snippet.rs +++ b/src/librustc_errors/snippet.rs @@ -13,12 +13,12 @@ use syntax_pos::{Span, FileMap}; use CodeMapper; use std::rc::Rc; -use {Level}; +use Level; #[derive(Clone)] pub struct SnippetData { codemap: Rc, - files: Vec + files: Vec, } #[derive(Clone)] @@ -84,4 +84,4 @@ pub enum Style { NoStyle, ErrorCode, Level(Level), -} \ No newline at end of file +} diff --git a/src/librustc_errors/styled_buffer.rs b/src/librustc_errors/styled_buffer.rs index 9768b68619e79..dfc7c64de0197 100644 --- a/src/librustc_errors/styled_buffer.rs +++ b/src/librustc_errors/styled_buffer.rs @@ -28,10 +28,9 @@ impl StyledBuffer { pub fn copy_tabs(&mut self, row: usize) { if row < self.text.len() { - for i in row+1..self.text.len() { + for i in row + 1..self.text.len() { for j in 0..self.text[i].len() { - if self.text[row].len() > j && - self.text[row][j] == '\t' && + if self.text[row].len() > j && self.text[row][j] == '\t' && self.text[i][j] == ' ' { self.text[i][j] = '\t'; } @@ -44,7 +43,7 @@ impl StyledBuffer { let mut output: Vec> = vec![]; let mut styled_vec: Vec = vec![]; - //before we render, do a little patch-up work to support tabs + // before we render, do a little patch-up work to support tabs self.copy_tabs(3); for (row, row_style) in self.text.iter().zip(&self.styles) { From b12f63b17a11520c6d8d358485d85ad99a43bb6f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 18 Oct 2016 20:36:44 +0200 Subject: [PATCH 43/60] Typos in some linkage --- src/libstd/io/mod.rs | 93 +++++++++++++++++++++++++------------------- 1 file changed, 52 insertions(+), 41 deletions(-) diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 14d046ab0520b..37c3f70d54dda 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -1154,10 +1154,7 @@ fn read_until(r: &mut R, delim: u8, buf: &mut Vec) /// /// For example, reading line-by-line is inefficient without using a buffer, so /// if you want to read by line, you'll need `BufRead`, which includes a -/// [`read_line()`][readline] method as well as a [`lines()`][lines] iterator. -/// -/// [readline]: #method.read_line -/// [lines]: #method.lines +/// [`read_line()`] method as well as a [`lines()`] iterator. /// /// # Examples /// @@ -1173,14 +1170,17 @@ fn read_until(r: &mut R, delim: u8, buf: &mut Vec) /// } /// ``` /// -/// If you have something that implements `Read`, you can use the [`BufReader` -/// type][bufreader] to turn it into a `BufRead`. +/// If you have something that implements [`Read`], you can use the [`BufReader` +/// type][`BufReader`] to turn it into a `BufRead`. /// -/// For example, [`File`][file] implements `Read`, but not `BufRead`. -/// `BufReader` to the rescue! +/// For example, [`File`] implements [`Read`], but not `BufRead`. +/// [`BufReader`] to the rescue! /// -/// [bufreader]: struct.BufReader.html -/// [file]: ../fs/struct.File.html +/// [`BufReader`]: struct.BufReader.html +/// [`File`]: ../fs/struct.File.html +/// [`read_line()`]: #method.read_line +/// [`lines()`]: #method.lines +/// [`Read`]: trait.Read.html /// /// ``` /// use std::io::{self, BufReader}; @@ -1204,13 +1204,13 @@ pub trait BufRead: Read { /// Fills the internal buffer of this object, returning the buffer contents. /// /// This function is a lower-level call. It needs to be paired with the - /// [`consume`][consume] method to function properly. When calling this + /// [`consume()`] method to function properly. When calling this /// method, none of the contents will be "read" in the sense that later - /// calling `read` may return the same contents. As such, `consume` must be - /// called with the number of bytes that are consumed from this buffer to + /// calling `read` may return the same contents. As such, [`consume()`] must + /// be called with the number of bytes that are consumed from this buffer to /// ensure that the bytes are never returned twice. /// - /// [consume]: #tymethod.consume + /// [`consume()`]: #tymethod.consume /// /// An empty buffer returned indicates that the stream has reached EOF. /// @@ -1251,21 +1251,21 @@ pub trait BufRead: Read { /// so they should no longer be returned in calls to `read`. /// /// This function is a lower-level call. It needs to be paired with the - /// [`fill_buf`][fillbuf] method to function properly. This function does + /// [`fill_buf()`] method to function properly. This function does /// not perform any I/O, it simply informs this object that some amount of - /// its buffer, returned from `fill_buf`, has been consumed and should no - /// longer be returned. As such, this function may do odd things if - /// `fill_buf` isn't called before calling it. - /// - /// [fillbuf]: #tymethod.fill_buf + /// its buffer, returned from [`fill_buf()`], has been consumed and should + /// no longer be returned. As such, this function may do odd things if + /// [`fill_buf()`] isn't called before calling it. /// /// The `amt` must be `<=` the number of bytes in the buffer returned by - /// `fill_buf`. + /// [`fill_buf()`]. /// /// # Examples /// - /// Since `consume()` is meant to be used with [`fill_buf()`][fillbuf], + /// Since `consume()` is meant to be used with [`fill_buf()`], /// that method's example includes an example of `consume()`. + /// + /// [`fill_buf()`]: #tymethod.fill_buf #[stable(feature = "rust1", since = "1.0.0")] fn consume(&mut self, amt: usize); @@ -1279,8 +1279,8 @@ pub trait BufRead: Read { /// /// # Errors /// - /// This function will ignore all instances of `ErrorKind::Interrupted` and - /// will otherwise return any errors returned by `fill_buf`. + /// This function will ignore all instances of [`ErrorKind::Interrupted`] and + /// will otherwise return any errors returned by [`fill_buf()`]. /// /// If an I/O error is encountered then all bytes read so far will be /// present in `buf` and its length will have been adjusted appropriately. @@ -1290,6 +1290,9 @@ pub trait BufRead: Read { /// A locked standard input implements `BufRead`. In this example, we'll /// read from standard input until we see an `a` byte. /// + /// [`fill_buf()`]: #tymethod.fill_buf + /// [`ErrorKind::Interrupted`]: enum.ErrorKind.html#variant.Interrupted + /// /// ``` /// use std::io; /// use std::io::prelude::*; @@ -1322,19 +1325,20 @@ pub trait BufRead: Read { /// /// # Errors /// - /// This function has the same error semantics as `read_until` and will also - /// return an error if the read bytes are not valid UTF-8. If an I/O error - /// is encountered then `buf` may contain some bytes already read in the - /// event that all data read so far was valid UTF-8. + /// This function has the same error semantics as [`read_until()`] and will + /// also return an error if the read bytes are not valid UTF-8. If an I/O + /// error is encountered then `buf` may contain some bytes already read in + /// the event that all data read so far was valid UTF-8. /// /// # Examples /// /// A locked standard input implements `BufRead`. In this example, we'll /// read all of the lines from standard input. If we were to do this in - /// an actual project, the [`lines()`][lines] method would be easier, of + /// an actual project, the [`lines()`] method would be easier, of /// course. /// - /// [lines]: #method.lines + /// [`lines()`]: #method.lines + /// [`read_until()`]: #method.read_until /// /// ``` /// use std::io; @@ -1363,17 +1367,21 @@ pub trait BufRead: Read { /// `byte`. /// /// The iterator returned from this function will return instances of - /// `io::Result>`. Each vector returned will *not* have the - /// delimiter byte at the end. + /// [`io::Result`]`<`[`Vec`]`>`. Each vector returned will *not* have + /// the delimiter byte at the end. /// - /// This function will yield errors whenever `read_until` would have also - /// yielded an error. + /// This function will yield errors whenever [`read_until()`] would have + /// also yielded an error. /// /// # Examples /// /// A locked standard input implements `BufRead`. In this example, we'll /// read some input from standard input, splitting on commas. /// + /// [`io::Result`]: type.Result.html + /// [`Vec`]: ../vec/struct.Vec.html + /// [`read_until()`]: #method.read_until + /// /// ``` /// use std::io; /// use std::io::prelude::*; @@ -1392,9 +1400,12 @@ pub trait BufRead: Read { /// Returns an iterator over the lines of this reader. /// /// The iterator returned from this function will yield instances of - /// `io::Result`. Each string returned will *not* have a newline + /// [`io::Result`]`<`[`String`]`>`. Each string returned will *not* have a newline /// byte (the 0xA byte) or CRLF (0xD, 0xA bytes) at the end. /// + /// [`io::Result`]: type.Result.html + /// [`String`]: ../string/struct.String.html + /// /// # Examples /// /// A locked standard input implements `BufRead`: @@ -1417,10 +1428,10 @@ pub trait BufRead: Read { /// Adaptor to chain together two readers. /// -/// This struct is generally created by calling [`chain()`][chain] on a reader. -/// Please see the documentation of `chain()` for more details. +/// This struct is generally created by calling [`chain()`] on a reader. +/// Please see the documentation of [`chain()`] for more details. /// -/// [chain]: trait.Read.html#method.chain +/// [`chain()`]: trait.Read.html#method.chain #[stable(feature = "rust1", since = "1.0.0")] pub struct Chain { first: T, @@ -1581,10 +1592,10 @@ fn read_one_byte(reader: &mut Read) -> Option> { /// An iterator over `u8` values of a reader. /// -/// This struct is generally created by calling [`bytes()`][bytes] on a reader. -/// Please see the documentation of `bytes()` for more details. +/// This struct is generally created by calling [`bytes()`] on a reader. +/// Please see the documentation of [`bytes()`] for more details. /// -/// [bytes]: trait.Read.html#method.bytes +/// [`bytes()`]: trait.Read.html#method.bytes #[stable(feature = "rust1", since = "1.0.0")] pub struct Bytes { inner: R, From 4a91a80b26afb23c0f33162acc52605cb9130b3e Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 12 Oct 2016 20:54:41 +0300 Subject: [PATCH 44/60] Fix some pretty printing tests --- src/libsyntax/parse/lexer/comments.rs | 46 ++++++++++++------- src/libsyntax/print/pprust.rs | 33 ++++++------- .../borrowck-use-uninitialized-in-cast.rs | 2 - src/test/compile-fail/coherence-cow.rs | 2 - .../compile-fail/coherence-vec-local-2.rs | 2 - src/test/compile-fail/coherence-vec-local.rs | 2 - src/test/compile-fail/issue-13352.rs | 2 - src/test/compile-fail/issue-19482.rs | 2 - .../meta-expected-error-correct-rev.rs | 1 - .../meta-expected-error-wrong-rev.rs | 1 - ...ct-lifetime-default-from-rptr-box-error.rs | 2 - ...lifetime-default-from-rptr-struct-error.rs | 2 - .../compile-fail/variance-trait-matching.rs | 2 - src/test/pretty/for-comment.rs | 1 - src/test/run-fail/divide-by-zero.rs | 2 - src/test/run-fail/glob-use-std.rs | 4 -- src/test/run-fail/mod-zero.rs | 2 - src/test/run-fail/overflowing-add.rs | 3 -- src/test/run-fail/overflowing-lsh-1.rs | 2 - src/test/run-fail/overflowing-lsh-2.rs | 2 - src/test/run-fail/overflowing-lsh-3.rs | 2 - src/test/run-fail/overflowing-lsh-4.rs | 2 - src/test/run-fail/overflowing-mul.rs | 2 - src/test/run-fail/overflowing-neg.rs | 2 - src/test/run-fail/overflowing-rsh-1.rs | 2 - src/test/run-fail/overflowing-rsh-2.rs | 2 - src/test/run-fail/overflowing-rsh-3.rs | 2 - src/test/run-fail/overflowing-rsh-4.rs | 2 - src/test/run-fail/overflowing-rsh-5.rs | 2 - src/test/run-fail/overflowing-rsh-6.rs | 2 - src/test/run-fail/overflowing-sub.rs | 2 - src/test/run-fail/run-unexported-tests.rs | 1 - src/test/run-fail/test-panic.rs | 1 - .../run-fail/test-should-fail-bad-message.rs | 1 - src/test/run-fail/test-tasks-invalid-value.rs | 1 - .../custom-derive-partial-eq.rs | 2 - src/test/run-pass-fulldeps/issue-16992.rs | 1 - .../issue-18763-quote-token-tree.rs | 2 - .../run-pass-fulldeps/lint-group-plugin.rs | 2 - .../lint-plugin-cmdline-load.rs | 1 - src/test/run-pass-fulldeps/lint-plugin.rs | 2 - src/test/run-pass-fulldeps/quote-tokens.rs | 2 - .../quote-unused-sp-no-warning.rs | 2 - .../run-pass-valgrind/cast-enum-with-dtor.rs | 2 - src/test/run-pass/backtrace-debuginfo.rs | 2 +- src/test/run-pass/backtrace.rs | 1 - .../run-pass/borrowck/borrowck-pat-enum.rs | 2 +- src/test/run-pass/cfg-in-crate-1.rs | 2 - src/test/run-pass/command-exec.rs | 3 +- src/test/run-pass/core-run-destroy.rs | 1 - .../run-pass/deprecated-macro_escape-inner.rs | 2 - src/test/run-pass/deprecated-macro_escape.rs | 2 - .../run-pass/deriving-cmp-generic-enum.rs | 3 -- .../deriving-meta-empty-trait-list.rs | 2 - src/test/run-pass/enum-size-variance.rs | 2 - src/test/run-pass/hygienic-labels-in-let.rs | 2 - src/test/run-pass/ifmt.rs | 2 - src/test/run-pass/imports.rs | 2 - src/test/run-pass/issue-11709.rs | 2 +- src/test/run-pass/issue-15189.rs | 2 - src/test/run-pass/issue-16492.rs | 2 - src/test/run-pass/issue-16597-empty.rs | 1 - src/test/run-pass/issue-16597.rs | 1 - src/test/run-pass/issue-16668.rs | 2 - src/test/run-pass/issue-18464.rs | 2 - src/test/run-pass/issue-20427.rs | 2 +- src/test/run-pass/issue-20823.rs | 1 - src/test/run-pass/issue-22992.rs | 2 +- .../issue-23338-ensure-param-drop-order.rs | 2 +- src/test/run-pass/issue-26873-multifile.rs | 5 +- .../run-pass/issue-27401-dropflag-reinit.rs | 2 +- src/test/run-pass/issue-27639.rs | 2 - src/test/run-pass/issue-28839.rs | 2 +- src/test/run-pass/issue-29740.rs | 2 - src/test/run-pass/issue-34932.rs | 2 - src/test/run-pass/issue-7911.rs | 2 - src/test/run-pass/issue-8460.rs | 2 - src/test/run-pass/issue-9129.rs | 2 +- ...line-endings-string-literal-doc-comment.rs | 2 +- src/test/run-pass/linear-for-loop.rs | 2 - src/test/run-pass/macro-2.rs | 2 - .../run-pass/macro-attribute-expansion.rs | 2 - src/test/run-pass/macro-attributes.rs | 2 - src/test/run-pass/macro-include-items.rs | 2 +- src/test/run-pass/macro-meta-items.rs | 1 - src/test/run-pass/macro-multiple-items.rs | 2 - src/test/run-pass/macro-stmt.rs | 2 - src/test/run-pass/mir_raw_fat_ptr.rs | 2 - src/test/run-pass/mod_dir_implicit.rs | 2 +- src/test/run-pass/mod_dir_path.rs | 2 +- src/test/run-pass/mod_dir_path2.rs | 2 +- src/test/run-pass/mod_dir_path3.rs | 2 +- src/test/run-pass/mod_dir_path_multi.rs | 2 +- src/test/run-pass/mod_dir_recursive.rs | 2 +- src/test/run-pass/mod_dir_simple.rs | 2 +- src/test/run-pass/mod_file.rs | 2 +- src/test/run-pass/mod_file_with_path_attr.rs | 2 +- .../run-pass/numeric-method-autoexport.rs | 2 - .../run-pass/reexport-test-harness-main.rs | 1 - .../regions-bound-lists-feature-gate-2.rs | 2 - .../regions-bound-lists-feature-gate.rs | 2 - src/test/run-pass/shebang.rs | 3 -- .../simd-intrinsic-generic-elements.rs | 2 - src/test/run-pass/super-fast-paren-parsing.rs | 2 - .../run-pass/syntax-extension-source-utils.rs | 11 ++--- src/test/run-pass/task-comm-3.rs | 1 - ...e-verification-for-explicit-return-type.rs | 1 - src/test/run-pass/test-runner-hides-main.rs | 2 - .../run-pass/test-should-fail-good-message.rs | 2 - src/test/run-pass/trait-bounds-in-arc.rs | 2 - .../union/union-with-drop-fields-lint.rs | 2 - 111 files changed, 72 insertions(+), 225 deletions(-) diff --git a/src/libsyntax/parse/lexer/comments.rs b/src/libsyntax/parse/lexer/comments.rs index 38f811d54dab8..ba83a55ea7937 100644 --- a/src/libsyntax/parse/lexer/comments.rs +++ b/src/libsyntax/parse/lexer/comments.rs @@ -24,7 +24,7 @@ use str::char_at; use std::io::Read; use std::usize; -#[derive(Clone, Copy, PartialEq)] +#[derive(Clone, Copy, PartialEq, Debug)] pub enum CommentStyle { /// No code on either side of each line of the comment Isolated, @@ -155,14 +155,13 @@ fn push_blank_line_comment(rdr: &StringReader, comments: &mut Vec) { fn consume_whitespace_counting_blank_lines(rdr: &mut StringReader, comments: &mut Vec) { while is_pattern_whitespace(rdr.ch) && !rdr.is_eof() { - if rdr.col == CharPos(0) && rdr.ch_is('\n') { + if rdr.ch_is('\n') { push_blank_line_comment(rdr, &mut *comments); } rdr.bump(); } } - fn read_shebang_comment(rdr: &mut StringReader, code_to_the_left: bool, comments: &mut Vec) { @@ -317,14 +316,22 @@ fn read_block_comment(rdr: &mut StringReader, } -fn consume_comment(rdr: &mut StringReader, code_to_the_left: bool, comments: &mut Vec) { +fn consume_comment(rdr: &mut StringReader, + comments: &mut Vec, + code_to_the_left: &mut bool, + anything_to_the_left: &mut bool) { debug!(">>> consume comment"); if rdr.ch_is('/') && rdr.nextch_is('/') { - read_line_comments(rdr, code_to_the_left, comments); + read_line_comments(rdr, *code_to_the_left, comments); + *code_to_the_left = false; + *anything_to_the_left = false; } else if rdr.ch_is('/') && rdr.nextch_is('*') { - read_block_comment(rdr, code_to_the_left, comments); + read_block_comment(rdr, *code_to_the_left, comments); + *anything_to_the_left = true; } else if rdr.ch_is('#') && rdr.nextch_is('!') { - read_shebang_comment(rdr, code_to_the_left, comments); + read_shebang_comment(rdr, *code_to_the_left, comments); + *code_to_the_left = false; + *anything_to_the_left = false; } else { panic!(); } @@ -352,23 +359,29 @@ pub fn gather_comments_and_literals(span_diagnostic: &errors::Handler, let mut comments: Vec = Vec::new(); let mut literals: Vec = Vec::new(); - let mut first_read: bool = true; + let mut code_to_the_left = false; // Only code + let mut anything_to_the_left = false; // Code or comments while !rdr.is_eof() { loop { - let mut code_to_the_left = !first_read; + // Eat all the whitespace and count blank lines. rdr.consume_non_eol_whitespace(); if rdr.ch_is('\n') { - code_to_the_left = false; + if anything_to_the_left { + rdr.bump(); // The line is not blank, do not count. + } consume_whitespace_counting_blank_lines(&mut rdr, &mut comments); + code_to_the_left = false; + anything_to_the_left = false; } - while rdr.peeking_at_comment() { - consume_comment(&mut rdr, code_to_the_left, &mut comments); - consume_whitespace_counting_blank_lines(&mut rdr, &mut comments); + // Eat one comment group + if rdr.peeking_at_comment() { + consume_comment(&mut rdr, &mut comments, + &mut code_to_the_left, &mut anything_to_the_left); + } else { + break } - break; } - let bstart = rdr.pos; rdr.next_token(); // discard, and look ahead; we're working with internal state @@ -384,7 +397,8 @@ pub fn gather_comments_and_literals(span_diagnostic: &errors::Handler, } else { debug!("tok: {}", pprust::token_to_string(&tok)); } - first_read = false; + code_to_the_left = true; + anything_to_the_left = true; } (comments, literals) diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index ecb437f31a5ad..c005933d50f05 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -545,15 +545,12 @@ pub trait PrintState<'a> { } fn maybe_print_comment(&mut self, pos: BytePos) -> io::Result<()> { - loop { - match self.next_comment() { - Some(ref cmnt) => { - if (*cmnt).pos < pos { - try!(self.print_comment(cmnt)); - self.cur_cmnt_and_lit().cur_cmnt += 1; - } else { break; } - } - _ => break + while let Some(ref cmnt) = self.next_comment() { + if cmnt.pos < pos { + try!(self.print_comment(cmnt)); + self.cur_cmnt_and_lit().cur_cmnt += 1; + } else { + break } } Ok(()) @@ -581,7 +578,9 @@ pub trait PrintState<'a> { Ok(()) } comments::Trailing => { - try!(word(self.writer(), " ")); + if !self.is_bol() { + try!(word(self.writer(), " ")); + } if cmnt.lines.len() == 1 { try!(word(self.writer(), &cmnt.lines[0])); hardbreak(self.writer()) @@ -1715,6 +1714,7 @@ impl<'a> State<'a> { for (i, st) in blk.stmts.iter().enumerate() { match st.node { ast::StmtKind::Expr(ref expr) if i == blk.stmts.len() - 1 => { + try!(self.maybe_print_comment(st.span.lo)); try!(self.space_if_not_bol()); try!(self.print_expr_outer_attr_style(&expr, false)); try!(self.maybe_print_trailing_comment(expr.span, Some(blk.span.hi))); @@ -2604,6 +2604,7 @@ impl<'a> State<'a> { } try!(self.cbox(INDENT_UNIT)); try!(self.ibox(0)); + try!(self.maybe_print_comment(arm.pats[0].span.lo)); try!(self.print_outer_attributes(&arm.attrs)); let mut first = true; for p in &arm.pats { @@ -3007,15 +3008,11 @@ impl<'a> State<'a> { _ => return Ok(()) }; if let Some(ref cmnt) = self.next_comment() { - if (*cmnt).style != comments::Trailing { return Ok(()) } + if cmnt.style != comments::Trailing { return Ok(()) } let span_line = cm.lookup_char_pos(span.hi); - let comment_line = cm.lookup_char_pos((*cmnt).pos); - let mut next = (*cmnt).pos + BytePos(1); - if let Some(p) = next_pos { - next = p; - } - if span.hi < (*cmnt).pos && (*cmnt).pos < next && - span_line.line == comment_line.line { + let comment_line = cm.lookup_char_pos(cmnt.pos); + let next = next_pos.unwrap_or(cmnt.pos + BytePos(1)); + if span.hi < cmnt.pos && cmnt.pos < next && span_line.line == comment_line.line { self.print_comment(cmnt)?; self.cur_cmnt_and_lit.cur_cmnt += 1; } diff --git a/src/test/compile-fail/borrowck/borrowck-use-uninitialized-in-cast.rs b/src/test/compile-fail/borrowck/borrowck-use-uninitialized-in-cast.rs index a3d5af80b533b..3f429bbd4b634 100644 --- a/src/test/compile-fail/borrowck/borrowck-use-uninitialized-in-cast.rs +++ b/src/test/compile-fail/borrowck/borrowck-use-uninitialized-in-cast.rs @@ -12,8 +12,6 @@ // The problem was specified to casting to `*`, as creating unsafe // pointers was not being fully checked. Issue #20791. -// pretty-expanded FIXME #23616 - fn main() { let x: &i32; let y = x as *const i32; //~ ERROR use of possibly uninitialized variable: `*x` diff --git a/src/test/compile-fail/coherence-cow.rs b/src/test/compile-fail/coherence-cow.rs index 6a2d1bac49381..86ae5b44d9db0 100644 --- a/src/test/compile-fail/coherence-cow.rs +++ b/src/test/compile-fail/coherence-cow.rs @@ -12,8 +12,6 @@ // aux-build:coherence_lib.rs -// pretty-expanded FIXME #23616 - // Test that the `Pair` type reports an error if it contains type // parameters, even when they are covered by local types. This test // was originally intended to test the opposite, but the rules changed diff --git a/src/test/compile-fail/coherence-vec-local-2.rs b/src/test/compile-fail/coherence-vec-local-2.rs index 5f0b56af2c226..196c2f4ee3cd3 100644 --- a/src/test/compile-fail/coherence-vec-local-2.rs +++ b/src/test/compile-fail/coherence-vec-local-2.rs @@ -13,8 +13,6 @@ // aux-build:coherence_lib.rs -// pretty-expanded FIXME #23616 - extern crate coherence_lib as lib; use lib::Remote; diff --git a/src/test/compile-fail/coherence-vec-local.rs b/src/test/compile-fail/coherence-vec-local.rs index c354caac2b5c2..49822dcfcb3f0 100644 --- a/src/test/compile-fail/coherence-vec-local.rs +++ b/src/test/compile-fail/coherence-vec-local.rs @@ -13,8 +13,6 @@ // aux-build:coherence_lib.rs -// pretty-expanded FIXME #23616 - extern crate coherence_lib as lib; use lib::Remote; diff --git a/src/test/compile-fail/issue-13352.rs b/src/test/compile-fail/issue-13352.rs index 13e677d72bc1e..0c446f5fe4703 100644 --- a/src/test/compile-fail/issue-13352.rs +++ b/src/test/compile-fail/issue-13352.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// pretty-expanded FIXME #23616 - fn foo(_: Box) {} fn main() { diff --git a/src/test/compile-fail/issue-19482.rs b/src/test/compile-fail/issue-19482.rs index 21a50f24d5e5c..b54f008f8ce3a 100644 --- a/src/test/compile-fail/issue-19482.rs +++ b/src/test/compile-fail/issue-19482.rs @@ -11,8 +11,6 @@ // Test that a partially specified trait object with unspecified associated // type does not type-check. -// pretty-expanded FIXME #23616 - trait Foo { type A; diff --git a/src/test/compile-fail/meta-expected-error-correct-rev.rs b/src/test/compile-fail/meta-expected-error-correct-rev.rs index 95b4e1a33cccd..bd70879d13e5f 100644 --- a/src/test/compile-fail/meta-expected-error-correct-rev.rs +++ b/src/test/compile-fail/meta-expected-error-correct-rev.rs @@ -9,7 +9,6 @@ // except according to those terms. // revisions: a -// pretty-expanded FIXME #23616 // Counterpart to `meta-expected-error-wrong-rev.rs` diff --git a/src/test/compile-fail/meta-expected-error-wrong-rev.rs b/src/test/compile-fail/meta-expected-error-wrong-rev.rs index 084c6ed4f4b41..3c13050812c93 100644 --- a/src/test/compile-fail/meta-expected-error-wrong-rev.rs +++ b/src/test/compile-fail/meta-expected-error-wrong-rev.rs @@ -10,7 +10,6 @@ // revisions: a // should-fail -// pretty-expanded FIXME #23616 // This is a "meta-test" of the compilertest framework itself. In // particular, it includes the right error message, but the message diff --git a/src/test/compile-fail/object-lifetime-default-from-rptr-box-error.rs b/src/test/compile-fail/object-lifetime-default-from-rptr-box-error.rs index e351c84c8afc6..98301ef1a0a1d 100644 --- a/src/test/compile-fail/object-lifetime-default-from-rptr-box-error.rs +++ b/src/test/compile-fail/object-lifetime-default-from-rptr-box-error.rs @@ -11,8 +11,6 @@ // Test that the lifetime from the enclosing `&` is "inherited" // through the `Box` struct. -// pretty-expanded FIXME #23616 - #![allow(dead_code)] trait Test { diff --git a/src/test/compile-fail/object-lifetime-default-from-rptr-struct-error.rs b/src/test/compile-fail/object-lifetime-default-from-rptr-struct-error.rs index 93268559e8e51..836e4fa114263 100644 --- a/src/test/compile-fail/object-lifetime-default-from-rptr-struct-error.rs +++ b/src/test/compile-fail/object-lifetime-default-from-rptr-struct-error.rs @@ -11,8 +11,6 @@ // Test that the lifetime from the enclosing `&` is "inherited" // through the `MyBox` struct. -// pretty-expanded FIXME #23616 - #![allow(dead_code)] #![feature(rustc_error)] diff --git a/src/test/compile-fail/variance-trait-matching.rs b/src/test/compile-fail/variance-trait-matching.rs index 49dc1e68c221f..2d78940ce4b9d 100644 --- a/src/test/compile-fail/variance-trait-matching.rs +++ b/src/test/compile-fail/variance-trait-matching.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// pretty-expanded FIXME #23616 - #![allow(dead_code)] // Get is covariant in T diff --git a/src/test/pretty/for-comment.rs b/src/test/pretty/for-comment.rs index af76c1d940664..32837fbcf87bc 100644 --- a/src/test/pretty/for-comment.rs +++ b/src/test/pretty/for-comment.rs @@ -17,6 +17,5 @@ fn f(v: &[isize]) -> isize { for e in v { n = *e; // This comment once triggered pretty printer bug } - n } diff --git a/src/test/run-fail/divide-by-zero.rs b/src/test/run-fail/divide-by-zero.rs index c9c4a88c9b53e..1f9e069526ce9 100644 --- a/src/test/run-fail/divide-by-zero.rs +++ b/src/test/run-fail/divide-by-zero.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty : (#23623) problems when ending with // comments - // error-pattern:attempt to divide by zero fn main() { diff --git a/src/test/run-fail/glob-use-std.rs b/src/test/run-fail/glob-use-std.rs index 6712b3b065908..a7ba283b25af3 100644 --- a/src/test/run-fail/glob-use-std.rs +++ b/src/test/run-fail/glob-use-std.rs @@ -10,10 +10,6 @@ // Issue #7580 -// ignore-pretty -// -// Expanded pretty printing causes resolve conflicts. - // error-pattern:panic works use std::*; diff --git a/src/test/run-fail/mod-zero.rs b/src/test/run-fail/mod-zero.rs index d2b598a7933bc..641d39e2324b8 100644 --- a/src/test/run-fail/mod-zero.rs +++ b/src/test/run-fail/mod-zero.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty : (#23623) problems when ending with // comments - // error-pattern:attempt to calculate the remainder with a divisor of zero fn main() { diff --git a/src/test/run-fail/overflowing-add.rs b/src/test/run-fail/overflowing-add.rs index acc7676db457e..250f0726dc9d6 100644 --- a/src/test/run-fail/overflowing-add.rs +++ b/src/test/run-fail/overflowing-add.rs @@ -8,12 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty : (#23623) problems when ending with // comments - // error-pattern:thread 'main' panicked at 'attempt to add with overflow' // compile-flags: -C debug-assertions - fn main() { let _x = 200u8 + 200u8 + 200u8; } diff --git a/src/test/run-fail/overflowing-lsh-1.rs b/src/test/run-fail/overflowing-lsh-1.rs index 29ce3b0e6a16d..baa1e05d559b6 100644 --- a/src/test/run-fail/overflowing-lsh-1.rs +++ b/src/test/run-fail/overflowing-lsh-1.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty : (#23623) problems when ending with // comments - // error-pattern:thread 'main' panicked at 'attempt to shift left with overflow' // compile-flags: -C debug-assertions diff --git a/src/test/run-fail/overflowing-lsh-2.rs b/src/test/run-fail/overflowing-lsh-2.rs index 62fc9230f353d..3438ed2c77c18 100644 --- a/src/test/run-fail/overflowing-lsh-2.rs +++ b/src/test/run-fail/overflowing-lsh-2.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty : (#23623) problems when ending with // comments - // error-pattern:thread 'main' panicked at 'attempt to shift left with overflow' // compile-flags: -C debug-assertions diff --git a/src/test/run-fail/overflowing-lsh-3.rs b/src/test/run-fail/overflowing-lsh-3.rs index 1bc1703a89ce3..ef5c43db6e285 100644 --- a/src/test/run-fail/overflowing-lsh-3.rs +++ b/src/test/run-fail/overflowing-lsh-3.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty : (#23623) problems when ending with // comments - // error-pattern:thread 'main' panicked at 'attempt to shift left with overflow' // compile-flags: -C debug-assertions diff --git a/src/test/run-fail/overflowing-lsh-4.rs b/src/test/run-fail/overflowing-lsh-4.rs index 8de44f25e0489..226ece6020db4 100644 --- a/src/test/run-fail/overflowing-lsh-4.rs +++ b/src/test/run-fail/overflowing-lsh-4.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty : (#23623) problems when ending with // comments - // error-pattern:thread 'main' panicked at 'attempt to shift left with overflow' // compile-flags: -C debug-assertions diff --git a/src/test/run-fail/overflowing-mul.rs b/src/test/run-fail/overflowing-mul.rs index a09c0f06a5cc6..b47d0fc4136cc 100644 --- a/src/test/run-fail/overflowing-mul.rs +++ b/src/test/run-fail/overflowing-mul.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty : (#23623) problems when ending with // comments - // error-pattern:thread 'main' panicked at 'attempt to multiply with overflow' // compile-flags: -C debug-assertions diff --git a/src/test/run-fail/overflowing-neg.rs b/src/test/run-fail/overflowing-neg.rs index 96853fc565b71..836d7e37319e9 100644 --- a/src/test/run-fail/overflowing-neg.rs +++ b/src/test/run-fail/overflowing-neg.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty : (#23623) problems when ending with // comments - // error-pattern:thread 'main' panicked at 'attempt to negate with overflow' // compile-flags: -C debug-assertions diff --git a/src/test/run-fail/overflowing-rsh-1.rs b/src/test/run-fail/overflowing-rsh-1.rs index ef4a503cfe425..8f198c887e491 100644 --- a/src/test/run-fail/overflowing-rsh-1.rs +++ b/src/test/run-fail/overflowing-rsh-1.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty : (#23623) problems when ending with // comments - // error-pattern:thread 'main' panicked at 'attempt to shift right with overflow' // compile-flags: -C debug-assertions diff --git a/src/test/run-fail/overflowing-rsh-2.rs b/src/test/run-fail/overflowing-rsh-2.rs index da072b5a9a5a9..e4f260b2bbbbb 100644 --- a/src/test/run-fail/overflowing-rsh-2.rs +++ b/src/test/run-fail/overflowing-rsh-2.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty : (#23623) problems when ending with // comments - // error-pattern:thread 'main' panicked at 'attempt to shift right with overflow' // compile-flags: -C debug-assertions diff --git a/src/test/run-fail/overflowing-rsh-3.rs b/src/test/run-fail/overflowing-rsh-3.rs index 0b7809402e6db..11aa98a0c3cbc 100644 --- a/src/test/run-fail/overflowing-rsh-3.rs +++ b/src/test/run-fail/overflowing-rsh-3.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty : (#23623) problems when ending with // comments - // error-pattern:thread 'main' panicked at 'attempt to shift right with overflow' // compile-flags: -C debug-assertions diff --git a/src/test/run-fail/overflowing-rsh-4.rs b/src/test/run-fail/overflowing-rsh-4.rs index 1e0cc18fbdcd6..742720e83c10c 100644 --- a/src/test/run-fail/overflowing-rsh-4.rs +++ b/src/test/run-fail/overflowing-rsh-4.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty : (#23623) problems when ending with // comments - // error-pattern:thread 'main' panicked at 'attempt to shift right with overflow' // compile-flags: -C debug-assertions diff --git a/src/test/run-fail/overflowing-rsh-5.rs b/src/test/run-fail/overflowing-rsh-5.rs index 690901ff0c25b..6106fdcb16a46 100644 --- a/src/test/run-fail/overflowing-rsh-5.rs +++ b/src/test/run-fail/overflowing-rsh-5.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty : (#23623) problems when ending with // comments - // error-pattern:thread 'main' panicked at 'attempt to shift right with overflow' // compile-flags: -C debug-assertions diff --git a/src/test/run-fail/overflowing-rsh-6.rs b/src/test/run-fail/overflowing-rsh-6.rs index 6a6ed4f11f20e..d419550fcc570 100644 --- a/src/test/run-fail/overflowing-rsh-6.rs +++ b/src/test/run-fail/overflowing-rsh-6.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty : (#23623) problems when ending with // comments - // error-pattern:thread 'main' panicked at 'attempt to shift right with overflow' // compile-flags: -C debug-assertions diff --git a/src/test/run-fail/overflowing-sub.rs b/src/test/run-fail/overflowing-sub.rs index 083e8d24467fd..f94cb31b16884 100644 --- a/src/test/run-fail/overflowing-sub.rs +++ b/src/test/run-fail/overflowing-sub.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty : (#23623) problems when ending with // comments - // error-pattern:thread 'main' panicked at 'attempt to subtract with overflow' // compile-flags: -C debug-assertions diff --git a/src/test/run-fail/run-unexported-tests.rs b/src/test/run-fail/run-unexported-tests.rs index 8158333ade818..3f75229948df0 100644 --- a/src/test/run-fail/run-unexported-tests.rs +++ b/src/test/run-fail/run-unexported-tests.rs @@ -11,7 +11,6 @@ // error-pattern:runned an unexported test // compile-flags:--test // check-stdout -// ignore-pretty: does not work well with `--test` mod m { pub fn exported() {} diff --git a/src/test/run-fail/test-panic.rs b/src/test/run-fail/test-panic.rs index 21ced01d9d69e..bb6f4abe1fc96 100644 --- a/src/test/run-fail/test-panic.rs +++ b/src/test/run-fail/test-panic.rs @@ -11,7 +11,6 @@ // check-stdout // error-pattern:thread 'test_foo' panicked at // compile-flags: --test -// ignore-pretty: does not work well with `--test` // ignore-emscripten #[test] diff --git a/src/test/run-fail/test-should-fail-bad-message.rs b/src/test/run-fail/test-should-fail-bad-message.rs index 74b5f17bcf9ba..eac9813f180ae 100644 --- a/src/test/run-fail/test-should-fail-bad-message.rs +++ b/src/test/run-fail/test-should-fail-bad-message.rs @@ -11,7 +11,6 @@ // check-stdout // error-pattern:thread 'test_foo' panicked at // compile-flags: --test -// ignore-pretty: does not work well with `--test` // ignore-emscripten #[test] diff --git a/src/test/run-fail/test-tasks-invalid-value.rs b/src/test/run-fail/test-tasks-invalid-value.rs index b5c222764d243..fcf3559e7da66 100644 --- a/src/test/run-fail/test-tasks-invalid-value.rs +++ b/src/test/run-fail/test-tasks-invalid-value.rs @@ -14,7 +14,6 @@ // error-pattern:should be a positive integer // compile-flags: --test // exec-env:RUST_TEST_THREADS=foo -// ignore-pretty: does not work well with `--test` // ignore-emscripten #[test] diff --git a/src/test/run-pass-fulldeps/custom-derive-partial-eq.rs b/src/test/run-pass-fulldeps/custom-derive-partial-eq.rs index 8cc7ab4219dc5..47f5f8397d1c5 100644 --- a/src/test/run-pass-fulldeps/custom-derive-partial-eq.rs +++ b/src/test/run-pass-fulldeps/custom-derive-partial-eq.rs @@ -10,8 +10,6 @@ // aux-build:custom_derive_partial_eq.rs // ignore-stage1 -// ignore-pretty : (#23623) problems when ending with // comments - #![feature(plugin, custom_derive)] #![plugin(custom_derive_partial_eq)] #![allow(unused)] diff --git a/src/test/run-pass-fulldeps/issue-16992.rs b/src/test/run-pass-fulldeps/issue-16992.rs index a439e2bb25b8c..3ab7f8429e601 100644 --- a/src/test/run-pass-fulldeps/issue-16992.rs +++ b/src/test/run-pass-fulldeps/issue-16992.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty // ignore-cross-compile #![feature(quote, rustc_private)] diff --git a/src/test/run-pass-fulldeps/issue-18763-quote-token-tree.rs b/src/test/run-pass-fulldeps/issue-18763-quote-token-tree.rs index 829fdb176bd31..03311d76e46d4 100644 --- a/src/test/run-pass-fulldeps/issue-18763-quote-token-tree.rs +++ b/src/test/run-pass-fulldeps/issue-18763-quote-token-tree.rs @@ -9,8 +9,6 @@ // except according to those terms. // ignore-cross-compile -// ignore-pretty: does not work well with `--test` - #![feature(quote, rustc_private)] extern crate syntax; diff --git a/src/test/run-pass-fulldeps/lint-group-plugin.rs b/src/test/run-pass-fulldeps/lint-group-plugin.rs index 21942b84bff9c..978a78cee4f1e 100644 --- a/src/test/run-pass-fulldeps/lint-group-plugin.rs +++ b/src/test/run-pass-fulldeps/lint-group-plugin.rs @@ -10,8 +10,6 @@ // aux-build:lint_group_plugin_test.rs // ignore-stage1 -// ignore-pretty - #![feature(plugin)] #![plugin(lint_group_plugin_test)] #![allow(dead_code)] diff --git a/src/test/run-pass-fulldeps/lint-plugin-cmdline-load.rs b/src/test/run-pass-fulldeps/lint-plugin-cmdline-load.rs index 2a6daa5040b71..2e86e11bd6a5f 100644 --- a/src/test/run-pass-fulldeps/lint-plugin-cmdline-load.rs +++ b/src/test/run-pass-fulldeps/lint-plugin-cmdline-load.rs @@ -10,7 +10,6 @@ // aux-build:lint_plugin_test.rs // ignore-stage1 -// ignore-pretty: Random space appears with the pretty test // compile-flags: -Z extra-plugins=lint_plugin_test #![allow(dead_code)] diff --git a/src/test/run-pass-fulldeps/lint-plugin.rs b/src/test/run-pass-fulldeps/lint-plugin.rs index b694a1c332079..753ad33bd01e9 100644 --- a/src/test/run-pass-fulldeps/lint-plugin.rs +++ b/src/test/run-pass-fulldeps/lint-plugin.rs @@ -10,8 +10,6 @@ // aux-build:lint_plugin_test.rs // ignore-stage1 -// ignore-pretty - #![feature(plugin)] #![plugin(lint_plugin_test)] #![allow(dead_code)] diff --git a/src/test/run-pass-fulldeps/quote-tokens.rs b/src/test/run-pass-fulldeps/quote-tokens.rs index 710e2fd1d07a3..9e9b7ce5bf29d 100644 --- a/src/test/run-pass-fulldeps/quote-tokens.rs +++ b/src/test/run-pass-fulldeps/quote-tokens.rs @@ -9,8 +9,6 @@ // except according to those terms. // ignore-cross-compile -// ignore-pretty: does not work well with `--test` - #![feature(quote, rustc_private)] extern crate syntax; diff --git a/src/test/run-pass-fulldeps/quote-unused-sp-no-warning.rs b/src/test/run-pass-fulldeps/quote-unused-sp-no-warning.rs index 460eab998c6fb..d3be1ddcb8c32 100644 --- a/src/test/run-pass-fulldeps/quote-unused-sp-no-warning.rs +++ b/src/test/run-pass-fulldeps/quote-unused-sp-no-warning.rs @@ -9,8 +9,6 @@ // except according to those terms. // ignore-cross-compile -// ignore-pretty: does not work well with `--test` - #![feature(quote, rustc_private)] #![deny(unused_variables)] diff --git a/src/test/run-pass-valgrind/cast-enum-with-dtor.rs b/src/test/run-pass-valgrind/cast-enum-with-dtor.rs index 7cf75924a28c0..2815863fe9961 100644 --- a/src/test/run-pass-valgrind/cast-enum-with-dtor.rs +++ b/src/test/run-pass-valgrind/cast-enum-with-dtor.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty : (#23623) problems when ending with // comments - // no-prefer-dynamic #![allow(dead_code)] diff --git a/src/test/run-pass/backtrace-debuginfo.rs b/src/test/run-pass/backtrace-debuginfo.rs index 838005cbc9119..72cf109fd5974 100644 --- a/src/test/run-pass/backtrace-debuginfo.rs +++ b/src/test/run-pass/backtrace-debuginfo.rs @@ -16,7 +16,7 @@ // "enable" to 0 instead. // compile-flags:-g -Cllvm-args=-enable-tail-merge=0 -// ignore-pretty as this critically relies on line numbers +// ignore-pretty issue #37195 // ignore-emscripten spawning processes is not supported use std::io; diff --git a/src/test/run-pass/backtrace.rs b/src/test/run-pass/backtrace.rs index f26706d1754e0..c438c17f51e3a 100644 --- a/src/test/run-pass/backtrace.rs +++ b/src/test/run-pass/backtrace.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// no-pretty-expanded FIXME #15189 // ignore-android FIXME #17520 // ignore-emscripten spawning processes is not supported // compile-flags:-g diff --git a/src/test/run-pass/borrowck/borrowck-pat-enum.rs b/src/test/run-pass/borrowck/borrowck-pat-enum.rs index b29cb63f6fa3b..8de45e4205dfb 100644 --- a/src/test/run-pass/borrowck/borrowck-pat-enum.rs +++ b/src/test/run-pass/borrowck/borrowck-pat-enum.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty +// ignore-pretty issue #37199 fn match_ref(v: Option) -> isize { match v { diff --git a/src/test/run-pass/cfg-in-crate-1.rs b/src/test/run-pass/cfg-in-crate-1.rs index 06f679b7fca9a..5dd6fa45bb96e 100644 --- a/src/test/run-pass/cfg-in-crate-1.rs +++ b/src/test/run-pass/cfg-in-crate-1.rs @@ -9,8 +9,6 @@ // except according to those terms. // compile-flags: --cfg bar -D warnings -// ignore-pretty - #![cfg(bar)] fn main() {} diff --git a/src/test/run-pass/command-exec.rs b/src/test/run-pass/command-exec.rs index 130526e72b19c..5be9b97aac7e6 100644 --- a/src/test/run-pass/command-exec.rs +++ b/src/test/run-pass/command-exec.rs @@ -9,9 +9,8 @@ // except according to those terms. // ignore-windows - this is a unix-specific test +// ignore-pretty issue #37199 // ignore-emscripten -// ignore-pretty - #![feature(process_exec)] use std::env; diff --git a/src/test/run-pass/core-run-destroy.rs b/src/test/run-pass/core-run-destroy.rs index ffcc1891c579e..c5b5b6b24ab1c 100644 --- a/src/test/run-pass/core-run-destroy.rs +++ b/src/test/run-pass/core-run-destroy.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty // compile-flags:--test // ignore-emscripten diff --git a/src/test/run-pass/deprecated-macro_escape-inner.rs b/src/test/run-pass/deprecated-macro_escape-inner.rs index 7960a91bdc4fc..1a2be7a719e17 100644 --- a/src/test/run-pass/deprecated-macro_escape-inner.rs +++ b/src/test/run-pass/deprecated-macro_escape-inner.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty - mod foo { #![macro_escape] //~ WARNING macro_escape is a deprecated synonym for macro_use //~^ HELP consider an outer attribute diff --git a/src/test/run-pass/deprecated-macro_escape.rs b/src/test/run-pass/deprecated-macro_escape.rs index b03905e1a0d63..b9f756cc79c8f 100644 --- a/src/test/run-pass/deprecated-macro_escape.rs +++ b/src/test/run-pass/deprecated-macro_escape.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty - #[macro_escape] //~ WARNING macro_escape is a deprecated synonym for macro_use mod foo { } diff --git a/src/test/run-pass/deriving-cmp-generic-enum.rs b/src/test/run-pass/deriving-cmp-generic-enum.rs index b1cd1877a7667..b2add21dcd487 100644 --- a/src/test/run-pass/deriving-cmp-generic-enum.rs +++ b/src/test/run-pass/deriving-cmp-generic-enum.rs @@ -8,9 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// no-pretty-expanded FIXME #15189 - - #[derive(PartialEq, Eq, PartialOrd, Ord)] enum E { E0, diff --git a/src/test/run-pass/deriving-meta-empty-trait-list.rs b/src/test/run-pass/deriving-meta-empty-trait-list.rs index ff513325d5e68..ed8a50998daee 100644 --- a/src/test/run-pass/deriving-meta-empty-trait-list.rs +++ b/src/test/run-pass/deriving-meta-empty-trait-list.rs @@ -1,5 +1,3 @@ -// ignore-pretty - // Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. diff --git a/src/test/run-pass/enum-size-variance.rs b/src/test/run-pass/enum-size-variance.rs index 21996c5fabf1a..26deb0ed72ade 100644 --- a/src/test/run-pass/enum-size-variance.rs +++ b/src/test/run-pass/enum-size-variance.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. // -// ignore-pretty - #![warn(variant_size_differences)] #![allow(dead_code)] diff --git a/src/test/run-pass/hygienic-labels-in-let.rs b/src/test/run-pass/hygienic-labels-in-let.rs index 5b45f1e0d3928..2aa5f59cda62d 100644 --- a/src/test/run-pass/hygienic-labels-in-let.rs +++ b/src/test/run-pass/hygienic-labels-in-let.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty: pprust doesn't print hygiene output - // Test that labels injected by macros do not break hygiene. This // checks cases where the macros invocations are under the rhs of a // let statement. diff --git a/src/test/run-pass/ifmt.rs b/src/test/run-pass/ifmt.rs index 0ebe1ca07c771..c9af2b190b21c 100644 --- a/src/test/run-pass/ifmt.rs +++ b/src/test/run-pass/ifmt.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// no-pretty-expanded unnecessary unsafe block generated - #![deny(warnings)] #![allow(unused_must_use)] #![allow(unused_features)] diff --git a/src/test/run-pass/imports.rs b/src/test/run-pass/imports.rs index 9851dfe0262f8..195b99c9788e8 100644 --- a/src/test/run-pass/imports.rs +++ b/src/test/run-pass/imports.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty : (#23623) problems when ending with // comments - #![feature(item_like_imports)] #![allow(unused)] diff --git a/src/test/run-pass/issue-11709.rs b/src/test/run-pass/issue-11709.rs index cfff7eb339522..88d74a65813be 100644 --- a/src/test/run-pass/issue-11709.rs +++ b/src/test/run-pass/issue-11709.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty +// ignore-pretty issue #37199 // Don't panic on blocks without results // There are several tests in this run-pass that raised diff --git a/src/test/run-pass/issue-15189.rs b/src/test/run-pass/issue-15189.rs index 24340ac3f13d7..35faa5789a9c8 100644 --- a/src/test/run-pass/issue-15189.rs +++ b/src/test/run-pass/issue-15189.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty - macro_rules! third { ($e:expr) => ({let x = 2; $e[x]}) } diff --git a/src/test/run-pass/issue-16492.rs b/src/test/run-pass/issue-16492.rs index 975557726ce8b..177550a0dd4a1 100644 --- a/src/test/run-pass/issue-16492.rs +++ b/src/test/run-pass/issue-16492.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty - use std::rc::Rc; use std::cell::Cell; diff --git a/src/test/run-pass/issue-16597-empty.rs b/src/test/run-pass/issue-16597-empty.rs index a6a1c5f16b31c..c51e33c01040b 100644 --- a/src/test/run-pass/issue-16597-empty.rs +++ b/src/test/run-pass/issue-16597-empty.rs @@ -9,7 +9,6 @@ // except according to those terms. // compile-flags:--test -// no-pretty-expanded // This verifies that the test generation doesn't crash when we have // no tests - for more information, see PR #16892. diff --git a/src/test/run-pass/issue-16597.rs b/src/test/run-pass/issue-16597.rs index 7f0a341f14715..583d8d46235d6 100644 --- a/src/test/run-pass/issue-16597.rs +++ b/src/test/run-pass/issue-16597.rs @@ -9,7 +9,6 @@ // except according to those terms. // compile-flags:--test -// ignore-pretty turns out the pretty-printer doesn't handle gensym'd things... mod tests { use super::*; diff --git a/src/test/run-pass/issue-16668.rs b/src/test/run-pass/issue-16668.rs index 0fd9965028489..18861feb1997a 100644 --- a/src/test/run-pass/issue-16668.rs +++ b/src/test/run-pass/issue-16668.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty - #![allow(unknown_features)] struct Parser<'a, I, O> { diff --git a/src/test/run-pass/issue-18464.rs b/src/test/run-pass/issue-18464.rs index 70217868a54b8..dff86bc1b4527 100644 --- a/src/test/run-pass/issue-18464.rs +++ b/src/test/run-pass/issue-18464.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty - #![deny(dead_code)] const LOW_RANGE: char = '0'; diff --git a/src/test/run-pass/issue-20427.rs b/src/test/run-pass/issue-20427.rs index dd3d952224c05..985ca067350a3 100644 --- a/src/test/run-pass/issue-20427.rs +++ b/src/test/run-pass/issue-20427.rs @@ -9,7 +9,7 @@ // except according to those terms. // aux-build:i8.rs -// ignore-pretty (#23623) +// ignore-pretty issue #37201 extern crate i8; use std::string as i16; diff --git a/src/test/run-pass/issue-20823.rs b/src/test/run-pass/issue-20823.rs index c297998b6493a..4d31d0cedb6d5 100644 --- a/src/test/run-pass/issue-20823.rs +++ b/src/test/run-pass/issue-20823.rs @@ -9,7 +9,6 @@ // except according to those terms. // compile-flags: --test -// no-pretty-expanded #![deny(unstable)] diff --git a/src/test/run-pass/issue-22992.rs b/src/test/run-pass/issue-22992.rs index ca8f804482aa1..dc612fc0bc71c 100644 --- a/src/test/run-pass/issue-22992.rs +++ b/src/test/run-pass/issue-22992.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty +// ignore-pretty issue #37201 struct X { val: i32 } impl std::ops::Deref for X { diff --git a/src/test/run-pass/issue-23338-ensure-param-drop-order.rs b/src/test/run-pass/issue-23338-ensure-param-drop-order.rs index fb84e7bae514d..9d0612f2a8daa 100644 --- a/src/test/run-pass/issue-23338-ensure-param-drop-order.rs +++ b/src/test/run-pass/issue-23338-ensure-param-drop-order.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty : (#23623) problems when ending with // comments +// ignore-pretty issue #37201 // This test is ensuring that parameters are indeed dropped after // temporaries in a fn body. diff --git a/src/test/run-pass/issue-26873-multifile.rs b/src/test/run-pass/issue-26873-multifile.rs index aa525ae95192e..51bf4bfe0e13e 100644 --- a/src/test/run-pass/issue-26873-multifile.rs +++ b/src/test/run-pass/issue-26873-multifile.rs @@ -7,10 +7,9 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. -// -// ignore-pretty + +// ignore-pretty issue #37195 mod issue_26873_multifile; fn main() {} - diff --git a/src/test/run-pass/issue-27401-dropflag-reinit.rs b/src/test/run-pass/issue-27401-dropflag-reinit.rs index ab8f22e78be72..37dc060d5d64d 100644 --- a/src/test/run-pass/issue-27401-dropflag-reinit.rs +++ b/src/test/run-pass/issue-27401-dropflag-reinit.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty #27582 +// ignore-pretty issue #37201 // Check that when a `let`-binding occurs in a loop, its associated // drop-flag is reinitialized (to indicate "needs-drop" at the end of diff --git a/src/test/run-pass/issue-27639.rs b/src/test/run-pass/issue-27639.rs index 44c1eb86de8df..ce1abb163d53b 100644 --- a/src/test/run-pass/issue-27639.rs +++ b/src/test/run-pass/issue-27639.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty - fn main() { const iter: i32 = 0; diff --git a/src/test/run-pass/issue-28839.rs b/src/test/run-pass/issue-28839.rs index a1012296626e2..2ff4403a42f97 100644 --- a/src/test/run-pass/issue-28839.rs +++ b/src/test/run-pass/issue-28839.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty : (#23623) problems with newlines before // comments +// ignore-pretty issue #37199 pub struct Foo; diff --git a/src/test/run-pass/issue-29740.rs b/src/test/run-pass/issue-29740.rs index 75bcd431ec8e1..eb7b740db6e4b 100644 --- a/src/test/run-pass/issue-29740.rs +++ b/src/test/run-pass/issue-29740.rs @@ -11,8 +11,6 @@ // Regression test for #29740. Inefficient MIR matching algorithms // generated way too much code for this sort of case, leading to OOM. -// ignore-pretty - pub mod KeyboardEventConstants { pub const DOM_KEY_LOCATION_STANDARD: u32 = 0; pub const DOM_KEY_LOCATION_LEFT: u32 = 1; diff --git a/src/test/run-pass/issue-34932.rs b/src/test/run-pass/issue-34932.rs index e83939e7aec6b..dca387dcc2117 100644 --- a/src/test/run-pass/issue-34932.rs +++ b/src/test/run-pass/issue-34932.rs @@ -10,8 +10,6 @@ // compile-flags:--test // rustc-env:RUSTC_BOOTSTRAP_KEY= -// ignore-pretty : (#23623) problems when ending with // comments - #![cfg(any())] // This test should be configured away #![feature(rustc_attrs)] // Test that this is allowed on stable/beta #![feature(iter_arith_traits)] // Test that this is not unused diff --git a/src/test/run-pass/issue-7911.rs b/src/test/run-pass/issue-7911.rs index 5324ddb49e79f..764d6fa791805 100644 --- a/src/test/run-pass/issue-7911.rs +++ b/src/test/run-pass/issue-7911.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty - // (Closes #7911) Test that we can use the same self expression // with different mutability in macro in two methods diff --git a/src/test/run-pass/issue-8460.rs b/src/test/run-pass/issue-8460.rs index f16057ccab16c..5148be5af8307 100644 --- a/src/test/run-pass/issue-8460.rs +++ b/src/test/run-pass/issue-8460.rs @@ -9,8 +9,6 @@ // except according to those terms. // ignore-emscripten no threads support -// ignore-pretty : (#23623) problems when ending with // comments - #![feature(rustc_attrs, zero_one)] use std::num::Zero; diff --git a/src/test/run-pass/issue-9129.rs b/src/test/run-pass/issue-9129.rs index 99db47c172e21..c46e8494e73b8 100644 --- a/src/test/run-pass/issue-9129.rs +++ b/src/test/run-pass/issue-9129.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty +// ignore-pretty unreported #![allow(unknown_features)] #![feature(box_syntax)] diff --git a/src/test/run-pass/lexer-crlf-line-endings-string-literal-doc-comment.rs b/src/test/run-pass/lexer-crlf-line-endings-string-literal-doc-comment.rs index 5c8db524cc2ed..05f1f1bfea0fb 100644 --- a/src/test/run-pass/lexer-crlf-line-endings-string-literal-doc-comment.rs +++ b/src/test/run-pass/lexer-crlf-line-endings-string-literal-doc-comment.rs @@ -15,7 +15,7 @@ // NB: this file needs CRLF line endings. The .gitattributes file in // this directory should enforce it. -// ignore-pretty +// ignore-pretty issue #37195 /// Doc comment that ends in CRLF pub fn foo() {} diff --git a/src/test/run-pass/linear-for-loop.rs b/src/test/run-pass/linear-for-loop.rs index ddb4e40aea633..3da2fc8ceacf7 100644 --- a/src/test/run-pass/linear-for-loop.rs +++ b/src/test/run-pass/linear-for-loop.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// no-pretty-expanded FIXME #15189 - pub fn main() { let x = vec!(1, 2, 3); let mut y = 0; diff --git a/src/test/run-pass/macro-2.rs b/src/test/run-pass/macro-2.rs index 2cac9226117a2..801d92b6dcb16 100644 --- a/src/test/run-pass/macro-2.rs +++ b/src/test/run-pass/macro-2.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty - token trees can't pretty print - pub fn main() { macro_rules! mylambda_tt { diff --git a/src/test/run-pass/macro-attribute-expansion.rs b/src/test/run-pass/macro-attribute-expansion.rs index 60217139cd778..c3de9f736fbe5 100644 --- a/src/test/run-pass/macro-attribute-expansion.rs +++ b/src/test/run-pass/macro-attribute-expansion.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty - token trees can't pretty print - macro_rules! descriptions { ($name:ident is $desc:expr) => { // Check that we will correctly expand attributes diff --git a/src/test/run-pass/macro-attributes.rs b/src/test/run-pass/macro-attributes.rs index 2752fc88b456b..839fee3a2d214 100644 --- a/src/test/run-pass/macro-attributes.rs +++ b/src/test/run-pass/macro-attributes.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty - token trees can't pretty print - #![feature(custom_attribute)] macro_rules! compiles_fine { diff --git a/src/test/run-pass/macro-include-items.rs b/src/test/run-pass/macro-include-items.rs index 1e31c85afad62..f8728ebb91517 100644 --- a/src/test/run-pass/macro-include-items.rs +++ b/src/test/run-pass/macro-include-items.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty +// ignore-pretty issue #37195 fn bar() {} diff --git a/src/test/run-pass/macro-meta-items.rs b/src/test/run-pass/macro-meta-items.rs index 605cade2b3f7e..9c1e1fca3413e 100644 --- a/src/test/run-pass/macro-meta-items.rs +++ b/src/test/run-pass/macro-meta-items.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty - token trees can't pretty print // compile-flags: --cfg foo macro_rules! compiles_fine { diff --git a/src/test/run-pass/macro-multiple-items.rs b/src/test/run-pass/macro-multiple-items.rs index f78f93e84810c..190bfc53a9edb 100644 --- a/src/test/run-pass/macro-multiple-items.rs +++ b/src/test/run-pass/macro-multiple-items.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty - token trees can't pretty print - macro_rules! make_foo { () => ( struct Foo; diff --git a/src/test/run-pass/macro-stmt.rs b/src/test/run-pass/macro-stmt.rs index 0d8b86012d6e0..027df9f93a88d 100644 --- a/src/test/run-pass/macro-stmt.rs +++ b/src/test/run-pass/macro-stmt.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty - token trees can't pretty print - macro_rules! myfn { ( $f:ident, ( $( $x:ident ),* ), $body:block ) => ( fn $f( $( $x : isize),* ) -> isize $body diff --git a/src/test/run-pass/mir_raw_fat_ptr.rs b/src/test/run-pass/mir_raw_fat_ptr.rs index c9fd88f2fb3cf..846318ec4fd34 100644 --- a/src/test/run-pass/mir_raw_fat_ptr.rs +++ b/src/test/run-pass/mir_raw_fat_ptr.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty : (#23623) problems when ending with // comments - // check raw fat pointer ops in mir // FIXME: please improve this when we get monomorphization support diff --git a/src/test/run-pass/mod_dir_implicit.rs b/src/test/run-pass/mod_dir_implicit.rs index 1b89464c543ce..f8034f9e07386 100644 --- a/src/test/run-pass/mod_dir_implicit.rs +++ b/src/test/run-pass/mod_dir_implicit.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty +// ignore-pretty issue #37195 mod mod_dir_implicit_aux; diff --git a/src/test/run-pass/mod_dir_path.rs b/src/test/run-pass/mod_dir_path.rs index 28dee15cfa043..e2f33963c4bad 100644 --- a/src/test/run-pass/mod_dir_path.rs +++ b/src/test/run-pass/mod_dir_path.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty +// ignore-pretty issue #37195 mod mod_dir_simple { #[path = "test.rs"] diff --git a/src/test/run-pass/mod_dir_path2.rs b/src/test/run-pass/mod_dir_path2.rs index 2b5e67a6e8396..b96c1ae072243 100644 --- a/src/test/run-pass/mod_dir_path2.rs +++ b/src/test/run-pass/mod_dir_path2.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty +// ignore-pretty issue #37195 #[path = "mod_dir_simple"] mod pancakes { diff --git a/src/test/run-pass/mod_dir_path3.rs b/src/test/run-pass/mod_dir_path3.rs index d6037bef6e576..3160064d7c244 100644 --- a/src/test/run-pass/mod_dir_path3.rs +++ b/src/test/run-pass/mod_dir_path3.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty +// ignore-pretty issue #37195 #[path = "mod_dir_simple"] mod pancakes { diff --git a/src/test/run-pass/mod_dir_path_multi.rs b/src/test/run-pass/mod_dir_path_multi.rs index f1bf83ed767f7..12b28cf98af0b 100644 --- a/src/test/run-pass/mod_dir_path_multi.rs +++ b/src/test/run-pass/mod_dir_path_multi.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty +// ignore-pretty issue #37195 #[path = "mod_dir_simple"] mod biscuits { diff --git a/src/test/run-pass/mod_dir_recursive.rs b/src/test/run-pass/mod_dir_recursive.rs index d7121ef769078..8964d9ccd2527 100644 --- a/src/test/run-pass/mod_dir_recursive.rs +++ b/src/test/run-pass/mod_dir_recursive.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty +// ignore-pretty issue #37195 // Testing that the parser for each file tracks its modules // and paths independently. The load_another_mod module should diff --git a/src/test/run-pass/mod_dir_simple.rs b/src/test/run-pass/mod_dir_simple.rs index 41c810b6fddab..429b4ebe63970 100644 --- a/src/test/run-pass/mod_dir_simple.rs +++ b/src/test/run-pass/mod_dir_simple.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty +// ignore-pretty issue #37195 mod mod_dir_simple { pub mod test; diff --git a/src/test/run-pass/mod_file.rs b/src/test/run-pass/mod_file.rs index ddda38bafd369..c18fecd7c569e 100644 --- a/src/test/run-pass/mod_file.rs +++ b/src/test/run-pass/mod_file.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty +// ignore-pretty issue #37195 // Testing that a plain .rs file can load modules from other source files diff --git a/src/test/run-pass/mod_file_with_path_attr.rs b/src/test/run-pass/mod_file_with_path_attr.rs index c6e51daaaf054..d9f28ceb0ecac 100644 --- a/src/test/run-pass/mod_file_with_path_attr.rs +++ b/src/test/run-pass/mod_file_with_path_attr.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty +// ignore-pretty issue #37195 // Testing that a plain .rs file can load modules from other source files diff --git a/src/test/run-pass/numeric-method-autoexport.rs b/src/test/run-pass/numeric-method-autoexport.rs index b1d71abc78599..15ece09abd80f 100644 --- a/src/test/run-pass/numeric-method-autoexport.rs +++ b/src/test/run-pass/numeric-method-autoexport.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// no-pretty-expanded - // This file is intended to test only that methods are automatically // reachable for each numeric type, for each exported impl, with no imports // necessary. Testing the methods of the impls is done within the source diff --git a/src/test/run-pass/reexport-test-harness-main.rs b/src/test/run-pass/reexport-test-harness-main.rs index 309ae1bcc56ec..88e3e6ba4acd3 100644 --- a/src/test/run-pass/reexport-test-harness-main.rs +++ b/src/test/run-pass/reexport-test-harness-main.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty // compile-flags:--test #![reexport_test_harness_main = "test_main"] diff --git a/src/test/run-pass/regions-bound-lists-feature-gate-2.rs b/src/test/run-pass/regions-bound-lists-feature-gate-2.rs index a06e0f6da785a..47d2fe363d369 100644 --- a/src/test/run-pass/regions-bound-lists-feature-gate-2.rs +++ b/src/test/run-pass/regions-bound-lists-feature-gate-2.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty - #![feature(issue_5723_bootstrap)] trait Foo { diff --git a/src/test/run-pass/regions-bound-lists-feature-gate.rs b/src/test/run-pass/regions-bound-lists-feature-gate.rs index 996583dc6de93..72db92aa93ce0 100644 --- a/src/test/run-pass/regions-bound-lists-feature-gate.rs +++ b/src/test/run-pass/regions-bound-lists-feature-gate.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty - #![feature(issue_5723_bootstrap)] trait Foo { diff --git a/src/test/run-pass/shebang.rs b/src/test/run-pass/shebang.rs index 15ab21bbc8da7..a0947cd49a42d 100644 --- a/src/test/run-pass/shebang.rs +++ b/src/test/run-pass/shebang.rs @@ -9,7 +9,4 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty: `expand` adds some preludes before shebang -// - pub fn main() { println!("Hello World"); } diff --git a/src/test/run-pass/simd-intrinsic-generic-elements.rs b/src/test/run-pass/simd-intrinsic-generic-elements.rs index 5cb57b63ada2c..f0444c2717056 100644 --- a/src/test/run-pass/simd-intrinsic-generic-elements.rs +++ b/src/test/run-pass/simd-intrinsic-generic-elements.rs @@ -10,8 +10,6 @@ #![feature(repr_simd, platform_intrinsics)] -// ignore-pretty : (#23623) problems when ending with // comments - #[repr(simd)] #[derive(Copy, Clone, Debug, PartialEq)] #[allow(non_camel_case_types)] diff --git a/src/test/run-pass/super-fast-paren-parsing.rs b/src/test/run-pass/super-fast-paren-parsing.rs index b764a983a0c09..a1bbd19021127 100644 --- a/src/test/run-pass/super-fast-paren-parsing.rs +++ b/src/test/run-pass/super-fast-paren-parsing.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty -// // exec-env:RUST_MIN_STACK=16000000 // rustc-env:RUST_MIN_STACK=16000000 // diff --git a/src/test/run-pass/syntax-extension-source-utils.rs b/src/test/run-pass/syntax-extension-source-utils.rs index 2f52e424936ea..3b5f033d07b7d 100644 --- a/src/test/run-pass/syntax-extension-source-utils.rs +++ b/src/test/run-pass/syntax-extension-source-utils.rs @@ -8,10 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(core)] - -// This test is brittle! -// ignore-pretty - the pretty tests lose path information, breaking include! +// ignore-pretty issue #37195 pub mod m1 { pub mod m2 { @@ -24,9 +21,9 @@ pub mod m1 { macro_rules! indirect_line { () => ( line!() ) } pub fn main() { - assert_eq!(line!(), 27); + assert_eq!(line!(), 24); assert_eq!(column!(), 4); - assert_eq!(indirect_line!(), 29); + assert_eq!(indirect_line!(), 26); assert!((file!().ends_with("syntax-extension-source-utils.rs"))); assert_eq!(stringify!((2*3) + 5).to_string(), "( 2 * 3 ) + 5".to_string()); assert!(include!("syntax-extension-source-utils-files/includeme.\ @@ -43,5 +40,5 @@ pub fn main() { // The Windows tests are wrapped in an extra module for some reason assert!((m1::m2::where_am_i().ends_with("m1::m2"))); - assert_eq!((46, "( 2 * 3 ) + 5"), (line!(), stringify!((2*3) + 5))); + assert_eq!((43, "( 2 * 3 ) + 5"), (line!(), stringify!((2*3) + 5))); } diff --git a/src/test/run-pass/task-comm-3.rs b/src/test/run-pass/task-comm-3.rs index 0e8542bababdd..78f29f46edf4a 100644 --- a/src/test/run-pass/task-comm-3.rs +++ b/src/test/run-pass/task-comm-3.rs @@ -11,7 +11,6 @@ #![feature(std_misc)] // ignore-emscripten no threads support -// no-pretty-expanded FIXME #15189 use std::thread; use std::sync::mpsc::{channel, Sender}; diff --git a/src/test/run-pass/test-fn-signature-verification-for-explicit-return-type.rs b/src/test/run-pass/test-fn-signature-verification-for-explicit-return-type.rs index d58b5d3a00fec..10ad838d3cb87 100644 --- a/src/test/run-pass/test-fn-signature-verification-for-explicit-return-type.rs +++ b/src/test/run-pass/test-fn-signature-verification-for-explicit-return-type.rs @@ -11,7 +11,6 @@ #![feature(test)] // compile-flags: --test -// no-pretty-expanded extern crate test; #[bench] diff --git a/src/test/run-pass/test-runner-hides-main.rs b/src/test/run-pass/test-runner-hides-main.rs index 839e91f3793d4..7b696c1f8d27c 100644 --- a/src/test/run-pass/test-runner-hides-main.rs +++ b/src/test/run-pass/test-runner-hides-main.rs @@ -9,8 +9,6 @@ // except according to those terms. // compile-flags:--test -// ignore-pretty: does not work well with `--test` - // Building as a test runner means that a synthetic main will be run, // not ours pub fn main() { panic!(); } diff --git a/src/test/run-pass/test-should-fail-good-message.rs b/src/test/run-pass/test-should-fail-good-message.rs index 28698499303a9..e665fa4fc7b58 100644 --- a/src/test/run-pass/test-should-fail-good-message.rs +++ b/src/test/run-pass/test-should-fail-good-message.rs @@ -9,8 +9,6 @@ // except according to those terms. // compile-flags: --test -// ignore-pretty: does not work well with `--test` - #[test] #[should_panic(expected = "foo")] pub fn test_foo() { diff --git a/src/test/run-pass/trait-bounds-in-arc.rs b/src/test/run-pass/trait-bounds-in-arc.rs index 0de6fbc91cc6b..f7fd86c957070 100644 --- a/src/test/run-pass/trait-bounds-in-arc.rs +++ b/src/test/run-pass/trait-bounds-in-arc.rs @@ -12,8 +12,6 @@ // and shared between threads as long as all types fulfill Send. // ignore-emscripten no threads support -// ignore-pretty - #![allow(unknown_features)] #![feature(box_syntax, std_misc)] diff --git a/src/test/run-pass/union/union-with-drop-fields-lint.rs b/src/test/run-pass/union/union-with-drop-fields-lint.rs index 5a1424830d074..6cb7e82d6b740 100644 --- a/src/test/run-pass/union/union-with-drop-fields-lint.rs +++ b/src/test/run-pass/union/union-with-drop-fields-lint.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty - #![feature(untagged_unions)] #![allow(dead_code)] #![allow(unions_with_drop_fields)] From 93417fa71ee73ddbb2e5c531e79ba39ec45beb5c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 4 Oct 2016 19:10:33 +0200 Subject: [PATCH 45/60] Add invalid doc comment help message --- src/libsyntax/config.rs | 16 ++++++++++------ src/libsyntax/feature_gate.rs | 9 +++++++-- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index 3b81ea4917f2b..01f81e5e2de17 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -9,7 +9,7 @@ // except according to those terms. use attr::HasAttrs; -use feature_gate::{emit_feature_err, EXPLAIN_STMT_ATTR_SYNTAX, Features, get_features, GateIssue}; +use feature_gate::{feature_err, EXPLAIN_STMT_ATTR_SYNTAX, Features, get_features, GateIssue}; use {fold, attr}; use ast; use codemap::{Spanned, respan}; @@ -157,11 +157,15 @@ impl<'a> StripUnconfigured<'a> { // flag the offending attributes for attr in attrs.iter() { if !self.features.map(|features| features.stmt_expr_attributes).unwrap_or(true) { - emit_feature_err(&self.sess, - "stmt_expr_attributes", - attr.span, - GateIssue::Language, - EXPLAIN_STMT_ATTR_SYNTAX); + let mut err = feature_err(&self.sess, + "stmt_expr_attributes", + attr.span, + GateIssue::Language, + EXPLAIN_STMT_ATTR_SYNTAX); + if attr.node.is_sugared_doc { + err.help("`///` is for documentation comments. For a plain comment, use `//`."); + } + err.emit(); } } } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 62b88888fc878..2e7a706a583f1 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -30,7 +30,7 @@ use ast::{self, NodeId, PatKind}; use attr; use codemap::{CodeMap, Spanned}; use syntax_pos::Span; -use errors::Handler; +use errors::{DiagnosticBuilder, Handler}; use visit::{self, FnKind, Visitor}; use parse::ParseSess; use parse::token::InternedString; @@ -792,6 +792,11 @@ pub enum GateIssue { pub fn emit_feature_err(sess: &ParseSess, feature: &str, span: Span, issue: GateIssue, explain: &str) { + feature_err(sess, feature, span, issue, explain).emit(); +} + +pub fn feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: GateIssue, + explain: &str) -> DiagnosticBuilder<'a> { let diag = &sess.span_diagnostic; let issue = match issue { @@ -812,7 +817,7 @@ pub fn emit_feature_err(sess: &ParseSess, feature: &str, span: Span, issue: Gate feature)); } - err.emit(); + err } const EXPLAIN_BOX_SYNTAX: &'static str = From d3c5905772d0ae1f251a5918fdaa52dbfd7519f2 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Tue, 18 Oct 2016 22:42:01 +0000 Subject: [PATCH 46/60] Allow bootstrapping without a key. Fixes #36548 This will make it easier for packagers to bootstrap rustc when they happen to have a bootstrap compiler with a slightly different version number. It's not ok for anything other than the build system to set this environment variable. --- mk/main.mk | 26 +++++--------------------- mk/target.mk | 21 --------------------- src/bootstrap/check.rs | 2 +- src/bootstrap/compile.rs | 3 +-- src/bootstrap/lib.rs | 17 ++++++----------- src/libsyntax/feature_gate.rs | 15 ++++++--------- src/stage0.txt | 1 - 7 files changed, 19 insertions(+), 66 deletions(-) diff --git a/mk/main.mk b/mk/main.mk index e68a8f3005561..d4efee90361b7 100644 --- a/mk/main.mk +++ b/mk/main.mk @@ -53,17 +53,6 @@ endif # versions in the same place CFG_FILENAME_EXTRA=$(shell printf '%s' $(CFG_RELEASE)$(CFG_EXTRA_FILENAME) | $(CFG_HASH_COMMAND)) -# A magic value that allows the compiler to use unstable features during the -# bootstrap even when doing so would normally be an error because of feature -# staging or because the build turns on warnings-as-errors and unstable features -# default to warnings. The build has to match this key in an env var. -# -# This value is keyed off the release to ensure that all compilers for one -# particular release have the same bootstrap key. Note that this is -# intentionally not "secure" by any definition, this is largely just a deterrent -# from users enabling unstable features on the stable compiler. -CFG_BOOTSTRAP_KEY=$(CFG_FILENAME_EXTRA) - # If local-rust is the same as the current version, then force a local-rebuild ifdef CFG_ENABLE_LOCAL_RUST ifeq ($(CFG_RELEASE),\ @@ -73,14 +62,6 @@ ifeq ($(CFG_RELEASE),\ endif endif -# The stage0 compiler needs to use the previous key recorded in src/stage0.txt, -# except for local-rebuild when it just uses the same current key. -ifdef CFG_ENABLE_LOCAL_REBUILD -CFG_BOOTSTRAP_KEY_STAGE0=$(CFG_BOOTSTRAP_KEY) -else -CFG_BOOTSTRAP_KEY_STAGE0=$(shell sed -ne 's/^rustc_key: //p' $(S)src/stage0.txt) -endif - # The name of the package to use for creating tarballs, installers etc. CFG_PACKAGE_NAME=rustc-$(CFG_PACKAGE_VERS) @@ -387,13 +368,16 @@ CFG_INFO := $(info cfg: disabling unstable features (CFG_DISABLE_UNSTABLE_FEATUR # Turn on feature-staging export CFG_DISABLE_UNSTABLE_FEATURES # Subvert unstable feature lints to do the self-build -export RUSTC_BOOTSTRAP_KEY:=$(CFG_BOOTSTRAP_KEY) +export RUSTC_BOOTSTRAP endif -export CFG_BOOTSTRAP_KEY ifdef CFG_MUSL_ROOT export CFG_MUSL_ROOT endif +# FIXME: Transitionary measure to bootstrap using the old bootstrap logic. +# Remove this once the bootstrap compiler uses the new login in Issue #36548. +export RUSTC_BOOTSTRAP_KEY=62b3e239 + ###################################################################### # Per-stage targets and runner ###################################################################### diff --git a/mk/target.mk b/mk/target.mk index 2a08b7b046534..1b139909ab458 100644 --- a/mk/target.mk +++ b/mk/target.mk @@ -42,23 +42,6 @@ $(foreach host,$(CFG_HOST), \ $(foreach crate,$(CRATES), \ $(eval $(call RUST_CRATE_FULLDEPS,$(stage),$(target),$(host),$(crate))))))) -# $(1) stage -# $(2) target -# $(3) host -define DEFINE_BOOTSTRAP_KEY -BOOTSTRAP_KEY$(1)_T_$(2)_H_$(3) := $$(CFG_BOOTSTRAP_KEY) -ifeq ($(1),0) -ifeq ($(3),$$(CFG_BUILD)) -BOOTSTRAP_KEY$(1)_T_$(2)_H_$(3) := $$(CFG_BOOTSTRAP_KEY_STAGE0) -endif -endif -endef - -$(foreach host,$(CFG_TARGET), \ - $(foreach target,$(CFG_TARGET), \ - $(foreach stage,$(STAGES), \ - $(eval $(call DEFINE_BOOTSTRAP_KEY,$(stage),$(target),$(host)))))) - # RUST_TARGET_STAGE_N template: This defines how target artifacts are built # for all stage/target architecture combinations. This is one giant rule which # works as follows: @@ -83,8 +66,6 @@ $(foreach host,$(CFG_TARGET), \ define RUST_TARGET_STAGE_N $$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$(4): CFG_COMPILER_HOST_TRIPLE = $(2) -$$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$(4): \ - export RUSTC_BOOTSTRAP_KEY := $$(BOOTSTRAP_KEY$(1)_T_$(2)_H_$(3)) $$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$(4): \ $$(CRATEFILE_$(4)) \ $$(CRATE_FULLDEPS_$(1)_T_$(2)_H_$(3)_$(4)) \ @@ -132,8 +113,6 @@ endef # $(4) - name of the tool being built define TARGET_TOOL -$$(TBIN$(1)_T_$(2)_H_$(3))/$(4)$$(X_$(2)): \ - export RUSTC_BOOTSTRAP_KEY := $$(BOOTSTRAP_KEY$(1)_T_$(2)_H_$(3)) $$(TBIN$(1)_T_$(2)_H_$(3))/$(4)$$(X_$(2)): \ $$(TOOL_SOURCE_$(4)) \ $$(TOOL_INPUTS_$(4)) \ diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index b8d0eb3ff996a..af76a49fed045 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -214,7 +214,7 @@ pub fn compiletest(build: &Build, } } } - build.add_bootstrap_key(compiler, &mut cmd); + build.add_bootstrap_key(&mut cmd); cmd.arg("--adb-path").arg("adb"); cmd.arg("--adb-test-dir").arg(ADB_TEST_DIR); diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 418c3a48ed348..ff8e4757bd1f1 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -119,7 +119,7 @@ fn build_startup_objects(build: &Build, target: &str, into: &Path) { for file in t!(fs::read_dir(build.src.join("src/rtstartup"))) { let file = t!(file); let mut cmd = Command::new(&compiler_path); - build.add_bootstrap_key(&compiler, &mut cmd); + build.add_bootstrap_key(&mut cmd); build.run(cmd.arg("--target").arg(target) .arg("--emit=obj") .arg("--out-dir").arg(into) @@ -185,7 +185,6 @@ pub fn rustc<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) { cargo.env("CFG_RELEASE", &build.release) .env("CFG_RELEASE_CHANNEL", &build.config.channel) .env("CFG_VERSION", &build.version) - .env("CFG_BOOTSTRAP_KEY", &build.bootstrap_key) .env("CFG_PREFIX", build.config.prefix.clone().unwrap_or(String::new())) .env("CFG_LIBDIR_RELATIVE", "lib"); diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 30983869c2e3b..a63c23b46212d 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -662,7 +662,7 @@ impl Build { .env("RUSTDOC_REAL", self.rustdoc(compiler)) .env("RUSTC_FLAGS", self.rustc_flags(target).join(" ")); - self.add_bootstrap_key(compiler, &mut cargo); + self.add_bootstrap_key(&mut cargo); // Specify some various options for build scripts used throughout // the build. @@ -871,16 +871,11 @@ impl Build { } /// Adds the compiler's bootstrap key to the environment of `cmd`. - fn add_bootstrap_key(&self, compiler: &Compiler, cmd: &mut Command) { - // In stage0 we're using a previously released stable compiler, so we - // use the stage0 bootstrap key. Otherwise we use our own build's - // bootstrap key. - let bootstrap_key = if compiler.is_snapshot(self) && !self.local_rebuild { - &self.bootstrap_key_stage0 - } else { - &self.bootstrap_key - }; - cmd.env("RUSTC_BOOTSTRAP_KEY", bootstrap_key); + fn add_bootstrap_key(&self, cmd: &mut Command) { + cmd.env("RUSTC_BOOTSTRAP", ""); + // FIXME: Transitionary measure to bootstrap using the old bootstrap logic. + // Remove this once the bootstrap compiler uses the new login in Issue #36548. + cmd.env("RUSTC_BOOTSTRAP_KEY", "62b3e239"); } /// Returns the compiler's libdir where it stores the dynamic libraries that diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 62b88888fc878..6cdfa35c9c5f4 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -1317,15 +1317,12 @@ impl UnstableFeatures { pub fn from_environment() -> UnstableFeatures { // Whether this is a feature-staged build, i.e. on the beta or stable channel let disable_unstable_features = option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some(); - // The secret key needed to get through the rustc build itself by - // subverting the unstable features lints - let bootstrap_secret_key = option_env!("CFG_BOOTSTRAP_KEY"); - // The matching key to the above, only known by the build system - let bootstrap_provided_key = env::var("RUSTC_BOOTSTRAP_KEY").ok(); - match (disable_unstable_features, bootstrap_secret_key, bootstrap_provided_key) { - (_, Some(ref s), Some(ref p)) if s == p => UnstableFeatures::Cheat, - (true, _, _) => UnstableFeatures::Disallow, - (false, _, _) => UnstableFeatures::Allow + // Whether we should enable unstable features for bootstrapping + let bootstrap = env::var("RUSTC_BOOTSTRAP").is_ok(); + match (disable_unstable_features, bootstrap) { + (_, true) => UnstableFeatures::Cheat, + (true, _) => UnstableFeatures::Disallow, + (false, _) => UnstableFeatures::Allow } } diff --git a/src/stage0.txt b/src/stage0.txt index 05189f2011b0d..ac2050a6fc8f1 100644 --- a/src/stage0.txt +++ b/src/stage0.txt @@ -13,5 +13,4 @@ # released on `$date` rustc: beta-2016-09-28 -rustc_key: 62b3e239 cargo: nightly-2016-09-26 From 016f69f459d1b3819aa7c9d632a0dc78c7764406 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 19 Oct 2016 12:06:46 +1100 Subject: [PATCH 47/60] Optimize `write_metadata`. `write_metadata` currently generates metadata unnecessarily in some cases, and also compresses it unnecessarily in some cases. This commit fixes that. It speeds up three of the rustc-benchmarks by 1--4%. --- src/librustc_trans/base.rs | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 3caf8c9e4c3b8..02aa7c069f9b3 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -1250,12 +1250,27 @@ fn write_metadata(cx: &SharedCrateContext, reachable_ids: &NodeSet) -> Vec { use flate; - let any_library = cx.sess() - .crate_types - .borrow() - .iter() - .any(|ty| *ty != config::CrateTypeExecutable); - if !any_library { + #[derive(PartialEq, Eq, PartialOrd, Ord)] + enum MetadataKind { + None, + Uncompressed, + Compressed + } + + let kind = cx.sess().crate_types.borrow().iter().map(|ty| { + match *ty { + config::CrateTypeExecutable | + config::CrateTypeStaticlib | + config::CrateTypeCdylib => MetadataKind::None, + + config::CrateTypeRlib => MetadataKind::Uncompressed, + + config::CrateTypeDylib | + config::CrateTypeProcMacro => MetadataKind::Compressed, + } + }).max().unwrap(); + + if kind == MetadataKind::None { return Vec::new(); } @@ -1265,6 +1280,11 @@ fn write_metadata(cx: &SharedCrateContext, cx.link_meta(), reachable_ids, cx.mir_map()); + if kind == MetadataKind::Uncompressed { + return metadata; + } + + assert!(kind == MetadataKind::Compressed); let mut compressed = cstore.metadata_encoding_version().to_vec(); compressed.extend_from_slice(&flate::deflate_bytes(&metadata)); From ab5dcff1314a800b03fd179a22610f4640a9d071 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 19 Oct 2016 07:37:20 +0300 Subject: [PATCH 48/60] Format comment in a nicer way. Just kidding I'm doing this only to unstuck @bors/homu/buildbot. --- src/librustc/ty/subst.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index 6beb2b968e2b5..e82da3c395831 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -306,8 +306,8 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx Substs<'tcx> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { let params: Vec<_> = self.iter().map(|k| k.fold_with(folder)).collect(); - // If folding doesn't change the substs, it's faster to avoid calling - // `mk_substs` and instead reuse the existing substs. + // If folding doesn't change the substs, it's faster to avoid + // calling `mk_substs` and instead reuse the existing substs. if params[..] == self[..] { self } else { From 6a6ef91ba757d33d0f5155c1ebb628998158a8cd Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Sun, 16 Oct 2016 02:38:08 +0000 Subject: [PATCH 49/60] nit: Import `Ident` in `resolve`. --- src/librustc_resolve/lib.rs | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 298f41b971d06..a89f8cffba146 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -55,7 +55,7 @@ use rustc::util::nodemap::{NodeMap, NodeSet, FnvHashMap, FnvHashSet}; use syntax::ext::hygiene::Mark; use syntax::ast::{self, FloatTy}; -use syntax::ast::{CRATE_NODE_ID, Name, NodeId, IntTy, UintTy}; +use syntax::ast::{CRATE_NODE_ID, Name, NodeId, Ident, IntTy, UintTy}; use syntax::ext::base::SyntaxExtension; use syntax::parse::token::{self, keywords}; use syntax::util::lev_distance::find_best_match_for_name; @@ -509,7 +509,7 @@ struct BindingInfo { } // Map from the name in a pattern to its binding mode. -type BindingMap = FnvHashMap; +type BindingMap = FnvHashMap; #[derive(Copy, Clone, PartialEq, Eq, Debug)] enum PatternSource { @@ -714,7 +714,7 @@ enum ModulePrefixResult<'a> { /// One local scope. #[derive(Debug)] struct Rib<'a> { - bindings: FnvHashMap, + bindings: FnvHashMap, kind: RibKind<'a>, } @@ -1479,7 +1479,7 @@ impl<'a> Resolver<'a> { // This is not a crate-relative path. We resolve the // first component of the path in the current lexical // scope and then proceed to resolve below that. - let ident = ast::Ident::with_empty_ctxt(module_path[0]); + let ident = Ident::with_empty_ctxt(module_path[0]); let lexical_binding = self.resolve_ident_in_lexical_scope(ident, TypeNS, span); if let Some(binding) = lexical_binding.and_then(LexicalScopeBinding::item) { @@ -1525,12 +1525,12 @@ impl<'a> Resolver<'a> { /// Invariant: This must only be called during main resolution, not during /// import resolution. fn resolve_ident_in_lexical_scope(&mut self, - mut ident: ast::Ident, + mut ident: Ident, ns: Namespace, record_used: Option) -> Option> { if ns == TypeNS { - ident = ast::Ident::with_empty_ctxt(ident.name); + ident = Ident::with_empty_ctxt(ident.name); } // Walk backwards up the ribs in scope. @@ -1649,7 +1649,7 @@ impl<'a> Resolver<'a> { /// Searches the current set of local scopes for labels. /// Stops after meeting a closure. - fn search_label(&self, mut ident: ast::Ident) -> Option { + fn search_label(&self, mut ident: Ident) -> Option { for rib in self.label_ribs.iter().rev() { match rib.kind { NormalRibKind => { @@ -1813,7 +1813,7 @@ impl<'a> Resolver<'a> { // plain insert (no renaming) let def_id = self.definitions.local_def_id(type_parameter.id); let def = Def::TyParam(def_id); - function_type_rib.bindings.insert(ast::Ident::with_empty_ctxt(name), def); + function_type_rib.bindings.insert(Ident::with_empty_ctxt(name), def); self.record_def(type_parameter.id, PathResolution::new(def)); } self.type_ribs.push(function_type_rib); @@ -2271,7 +2271,7 @@ impl<'a> Resolver<'a> { pat_id: NodeId, outer_pat_id: NodeId, pat_src: PatternSource, - bindings: &mut FnvHashMap) + bindings: &mut FnvHashMap) -> PathResolution { // Add the binding to the local ribs, if it // doesn't already exist in the bindings map. (We @@ -2372,7 +2372,7 @@ impl<'a> Resolver<'a> { pat_src: PatternSource, // Maps idents to the node ID for the // outermost pattern that binds them. - bindings: &mut FnvHashMap) { + bindings: &mut FnvHashMap) { // Visit all direct subpatterns of this pattern. let outer_pat_id = pat.id; pat.walk(&mut |pat| { @@ -2573,7 +2573,7 @@ impl<'a> Resolver<'a> { // Resolve a single identifier fn resolve_identifier(&mut self, - identifier: ast::Ident, + identifier: Ident, namespace: Namespace, record_used: Option) -> Option { @@ -2835,7 +2835,7 @@ impl<'a> Resolver<'a> { } SuggestionType::NotFound } - fn resolve_labeled_block(&mut self, label: Option, id: NodeId, block: &Block) { + fn resolve_labeled_block(&mut self, label: Option, id: NodeId, block: &Block) { if let Some(label) = label { let def = Def::Label(id); self.with_label_rib(|this| { @@ -3237,7 +3237,7 @@ impl<'a> Resolver<'a> { if name == lookup_name && ns == namespace { if filter_fn(name_binding.def()) { // create the path - let ident = ast::Ident::with_empty_ctxt(name); + let ident = Ident::with_empty_ctxt(name); let params = PathParameters::none(); let segment = PathSegment { identifier: ident, @@ -3271,7 +3271,7 @@ impl<'a> Resolver<'a> { _ if module.parent.is_none() => path_segments.clone(), ModuleKind::Def(_, name) => { let mut paths = path_segments.clone(); - let ident = ast::Ident::with_empty_ctxt(name); + let ident = Ident::with_empty_ctxt(name); let params = PathParameters::none(); let segm = PathSegment { identifier: ident, From 7b81106a8525f96d5a5890720cee265e49e77028 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Sun, 16 Oct 2016 03:06:09 +0000 Subject: [PATCH 50/60] Use `Ident`s instead of `Name`s in `ImportDirective`'s paths. --- src/librustc_resolve/build_reduced_graph.rs | 8 +-- src/librustc_resolve/lib.rs | 65 +++++++++------------ src/librustc_resolve/resolve_imports.rs | 8 +-- 3 files changed, 37 insertions(+), 44 deletions(-) diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index e0abe8da82b9c..b26f40839d009 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -95,14 +95,14 @@ impl<'b> Resolver<'b> { // Extract and intern the module part of the path. For // globs and lists, the path is found directly in the AST; // for simple paths we have to munge the path a little. - let module_path: Vec = match view_path.node { + let module_path: Vec<_> = match view_path.node { ViewPathSimple(_, ref full_path) => { full_path.segments .split_last() .unwrap() .1 .iter() - .map(|seg| seg.identifier.name) + .map(|seg| seg.identifier) .collect() } @@ -110,7 +110,7 @@ impl<'b> Resolver<'b> { ViewPathList(ref module_ident_path, _) => { module_ident_path.segments .iter() - .map(|seg| seg.identifier.name) + .map(|seg| seg.identifier) .collect() } }; @@ -159,7 +159,7 @@ impl<'b> Resolver<'b> { (module_path.clone(), node.name.name, rename) } else { let name = match module_path.last() { - Some(name) => *name, + Some(ident) => ident.name, None => { resolve_error( self, diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index a89f8cffba146..172648c01e046 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1178,18 +1178,18 @@ impl<'a> hir::lowering::Resolver for Resolver<'a> { } trait Named { - fn name(&self) -> Name; + fn ident(&self) -> Ident; } impl Named for ast::PathSegment { - fn name(&self) -> Name { - self.identifier.name + fn ident(&self) -> Ident { + self.identifier } } impl Named for hir::PathSegment { - fn name(&self) -> Name { - self.name + fn ident(&self) -> Ident { + Ident::with_empty_ctxt(self.name) } } @@ -1364,7 +1364,7 @@ impl<'a> Resolver<'a> { /// Resolves the given module path from the given root `search_module`. fn resolve_module_path_from_root(&mut self, mut search_module: Module<'a>, - module_path: &[Name], + module_path: &[Ident], index: usize, span: Option) -> ResolveResult> { @@ -1387,7 +1387,7 @@ impl<'a> Resolver<'a> { // upward though scope chains; we simply resolve names directly in // modules as we go. while index < module_path_len { - let name = module_path[index]; + let name = module_path[index].name; match self.resolve_name_in_module(search_module, name, TypeNS, false, span) { Failed(_) => { let segment_name = name.as_str(); @@ -1441,7 +1441,7 @@ impl<'a> Resolver<'a> { /// Attempts to resolve the module part of an import directive or path /// rooted at the given module. fn resolve_module_path(&mut self, - module_path: &[Name], + module_path: &[Ident], use_lexical_scope: UseLexicalScopeFlag, span: Option) -> ResolveResult> { @@ -1479,7 +1479,7 @@ impl<'a> Resolver<'a> { // This is not a crate-relative path. We resolve the // first component of the path in the current lexical // scope and then proceed to resolve below that. - let ident = Ident::with_empty_ctxt(module_path[0]); + let ident = module_path[0]; let lexical_binding = self.resolve_ident_in_lexical_scope(ident, TypeNS, span); if let Some(binding) = lexical_binding.and_then(LexicalScopeBinding::item) { @@ -1577,11 +1577,11 @@ impl<'a> Resolver<'a> { /// Resolves a "module prefix". A module prefix is one or both of (a) `self::`; /// (b) some chain of `super::`. /// grammar: (SELF MOD_SEP ) ? (SUPER MOD_SEP) * - fn resolve_module_prefix(&mut self, module_path: &[Name], span: Option) + fn resolve_module_prefix(&mut self, module_path: &[Ident], span: Option) -> ResolveResult> { // Start at the current module if we see `self` or `super`, or at the // top of the crate otherwise. - let mut i = match &*module_path[0].as_str() { + let mut i = match &*module_path[0].name.as_str() { "self" => 1, "super" => 0, _ => return Success(NoPrefixFound), @@ -1591,7 +1591,7 @@ impl<'a> Resolver<'a> { self.module_map[&self.current_module.normal_ancestor_id.unwrap()]; // Now loop through all the `super`s we find. - while i < module_path.len() && "super" == module_path[i].as_str() { + while i < module_path.len() && "super" == module_path[i].name.as_str() { debug!("(resolving module prefix) resolving `super` at {}", module_to_string(&containing_module)); if let Some(parent) = containing_module.parent { @@ -2681,12 +2681,8 @@ impl<'a> Resolver<'a> { namespace: Namespace) -> Result<&'a NameBinding<'a>, bool /* true if an error was reported */> { - let module_path = segments.split_last() - .unwrap() - .1 - .iter() - .map(|ps| ps.identifier.name) - .collect::>(); + let module_path = + segments.split_last().unwrap().1.iter().map(|ps| ps.identifier).collect::>(); let containing_module; match self.resolve_module_path(&module_path, UseLexicalScope, Some(span)) { @@ -2715,7 +2711,7 @@ impl<'a> Resolver<'a> { bool /* true if an error was reported */> where T: Named, { - let module_path = segments.split_last().unwrap().1.iter().map(T::name).collect::>(); + let module_path = segments.split_last().unwrap().1.iter().map(T::ident).collect::>(); let root_module = self.graph_root; let containing_module; @@ -2734,7 +2730,7 @@ impl<'a> Resolver<'a> { } } - let name = segments.last().unwrap().name(); + let name = segments.last().unwrap().ident().name; let result = self.resolve_name_in_module(containing_module, name, namespace, false, Some(span)); result.success().ok_or(false) @@ -2976,9 +2972,8 @@ impl<'a> Resolver<'a> { msg = format!("did you mean {}?", msg); } else { // we display a help message if this is a module - let name_path = path.segments.iter() - .map(|seg| seg.identifier.name) - .collect::>(); + let name_path: Vec<_> = + path.segments.iter().map(|seg| seg.identifier).collect(); match self.resolve_module_path(&name_path[..], UseLexicalScope, @@ -3317,7 +3312,7 @@ impl<'a> Resolver<'a> { } }; - let segments: Vec<_> = path.segments.iter().map(|seg| seg.identifier.name).collect(); + let segments: Vec<_> = path.segments.iter().map(|seg| seg.identifier).collect(); let mut path_resolution = err_path_resolution(); let vis = match self.resolve_module_path(&segments, DontUseLexicalScope, Some(path.span)) { Success(module) => { @@ -3469,26 +3464,24 @@ impl<'a> Resolver<'a> { } } -fn names_to_string(names: &[Name]) -> String { +fn names_to_string(names: &[Ident]) -> String { let mut first = true; let mut result = String::new(); - for name in names { + for ident in names { if first { first = false } else { result.push_str("::") } - result.push_str(&name.as_str()); + result.push_str(&ident.name.as_str()); } result } fn path_names_to_string(path: &Path, depth: usize) -> String { - let names: Vec = path.segments[..path.segments.len() - depth] - .iter() - .map(|seg| seg.identifier.name) - .collect(); - names_to_string(&names[..]) + let names: Vec<_> = + path.segments[..path.segments.len() - depth].iter().map(|seg| seg.identifier).collect(); + names_to_string(&names) } /// When an entity with a given name is not available in scope, we search for @@ -3551,15 +3544,15 @@ fn show_candidates(session: &mut DiagnosticBuilder, fn module_to_string(module: Module) -> String { let mut names = Vec::new(); - fn collect_mod(names: &mut Vec, module: Module) { + fn collect_mod(names: &mut Vec, module: Module) { if let ModuleKind::Def(_, name) = module.kind { if let Some(parent) = module.parent { - names.push(name); + names.push(Ident::with_empty_ctxt(name)); collect_mod(names, parent); } } else { // danger, shouldn't be ident? - names.push(token::intern("")); + names.push(token::str_to_ident("")); collect_mod(names, module.parent.unwrap()); } } @@ -3568,7 +3561,7 @@ fn module_to_string(module: Module) -> String { if names.is_empty() { return "???".to_string(); } - names_to_string(&names.into_iter().rev().collect::>()) + names_to_string(&names.into_iter().rev().collect::>()) } fn err_path_resolution() -> PathResolution { diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 0939e6f1644de..2b3945bd0d920 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -24,7 +24,7 @@ use rustc::ty; use rustc::lint::builtin::PRIVATE_IN_PUBLIC; use rustc::hir::def::*; -use syntax::ast::{NodeId, Name}; +use syntax::ast::{Ident, NodeId, Name}; use syntax::ext::base::Determinacy::{self, Determined, Undetermined}; use syntax::util::lev_distance::find_best_match_for_name; use syntax_pos::Span; @@ -69,7 +69,7 @@ impl<'a> ImportDirectiveSubclass<'a> { pub struct ImportDirective<'a> { pub id: NodeId, parent: Module<'a>, - module_path: Vec, + module_path: Vec, imported_module: Cell>>, // the resolution of `module_path` subclass: ImportDirectiveSubclass<'a>, span: Span, @@ -252,7 +252,7 @@ impl<'a> Resolver<'a> { // Add an import directive to the current module. pub fn add_import_directive(&mut self, - module_path: Vec, + module_path: Vec, subclass: ImportDirectiveSubclass<'a>, span: Span, id: NodeId, @@ -816,7 +816,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { } } -fn import_path_to_string(names: &[Name], subclass: &ImportDirectiveSubclass) -> String { +fn import_path_to_string(names: &[Ident], subclass: &ImportDirectiveSubclass) -> String { if names.is_empty() { import_directive_subclass_to_string(subclass) } else { From 8b0c292a728c113aaf1f27f079aae6a28110c587 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Sun, 16 Oct 2016 03:39:52 +0000 Subject: [PATCH 51/60] Improve `$crate`. --- src/librustc_resolve/build_reduced_graph.rs | 17 +++++++++++ src/librustc_resolve/lib.rs | 13 ++++++++- src/librustc_resolve/macros.rs | 4 +-- src/librustdoc/html/highlight.rs | 5 ++-- src/libsyntax/ext/expand.rs | 2 +- src/libsyntax/ext/tt/macro_rules.rs | 12 ++------ src/libsyntax/ext/tt/transcribe.rs | 31 ++------------------- src/libsyntax/parse/mod.rs | 2 +- src/libsyntax/parse/parser.rs | 9 ++++-- src/libsyntax/parse/token.rs | 17 ----------- src/libsyntax/print/pprust.rs | 2 -- src/libsyntax/tokenstream.rs | 7 ----- src/test/pretty/issue-4264.pp | 2 +- 13 files changed, 47 insertions(+), 76 deletions(-) diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index b26f40839d009..f19afd67faa21 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -37,6 +37,7 @@ use syntax::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind}; use syntax::ast::{Mutability, StmtKind, TraitItem, TraitItemKind}; use syntax::ast::{Variant, ViewPathGlob, ViewPathList, ViewPathSimple}; use syntax::ext::base::{SyntaxExtension, Resolver as SyntaxResolver}; +use syntax::ext::expand::mark_tts; use syntax::ext::hygiene::Mark; use syntax::feature_gate::{self, emit_feature_err}; use syntax::ext::tt::macro_rules; @@ -207,11 +208,16 @@ impl<'b> Resolver<'b> { }; let mut custom_derive_crate = false; + // The mark of the expansion that generates the loaded macros. + let mut opt_mark = None; for loaded_macro in self.crate_loader.load_macros(item, is_crate_root) { + let mark = opt_mark.unwrap_or_else(Mark::fresh); + opt_mark = Some(mark); match loaded_macro.kind { LoadedMacroKind::Def(mut def) => { if def.use_locally { self.macro_names.insert(def.ident.name); + def.body = mark_tts(&def.body, mark); let ext = macro_rules::compile(&self.session.parse_sess, &def); import_macro(self, def.ident.name, ext, loaded_macro.import_site); } @@ -249,6 +255,17 @@ impl<'b> Resolver<'b> { }); self.define(parent, name, TypeNS, (module, sp, vis)); + if let Some(mark) = opt_mark { + let invocation = self.arenas.alloc_invocation_data(InvocationData { + module: Cell::new(module), + def_index: CRATE_DEF_INDEX, + const_integer: false, + legacy_scope: Cell::new(LegacyScope::Empty), + expansion: Cell::new(LegacyScope::Empty), + }); + self.invocations.insert(mark, invocation); + } + self.populate_module_if_necessary(module); } else if custom_derive_crate { // Define an empty module diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 172648c01e046..7091d7d2a6321 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -53,7 +53,7 @@ use rustc::ty; use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap}; use rustc::util::nodemap::{NodeMap, NodeSet, FnvHashMap, FnvHashSet}; -use syntax::ext::hygiene::Mark; +use syntax::ext::hygiene::{Mark, SyntaxContext}; use syntax::ast::{self, FloatTy}; use syntax::ast::{CRATE_NODE_ID, Name, NodeId, Ident, IntTy, UintTy}; use syntax::ext::base::SyntaxExtension; @@ -1579,6 +1579,17 @@ impl<'a> Resolver<'a> { /// grammar: (SELF MOD_SEP ) ? (SUPER MOD_SEP) * fn resolve_module_prefix(&mut self, module_path: &[Ident], span: Option) -> ResolveResult> { + if &*module_path[0].name.as_str() == "$crate" { + let mut ctxt = module_path[0].ctxt; + while ctxt.source().0 != SyntaxContext::empty() { + ctxt = ctxt.source().0; + } + let module = self.invocations[&ctxt.source().1].module.get(); + let crate_root = + if module.def_id().unwrap().is_local() { self.graph_root } else { module }; + return Success(PrefixFound(crate_root, 1)) + } + // Start at the current module if we see `self` or `super`, or at the // top of the crate otherwise. let mut i = match &*module_path[0].name.as_str() { diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index cf5ea236b3ec7..0f42b4520c9b7 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -29,10 +29,10 @@ use syntax_pos::Span; #[derive(Clone)] pub struct InvocationData<'a> { pub module: Cell>, - def_index: DefIndex, + pub def_index: DefIndex, // True if this expansion is in a `const_integer` position, for example `[u32; m!()]`. // c.f. `DefCollector::visit_ast_const_integer`. - const_integer: bool, + pub const_integer: bool, // The scope in which the invocation path is resolved. pub legacy_scope: Cell>, // The smallest scope that includes this invocation's expansion, diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index d1fe7853445f2..bd47b1e7c121c 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -295,7 +295,9 @@ impl<'a> Classifier<'a> { "Option" | "Result" => Class::PreludeTy, "Some" | "None" | "Ok" | "Err" => Class::PreludeVal, + "$crate" => Class::KeyWord, _ if tas.tok.is_any_keyword() => Class::KeyWord, + _ => { if self.in_macro_nonterminal { self.in_macro_nonterminal = false; @@ -310,9 +312,6 @@ impl<'a> Classifier<'a> { } } - // Special macro vars are like keywords. - token::SpecialVarNt(_) => Class::KeyWord, - token::Lifetime(..) => Class::Lifetime, token::Underscore | token::Eof | token::Interpolated(..) | diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 6aeb46fd52276..e84a9208029a5 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -939,6 +939,6 @@ impl Folder for Marker { } // apply a given mark to the given token trees. Used prior to expansion of a macro. -fn mark_tts(tts: &[TokenTree], m: Mark) -> Vec { +pub fn mark_tts(tts: &[TokenTree], m: Mark) -> Vec { noop_fold_tts(tts, &mut Marker{mark:m, expn_id: None}) } diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index a74d335d6046d..5496d27c08740 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -58,7 +58,6 @@ impl<'a> ParserAnyMacro<'a> { struct MacroRulesMacroExpander { name: ast::Ident, - imported_from: Option, lhses: Vec, rhses: Vec, valid: bool, @@ -76,7 +75,6 @@ impl TTMacroExpander for MacroRulesMacroExpander { generic_extension(cx, sp, self.name, - self.imported_from, arg, &self.lhses, &self.rhses) @@ -87,7 +85,6 @@ impl TTMacroExpander for MacroRulesMacroExpander { fn generic_extension<'cx>(cx: &'cx ExtCtxt, sp: Span, name: ast::Ident, - imported_from: Option, arg: &[TokenTree], lhses: &[TokenTree], rhses: &[TokenTree]) @@ -116,10 +113,8 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt, _ => cx.span_bug(sp, "malformed macro rhs"), }; // rhs has holes ( `$id` and `$(...)` that need filled) - let trncbr = new_tt_reader(&cx.parse_sess.span_diagnostic, - Some(named_matches), - imported_from, - rhs); + let trncbr = + new_tt_reader(&cx.parse_sess.span_diagnostic, Some(named_matches), rhs); let mut p = Parser::new(cx.parse_sess(), cx.cfg().clone(), Box::new(trncbr)); p.directory = cx.current_expansion.module.directory.clone(); p.restrictions = match cx.current_expansion.no_noninline_mod { @@ -223,7 +218,7 @@ pub fn compile(sess: &ParseSess, def: &ast::MacroDef) -> SyntaxExtension { ]; // Parse the macro_rules! invocation (`none` is for no interpolations): - let arg_reader = new_tt_reader(&sess.span_diagnostic, None, None, def.body.clone()); + let arg_reader = new_tt_reader(&sess.span_diagnostic, None, def.body.clone()); let argument_map = match parse(sess, &Vec::new(), arg_reader, &argument_gram) { Success(m) => m, @@ -269,7 +264,6 @@ pub fn compile(sess: &ParseSess, def: &ast::MacroDef) -> SyntaxExtension { let exp: Box<_> = Box::new(MacroRulesMacroExpander { name: def.ident, - imported_from: def.imported_from, lhses: lhses, rhses: rhses, valid: valid, diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index 205c709d6cb40..38a926b6e87c9 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -14,7 +14,7 @@ use syntax_pos::{Span, DUMMY_SP}; use errors::{Handler, DiagnosticBuilder}; use ext::tt::macro_parser::{NamedMatch, MatchedSeq, MatchedNonterminal}; use parse::token::{DocComment, MatchNt, SubstNt}; -use parse::token::{Token, Interpolated, NtIdent, NtTT, SpecialMacroVar}; +use parse::token::{Token, Interpolated, NtIdent, NtTT}; use parse::token; use parse::lexer::TokenAndSpan; use tokenstream::{self, TokenTree}; @@ -39,10 +39,7 @@ pub struct TtReader<'a> { stack: Vec, /* for MBE-style macro transcription */ interpolations: HashMap>, - imported_from: Option, - // Some => return imported_from as the next token - crate_name_next: Option, repeat_idx: Vec, repeat_len: Vec, /* cached: */ @@ -59,10 +56,9 @@ pub struct TtReader<'a> { /// (and should) be None. pub fn new_tt_reader(sp_diag: &Handler, interp: Option>>, - imported_from: Option, src: Vec) -> TtReader { - new_tt_reader_with_doc_flag(sp_diag, interp, imported_from, src, false) + new_tt_reader_with_doc_flag(sp_diag, interp, src, false) } /// The extra `desugar_doc_comments` flag enables reading doc comments @@ -73,7 +69,6 @@ pub fn new_tt_reader(sp_diag: &Handler, /// (and should) be None. pub fn new_tt_reader_with_doc_flag(sp_diag: &Handler, interp: Option>>, - imported_from: Option, src: Vec, desugar_doc_comments: bool) -> TtReader { @@ -93,8 +88,6 @@ pub fn new_tt_reader_with_doc_flag(sp_diag: &Handler, None => HashMap::new(), Some(x) => x, }, - imported_from: imported_from, - crate_name_next: None, repeat_idx: Vec::new(), repeat_len: Vec::new(), desugar_doc_comments: desugar_doc_comments, @@ -189,14 +182,6 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan { sp: r.cur_span.clone(), }; loop { - match r.crate_name_next.take() { - None => (), - Some(sp) => { - r.cur_span = sp; - r.cur_tok = token::Ident(r.imported_from.unwrap()); - return ret_val; - }, - } let should_pop = match r.stack.last() { None => { assert_eq!(ret_val.tok, token::Eof); @@ -346,18 +331,6 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan { sep: None }); } - TokenTree::Token(sp, token::SpecialVarNt(SpecialMacroVar::CrateMacroVar)) => { - r.stack.last_mut().unwrap().idx += 1; - - if r.imported_from.is_some() { - r.cur_span = sp; - r.cur_tok = token::ModSep; - r.crate_name_next = Some(sp); - return ret_val; - } - - // otherwise emit nothing and proceed to the next token - } TokenTree::Token(sp, tok) => { r.cur_span = sp; r.cur_tok = tok; diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 1e286c143de9b..1a84a750463c8 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -276,7 +276,7 @@ pub fn filemap_to_tts(sess: &ParseSess, filemap: Rc) pub fn tts_to_parser<'a>(sess: &'a ParseSess, tts: Vec, cfg: ast::CrateConfig) -> Parser<'a> { - let trdr = lexer::new_tt_reader(&sess.span_diagnostic, None, None, tts); + let trdr = lexer::new_tt_reader(&sess.span_diagnostic, None, tts); let mut p = Parser::new(sess, cfg, Box::new(trdr)); p.check_unknown_macro_variable(); p diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 61268d457ce44..eac78f5e6c68c 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -48,8 +48,7 @@ use parse::classify; use parse::common::SeqSep; use parse::lexer::{Reader, TokenAndSpan}; use parse::obsolete::ObsoleteSyntax; -use parse::token::{self, intern, MatchNt, SubstNt, SpecialVarNt, InternedString}; -use parse::token::{keywords, SpecialMacroVar}; +use parse::token::{self, intern, keywords, MatchNt, SubstNt, InternedString}; use parse::{new_sub_parser_from_file, ParseSess}; use util::parser::{AssocOp, Fixity}; use print::pprust; @@ -2653,8 +2652,12 @@ impl<'a> Parser<'a> { num_captures: name_num }))); } else if self.token.is_keyword(keywords::Crate) { + let ident = match self.token { + token::Ident(id) => ast::Ident { name: token::intern("$crate"), ..id }, + _ => unreachable!(), + }; self.bump(); - return Ok(TokenTree::Token(sp, SpecialVarNt(SpecialMacroVar::CrateMacroVar))); + return Ok(TokenTree::Token(sp, token::Ident(ident))); } else { sp = mk_sp(sp.lo, self.span.hi); self.parse_ident().unwrap_or_else(|mut e| { diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 3d4dd9ec06457..26b5b99c8cce6 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -52,21 +52,6 @@ pub enum DelimToken { NoDelim, } -#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)] -pub enum SpecialMacroVar { - /// `$crate` will be filled in with the name of the crate a macro was - /// imported from, if any. - CrateMacroVar, -} - -impl SpecialMacroVar { - pub fn as_str(self) -> &'static str { - match self { - SpecialMacroVar::CrateMacroVar => "crate", - } - } -} - #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)] pub enum Lit { Byte(ast::Name), @@ -148,8 +133,6 @@ pub enum Token { // In right-hand-sides of MBE macros: /// A syntactic variable that will be filled in by macro expansion. SubstNt(ast::Ident), - /// A macro variable with special meaning. - SpecialVarNt(SpecialMacroVar), // Junk. These carry no data because we don't really care about the data // they *would* carry, and don't really want to allocate a new ident for diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 89834da28219c..c6f63d772426a 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -285,8 +285,6 @@ pub fn token_to_string(tok: &Token) -> String { token::Comment => "/* */".to_string(), token::Shebang(s) => format!("/* shebang: {}*/", s), - token::SpecialVarNt(var) => format!("${}", var.as_str()), - token::Interpolated(ref nt) => match *nt { token::NtExpr(ref e) => expr_to_string(&e), token::NtMeta(ref e) => meta_item_to_string(&e), diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs index b35b4617ea11e..f22f920a7fa0e 100644 --- a/src/libsyntax/tokenstream.rs +++ b/src/libsyntax/tokenstream.rs @@ -134,7 +134,6 @@ impl TokenTree { AttrStyle::Inner => 3, } } - TokenTree::Token(_, token::SpecialVarNt(..)) => 2, TokenTree::Token(_, token::MatchNt(..)) => 3, TokenTree::Token(_, token::Interpolated(Nonterminal::NtTT(..))) => 1, TokenTree::Delimited(_, ref delimed) => delimed.tts.len() + 2, @@ -188,11 +187,6 @@ impl TokenTree { } delimed.tts[index - 1].clone() } - (&TokenTree::Token(sp, token::SpecialVarNt(var)), _) => { - let v = [TokenTree::Token(sp, token::Dollar), - TokenTree::Token(sp, token::Ident(token::str_to_ident(var.as_str())))]; - v[index].clone() - } (&TokenTree::Token(sp, token::MatchNt(name, kind)), _) => { let v = [TokenTree::Token(sp, token::SubstNt(name)), TokenTree::Token(sp, token::Colon), @@ -223,7 +217,6 @@ impl TokenTree { -> macro_parser::NamedParseResult { // `None` is because we're not interpolating let arg_rdr = lexer::new_tt_reader_with_doc_flag(&cx.parse_sess().span_diagnostic, - None, None, tts.iter().cloned().collect(), true); diff --git a/src/test/pretty/issue-4264.pp b/src/test/pretty/issue-4264.pp index 6ce534d52b883..40ff4852e3856 100644 --- a/src/test/pretty/issue-4264.pp +++ b/src/test/pretty/issue-4264.pp @@ -38,7 +38,7 @@ - ((::std::fmt::format as + (($crate::fmt::format as fn(std::fmt::Arguments<'_>) -> std::string::String {std::fmt::format})(((::std::fmt::Arguments::new_v1 as fn(&[&str], &[std::fmt::ArgumentV1<'_>]) -> std::fmt::Arguments<'_> {std::fmt::Arguments<'_>::new_v1})(({ From a714c2a15c8cc36dc2cce36e32dfe3a8fc836532 Mon Sep 17 00:00:00 2001 From: Mark-Simulacrum Date: Mon, 17 Oct 2016 15:03:40 -0600 Subject: [PATCH 52/60] Add TypedArena::alloc_slice. --- src/libarena/lib.rs | 45 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 39 insertions(+), 6 deletions(-) diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index 4986c9850d7c7..cfbd29571f7b2 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -46,6 +46,7 @@ use std::intrinsics; use std::marker::{PhantomData, Send}; use std::mem; use std::ptr; +use std::slice; use alloc::heap; use alloc::raw_vec::RawVec; @@ -133,7 +134,7 @@ impl TypedArena { #[inline] pub fn alloc(&self, object: T) -> &mut T { if self.ptr == self.end { - self.grow() + self.grow(1) } unsafe { @@ -154,24 +155,56 @@ impl TypedArena { } } + /// Allocates a slice of objects that are copy into the `TypedArena`, returning a mutable + /// reference to it. Will panic if passed a zero-sized types. + #[inline] + pub fn alloc_slice(&self, slice: &[T]) -> &mut [T] + where T: Copy { + assert!(mem::size_of::() != 0); + if slice.len() == 0 { + return unsafe { slice::from_raw_parts_mut(heap::EMPTY as *mut T, 0) }; + } + + let available_capacity_bytes = self.end.get() as usize - self.ptr.get() as usize; + let at_least_bytes = slice.len() * mem::size_of::(); + if available_capacity_bytes < at_least_bytes { + self.grow(slice.len()); + } + + unsafe { + let start_ptr = self.ptr.get(); + let arena_slice = slice::from_raw_parts_mut(start_ptr, slice.len()); + self.ptr.set(start_ptr.offset(arena_slice.len() as isize)); + arena_slice.copy_from_slice(slice); + arena_slice + } + } + /// Grows the arena. #[inline(never)] #[cold] - fn grow(&self) { + fn grow(&self, n: usize) { unsafe { let mut chunks = self.chunks.borrow_mut(); - let (chunk, new_capacity); + let (chunk, mut new_capacity); if let Some(last_chunk) = chunks.last_mut() { - if last_chunk.storage.double_in_place() { + let used_bytes = self.ptr.get() as usize - last_chunk.start() as usize; + let currently_used_cap = used_bytes / mem::size_of::(); + if last_chunk.storage.reserve_in_place(currently_used_cap, n) { self.end.set(last_chunk.end()); return; } else { let prev_capacity = last_chunk.storage.cap(); - new_capacity = prev_capacity.checked_mul(2).unwrap(); + loop { + new_capacity = prev_capacity.checked_mul(2).unwrap(); + if new_capacity >= currently_used_cap + n { + break; + } + } } } else { let elem_size = cmp::max(1, mem::size_of::()); - new_capacity = cmp::max(1, PAGE / elem_size); + new_capacity = cmp::max(n, PAGE / elem_size); } chunk = TypedArenaChunk::::new(new_capacity); self.ptr.set(chunk.start()); From 83b198249f6a417a96bce9d4264257f53ff7b48f Mon Sep 17 00:00:00 2001 From: Mark-Simulacrum Date: Sun, 16 Oct 2016 21:21:25 -0600 Subject: [PATCH 53/60] Use TypedArena::alloc_slice in rustc. --- src/librustc/mir/tcx.rs | 4 +-- src/librustc/traits/util.rs | 2 +- src/librustc/ty/context.rs | 38 +++++++++++++----------- src/librustc/ty/mod.rs | 2 +- src/librustc/ty/relate.rs | 6 ++-- src/librustc/ty/structural_impls.rs | 4 +-- src/librustc/ty/subst.rs | 4 +-- src/librustc_driver/test.rs | 10 +++---- src/librustc_metadata/decoder.rs | 4 +-- src/librustc_mir/build/expr/as_rvalue.rs | 2 +- src/librustc_trans/callee.rs | 2 +- src/librustc_trans/mir/constant.rs | 2 +- src/librustc_trans/mir/rvalue.rs | 2 +- src/librustc_typeck/astconv.rs | 6 ++-- src/librustc_typeck/check/_match.rs | 2 +- src/librustc_typeck/check/closure.rs | 4 +-- src/librustc_typeck/check/intrinsic.rs | 4 +-- src/librustc_typeck/check/mod.rs | 6 ++-- 18 files changed, 54 insertions(+), 50 deletions(-) diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index 960d61adba72c..6fe6498ff789c 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -163,7 +163,7 @@ impl<'tcx> Rvalue<'tcx> { let lhs_ty = lhs.ty(mir, tcx); let rhs_ty = rhs.ty(mir, tcx); let ty = op.ty(tcx, lhs_ty, rhs_ty); - let ty = tcx.mk_tup(vec![ty, tcx.types.bool]); + let ty = tcx.mk_tup(&[ty, tcx.types.bool]); Some(ty) } &Rvalue::UnaryOp(_, ref operand) => { @@ -184,7 +184,7 @@ impl<'tcx> Rvalue<'tcx> { } AggregateKind::Tuple => { Some(tcx.mk_tup( - ops.iter().map(|op| op.ty(mir, tcx)).collect() + &ops.iter().map(|op| op.ty(mir, tcx)).collect::>() )) } AggregateKind::Adt(def, _, substs, _) => { diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs index 2cefc2ad79646..fa951b5efdb2b 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -486,7 +486,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { { let arguments_tuple = match tuple_arguments { TupleArgumentsFlag::No => sig.0.inputs[0], - TupleArgumentsFlag::Yes => self.mk_tup(sig.0.inputs.to_vec()), + TupleArgumentsFlag::Yes => self.mk_tup(&sig.0.inputs), }; let trait_ref = ty::TraitRef { def_id: fn_trait_def_id, diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 8352d6bed5073..d075b08f7385a 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -54,8 +54,8 @@ use hir; pub struct CtxtArenas<'tcx> { // internings type_: TypedArena>, - type_list: TypedArena>>, - substs: TypedArena>>, + type_list: TypedArena>, + substs: TypedArena>, bare_fn: TypedArena>, region: TypedArena, stability: TypedArena, @@ -1117,6 +1117,7 @@ impl<'tcx> Borrow for Interned<'tcx, Region> { macro_rules! intern_method { ($lt_tcx:tt, $name:ident: $method:ident($alloc:ty, + $alloc_method:ident, $alloc_to_key:expr, $alloc_to_ret:expr, $needs_infer:expr) -> $ty:ty) => { @@ -1142,7 +1143,8 @@ macro_rules! intern_method { let v = unsafe { mem::transmute(v) }; - let i = ($alloc_to_ret)(self.global_interners.arenas.$name.alloc(v)); + let i = ($alloc_to_ret)(self.global_interners.arenas.$name + .$alloc_method(v)); self.global_interners.$name.borrow_mut().insert(Interned(i)); return i; } @@ -1156,7 +1158,7 @@ macro_rules! intern_method { } } - let i = ($alloc_to_ret)(self.interners.arenas.$name.alloc(v)); + let i = ($alloc_to_ret)(self.interners.arenas.$name.$alloc_method(v)); self.interners.$name.borrow_mut().insert(Interned(i)); i } @@ -1180,7 +1182,7 @@ macro_rules! direct_interners { } } - intern_method!($lt_tcx, $name: $method($ty, |x| x, |x| x, $needs_infer) -> $ty);)+ + intern_method!($lt_tcx, $name: $method($ty, alloc, |x| x, |x| x, $needs_infer) -> $ty);)+ } } @@ -1200,16 +1202,18 @@ direct_interners!('tcx, }) -> Region ); -intern_method!('tcx, - type_list: mk_type_list(Vec>, Deref::deref, |xs: &[Ty]| -> &Slice { - unsafe { mem::transmute(xs) } - }, keep_local) -> Slice> -); +macro_rules! slice_interners { + ($($field:ident: $method:ident($ty:ident)),+) => ( + $(intern_method!('tcx, $field: $method(&[$ty<'tcx>], alloc_slice, Deref::deref, + |xs: &[$ty]| -> &Slice<$ty> { + unsafe { mem::transmute(xs) } + }, |xs: &[$ty]| xs.iter().any(keep_local)) -> Slice<$ty<'tcx>>);)+ + ) +} -intern_method!('tcx, - substs: mk_substs(Vec>, Deref::deref, |xs: &[Kind]| -> &Slice { - unsafe { mem::transmute(xs) } - }, keep_local) -> Slice> +slice_interners!( + type_list: mk_type_list(Ty), + substs: mk_substs(Kind) ); impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { @@ -1314,12 +1318,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.mk_ty(TySlice(ty)) } - pub fn mk_tup(self, ts: Vec>) -> Ty<'tcx> { + pub fn mk_tup(self, ts: &[Ty<'tcx>]) -> Ty<'tcx> { self.mk_ty(TyTuple(self.mk_type_list(ts))) } pub fn mk_nil(self) -> Ty<'tcx> { - self.mk_tup(Vec::new()) + self.mk_tup(&[]) } pub fn mk_diverging_default(self) -> Ty<'tcx> { @@ -1361,7 +1365,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn mk_closure(self, closure_id: DefId, substs: &'tcx Substs<'tcx>, - tys: Vec>) + tys: &[Ty<'tcx>]) -> Ty<'tcx> { self.mk_closure_from_closure_substs(closure_id, ClosureSubsts { func_substs: substs, diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 03d0e1e41be2e..018f01e5913c0 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1797,7 +1797,7 @@ impl<'a, 'tcx> AdtDefData<'tcx, 'tcx> { _ if tys.references_error() => tcx.types.err, 0 => tcx.types.bool, 1 => tys[0], - _ => tcx.mk_tup(tys) + _ => tcx.mk_tup(&tys) }; match self.sized_constraint.get(dep_node()) { diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index b10c731fe27d0..48b0b4ec9e58f 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -491,8 +491,8 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R, if as_.len() == bs.len() { let ts = as_.iter().zip(bs) .map(|(a, b)| relation.relate(a, b)) - .collect::>()?; - Ok(tcx.mk_tup(ts)) + .collect::, _>>()?; + Ok(tcx.mk_tup(&ts)) } else if !(as_.is_empty() || bs.is_empty()) { Err(TypeError::TupleSize( expected_found(relation, &as_.len(), &bs.len()))) @@ -547,7 +547,7 @@ impl<'tcx> Relate<'tcx> for ty::ClosureSubsts<'tcx> { let upvar_tys = relation.relate_zip(&a.upvar_tys, &b.upvar_tys)?; Ok(ty::ClosureSubsts { func_substs: substs, - upvar_tys: relation.tcx().mk_type_list(upvar_tys) + upvar_tys: relation.tcx().mk_type_list(&upvar_tys) }) } } diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 49683c634692c..0f4cff3d4875b 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -448,8 +448,8 @@ impl<'tcx> TypeFoldable<'tcx> for ty::TraitObject<'tcx> { impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Slice> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - let tys = self.iter().map(|t| t.fold_with(folder)).collect(); - folder.tcx().mk_type_list(tys) + let tys = self.iter().map(|t| t.fold_with(folder)).collect::>(); + folder.tcx().mk_type_list(&tys) } fn super_visit_with>(&self, visitor: &mut V) -> bool { diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index e82da3c395831..b0fdaa170996d 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -167,7 +167,7 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> { pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, params: I) -> &'tcx Substs<'tcx> where I: IntoIterator> { - tcx.mk_substs(params.into_iter().collect()) + tcx.mk_substs(¶ms.into_iter().collect::>()) } pub fn maybe_new(tcx: TyCtxt<'a, 'gcx, 'tcx>, params: I) @@ -311,7 +311,7 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx Substs<'tcx> { if params[..] == self[..] { self } else { - folder.tcx().mk_substs(params) + folder.tcx().mk_substs(¶ms) } } diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index f6772b8771844..15be80f4ee5a5 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -275,7 +275,7 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> { } pub fn t_pair(&self, ty1: Ty<'tcx>, ty2: Ty<'tcx>) -> Ty<'tcx> { - self.infcx.tcx.mk_tup(vec![ty1, ty2]) + self.infcx.tcx.mk_tup(&[ty1, ty2]) } pub fn t_param(&self, index: u32) -> Ty<'tcx> { @@ -803,8 +803,8 @@ fn walk_ty() { let tcx = env.infcx.tcx; let int_ty = tcx.types.isize; let uint_ty = tcx.types.usize; - let tup1_ty = tcx.mk_tup(vec![int_ty, uint_ty, int_ty, uint_ty]); - let tup2_ty = tcx.mk_tup(vec![tup1_ty, tup1_ty, uint_ty]); + let tup1_ty = tcx.mk_tup(&[int_ty, uint_ty, int_ty, uint_ty]); + let tup2_ty = tcx.mk_tup(&[tup1_ty, tup1_ty, uint_ty]); let uniq_ty = tcx.mk_box(tup2_ty); let walked: Vec<_> = uniq_ty.walk().collect(); assert_eq!(walked, @@ -819,8 +819,8 @@ fn walk_ty_skip_subtree() { let tcx = env.infcx.tcx; let int_ty = tcx.types.isize; let uint_ty = tcx.types.usize; - let tup1_ty = tcx.mk_tup(vec![int_ty, uint_ty, int_ty, uint_ty]); - let tup2_ty = tcx.mk_tup(vec![tup1_ty, tup1_ty, uint_ty]); + let tup1_ty = tcx.mk_tup(&[int_ty, uint_ty, int_ty, uint_ty]); + let tup2_ty = tcx.mk_tup(&[tup1_ty, tup1_ty, uint_ty]); let uniq_ty = tcx.mk_box(tup2_ty); // types we expect to see (in order), plus a boolean saying diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index bdb4d383cee7d..e18fd58144398 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -374,7 +374,7 @@ impl<'a, 'tcx> SpecializedDecoder> for DecodeContext impl<'a, 'tcx> SpecializedDecoder<&'tcx Substs<'tcx>> for DecodeContext<'a, 'tcx> { fn specialized_decode(&mut self) -> Result<&'tcx Substs<'tcx>, Self::Error> { - Ok(self.tcx().mk_substs(Decodable::decode(self)?)) + Ok(self.tcx().mk_substs(&Vec::decode(self)?)) } } @@ -386,7 +386,7 @@ impl<'a, 'tcx> SpecializedDecoder<&'tcx ty::Region> for DecodeContext<'a, 'tcx> impl<'a, 'tcx> SpecializedDecoder<&'tcx ty::Slice>> for DecodeContext<'a, 'tcx> { fn specialized_decode(&mut self) -> Result<&'tcx ty::Slice>, Self::Error> { - Ok(self.tcx().mk_type_list(Decodable::decode(self)?)) + Ok(self.tcx().mk_type_list(&Vec::decode(self)?)) } } diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index 9b7f3468c19e5..d30af8b82555c 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -257,7 +257,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let source_info = self.source_info(span); let bool_ty = self.hir.bool_ty(); if self.hir.check_overflow() && op.is_checkable() && ty.is_integral() { - let result_tup = self.hir.tcx().mk_tup(vec![ty, bool_ty]); + let result_tup = self.hir.tcx().mk_tup(&[ty, bool_ty]); let result_value = self.temp(result_tup); self.cfg.push_assign(block, source_info, diff --git a/src/librustc_trans/callee.rs b/src/librustc_trans/callee.rs index 05e22896c4006..5c7ab77648e5e 100644 --- a/src/librustc_trans/callee.rs +++ b/src/librustc_trans/callee.rs @@ -327,7 +327,7 @@ fn trans_fn_pointer_shim<'a, 'tcx>( } }; let sig = tcx.erase_late_bound_regions_and_normalize(sig); - let tuple_input_ty = tcx.mk_tup(sig.inputs.to_vec()); + let tuple_input_ty = tcx.mk_tup(&sig.inputs); let sig = ty::FnSig { inputs: vec![bare_fn_ty_maybe_ref, tuple_input_ty], diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index 76b63512bdbd0..baa306069f168 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -773,7 +773,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { let rhs = self.const_operand(rhs, span)?; let ty = lhs.ty; let val_ty = op.ty(tcx, lhs.ty, rhs.ty); - let binop_ty = tcx.mk_tup(vec![val_ty, tcx.types.bool]); + let binop_ty = tcx.mk_tup(&[val_ty, tcx.types.bool]); let (lhs, rhs) = (lhs.llval, rhs.llval); assert!(!ty.is_fp()); diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs index 97aa475be68a7..5ffaadf972a63 100644 --- a/src/librustc_trans/mir/rvalue.rs +++ b/src/librustc_trans/mir/rvalue.rs @@ -430,7 +430,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { lhs.immediate(), rhs.immediate(), lhs.ty); let val_ty = op.ty(bcx.tcx(), lhs.ty, rhs.ty); - let operand_ty = bcx.tcx().mk_tup(vec![val_ty, bcx.tcx().types.bool]); + let operand_ty = bcx.tcx().mk_tup(&[val_ty, bcx.tcx().types.bool]); let operand = OperandRef { val: result, ty: operand_ty diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index c9ce320988c47..0c4e6324b8911 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -660,7 +660,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { span: output_span }; - (self.tcx().mk_tup(inputs), output_binding) + (self.tcx().mk_tup(&inputs), output_binding) } pub fn instantiate_poly_trait_ref(&self, @@ -1663,8 +1663,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { hir::TyTup(ref fields) => { let flds = fields.iter() .map(|t| self.ast_ty_to_ty(rscope, &t)) - .collect(); - tcx.mk_tup(flds) + .collect::>(); + tcx.mk_tup(&flds) } hir::TyBareFn(ref bf) => { require_c_abi_if_variadic(tcx, &bf.decl, bf.abi, ast_ty.span); diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 87729da773f45..f7e590871fc5e 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -169,7 +169,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let max_len = cmp::max(expected_len, elements.len()); let element_tys: Vec<_> = (0 .. max_len).map(|_| self.next_ty_var()).collect(); - let pat_ty = tcx.mk_tup(element_tys.clone()); + let pat_ty = tcx.mk_tup(&element_tys); self.demand_eqtype(pat.span, expected, pat_ty); for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) { self.check_pat(elem, &element_tys[i]); diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 1dbd0728bf217..7b05cd1d48328 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -71,7 +71,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let closure_type = self.tcx.mk_closure(expr_def_id, self.parameter_environment.free_substs, - upvar_tys); + &upvar_tys); let fn_sig = self.tcx .liberate_late_bound_regions(self.tcx.region_maps.call_site_extent(expr.id, body.id), @@ -88,7 +88,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Tuple up the arguments and insert the resulting function type into // the `closures` table. - fn_ty.sig.0.inputs = vec![self.tcx.mk_tup(fn_ty.sig.0.inputs)]; + fn_ty.sig.0.inputs = vec![self.tcx.mk_tup(&fn_ty.sig.0.inputs)]; debug!("closure for {:?} --> sig={:?} opt_kind={:?}", expr_def_id, diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index 93d8b3e1563d9..7171b33a3af39 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -89,7 +89,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &hir::ForeignItem) { "cxchg" | "cxchgweak" => (1, vec!(tcx.mk_mut_ptr(param(ccx, 0)), param(ccx, 0), param(ccx, 0)), - tcx.mk_tup(vec!(param(ccx, 0), tcx.types.bool))), + tcx.mk_tup(&[param(ccx, 0), tcx.types.bool])), "load" => (1, vec!(tcx.mk_imm_ptr(param(ccx, 0))), param(ccx, 0)), "store" => (1, vec!(tcx.mk_mut_ptr(param(ccx, 0)), param(ccx, 0)), @@ -274,7 +274,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &hir::ForeignItem) { "add_with_overflow" | "sub_with_overflow" | "mul_with_overflow" => (1, vec!(param(ccx, 0), param(ccx, 0)), - tcx.mk_tup(vec!(param(ccx, 0), tcx.types.bool))), + tcx.mk_tup(&[param(ccx, 0), tcx.types.bool])), "unchecked_div" | "unchecked_rem" => (1, vec![param(ccx, 0), param(ccx, 0)], param(ccx, 0)), diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 2224b747210a6..af5a1d7b71383 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2380,7 +2380,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let err_inputs = match tuple_arguments { DontTupleArguments => err_inputs, - TupleArguments => vec![self.tcx.mk_tup(err_inputs)], + TupleArguments => vec![self.tcx.mk_tup(&err_inputs)], }; self.check_argument_types(sp, &err_inputs[..], &[], args_no_rcvr, @@ -3733,11 +3733,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }; err_field = err_field || t.references_error(); t - }).collect(); + }).collect::>(); if err_field { tcx.types.err } else { - tcx.mk_tup(elt_ts) + tcx.mk_tup(&elt_ts) } } hir::ExprStruct(ref path, ref fields, ref base_expr) => { From 81d97957a7807d3ac1a9defde037c6e504e3d797 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 19 Oct 2016 08:21:00 -0700 Subject: [PATCH 54/60] Detect local-rebuild by just the MAJOR.MINOR version A new point-release shouldn't change any language semantics, so a local stage0 that matches MAJOR.MINOR version should still be considered a local-rebuild as far as `--cfg stageN` features go. e.g. `1.14.0` should be considered a local-rebuild for any `1.14.X`. (Bootstrap keys used to be an issue too, until #37265.) --- mk/main.mk | 9 +++++---- src/bootstrap/lib.rs | 6 +++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/mk/main.mk b/mk/main.mk index d4efee90361b7..f56e02e258437 100644 --- a/mk/main.mk +++ b/mk/main.mk @@ -53,11 +53,12 @@ endif # versions in the same place CFG_FILENAME_EXTRA=$(shell printf '%s' $(CFG_RELEASE)$(CFG_EXTRA_FILENAME) | $(CFG_HASH_COMMAND)) -# If local-rust is the same as the current version, then force a local-rebuild +# If local-rust is the same major.minor as the current version, then force a local-rebuild ifdef CFG_ENABLE_LOCAL_RUST -ifeq ($(CFG_RELEASE),\ - $(shell $(S)src/etc/local_stage0.sh --print-rustc-release $(CFG_LOCAL_RUST_ROOT))) - CFG_INFO := $(info cfg: auto-detected local-rebuild $(CFG_RELEASE)) +SEMVER_PREFIX=$(shell echo $(CFG_RELEASE_NUM) | grep -E -o '^[[:digit:]]+\.[[:digit:]]+') +LOCAL_RELEASE=$(shell $(S)src/etc/local_stage0.sh --print-rustc-release $(CFG_LOCAL_RUST_ROOT)) +ifneq (,$(filter $(SEMVER_PREFIX).%,$(LOCAL_RELEASE))) + CFG_INFO := $(info cfg: auto-detected local-rebuild using $(LOCAL_RELEASE)) CFG_ENABLE_LOCAL_REBUILD = 1 endif endif diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index a63c23b46212d..60dca29984630 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -220,14 +220,14 @@ impl Build { sanity::check(self); self.verbose("collecting channel variables"); channel::collect(self); - // If local-rust is the same as the current version, then force a local-rebuild + // 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")); let local_release = local_version_verbose .lines().filter(|x| x.starts_with("release:")) .next().unwrap().trim_left_matches("release:").trim(); - if local_release == self.release { - self.verbose(&format!("auto-detected local-rebuild {}", self.release)); + if local_release.split('.').take(2).eq(self.release.split('.').take(2)) { + self.verbose(&format!("auto-detected local-rebuild {}", local_release)); self.local_rebuild = true; } self.verbose("updating submodules"); From 8bb76f9241f6c26b84dbf795e14d73c47be86529 Mon Sep 17 00:00:00 2001 From: Raph Levien Date: Tue, 18 Oct 2016 13:52:22 -0700 Subject: [PATCH 55/60] LLVM: Add triple for Fuchsia Update subproject commit. --- src/llvm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llvm b/src/llvm index ac1c94226e9fa..8c9961a9cc406 160000 --- a/src/llvm +++ b/src/llvm @@ -1 +1 @@ -Subproject commit ac1c94226e9fa17005ce7e2dd52dd6d1875f3137 +Subproject commit 8c9961a9cc406c9bcb29a8752a4a2ad9f5f98b1b From b8697d939a4fa6bfd8a1912c1f28d273251606e1 Mon Sep 17 00:00:00 2001 From: Raph Levien Date: Tue, 18 Oct 2016 15:23:02 -0700 Subject: [PATCH 56/60] Update llvm-auto-clean-trigger Update the datestamp so that buildbots do a clean rebuild of llvm. --- src/rustllvm/llvm-auto-clean-trigger | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rustllvm/llvm-auto-clean-trigger b/src/rustllvm/llvm-auto-clean-trigger index f4b5ca7a15724..0f63d70af9d37 100644 --- a/src/rustllvm/llvm-auto-clean-trigger +++ b/src/rustllvm/llvm-auto-clean-trigger @@ -1,4 +1,4 @@ # If this file is modified, then llvm will be forcibly 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. -2016-10-10b +2016-10-18 From d79ec7e310edff89e7f3b0322a8acb2403a7dc28 Mon Sep 17 00:00:00 2001 From: Paul Osborne Date: Wed, 19 Oct 2016 13:37:15 -0500 Subject: [PATCH 57/60] Fix grammatical errors in `tests` directory docs --- src/doc/book/testing.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/doc/book/testing.md b/src/doc/book/testing.md index 86729147ed065..3bdf1b7b7f229 100644 --- a/src/doc/book/testing.md +++ b/src/doc/book/testing.md @@ -380,9 +380,9 @@ the `tests` directory. # The `tests` directory -Each file in `tests/*.rs` directory is treated as individual crate. -So, to write an integration test, let's make a `tests` directory, and -put a `tests/integration_test.rs` file inside, with this as its contents: +Each file in `tests/*.rs` directory is treated as an individual crate. +To write an integration test, let's make a `tests` directory and +put a `tests/integration_test.rs` file inside with this as its contents: ```rust,ignore extern crate adder; From f1e4ae17b1a80119599e501e26fed0d7635b65f7 Mon Sep 17 00:00:00 2001 From: Srinivas Reddy Thatiparthy Date: Thu, 20 Oct 2016 00:25:19 +0530 Subject: [PATCH 58/60] run rustfmt on control_flow_graph folder --- .../control_flow_graph/dominators/mod.rs | 28 +++++++++---------- .../control_flow_graph/dominators/test.rs | 22 +++------------ .../control_flow_graph/iterate/test.rs | 20 ++----------- .../control_flow_graph/mod.rs | 6 ++-- .../control_flow_graph/reachable/mod.rs | 9 ++---- .../control_flow_graph/reachable/test.rs | 22 +++------------ .../control_flow_graph/reference.rs | 8 +++--- .../control_flow_graph/test.rs | 11 ++++---- .../control_flow_graph/transpose.rs | 11 ++++++-- 9 files changed, 48 insertions(+), 89 deletions(-) diff --git a/src/librustc_data_structures/control_flow_graph/dominators/mod.rs b/src/librustc_data_structures/control_flow_graph/dominators/mod.rs index 250b89d12ed05..ab675db21503e 100644 --- a/src/librustc_data_structures/control_flow_graph/dominators/mod.rs +++ b/src/librustc_data_structures/control_flow_graph/dominators/mod.rs @@ -57,9 +57,9 @@ pub fn dominators_given_rpo(graph: &G, // (*) // (*) dominators for `pred` have been calculated new_idom = intersect_opt(&post_order_rank, - &immediate_dominators, - new_idom, - Some(pred)); + &immediate_dominators, + new_idom, + Some(pred)); } } @@ -77,10 +77,10 @@ pub fn dominators_given_rpo(graph: &G, } fn intersect_opt(post_order_rank: &IndexVec, - immediate_dominators: &IndexVec>, - node1: Option, - node2: Option) - -> Option { + immediate_dominators: &IndexVec>, + node1: Option, + node2: Option) + -> Option { match (node1, node2) { (None, None) => None, (Some(n), None) | (None, Some(n)) => Some(n), @@ -89,10 +89,10 @@ fn intersect_opt(post_order_rank: &IndexVec, } fn intersect(post_order_rank: &IndexVec, - immediate_dominators: &IndexVec>, - mut node1: Node, - mut node2: Node) - -> Node { + immediate_dominators: &IndexVec>, + mut node1: Node, + mut node2: Node) + -> Node { while node1 != node2 { while post_order_rank[node1] < post_order_rank[node2] { node1 = immediate_dominators[node1].unwrap(); @@ -142,9 +142,9 @@ impl Dominators { "node {:?} is not reachable", node2); intersect::(&self.post_order_rank, - &self.immediate_dominators, - node1, - node2) + &self.immediate_dominators, + node1, + node2) } pub fn mutual_dominator(&self, iter: I) -> Option diff --git a/src/librustc_data_structures/control_flow_graph/dominators/test.rs b/src/librustc_data_structures/control_flow_graph/dominators/test.rs index a6db5f2fe3ea1..0af878cac2df1 100644 --- a/src/librustc_data_structures/control_flow_graph/dominators/test.rs +++ b/src/librustc_data_structures/control_flow_graph/dominators/test.rs @@ -14,12 +14,7 @@ use super::*; #[test] fn diamond() { - let graph = TestGraph::new(0, &[ - (0, 1), - (0, 2), - (1, 3), - (2, 3), - ]); + let graph = TestGraph::new(0, &[(0, 1), (0, 2), (1, 3), (2, 3)]); let dominators = dominators(&graph); let immediate_dominators = dominators.all_immediate_dominators(); @@ -32,17 +27,9 @@ fn diamond() { #[test] fn paper() { // example from the paper: - let graph = TestGraph::new(6, &[ - (6, 5), - (6, 4), - (5, 1), - (4, 2), - (4, 3), - (1, 2), - (2, 3), - (3, 2), - (2, 1), - ]); + let graph = TestGraph::new(6, + &[(6, 5), (6, 4), (5, 1), (4, 2), (4, 3), (1, 2), (2, 3), (3, 2), + (2, 1)]); let dominators = dominators(&graph); let immediate_dominators = dominators.all_immediate_dominators(); @@ -54,4 +41,3 @@ fn paper() { assert_eq!(immediate_dominators[5], Some(6)); assert_eq!(immediate_dominators[6], Some(6)); } - diff --git a/src/librustc_data_structures/control_flow_graph/iterate/test.rs b/src/librustc_data_structures/control_flow_graph/iterate/test.rs index 28297d55bdf32..dca45602f17c4 100644 --- a/src/librustc_data_structures/control_flow_graph/iterate/test.rs +++ b/src/librustc_data_structures/control_flow_graph/iterate/test.rs @@ -15,12 +15,7 @@ use super::*; #[test] fn diamond_post_order() { - let graph = TestGraph::new(0, &[ - (0, 1), - (0, 2), - (1, 3), - (2, 3), - ]); + let graph = TestGraph::new(0, &[(0, 1), (0, 2), (1, 3), (2, 3)]); let result = post_order_from(&graph, 0); assert_eq!(result, vec![3, 1, 2, 0]); @@ -33,16 +28,8 @@ fn rev_post_order_inner_loop() { // ^ ^ v | // | 6 <- 4 | // +-----------------+ - let graph = TestGraph::new(0, &[ - (0, 1), - (1, 2), - (2, 3), - (3, 5), - (3, 1), - (2, 4), - (4, 6), - (6, 2), - ]); + let graph = TestGraph::new(0, + &[(0, 1), (1, 2), (2, 3), (3, 5), (3, 1), (2, 4), (4, 6), (6, 2)]); let rev_graph = TransposedGraph::new(&graph); @@ -52,4 +39,3 @@ fn rev_post_order_inner_loop() { let result = post_order_from_to(&rev_graph, 3, Some(1)); assert_eq!(result, vec![4, 6, 2, 3]); } - diff --git a/src/librustc_data_structures/control_flow_graph/mod.rs b/src/librustc_data_structures/control_flow_graph/mod.rs index f9e75b12e0358..eb6839df6274f 100644 --- a/src/librustc_data_structures/control_flow_graph/mod.rs +++ b/src/librustc_data_structures/control_flow_graph/mod.rs @@ -36,10 +36,10 @@ pub trait ControlFlowGraph pub trait GraphPredecessors<'graph> { type Item; - type Iter: Iterator; + type Iter: Iterator; } pub trait GraphSuccessors<'graph> { type Item; - type Iter: Iterator; -} \ No newline at end of file + type Iter: Iterator; +} diff --git a/src/librustc_data_structures/control_flow_graph/reachable/mod.rs b/src/librustc_data_structures/control_flow_graph/reachable/mod.rs index e520e23f3afb8..24210ebb95d3d 100644 --- a/src/librustc_data_structures/control_flow_graph/reachable/mod.rs +++ b/src/librustc_data_structures/control_flow_graph/reachable/mod.rs @@ -19,8 +19,7 @@ use super::super::indexed_vec::{IndexVec, Idx}; #[cfg(test)] mod test; -pub fn reachable(graph: &G) - -> Reachability { +pub fn reachable(graph: &G) -> Reachability { let reverse_post_order = reverse_post_order(graph, graph.start_node()); reachable_given_rpo(graph, &reverse_post_order) } @@ -53,12 +52,10 @@ pub struct Reachability { impl Reachability { fn new(graph: &G) -> Self { let num_nodes = graph.num_nodes(); - Reachability { - bits: IndexVec::from_elem_n(BitVector::new(num_nodes), num_nodes), - } + Reachability { bits: IndexVec::from_elem_n(BitVector::new(num_nodes), num_nodes) } } - pub fn can_reach(&self, source: Node, target: Node)-> bool { + pub fn can_reach(&self, source: Node, target: Node) -> bool { let bit: usize = target.index(); self.bits[source].contains(bit) } diff --git a/src/librustc_data_structures/control_flow_graph/reachable/test.rs b/src/librustc_data_structures/control_flow_graph/reachable/test.rs index 6aa906a0804e2..ef45deeaafc78 100644 --- a/src/librustc_data_structures/control_flow_graph/reachable/test.rs +++ b/src/librustc_data_structures/control_flow_graph/reachable/test.rs @@ -17,15 +17,7 @@ fn test1() { // 0 -> 1 -> 2 -> 3 // ^ v // 6 <- 4 -> 5 - let graph = TestGraph::new(0, &[ - (0, 1), - (1, 2), - (2, 3), - (2, 4), - (4, 5), - (4, 6), - (6, 1), - ]); + let graph = TestGraph::new(0, &[(0, 1), (1, 2), (2, 3), (2, 4), (4, 5), (4, 6), (6, 1)]); let reachable = reachable(&graph); assert!((0..6).all(|i| reachable.can_reach(0, i))); assert!((1..6).all(|i| reachable.can_reach(1, i))); @@ -43,15 +35,9 @@ fn test2() { // 30 -> 31 -> 32 -> 33 // ^ v // 36 <- 34 -> 35 - let graph = TestGraph::new(30, &[ - (30, 31), - (31, 32), - (32, 33), - (32, 34), - (34, 35), - (34, 36), - (36, 31), - ]); + let graph = TestGraph::new(30, + &[(30, 31), (31, 32), (32, 33), (32, 34), (34, 35), (34, 36), + (36, 31)]); let reachable = reachable(&graph); assert!((30..36).all(|i| reachable.can_reach(30, i))); assert!((31..36).all(|i| reachable.can_reach(31, i))); diff --git a/src/librustc_data_structures/control_flow_graph/reference.rs b/src/librustc_data_structures/control_flow_graph/reference.rs index d735be1ed2f54..3b8b01f2ff43b 100644 --- a/src/librustc_data_structures/control_flow_graph/reference.rs +++ b/src/librustc_data_structures/control_flow_graph/reference.rs @@ -21,13 +21,13 @@ impl<'graph, G: ControlFlowGraph> ControlFlowGraph for &'graph G { (**self).start_node() } - fn predecessors<'iter>(&'iter self, node: Self::Node) - -> >::Iter { + fn predecessors<'iter>(&'iter self, + node: Self::Node) + -> >::Iter { (**self).predecessors(node) } - fn successors<'iter>(&'iter self, node: Self::Node) - -> >::Iter { + fn successors<'iter>(&'iter self, node: Self::Node) -> >::Iter { (**self).successors(node) } } diff --git a/src/librustc_data_structures/control_flow_graph/test.rs b/src/librustc_data_structures/control_flow_graph/test.rs index 57b2a858de568..d48a6e684ad8e 100644 --- a/src/librustc_data_structures/control_flow_graph/test.rs +++ b/src/librustc_data_structures/control_flow_graph/test.rs @@ -28,7 +28,7 @@ impl TestGraph { num_nodes: start_node + 1, start_node: start_node, successors: HashMap::new(), - predecessors: HashMap::new() + predecessors: HashMap::new(), }; for &(source, target) in edges { graph.num_nodes = max(graph.num_nodes, source + 1); @@ -55,13 +55,13 @@ impl ControlFlowGraph for TestGraph { self.num_nodes } - fn predecessors<'graph>(&'graph self, node: usize) + fn predecessors<'graph>(&'graph self, + node: usize) -> >::Iter { - self.predecessors[&node].iter().cloned() + self.predecessors[&node].iter().cloned() } - fn successors<'graph>(&'graph self, node: usize) - -> >::Iter { + fn successors<'graph>(&'graph self, node: usize) -> >::Iter { self.successors[&node].iter().cloned() } } @@ -75,4 +75,3 @@ impl<'graph> GraphSuccessors<'graph> for TestGraph { type Item = usize; type Iter = iter::Cloned>; } - diff --git a/src/librustc_data_structures/control_flow_graph/transpose.rs b/src/librustc_data_structures/control_flow_graph/transpose.rs index 792e079c28c85..a1a117edb94fc 100644 --- a/src/librustc_data_structures/control_flow_graph/transpose.rs +++ b/src/librustc_data_structures/control_flow_graph/transpose.rs @@ -22,7 +22,10 @@ impl TransposedGraph { } pub fn with_start(base_graph: G, start_node: G::Node) -> Self { - TransposedGraph { base_graph: base_graph, start_node: start_node } + TransposedGraph { + base_graph: base_graph, + start_node: start_node, + } } } @@ -37,12 +40,14 @@ impl ControlFlowGraph for TransposedGraph { self.start_node } - fn predecessors<'graph>(&'graph self, node: Self::Node) + fn predecessors<'graph>(&'graph self, + node: Self::Node) -> >::Iter { self.base_graph.successors(node) } - fn successors<'graph>(&'graph self, node: Self::Node) + fn successors<'graph>(&'graph self, + node: Self::Node) -> >::Iter { self.base_graph.predecessors(node) } From c2d0d4fea6598c6d366b23d45b76b9c0572e7ac4 Mon Sep 17 00:00:00 2001 From: Srinivas Reddy Thatiparthy Date: Thu, 20 Oct 2016 00:38:55 +0530 Subject: [PATCH 59/60] run rustfmt on unify folder --- src/librustc_data_structures/unify/mod.rs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/librustc_data_structures/unify/mod.rs b/src/librustc_data_structures/unify/mod.rs index 3feea3218d013..1f4d09a92247e 100644 --- a/src/librustc_data_structures/unify/mod.rs +++ b/src/librustc_data_structures/unify/mod.rs @@ -27,7 +27,7 @@ mod tests; /// /// Clients are expected to provide implementations of this trait; you /// can see some examples in the `test` module. -pub trait UnifyKey : Copy + Clone + Debug + PartialEq { +pub trait UnifyKey: Copy + Clone + Debug + PartialEq { type Value: Clone + PartialEq + Debug; fn index(&self) -> u32; @@ -115,11 +115,7 @@ impl VarValue { } fn if_not_self(&self, key: K, self_key: K) -> Option { - if key == self_key { - None - } else { - Some(key) - } + if key == self_key { None } else { Some(key) } } } @@ -236,7 +232,8 @@ impl UnificationTable { new_rank: u32, old_root: VarValue, new_root: VarValue, - new_value: K::Value) -> K { + new_value: K::Value) + -> K { let old_root_key = old_root.key(); let new_root_key = new_root.key(); self.set(old_root_key, old_root.redirect(new_root_key)); @@ -306,7 +303,8 @@ impl<'tcx, K, V> UnificationTable let combined = { match (&node_a.value, &node_b.value) { (&None, &None) => None, - (&Some(ref v), &None) | (&None, &Some(ref v)) => Some(v.clone()), + (&Some(ref v), &None) | + (&None, &Some(ref v)) => Some(v.clone()), (&Some(ref v1), &Some(ref v2)) => { if *v1 != *v2 { return Err((v1.clone(), v2.clone())); From 4e898116905d1b39fb10b7b58c78dd8143ef4e25 Mon Sep 17 00:00:00 2001 From: Srinivas Reddy Thatiparthy Date: Thu, 20 Oct 2016 00:40:05 +0530 Subject: [PATCH 60/60] run rustfmt on snapshot_map --- .../snapshot_map/mod.rs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/librustc_data_structures/snapshot_map/mod.rs b/src/librustc_data_structures/snapshot_map/mod.rs index b3989013d2114..0306066d6e784 100644 --- a/src/librustc_data_structures/snapshot_map/mod.rs +++ b/src/librustc_data_structures/snapshot_map/mod.rs @@ -23,7 +23,7 @@ pub struct SnapshotMap } pub struct Snapshot { - len: usize + len: usize, } enum UndoLog { @@ -39,7 +39,7 @@ impl SnapshotMap pub fn new() -> Self { SnapshotMap { map: FnvHashMap(), - undo_log: vec![] + undo_log: vec![], } } @@ -68,9 +68,7 @@ impl SnapshotMap } true } - None => { - false - } + None => false, } } @@ -88,7 +86,7 @@ impl SnapshotMap assert!(snapshot.len < self.undo_log.len()); assert!(match self.undo_log[snapshot.len] { UndoLog::OpenSnapshot => true, - _ => false + _ => false, }); } @@ -110,7 +108,7 @@ impl SnapshotMap panic!("cannot rollback an uncommitted snapshot"); } - UndoLog::CommittedSnapshot => { } + UndoLog::CommittedSnapshot => {} UndoLog::Inserted(key) => { self.map.remove(&key); @@ -123,7 +121,10 @@ impl SnapshotMap } let v = self.undo_log.pop().unwrap(); - assert!(match v { UndoLog::OpenSnapshot => true, _ => false }); + assert!(match v { + UndoLog::OpenSnapshot => true, + _ => false, + }); assert!(self.undo_log.len() == snapshot.len); } }