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/42] 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/42] 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/42] 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/42] 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/42] 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/42] 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/42] 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/42] 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/42] 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/42] 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/42] 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 094c3a2c785c251dffb9cadbbad02d7b1e4afc4d Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 14 Oct 2016 12:48:53 -0700 Subject: [PATCH 12/42] 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 13/42] 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 ac42f3f2064130fa0c841fdf645616e0fa46734a Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Sat, 15 Oct 2016 11:40:12 -0700 Subject: [PATCH 14/42] 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 15/42] 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 16/42] 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 17/42] 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 18/42] 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 19/42] 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 20/42] 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 21/42] 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 22/42] 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 23/42] 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 24/42] 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 25/42] 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 26/42] 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 27/42] 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 28/42] 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 29/42] 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 30/42] 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 31/42] 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 32/42] 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 33/42] 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 34/42] 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 10a58ac49b7529e39fc2ad823204853f3538d90b Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 18 Oct 2016 14:46:55 +0200 Subject: [PATCH 35/42] 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 d11cd46ef7d84e8bfb7a16e774c1b385e5a48f8f Mon Sep 17 00:00:00 2001 From: Mark-Simulacrum Date: Mon, 17 Oct 2016 15:03:40 -0600 Subject: [PATCH 36/42] 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 7a3859913a9106826a7fc9e37479d35a9ebb014e Mon Sep 17 00:00:00 2001 From: Mark-Simulacrum Date: Sun, 16 Oct 2016 21:21:25 -0600 Subject: [PATCH 37/42] 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 | 6 ++-- 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, 55 insertions(+), 51 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 d1fa2128842ba..69bbf0dcaa6f5 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1779,7 +1779,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 5948e02620eca..9f9bfb998e635 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 7d7bbd931225f..19d1dd44bc6dd 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) @@ -304,8 +304,8 @@ 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 = self.iter().map(|k| k.fold_with(folder)).collect::>(); + folder.tcx().mk_substs(¶ms) } fn fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { 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 d58b8f083e248..ce1f2480e77a4 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 1cc1dcce7d7e934817c3bf3543ca8e7753960d0b Mon Sep 17 00:00:00 2001 From: Srinivas Reddy Thatiparthy Date: Tue, 18 Oct 2016 23:09:47 +0530 Subject: [PATCH 38/42] 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 39/42] 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 4a91a80b26afb23c0f33162acc52605cb9130b3e Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 12 Oct 2016 20:54:41 +0300 Subject: [PATCH 40/42] 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 41/42] 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 42/42] 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