From 15241a4d4106b12cb6cbe25837cc56b629aad2dd Mon Sep 17 00:00:00 2001 From: Chris Gregory Date: Fri, 24 May 2019 15:28:55 -0500 Subject: [PATCH 01/30] Fix documentation of `Rc::make_mut` regarding `rc::Weak`. --- src/liballoc/rc.rs | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 0dffb19476f3d..40fae408a579c 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -584,15 +584,18 @@ impl Rc { impl Rc { /// Makes a mutable reference into the given `Rc`. /// - /// If there are other `Rc` or [`Weak`][weak] pointers to the same value, - /// then `make_mut` will invoke [`clone`][clone] on the inner value to - /// ensure unique ownership. This is also referred to as clone-on-write. + /// If there are other `Rc` pointers to the same value, then `make_mut` will + /// [`clone`] the inner value to ensure unique ownership. This is also + /// referred to as clone-on-write. /// - /// See also [`get_mut`][get_mut], which will fail rather than cloning. + /// If there are not other `Rc` pointers to this value, then [`Weak`] + /// pointers to this value will be dissassociated. /// - /// [weak]: struct.Weak.html - /// [clone]: ../../std/clone/trait.Clone.html#tymethod.clone - /// [get_mut]: struct.Rc.html#method.get_mut + /// See also [`get_mut`], which will fail rather than cloning. + /// + /// [`Weak`]: struct.Weak.html + /// [`clone`]: ../../std/clone/trait.Clone.html#tymethod.clone + /// [`get_mut`]: struct.Rc.html#method.get_mut /// /// # Examples /// @@ -611,6 +614,23 @@ impl Rc { /// assert_eq!(*data, 8); /// assert_eq!(*other_data, 12); /// ``` + /// + /// [`Weak`] pointers will be dissassociated: + /// + /// ``` + /// use std::rc::{Rc, Weak}; + /// + /// let mut data = Rc::new(75); + /// let weak = Rc::downgrade(&data); + /// + /// assert!(75 == *data); + /// assert!(75 == *weak.upgrade().unwrap()); + /// + /// *Rc::make_mut(&mut data) += 1; + /// + /// assert!(76 == *data); + /// assert!(weak.upgrade().is_none()); + /// ``` #[inline] #[stable(feature = "rc_unique", since = "1.4.0")] pub fn make_mut(this: &mut Self) -> &mut T { From fbe9f16bc2102b2450384a103d9799debd4c914e Mon Sep 17 00:00:00 2001 From: Chris Gregory Date: Fri, 24 May 2019 21:08:59 -0500 Subject: [PATCH 02/30] Reword `are not other` to `are no other` Co-Authored-By: Jonas Schievink --- src/liballoc/rc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 40fae408a579c..ce9067c2ff947 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -588,7 +588,7 @@ impl Rc { /// [`clone`] the inner value to ensure unique ownership. This is also /// referred to as clone-on-write. /// - /// If there are not other `Rc` pointers to this value, then [`Weak`] + /// If there are no other `Rc` pointers to this value, then [`Weak`] /// pointers to this value will be dissassociated. /// /// See also [`get_mut`], which will fail rather than cloning. From b34b714a896644c7ac5787b214f4115fc0226d96 Mon Sep 17 00:00:00 2001 From: Chris Gregory Date: Fri, 24 May 2019 21:10:17 -0500 Subject: [PATCH 03/30] Remove unused import in doctest --- src/liballoc/rc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index ce9067c2ff947..2cca8d4a39608 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -618,7 +618,7 @@ impl Rc { /// [`Weak`] pointers will be dissassociated: /// /// ``` - /// use std::rc::{Rc, Weak}; + /// use std::rc::Rc; /// /// let mut data = Rc::new(75); /// let weak = Rc::downgrade(&data); From f23cbeab1ddab22a81e8cc5dbca4a4eb205503ea Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 31 May 2019 18:57:47 +0200 Subject: [PATCH 04/30] miri unsizing: fix projecting into a field of an operand --- src/librustc_mir/interpret/cast.rs | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs index 76b11ac2fe646..3dae259e99643 100644 --- a/src/librustc_mir/interpret/cast.rs +++ b/src/librustc_mir/interpret/cast.rs @@ -11,7 +11,7 @@ use rustc::mir::interpret::{ use rustc::mir::CastKind; use rustc_apfloat::Float; -use super::{InterpretCx, Machine, PlaceTy, OpTy, ImmTy, Immediate}; +use super::{InterpretCx, Machine, PlaceTy, OpTy, Immediate}; impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> { fn type_is_fat_ptr(&self, ty: Ty<'tcx>) -> bool { @@ -306,6 +306,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> src: OpTy<'tcx, M::PointerTag>, dest: PlaceTy<'tcx, M::PointerTag>, ) -> EvalResult<'tcx> { + trace!("Unsizing {:?} into {:?}", src, dest); match (&src.layout.ty.sty, &dest.layout.ty.sty) { (&ty::Ref(_, s, _), &ty::Ref(_, d, _)) | (&ty::Ref(_, s, _), &ty::RawPtr(TypeAndMut { ty: d, .. })) | @@ -335,20 +336,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> if dst_field.layout.is_zst() { continue; } - let src_field = match src.try_as_mplace() { - Ok(mplace) => { - let src_field = self.mplace_field(mplace, i as u64)?; - src_field.into() - } - Err(..) => { - let src_field_layout = src.layout.field(self, i)?; - // this must be a field covering the entire thing - assert_eq!(src.layout.fields.offset(i).bytes(), 0); - assert_eq!(src_field_layout.size, src.layout.size); - // just sawp out the layout - OpTy::from(ImmTy { imm: src.to_immediate(), layout: src_field_layout }) - } - }; + let src_field = self.operand_field(src, i as u64)?; if src_field.layout.ty == dst_field.layout.ty { self.copy_op(src_field, dst_field)?; } else { From 5e3ff4c2f195cbaa0412550a997497aa53752e23 Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 31 May 2019 20:49:19 +0100 Subject: [PATCH 05/30] Add test for condition in trait const param --- .../ui/const-generics/condition-in-trait-const-arg.rs | 10 ++++++++++ .../const-generics/condition-in-trait-const-arg.stderr | 6 ++++++ 2 files changed, 16 insertions(+) create mode 100644 src/test/ui/const-generics/condition-in-trait-const-arg.rs create mode 100644 src/test/ui/const-generics/condition-in-trait-const-arg.stderr diff --git a/src/test/ui/const-generics/condition-in-trait-const-arg.rs b/src/test/ui/const-generics/condition-in-trait-const-arg.rs new file mode 100644 index 0000000000000..18105eb7a75ff --- /dev/null +++ b/src/test/ui/const-generics/condition-in-trait-const-arg.rs @@ -0,0 +1,10 @@ +// run-pass + +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +trait IsZeroTrait{} + +impl IsZeroTrait<{0u8 == 0u8}> for () {} + +fn main() {} diff --git a/src/test/ui/const-generics/condition-in-trait-const-arg.stderr b/src/test/ui/const-generics/condition-in-trait-const-arg.stderr new file mode 100644 index 0000000000000..7c85651e7082f --- /dev/null +++ b/src/test/ui/const-generics/condition-in-trait-const-arg.stderr @@ -0,0 +1,6 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/condition-in-trait-const-arg.rs:3:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + From dfd9d0429cbea6133d240a37d6f4edf2a5a90a85 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 1 Jun 2019 00:23:26 -0700 Subject: [PATCH 06/30] Add an unusual-conversion example to to_uppercase MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Like how to_lowercase has ὈΔΥΣΣΕΎΣ. --- src/liballoc/str.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/liballoc/str.rs b/src/liballoc/str.rs index f66ff894ae865..0c7d2b837a39a 100644 --- a/src/liballoc/str.rs +++ b/src/liballoc/str.rs @@ -431,6 +431,13 @@ impl str { /// /// assert_eq!(new_year, new_year.to_uppercase()); /// ``` + /// + /// One character can become multiple: + /// ``` + /// let s = "tschüß"; + /// + /// assert_eq!("TSCHÜSS", s.to_uppercase()); + /// ``` #[stable(feature = "unicode_case_mapping", since = "1.2.0")] pub fn to_uppercase(&self) -> String { let mut s = String::with_capacity(self.len()); From 7bdc38d3a49d57fd56d2e69c8412f688b715f8ab Mon Sep 17 00:00:00 2001 From: Felix Rabe Date: Sat, 1 Jun 2019 11:26:08 +0200 Subject: [PATCH 07/30] Succinctify splice docs --- src/liballoc/vec.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 5cb91395b7bf7..92fe0834dd029 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -2018,16 +2018,14 @@ impl Vec { /// with the given `replace_with` iterator and yields the removed items. /// `replace_with` does not need to be the same length as `range`. /// - /// Note 1: The element range is removed even if the iterator is not - /// consumed until the end. + /// The element range is removed even if the iterator is not consumed until the end. /// - /// Note 2: It is unspecified how many elements are removed from the vector, + /// It is unspecified how many elements are removed from the vector /// if the `Splice` value is leaked. /// - /// Note 3: The input iterator `replace_with` is only consumed - /// when the `Splice` value is dropped. + /// The input iterator `replace_with` is only consumed when the `Splice` value is dropped. /// - /// Note 4: This is optimal if: + /// This is optimal if: /// /// * The tail (elements in the vector after `range`) is empty, /// * or `replace_with` yields fewer elements than `range`’s length From 911d205b1fab7cb0b84e1768c1744d89bd2c5c27 Mon Sep 17 00:00:00 2001 From: Chris Gregory Date: Sat, 1 Jun 2019 18:42:59 -0500 Subject: [PATCH 08/30] On TerminatorKind::DropAndReplace still handle unused_mut correctly --- src/librustc_mir/borrow_check/used_muts.rs | 44 +++++++++++----------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/src/librustc_mir/borrow_check/used_muts.rs b/src/librustc_mir/borrow_check/used_muts.rs index abfc2f9466c8e..2334bd33694c0 100644 --- a/src/librustc_mir/borrow_check/used_muts.rs +++ b/src/librustc_mir/borrow_check/used_muts.rs @@ -52,6 +52,24 @@ struct GatherUsedMutsVisitor<'visit, 'cx: 'visit, 'gcx: 'tcx, 'tcx: 'cx> { mbcx: &'visit mut MirBorrowckCtxt<'cx, 'gcx, 'tcx>, } +impl<'visit, 'cx, 'gcx, 'tcx> GatherUsedMutsVisitor<'visit, 'cx, 'gcx, 'tcx> { + fn remove_never_initialized_mut_locals(into: &Place) { + // Remove any locals that we found were initialized from the + // `never_initialized_mut_locals` set. At the end, the only remaining locals will + // be those that were never initialized - we will consider those as being used as + // they will either have been removed by unreachable code optimizations; or linted + // as unused variables. + if let Some(local) = into.base_local() { + debug!( + "visit_statement: statement={:?} local={:?} \ + never_initialized_mut_locals={:?}", + statement, local, self.never_initialized_mut_locals + ); + let _ = self.never_initialized_mut_locals.remove(&local); + } + } +} + impl<'visit, 'cx, 'gcx, 'tcx> Visitor<'tcx> for GatherUsedMutsVisitor<'visit, 'cx, 'gcx, 'tcx> { fn visit_terminator_kind( &mut self, @@ -61,14 +79,10 @@ impl<'visit, 'cx, 'gcx, 'tcx> Visitor<'tcx> for GatherUsedMutsVisitor<'visit, 'c debug!("visit_terminator_kind: kind={:?}", kind); match &kind { TerminatorKind::Call { destination: Some((into, _)), .. } => { - if let Some(local) = into.base_local() { - debug!( - "visit_terminator_kind: kind={:?} local={:?} \ - never_initialized_mut_locals={:?}", - kind, local, self.never_initialized_mut_locals - ); - let _ = self.never_initialized_mut_locals.remove(&local); - } + self.remove_never_initialized_mut_locals(&into); + }, + TerminatorKind::DropAndReplace { location, .. } => { + self.remove_never_initialized_mut_locals(&location); }, _ => {}, } @@ -81,19 +95,7 @@ impl<'visit, 'cx, 'gcx, 'tcx> Visitor<'tcx> for GatherUsedMutsVisitor<'visit, 'c ) { match &statement.kind { StatementKind::Assign(into, _) => { - // Remove any locals that we found were initialized from the - // `never_initialized_mut_locals` set. At the end, the only remaining locals will - // be those that were never initialized - we will consider those as being used as - // they will either have been removed by unreachable code optimizations; or linted - // as unused variables. - if let Some(local) = into.base_local() { - debug!( - "visit_statement: statement={:?} local={:?} \ - never_initialized_mut_locals={:?}", - statement, local, self.never_initialized_mut_locals - ); - let _ = self.never_initialized_mut_locals.remove(&local); - } + self.remove_never_initialized_mut_locals(into); }, _ => {}, } From c25b3df3e548ec42de1bb8a3aaad1e10d9de4aab Mon Sep 17 00:00:00 2001 From: Chris Gregory Date: Sat, 1 Jun 2019 16:50:15 -0700 Subject: [PATCH 09/30] Elide lifetimes not used Co-Authored-By: Mazdak Farrokhzad --- src/librustc_mir/borrow_check/used_muts.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/borrow_check/used_muts.rs b/src/librustc_mir/borrow_check/used_muts.rs index 2334bd33694c0..db5c3c7a34046 100644 --- a/src/librustc_mir/borrow_check/used_muts.rs +++ b/src/librustc_mir/borrow_check/used_muts.rs @@ -52,7 +52,7 @@ struct GatherUsedMutsVisitor<'visit, 'cx: 'visit, 'gcx: 'tcx, 'tcx: 'cx> { mbcx: &'visit mut MirBorrowckCtxt<'cx, 'gcx, 'tcx>, } -impl<'visit, 'cx, 'gcx, 'tcx> GatherUsedMutsVisitor<'visit, 'cx, 'gcx, 'tcx> { +impl GatherUsedMutsVisitor<'_, '_, '_, '_> { fn remove_never_initialized_mut_locals(into: &Place) { // Remove any locals that we found were initialized from the // `never_initialized_mut_locals` set. At the end, the only remaining locals will From a39fffea220b5bd72b1ae3d34c25e97d77fac1dc Mon Sep 17 00:00:00 2001 From: Chris Gregory Date: Sat, 1 Jun 2019 19:05:08 -0500 Subject: [PATCH 10/30] Add self parameter --- src/librustc_mir/borrow_check/used_muts.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/borrow_check/used_muts.rs b/src/librustc_mir/borrow_check/used_muts.rs index db5c3c7a34046..828429a1808c3 100644 --- a/src/librustc_mir/borrow_check/used_muts.rs +++ b/src/librustc_mir/borrow_check/used_muts.rs @@ -53,7 +53,7 @@ struct GatherUsedMutsVisitor<'visit, 'cx: 'visit, 'gcx: 'tcx, 'tcx: 'cx> { } impl GatherUsedMutsVisitor<'_, '_, '_, '_> { - fn remove_never_initialized_mut_locals(into: &Place) { + fn remove_never_initialized_mut_locals(&mut self, into: &Place) { // Remove any locals that we found were initialized from the // `never_initialized_mut_locals` set. At the end, the only remaining locals will // be those that were never initialized - we will consider those as being used as From 0a6a5c81ac8c853a8f026ab109965338ced4c3bb Mon Sep 17 00:00:00 2001 From: Chris Gregory Date: Sat, 1 Jun 2019 19:05:18 -0500 Subject: [PATCH 11/30] Move debug statement into statement visitor --- src/librustc_mir/borrow_check/used_muts.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/librustc_mir/borrow_check/used_muts.rs b/src/librustc_mir/borrow_check/used_muts.rs index 828429a1808c3..b9accd40c3998 100644 --- a/src/librustc_mir/borrow_check/used_muts.rs +++ b/src/librustc_mir/borrow_check/used_muts.rs @@ -60,11 +60,6 @@ impl GatherUsedMutsVisitor<'_, '_, '_, '_> { // they will either have been removed by unreachable code optimizations; or linted // as unused variables. if let Some(local) = into.base_local() { - debug!( - "visit_statement: statement={:?} local={:?} \ - never_initialized_mut_locals={:?}", - statement, local, self.never_initialized_mut_locals - ); let _ = self.never_initialized_mut_locals.remove(&local); } } @@ -95,6 +90,13 @@ impl<'visit, 'cx, 'gcx, 'tcx> Visitor<'tcx> for GatherUsedMutsVisitor<'visit, 'c ) { match &statement.kind { StatementKind::Assign(into, _) => { + if let Some(local) = into.base_local() { + debug!( + "visit_statement: statement={:?} local={:?} \ + never_initialized_mut_locals={:?}", + statement, local, self.never_initialized_mut_locals + ); + } self.remove_never_initialized_mut_locals(into); }, _ => {}, From 2a3b29ef97449038bf15f982d74e0d9379a4b953 Mon Sep 17 00:00:00 2001 From: Chris Gregory Date: Sat, 1 Jun 2019 19:06:22 -0500 Subject: [PATCH 12/30] Add anonymous lifetime to Place parameter --- src/librustc_mir/borrow_check/used_muts.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/borrow_check/used_muts.rs b/src/librustc_mir/borrow_check/used_muts.rs index b9accd40c3998..4a4787337ab58 100644 --- a/src/librustc_mir/borrow_check/used_muts.rs +++ b/src/librustc_mir/borrow_check/used_muts.rs @@ -53,7 +53,7 @@ struct GatherUsedMutsVisitor<'visit, 'cx: 'visit, 'gcx: 'tcx, 'tcx: 'cx> { } impl GatherUsedMutsVisitor<'_, '_, '_, '_> { - fn remove_never_initialized_mut_locals(&mut self, into: &Place) { + fn remove_never_initialized_mut_locals(&mut self, into: &Place<'_>) { // Remove any locals that we found were initialized from the // `never_initialized_mut_locals` set. At the end, the only remaining locals will // be those that were never initialized - we will consider those as being used as From 7feeaf0d2748f9ff81076a96c16ef360c9033071 Mon Sep 17 00:00:00 2001 From: Chris Gregory Date: Sat, 1 Jun 2019 19:14:09 -0500 Subject: [PATCH 13/30] Add test --- src/test/ui/nll/issue-61424.rs | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 src/test/ui/nll/issue-61424.rs diff --git a/src/test/ui/nll/issue-61424.rs b/src/test/ui/nll/issue-61424.rs new file mode 100644 index 0000000000000..fcb5ff675986e --- /dev/null +++ b/src/test/ui/nll/issue-61424.rs @@ -0,0 +1,7 @@ +#![deny(unused_mut)] + +fn main() { + let mut x; //~ ERROR: variable does not need to be mutable + x = 0; + dbg!(0); +} From eb73b73b8d50b29658d87670670d939746b2d00c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 1 Jun 2019 16:24:19 -0700 Subject: [PATCH 14/30] Suggest using `as_ref` on `*const T` --- src/librustc_typeck/check/method/suggest.rs | 5 +++++ src/test/ui/issues/issue-21596.rs | 5 +++++ src/test/ui/issues/issue-21596.stderr | 13 +++++++++++++ 3 files changed, 23 insertions(+) create mode 100644 src/test/ui/issues/issue-21596.rs create mode 100644 src/test/ui/issues/issue-21596.stderr diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 9ef6112a94591..f05e0d31582fa 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -324,6 +324,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ); } } + if let ty::RawPtr(_) = &actual.sty { + err.note("try using `<*const T>::as_ref()` to get a reference to the \ + type behind the pointer: https://doc.rust-lang.org/std/\ + primitive.pointer.html#method.as_ref"); + } err } } else { diff --git a/src/test/ui/issues/issue-21596.rs b/src/test/ui/issues/issue-21596.rs new file mode 100644 index 0000000000000..79f6c91d9ac97 --- /dev/null +++ b/src/test/ui/issues/issue-21596.rs @@ -0,0 +1,5 @@ +fn main() { + let x = 8u8; + let z: *const u8 = &x; + println!("{}", z.to_string()); //~ ERROR E0599 +} diff --git a/src/test/ui/issues/issue-21596.stderr b/src/test/ui/issues/issue-21596.stderr new file mode 100644 index 0000000000000..07d29f30e988a --- /dev/null +++ b/src/test/ui/issues/issue-21596.stderr @@ -0,0 +1,13 @@ +error[E0599]: no method named `to_string` found for type `*const u8` in the current scope + --> $DIR/issue-21596.rs:4:22 + | +LL | println!("{}", z.to_string()); + | ^^^^^^^^^ + | + = note: try using `<*const T>::as_ref()` to get a reference to the type behind the pointer: https://doc.rust-lang.org/std/primitive.pointer.html#method.as_ref + = note: the method `to_string` exists but the following trait bounds were not satisfied: + `*const u8 : std::string::ToString` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. From fea2cdb0a48e0cc6119d036a2ff4954e71bb8670 Mon Sep 17 00:00:00 2001 From: Chris Gregory Date: Sun, 2 Jun 2019 19:11:15 -0700 Subject: [PATCH 15/30] Use a type implementing Drop --- src/test/ui/nll/issue-61424.rs | 4 ++-- src/test/ui/nll/issue-61424.stderr | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/nll/issue-61424.stderr diff --git a/src/test/ui/nll/issue-61424.rs b/src/test/ui/nll/issue-61424.rs index fcb5ff675986e..44c8e9f7256f5 100644 --- a/src/test/ui/nll/issue-61424.rs +++ b/src/test/ui/nll/issue-61424.rs @@ -2,6 +2,6 @@ fn main() { let mut x; //~ ERROR: variable does not need to be mutable - x = 0; - dbg!(0); + x = String::new(); + dbg!(x); } diff --git a/src/test/ui/nll/issue-61424.stderr b/src/test/ui/nll/issue-61424.stderr new file mode 100644 index 0000000000000..ae336b2fe1c03 --- /dev/null +++ b/src/test/ui/nll/issue-61424.stderr @@ -0,0 +1,16 @@ +error: variable does not need to be mutable + --> $DIR/issue-61424.rs:4:9 + | +LL | let mut x; + | ----^ + | | + | help: remove this `mut` + | +note: lint level defined here + --> $DIR/issue-61424.rs:1:9 + | +LL | #![deny(unused_mut)] + | ^^^^^^^^^^ + +error: aborting due to previous error + From 2be25e93addf6f5dc64bc033be8636e3028082fa Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 31 May 2019 20:49:30 +0100 Subject: [PATCH 16/30] Allow TraitRef as AnonConst parent --- src/librustc_typeck/collect.rs | 155 +++++++++++++++++---------------- 1 file changed, 82 insertions(+), 73 deletions(-) diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 3806fd0998b5e..a9a106b787faf 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1335,88 +1335,97 @@ pub fn checked_type_of<'a, 'tcx>( Node::Ty(&hir::Ty { node: hir::TyKind::Path(_), .. }) | Node::Expr(&hir::Expr { node: ExprKind::Struct(..), .. }) | - Node::Expr(&hir::Expr { node: ExprKind::Path(_), .. }) => { + Node::Expr(&hir::Expr { node: ExprKind::Path(_), .. }) | + Node::TraitRef(..) => { let path = match parent_node { - Node::Ty(&hir::Ty { node: hir::TyKind::Path(ref path), .. }) | - Node::Expr(&hir::Expr { node: ExprKind::Path(ref path), .. }) => { - path + Node::Ty(&hir::Ty { + node: hir::TyKind::Path(QPath::Resolved(_, ref path)), + .. + }) + | Node::Expr(&hir::Expr { + node: ExprKind::Path(QPath::Resolved(_, ref path)), + .. + }) => { + Some(&**path) } Node::Expr(&hir::Expr { node: ExprKind::Struct(ref path, ..), .. }) => { - &*path + if let QPath::Resolved(_, ref path) = **path { + Some(&**path) + } else { + None + } } - _ => unreachable!(), + Node::TraitRef(&hir::TraitRef { ref path, .. }) => Some(path), + _ => None, }; - match path { - QPath::Resolved(_, ref path) => { - let arg_index = path.segments.iter() - .filter_map(|seg| seg.args.as_ref()) - .map(|generic_args| generic_args.args.as_ref()) - .find_map(|args| { - args.iter() - .filter(|arg| arg.is_const()) - .enumerate() - .filter(|(_, arg)| arg.id() == hir_id) - .map(|(index, _)| index) - .next() - }) - .or_else(|| { - if !fail { - None - } else { - bug!("no arg matching AnonConst in path") - } - })?; - - // We've encountered an `AnonConst` in some path, so we need to - // figure out which generic parameter it corresponds to and return - // the relevant type. - let generics = match path.res { - Res::Def(DefKind::Ctor(..), def_id) => - tcx.generics_of(tcx.parent(def_id).unwrap()), - Res::Def(_, def_id) => - tcx.generics_of(def_id), - Res::Err => - return Some(tcx.types.err), - _ if !fail => - return None, - x => { - tcx.sess.delay_span_bug( - DUMMY_SP, - &format!( - "unexpected const parent path def {:?}", x - ), - ); - return Some(tcx.types.err); + if let Some(path) = path { + let arg_index = path.segments.iter() + .filter_map(|seg| seg.args.as_ref()) + .map(|generic_args| generic_args.args.as_ref()) + .find_map(|args| { + args.iter() + .filter(|arg| arg.is_const()) + .enumerate() + .filter(|(_, arg)| arg.id() == hir_id) + .map(|(index, _)| index) + .next() + }) + .or_else(|| { + if !fail { + None + } else { + bug!("no arg matching AnonConst in path") } - }; - - generics.params.iter() - .filter(|param| { - if let ty::GenericParamDefKind::Const = param.kind { - true - } else { - false - } - }) - .nth(arg_index) - .map(|param| tcx.type_of(param.def_id)) - // This is no generic parameter associated with the arg. This is - // probably from an extra arg where one is not needed. - .unwrap_or(tcx.types.err) - } - x => { - if !fail { - return None; + })?; + + // We've encountered an `AnonConst` in some path, so we need to + // figure out which generic parameter it corresponds to and return + // the relevant type. + let generics = match path.res { + Res::Def(DefKind::Ctor(..), def_id) => { + tcx.generics_of(tcx.parent(def_id).unwrap()) } - tcx.sess.delay_span_bug( - DUMMY_SP, - &format!( - "unexpected const parent path {:?}", x - ), - ); - tcx.types.err + Res::Def(_, def_id) => tcx.generics_of(def_id), + Res::Err => return Some(tcx.types.err), + _ if !fail => return None, + res => { + tcx.sess.delay_span_bug( + DUMMY_SP, + &format!( + "unexpected const parent path def {:?}", + res, + ), + ); + return Some(tcx.types.err); + } + }; + + generics.params.iter() + .filter(|param| { + if let ty::GenericParamDefKind::Const = param.kind { + true + } else { + false + } + }) + .nth(arg_index) + .map(|param| tcx.type_of(param.def_id)) + // This is no generic parameter associated with the arg. This is + // probably from an extra arg where one is not needed. + .unwrap_or(tcx.types.err) + } else { + if !fail { + return None; } + tcx.sess.delay_span_bug( + DUMMY_SP, + &format!( + "unexpected const parent path {:?}", + parent_node, + ), + ); + return Some(tcx.types.err); } } From 2b27c6235b4feb1e2aaac2dde5c5c67a29470127 Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 31 May 2019 21:18:43 +0100 Subject: [PATCH 17/30] Allow `true` and `false` in const generic arguments --- src/libsyntax/parse/parser.rs | 10 +++++++--- .../ui/const-generics/condition-in-trait-const-arg.rs | 2 ++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 746e9cad4962c..a562d2a1d2b44 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -5250,9 +5250,13 @@ impl<'a> Parser<'a> { // FIXME(const_generics): to distinguish between idents for types and consts, // we should introduce a GenericArg::Ident in the AST and distinguish when // lowering to the HIR. For now, idents for const args are not permitted. - return Err( - self.fatal("identifiers may currently not be used for const generics") - ); + if self.token.is_keyword(kw::True) || self.token.is_keyword(kw::False) { + self.parse_literal_maybe_minus()? + } else { + return Err( + self.fatal("identifiers may currently not be used for const generics") + ); + } } else { self.parse_literal_maybe_minus()? }; diff --git a/src/test/ui/const-generics/condition-in-trait-const-arg.rs b/src/test/ui/const-generics/condition-in-trait-const-arg.rs index 18105eb7a75ff..091fe904826d4 100644 --- a/src/test/ui/const-generics/condition-in-trait-const-arg.rs +++ b/src/test/ui/const-generics/condition-in-trait-const-arg.rs @@ -7,4 +7,6 @@ trait IsZeroTrait{} impl IsZeroTrait<{0u8 == 0u8}> for () {} +impl IsZeroTrait for ((),) {} + fn main() {} From d0c78dd7aa692a9338b2085e8d227cde73d2a5f9 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 29 May 2019 04:10:49 +0300 Subject: [PATCH 18/30] syntax: revert `ast::AsyncArgument` and associated changes. Here follows the main reverts applied in order to make this commit: Revert "Rollup merge of #60676 - davidtwco:issue-60674, r=cramertj" This reverts commit 45b09453dbf120cc23d889435aac3ed7d2ec8eb7, reversing changes made to f6df1f6c30b469cb9e65c5453a0efa03cbb6005e. Revert "Rollup merge of #60437 - davidtwco:issue-60236, r=nikomatsakis" This reverts commit 16939a50ea440e72cb6ecefdaabb988addb1ec0e, reversing changes made to 12bf98155249783583a91863c5dccf9e346f1226. Revert "Rollup merge of #59823 - davidtwco:issue-54716, r=cramertj" This reverts commit 62d1574876f5531bce1b267e62dff520d7adcbbb, reversing changes made to 4eff8526a789e0dfa8b97f7dec91b7b5c18e8544. --- src/librustc/hir/lowering.rs | 187 +++++--------------------- src/librustc/hir/map/def_collector.rs | 41 ++---- src/librustc/lint/context.rs | 24 ---- src/librustc_passes/ast_validation.rs | 6 +- src/librustc_resolve/lib.rs | 72 +++------- src/librustc_save_analysis/sig.rs | 2 +- src/libsyntax/ast.rs | 55 +------- src/libsyntax/ext/build.rs | 6 +- src/libsyntax/ext/placeholders.rs | 23 +--- src/libsyntax/mut_visit.rs | 42 +----- src/libsyntax/parse/diagnostics.rs | 2 +- src/libsyntax/parse/parser.rs | 141 ++----------------- src/libsyntax/print/pprust.rs | 23 ++-- src/libsyntax/visit.rs | 3 - src/libsyntax_ext/deriving/debug.rs | 1 - 15 files changed, 108 insertions(+), 520 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 08fbd0d20d74d..a61bdeb829915 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -465,32 +465,6 @@ impl<'a> LoweringContext<'a> { visit::walk_pat(self, p) } - fn visit_fn(&mut self, fk: visit::FnKind<'lcx>, fd: &'lcx FnDecl, s: Span, _: NodeId) { - if fk.header().map(|h| h.asyncness.node.is_async()).unwrap_or(false) { - // Don't visit the original pattern for async functions as it will be - // replaced. - for arg in &fd.inputs { - if let ArgSource::AsyncFn(pat) = &arg.source { self.visit_pat(pat); } - self.visit_ty(&arg.ty) - } - self.visit_fn_ret_ty(&fd.output); - - match fk { - visit::FnKind::ItemFn(_, decl, _, body) => { - self.visit_fn_header(decl); - self.visit_block(body) - }, - visit::FnKind::Method(_, sig, _, body) => { - self.visit_fn_header(&sig.header); - self.visit_block(body) - }, - visit::FnKind::Closure(body) => self.visit_expr(body), - } - } else { - visit::walk_fn(self, fk, fd, s) - } - } - fn visit_item(&mut self, item: &'lcx Item) { let hir_id = self.lctx.allocate_hir_id_counter(item.id); @@ -2266,17 +2240,10 @@ impl<'a> LoweringContext<'a> { init: l.init.as_ref().map(|e| P(self.lower_expr(e))), span: l.span, attrs: l.attrs.clone(), - source: self.lower_local_source(l.source), + source: hir::LocalSource::Normal, }, ids) } - fn lower_local_source(&mut self, ls: LocalSource) -> hir::LocalSource { - match ls { - LocalSource::Normal => hir::LocalSource::Normal, - LocalSource::AsyncFn => hir::LocalSource::AsyncFn, - } - } - fn lower_mutability(&mut self, m: Mutability) -> hir::Mutability { match m { Mutability::Mutable => hir::MutMutable, @@ -2292,14 +2259,7 @@ impl<'a> LoweringContext<'a> { hir::Arg { hir_id: self.lower_node_id(arg.id), pat: self.lower_pat(&arg.pat), - source: self.lower_arg_source(&arg.source), - } - } - - fn lower_arg_source(&mut self, source: &ArgSource) -> hir::ArgSource { - match source { - ArgSource::Normal => hir::ArgSource::Normal, - ArgSource::AsyncFn(pat) => hir::ArgSource::AsyncFn(self.lower_pat(pat)), + source: hir::ArgSource::Normal, } } @@ -3028,44 +2988,13 @@ impl<'a> LoweringContext<'a> { fn lower_async_body( &mut self, decl: &FnDecl, - asyncness: &IsAsync, + asyncness: IsAsync, body: &Block, ) -> hir::BodyId { self.lower_body(Some(&decl), |this| { - if let IsAsync::Async { closure_id, ref arguments, .. } = asyncness { - let mut body = body.clone(); - - // Async function arguments are lowered into the closure body so that they are - // captured and so that the drop order matches the equivalent non-async functions. - // - // async fn foo(: , : , : ) { - // async move { - // } - // } - // - // // ...becomes... - // fn foo(__arg0: , __arg1: , __arg2: ) { - // async move { - // let __arg2 = __arg2; - // let = __arg2; - // let __arg1 = __arg1; - // let = __arg1; - // let __arg0 = __arg0; - // let = __arg0; - // } - // } - // - // If `` is a simple ident, then it is lowered to a single - // `let = ;` statement as an optimization. - for a in arguments.iter().rev() { - if let Some(pat_stmt) = a.pat_stmt.clone() { - body.stmts.insert(0, pat_stmt); - } - body.stmts.insert(0, a.move_stmt.clone()); - } - + if let IsAsync::Async { closure_id, .. } = asyncness { let async_expr = this.make_async_expr( - CaptureBy::Value, *closure_id, None, body.span, + CaptureBy::Value, closure_id, None, body.span, |this| { let body = this.lower_block(&body, false); this.expr_block(body, ThinVec::new()) @@ -3126,47 +3055,26 @@ impl<'a> LoweringContext<'a> { value ) } - ItemKind::Fn(ref decl, ref header, ref generics, ref body) => { + ItemKind::Fn(ref decl, header, ref generics, ref body) => { let fn_def_id = self.resolver.definitions().local_def_id(id); self.with_new_scopes(|this| { + // Note: we don't need to change the return type from `T` to + // `impl Future` here because lower_body + // only cares about the input argument patterns in the function + // declaration (decl), not the return types. + let body_id = this.lower_async_body(decl, header.asyncness.node, body); + let (generics, fn_decl) = this.add_in_band_defs( + generics, + fn_def_id, + AnonymousLifetimeMode::PassThrough, + |this, idty| this.lower_fn_decl( + decl, + Some((fn_def_id, idty)), + true, + header.asyncness.node.opt_return_id() + ), + ); this.current_item = Some(ident.span); - let mut lower_fn = |decl: &FnDecl| { - // Note: we don't need to change the return type from `T` to - // `impl Future` here because lower_body - // only cares about the input argument patterns in the function - // declaration (decl), not the return types. - let body_id = this.lower_async_body(&decl, &header.asyncness.node, body); - - let (generics, fn_decl) = this.add_in_band_defs( - generics, - fn_def_id, - AnonymousLifetimeMode::PassThrough, - |this, idty| this.lower_fn_decl( - &decl, - Some((fn_def_id, idty)), - true, - header.asyncness.node.opt_return_id() - ), - ); - - (body_id, generics, fn_decl) - }; - - let (body_id, generics, fn_decl) = if let IsAsync::Async { - arguments, .. - } = &header.asyncness.node { - let mut decl = decl.clone(); - // Replace the arguments of this async function with the generated - // arguments that will be moved into the closure. - for (i, a) in arguments.clone().drain(..).enumerate() { - if let Some(arg) = a.arg { - decl.inputs[i] = arg; - } - } - lower_fn(&decl) - } else { - lower_fn(decl) - }; hir::ItemKind::Fn( fn_decl, @@ -3638,36 +3546,15 @@ impl<'a> LoweringContext<'a> { ) } ImplItemKind::Method(ref sig, ref body) => { - let mut lower_method = |sig: &MethodSig| { - let body_id = self.lower_async_body( - &sig.decl, &sig.header.asyncness.node, body - ); - let impl_trait_return_allow = !self.is_in_trait_impl; - let (generics, sig) = self.lower_method_sig( - &i.generics, - sig, - impl_item_def_id, - impl_trait_return_allow, - sig.header.asyncness.node.opt_return_id(), - ); - (body_id, generics, sig) - }; - - let (body_id, generics, sig) = if let IsAsync::Async { - ref arguments, .. - } = sig.header.asyncness.node { - let mut sig = sig.clone(); - // Replace the arguments of this async function with the generated - // arguments that will be moved into the closure. - for (i, a) in arguments.clone().drain(..).enumerate() { - if let Some(arg) = a.arg { - sig.decl.inputs[i] = arg; - } - } - lower_method(&sig) - } else { - lower_method(sig) - }; + let body_id = self.lower_async_body(&sig.decl, sig.header.asyncness.node, body); + let impl_trait_return_allow = !self.is_in_trait_impl; + let (generics, sig) = self.lower_method_sig( + &i.generics, + sig, + impl_item_def_id, + impl_trait_return_allow, + sig.header.asyncness.node.opt_return_id(), + ); self.current_item = Some(i.span); (generics, hir::ImplItemKind::Method(sig, body_id)) @@ -3860,7 +3747,7 @@ impl<'a> LoweringContext<'a> { impl_trait_return_allow: bool, is_async: Option, ) -> (hir::Generics, hir::MethodSig) { - let header = self.lower_fn_header(&sig.header); + let header = self.lower_fn_header(sig.header); let (generics, decl) = self.add_in_band_defs( generics, fn_def_id, @@ -3882,10 +3769,10 @@ impl<'a> LoweringContext<'a> { } } - fn lower_fn_header(&mut self, h: &FnHeader) -> hir::FnHeader { + fn lower_fn_header(&mut self, h: FnHeader) -> hir::FnHeader { hir::FnHeader { unsafety: self.lower_unsafety(h.unsafety), - asyncness: self.lower_asyncness(&h.asyncness.node), + asyncness: self.lower_asyncness(h.asyncness.node), constness: self.lower_constness(h.constness), abi: h.abi, } @@ -3905,7 +3792,7 @@ impl<'a> LoweringContext<'a> { } } - fn lower_asyncness(&mut self, a: &IsAsync) -> hir::IsAsync { + fn lower_asyncness(&mut self, a: IsAsync) -> hir::IsAsync { match a { IsAsync::Async { .. } => hir::IsAsync::Async, IsAsync::NotAsync => hir::IsAsync::NotAsync, @@ -4222,7 +4109,7 @@ impl<'a> LoweringContext<'a> { } ExprKind::Await(_origin, ref expr) => self.lower_await(e.span, expr), ExprKind::Closure( - capture_clause, ref asyncness, movability, ref decl, ref body, fn_decl_span + capture_clause, asyncness, movability, ref decl, ref body, fn_decl_span ) => { if let IsAsync::Async { closure_id, .. } = asyncness { let outer_decl = FnDecl { @@ -4260,7 +4147,7 @@ impl<'a> LoweringContext<'a> { Some(&**ty) } else { None }; let async_body = this.make_async_expr( - capture_clause, *closure_id, async_ret_ty, body.span, + capture_clause, closure_id, async_ret_ty, body.span, |this| { this.with_new_scopes(|this| this.lower_expr(body)) }); diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index bde27c71f9a6d..a4484c8173898 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -64,17 +64,16 @@ impl<'a> DefCollector<'a> { id: NodeId, name: Name, span: Span, - header: &'a FnHeader, + header: &FnHeader, generics: &'a Generics, decl: &'a FnDecl, body: &'a Block, ) { - let (closure_id, return_impl_trait_id, arguments) = match &header.asyncness.node { + let (closure_id, return_impl_trait_id) = match header.asyncness.node { IsAsync::Async { closure_id, return_impl_trait_id, - arguments, - } => (closure_id, return_impl_trait_id, arguments), + } => (closure_id, return_impl_trait_id), _ => unreachable!(), }; @@ -83,38 +82,16 @@ impl<'a> DefCollector<'a> { let fn_def_data = DefPathData::ValueNs(name.as_interned_str()); let fn_def = self.create_def(id, fn_def_data, span); return self.with_parent(fn_def, |this| { - this.create_def(*return_impl_trait_id, DefPathData::ImplTrait, span); + this.create_def(return_impl_trait_id, DefPathData::ImplTrait, span); visit::walk_generics(this, generics); - - // Walk the generated arguments for the `async fn`. - for (i, a) in arguments.iter().enumerate() { - use visit::Visitor; - if let Some(arg) = &a.arg { - this.visit_ty(&arg.ty); - } else { - this.visit_ty(&decl.inputs[i].ty); - } - } - - // We do not invoke `walk_fn_decl` as this will walk the arguments that are being - // replaced. - visit::walk_fn_ret_ty(this, &decl.output); + visit::walk_fn_decl(this, decl); let closure_def = this.create_def( - *closure_id, DefPathData::ClosureExpr, span, + closure_id, DefPathData::ClosureExpr, span, ); this.with_parent(closure_def, |this| { - use visit::Visitor; - // Walk each of the generated statements before the regular block body. - for a in arguments { - this.visit_stmt(&a.move_stmt); - if let Some(pat_stmt) = &a.pat_stmt { - this.visit_stmt(&pat_stmt); - } - } - - visit::walk_block(this, &body); + visit::walk_block(this, body); }) }) } @@ -302,7 +279,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { match expr.node { ExprKind::Mac(..) => return self.visit_macro_invoc(expr.id), - ExprKind::Closure(_, ref asyncness, ..) => { + ExprKind::Closure(_, asyncness, ..) => { let closure_def = self.create_def(expr.id, DefPathData::ClosureExpr, expr.span); @@ -311,7 +288,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { // Async closures desugar to closures inside of closures, so // we must create two defs. if let IsAsync::Async { closure_id, .. } = asyncness { - let async_def = self.create_def(*closure_id, + let async_def = self.create_def(closure_id, DefPathData::ClosureExpr, expr.span); self.parent_def = Some(async_def); diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index c6583dd7a27b7..c5c6c4b944700 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -1335,30 +1335,6 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> run_early_pass!(self, check_mac, mac); } - - fn visit_fn_header(&mut self, header: &'a ast::FnHeader) { - // Unlike in HIR lowering and name resolution, the `AsyncArgument` statements are not added - // to the function body and the arguments do not replace those in the declaration. They are - // still visited manually here so that buffered lints can be emitted. - if let ast::IsAsync::Async { ref arguments, .. } = header.asyncness.node { - for a in arguments { - // Visit the argument.. - if let Some(arg) = &a.arg { - self.visit_pat(&arg.pat); - if let ast::ArgSource::AsyncFn(pat) = &arg.source { - self.visit_pat(pat); - } - self.visit_ty(&arg.ty); - } - - // ..and the statement. - self.visit_stmt(&a.move_stmt); - if let Some(pat_stmt) = &a.pat_stmt { - self.visit_stmt(&pat_stmt); - } - } - } - } } struct LateLintPassObjects<'a> { diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 2afcbe8a15137..89c4a9106a477 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -222,7 +222,7 @@ impl<'a> AstValidator<'a> { } } - fn check_trait_fn_not_async(&self, span: Span, asyncness: &IsAsync) { + fn check_trait_fn_not_async(&self, span: Span, asyncness: IsAsync) { if asyncness.is_async() { struct_span_err!(self.session, span, E0706, "trait fns cannot be declared `async`").emit() @@ -561,7 +561,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.invalid_visibility(&impl_item.vis, None); if let ImplItemKind::Method(ref sig, _) = impl_item.node { self.check_trait_fn_not_const(sig.header.constness); - self.check_trait_fn_not_async(impl_item.span, &sig.header.asyncness.node); + self.check_trait_fn_not_async(impl_item.span, sig.header.asyncness.node); } } } @@ -633,7 +633,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.no_questions_in_bounds(bounds, "supertraits", true); for trait_item in trait_items { if let TraitItemKind::Method(ref sig, ref block) = trait_item.node { - self.check_trait_fn_not_async(trait_item.span, &sig.header.asyncness.node); + self.check_trait_fn_not_async(trait_item.span, sig.header.asyncness.node); self.check_trait_fn_not_const(sig.header.constness); if block.is_none() { self.check_decl_no_pat(&sig.decl, |span, mut_ident| { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 21e759ccc650e..99abe69017da7 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -855,15 +855,10 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> { _: NodeId) { debug!("(resolving function) entering function"); - let (rib_kind, asyncness) = match function_kind { - FnKind::ItemFn(_, ref header, ..) => - (FnItemRibKind, &header.asyncness.node), - FnKind::Method(_, ref sig, _, _) => - (AssocItemRibKind, &sig.header.asyncness.node), - FnKind::Closure(_) => - // Async closures aren't resolved through `visit_fn`-- they're - // processed separately - (NormalRibKind, &IsAsync::NotAsync), + let rib_kind = match function_kind { + FnKind::ItemFn(..) => FnItemRibKind, + FnKind::Method(..) => AssocItemRibKind, + FnKind::Closure(_) => NormalRibKind, }; // Create a value rib for the function. @@ -874,45 +869,20 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> { // Add each argument to the rib. let mut bindings_list = FxHashMap::default(); - let mut add_argument = |argument: &ast::Arg| { + for argument in &declaration.inputs { self.resolve_pattern(&argument.pat, PatternSource::FnParam, &mut bindings_list); + self.visit_ty(&argument.ty); - debug!("(resolving function) recorded argument"); - }; - // Walk the generated async arguments if this is an `async fn`, otherwise walk the - // normal arguments. - if let IsAsync::Async { ref arguments, .. } = asyncness { - for (i, a) in arguments.iter().enumerate() { - if let Some(arg) = &a.arg { - add_argument(&arg); - } else { - add_argument(&declaration.inputs[i]); - } - } - } else { - for a in &declaration.inputs { add_argument(a); } + debug!("(resolving function) recorded argument"); } - visit::walk_fn_ret_ty(self, &declaration.output); // Resolve the function body, potentially inside the body of an async closure match function_kind { - FnKind::ItemFn(.., body) | FnKind::Method(.., body) => { - if let IsAsync::Async { ref arguments, .. } = asyncness { - let mut body = body.clone(); - // Insert the generated statements into the body before attempting to - // resolve names. - for a in arguments.iter().rev() { - if let Some(pat_stmt) = a.pat_stmt.clone() { - body.stmts.insert(0, pat_stmt); - } - body.stmts.insert(0, a.move_stmt.clone()); - } - self.visit_block(&body); - } else { - self.visit_block(body); - } + FnKind::ItemFn(.., body) | + FnKind::Method(.., body) => { + self.visit_block(body); } FnKind::Closure(body) => { self.visit_expr(body); @@ -4178,7 +4148,7 @@ impl<'a> Resolver<'a> { let add_module_candidates = |module: Module<'_>, names: &mut Vec| { for (&(ident, _), resolution) in module.resolutions.borrow().iter() { if let Some(binding) = resolution.borrow().binding { - if !ident.is_gensymed() && filter_fn(binding.res()) { + if filter_fn(binding.res()) { names.push(TypoSuggestion { candidate: ident.name, article: binding.res().article(), @@ -4196,7 +4166,7 @@ impl<'a> Resolver<'a> { for rib in self.ribs[ns].iter().rev() { // Locals and type parameters for (ident, &res) in &rib.bindings { - if !ident.is_gensymed() && filter_fn(res) { + if filter_fn(res) { names.push(TypoSuggestion { candidate: ident.name, article: res.article(), @@ -4226,7 +4196,7 @@ impl<'a> Resolver<'a> { }, ); - if !ident.is_gensymed() && filter_fn(crate_mod) { + if filter_fn(crate_mod) { Some(TypoSuggestion { candidate: ident.name, article: "a", @@ -4249,15 +4219,13 @@ impl<'a> Resolver<'a> { // Add primitive types to the mix if filter_fn(Res::PrimTy(Bool)) { names.extend( - self.primitive_type_table.primitive_types - .iter() - .map(|(name, _)| { - TypoSuggestion { - candidate: *name, - article: "a", - kind: "primitive type", - } - }) + self.primitive_type_table.primitive_types.iter().map(|(name, _)| { + TypoSuggestion { + candidate: *name, + article: "a", + kind: "primitive type", + } + }) ) } } else { diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs index 109863f8a56b2..db8b5eacd94d9 100644 --- a/src/librustc_save_analysis/sig.rs +++ b/src/librustc_save_analysis/sig.rs @@ -374,7 +374,7 @@ impl Sig for ast::Item { Ok(extend_sig(ty, text, defs, vec![])) } - ast::ItemKind::Fn(ref decl, ref header, ref generics, _) => { + ast::ItemKind::Fn(ref decl, header, ref generics, _) => { let mut text = String::new(); if header.constness.node == ast::Constness::Const { text.push_str("const "); diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 75e83bd9f9c74..b8a10d90c3c0a 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -879,17 +879,6 @@ pub struct Local { pub id: NodeId, pub span: Span, pub attrs: ThinVec, - /// Origin of this local variable. - pub source: LocalSource, -} - -#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)] -pub enum LocalSource { - /// Local was parsed from source. - Normal, - /// Within `ast::IsAsync::Async`, a local is generated that will contain the moved arguments - /// of an `async fn`. - AsyncFn, } /// An arm of a 'match'. @@ -1770,16 +1759,6 @@ pub struct Arg { pub ty: P, pub pat: P, pub id: NodeId, - pub source: ArgSource, -} - -/// The source of an argument in a function header. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub enum ArgSource { - /// Argument as written by the user. - Normal, - /// Argument from `async fn` lowering, contains the original binding pattern. - AsyncFn(P), } /// Alternative representation for `Arg`s describing `self` parameter of methods. @@ -1839,7 +1818,6 @@ impl Arg { }), ty, id: DUMMY_NODE_ID, - source: ArgSource::Normal, }; match eself.node { SelfKind::Explicit(ty, mutbl) => arg(mutbl, ty), @@ -1894,39 +1872,18 @@ pub enum Unsafety { Normal, } -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct AsyncArgument { - /// `__arg0` - pub ident: Ident, - /// `__arg0: ` argument to replace existing function argument `: `. Only if - /// argument is not a simple binding. - pub arg: Option, - /// `let __arg0 = __arg0;` statement to be inserted at the start of the block. - pub move_stmt: Stmt, - /// `let = __arg0;` statement to be inserted at the start of the block, after matching - /// move statement. Only if argument is not a simple binding. - pub pat_stmt: Option, -} - -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug)] pub enum IsAsync { Async { closure_id: NodeId, return_impl_trait_id: NodeId, - /// This field stores the arguments and statements that are used in HIR lowering to - /// ensure that `async fn` arguments are dropped at the correct time. - /// - /// The argument and statements here are generated at parse time as they are required in - /// both the hir lowering, def collection and name resolution and this stops them needing - /// to be created in each place. - arguments: Vec, }, NotAsync, } impl IsAsync { - pub fn is_async(&self) -> bool { - if let IsAsync::Async { .. } = *self { + pub fn is_async(self) -> bool { + if let IsAsync::Async { .. } = self { true } else { false @@ -1934,12 +1891,12 @@ impl IsAsync { } /// In ths case this is an `async` return, the `NodeId` for the generated `impl Trait` item. - pub fn opt_return_id(&self) -> Option { + pub fn opt_return_id(self) -> Option { match self { IsAsync::Async { return_impl_trait_id, .. - } => Some(*return_impl_trait_id), + } => Some(return_impl_trait_id), IsAsync::NotAsync => None, } } @@ -2279,7 +2236,7 @@ impl Item { /// /// All the information between the visibility and the name of the function is /// included in this struct (e.g., `async unsafe fn` or `const extern "C" fn`). -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)] pub struct FnHeader { pub unsafety: Unsafety, pub asyncness: Spanned, diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 9c0ffc1f6e8cb..47c79f8466a95 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -516,7 +516,6 @@ impl<'a> AstBuilder for ExtCtxt<'a> { id: ast::DUMMY_NODE_ID, span: sp, attrs: ThinVec::new(), - source: ast::LocalSource::Normal, }); ast::Stmt { id: ast::DUMMY_NODE_ID, @@ -545,7 +544,6 @@ impl<'a> AstBuilder for ExtCtxt<'a> { id: ast::DUMMY_NODE_ID, span: sp, attrs: ThinVec::new(), - source: ast::LocalSource::Normal, }); ast::Stmt { id: ast::DUMMY_NODE_ID, @@ -563,7 +561,6 @@ impl<'a> AstBuilder for ExtCtxt<'a> { id: ast::DUMMY_NODE_ID, span, attrs: ThinVec::new(), - source: ast::LocalSource::Normal, }); ast::Stmt { id: ast::DUMMY_NODE_ID, @@ -971,8 +968,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { ast::Arg { ty, pat: arg_pat, - id: ast::DUMMY_NODE_ID, - source: ast::ArgSource::Normal, + id: ast::DUMMY_NODE_ID } } diff --git a/src/libsyntax/ext/placeholders.rs b/src/libsyntax/ext/placeholders.rs index 8f24d11cfd5b0..c56c156182bd6 100644 --- a/src/libsyntax/ext/placeholders.rs +++ b/src/libsyntax/ext/placeholders.rs @@ -101,13 +101,6 @@ impl<'a, 'b> PlaceholderExpander<'a, 'b> { fn remove(&mut self, id: ast::NodeId) -> AstFragment { self.expanded_fragments.remove(&id).unwrap() } - - fn next_id(&mut self, id: &mut ast::NodeId) { - if self.monotonic { - assert_eq!(*id, ast::DUMMY_NODE_ID); - *id = self.cx.resolver.next_node_id() - } - } } impl<'a, 'b> MutVisitor for PlaceholderExpander<'a, 'b> { @@ -189,19 +182,9 @@ impl<'a, 'b> MutVisitor for PlaceholderExpander<'a, 'b> { noop_visit_block(block, self); for stmt in block.stmts.iter_mut() { - self.next_id(&mut stmt.id); - } - } - - fn visit_asyncness(&mut self, a: &mut ast::IsAsync) { - noop_visit_asyncness(a, self); - - if let ast::IsAsync::Async { ref mut arguments, .. } = a { - for argument in arguments.iter_mut() { - self.next_id(&mut argument.move_stmt.id); - if let Some(ref mut pat_stmt) = &mut argument.pat_stmt { - self.next_id(&mut pat_stmt.id); - } + if self.monotonic { + assert_eq!(stmt.id, ast::DUMMY_NODE_ID); + stmt.id = self.cx.resolver.next_node_id(); } } } diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index 0016c0d4d7e2b..757513098995b 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -207,10 +207,6 @@ pub trait MutVisitor: Sized { noop_visit_local(l, self); } - fn visit_local_source(&mut self, l: &mut LocalSource) { - noop_visit_local_source(l, self); - } - fn visit_mac(&mut self, _mac: &mut Mac) { panic!("visit_mac disabled by default"); // N.B., see note about macros above. If you really want a visitor that @@ -234,10 +230,6 @@ pub trait MutVisitor: Sized { noop_visit_arg(a, self); } - fn visit_arg_source(&mut self, a: &mut ArgSource) { - noop_visit_arg_source(a, self); - } - fn visit_generics(&mut self, generics: &mut Generics) { noop_visit_generics(generics, self); } @@ -522,17 +514,13 @@ pub fn noop_visit_parenthesized_parameter_data(args: &mut Parenth } pub fn noop_visit_local(local: &mut P, vis: &mut T) { - let Local { id, pat, ty, init, span, attrs, source } = local.deref_mut(); + let Local { id, pat, ty, init, span, attrs } = local.deref_mut(); vis.visit_id(id); vis.visit_pat(pat); visit_opt(ty, |ty| vis.visit_ty(ty)); visit_opt(init, |init| vis.visit_expr(init)); vis.visit_span(span); visit_thin_attrs(attrs, vis); - vis.visit_local_source(source); -} - -pub fn noop_visit_local_source(_local_source: &mut LocalSource, _vis: &mut T) { } pub fn noop_visit_attribute(attr: &mut Attribute, vis: &mut T) { @@ -571,18 +559,10 @@ pub fn noop_visit_meta_item(mi: &mut MetaItem, vis: &mut T) { vis.visit_span(span); } -pub fn noop_visit_arg(Arg { id, pat, ty, source }: &mut Arg, vis: &mut T) { +pub fn noop_visit_arg(Arg { id, pat, ty }: &mut Arg, vis: &mut T) { vis.visit_id(id); vis.visit_pat(pat); vis.visit_ty(ty); - vis.visit_arg_source(source); -} - -pub fn noop_visit_arg_source(source: &mut ArgSource, vis: &mut T) { - match source { - ArgSource::Normal => {}, - ArgSource::AsyncFn(pat) => vis.visit_pat(pat), - } } pub fn noop_visit_tt(tt: &mut TokenTree, vis: &mut T) { @@ -690,25 +670,9 @@ pub fn noop_visit_interpolated(nt: &mut token::Nonterminal, vis: pub fn noop_visit_asyncness(asyncness: &mut IsAsync, vis: &mut T) { match asyncness { - IsAsync::Async { closure_id, return_impl_trait_id, ref mut arguments } => { + IsAsync::Async { closure_id, return_impl_trait_id } => { vis.visit_id(closure_id); vis.visit_id(return_impl_trait_id); - for AsyncArgument { ident, arg, pat_stmt, move_stmt } in arguments.iter_mut() { - vis.visit_ident(ident); - if let Some(arg) = arg { - vis.visit_arg(arg); - } - visit_clobber(move_stmt, |stmt| { - vis.flat_map_stmt(stmt) - .expect_one("expected visitor to produce exactly one item") - }); - visit_opt(pat_stmt, |stmt| { - visit_clobber(stmt, |stmt| { - vis.flat_map_stmt(stmt) - .expect_one("expected visitor to produce exactly one item") - }) - }); - } } IsAsync::NotAsync => {} } diff --git a/src/libsyntax/parse/diagnostics.rs b/src/libsyntax/parse/diagnostics.rs index af9092dd5b05a..5df22f28797a4 100644 --- a/src/libsyntax/parse/diagnostics.rs +++ b/src/libsyntax/parse/diagnostics.rs @@ -27,7 +27,7 @@ crate fn dummy_arg(ident: Ident) -> Arg { span: ident.span, id: ast::DUMMY_NODE_ID }; - Arg { ty: P(ty), pat: pat, id: ast::DUMMY_NODE_ID, source: ast::ArgSource::Normal } + Arg { ty: P(ty), pat: pat, id: ast::DUMMY_NODE_ID } } pub enum Error { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index f200d3ec8d5c1..d8891816c9e9c 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1,9 +1,9 @@ // ignore-tidy-filelength -use crate::ast::{AngleBracketedArgs, AsyncArgument, ParenthesizedArgs, AttrStyle, BareFnTy}; +use crate::ast::{AngleBracketedArgs, ParenthesizedArgs, AttrStyle, BareFnTy}; use crate::ast::{GenericBound, TraitBoundModifier}; use crate::ast::Unsafety; -use crate::ast::{Mod, AnonConst, Arg, ArgSource, Arm, Guard, Attribute, BindingMode, TraitItemKind}; +use crate::ast::{Mod, AnonConst, Arg, Arm, Guard, Attribute, BindingMode, TraitItemKind}; use crate::ast::Block; use crate::ast::{BlockCheckMode, CaptureBy, Movability}; use crate::ast::{Constness, Crate}; @@ -16,7 +16,7 @@ use crate::ast::{GenericParam, GenericParamKind}; use crate::ast::GenericArg; use crate::ast::{Ident, ImplItem, IsAsync, IsAuto, Item, ItemKind}; use crate::ast::{Label, Lifetime}; -use crate::ast::{Local, LocalSource}; +use crate::ast::Local; use crate::ast::MacStmtStyle; use crate::ast::{Mac, Mac_, MacDelimiter}; use crate::ast::{MutTy, Mutability}; @@ -51,7 +51,7 @@ use crate::parse::diagnostics::{Error, dummy_arg}; use errors::{Applicability, DiagnosticBuilder, DiagnosticId, FatalError}; use rustc_target::spec::abi::{self, Abi}; -use syntax_pos::{Span, BytePos, DUMMY_SP, FileName, hygiene::CompilerDesugaringKind}; +use syntax_pos::{Span, BytePos, DUMMY_SP, FileName}; use log::debug; use std::borrow::Cow; @@ -1126,7 +1126,6 @@ impl<'a> Parser<'a> { IsAsync::Async { closure_id: ast::DUMMY_NODE_ID, return_impl_trait_id: ast::DUMMY_NODE_ID, - arguments: Vec::new(), } } else { IsAsync::NotAsync @@ -1185,12 +1184,12 @@ impl<'a> Parser<'a> { // trait item macro. (Ident::invalid(), ast::TraitItemKind::Macro(mac), ast::Generics::default()) } else { - let (constness, unsafety, mut asyncness, abi) = self.parse_fn_front_matter()?; + let (constness, unsafety, asyncness, abi) = self.parse_fn_front_matter()?; let ident = self.parse_ident()?; let mut generics = self.parse_generics()?; - let mut decl = self.parse_fn_decl_with_self(|p: &mut Parser<'a>| { + let decl = self.parse_fn_decl_with_self(|p: &mut Parser<'a>| { // This is somewhat dubious; We don't want to allow // argument names to be left off if there is a // definition... @@ -1199,7 +1198,6 @@ impl<'a> Parser<'a> { p.parse_arg_general(p.span.rust_2018(), true, false) })?; generics.where_clause = self.parse_where_clause()?; - self.construct_async_arguments(&mut asyncness, &mut decl); let sig = ast::MethodSig { header: FnHeader { @@ -1563,7 +1561,7 @@ impl<'a> Parser<'a> { } }; - Ok(Arg { ty, pat, id: ast::DUMMY_NODE_ID, source: ast::ArgSource::Normal }) + Ok(Arg { ty, pat, id: ast::DUMMY_NODE_ID }) } /// Parses an argument in a lambda header (e.g., `|arg, arg|`). @@ -1581,8 +1579,7 @@ impl<'a> Parser<'a> { Ok(Arg { ty: t, pat, - id: ast::DUMMY_NODE_ID, - source: ast::ArgSource::Normal, + id: ast::DUMMY_NODE_ID }) } @@ -4213,7 +4210,6 @@ impl<'a> Parser<'a> { id: ast::DUMMY_NODE_ID, span: lo.to(hi), attrs, - source: LocalSource::Normal, })) } @@ -5660,16 +5656,15 @@ impl<'a> Parser<'a> { /// Parses an item-position function declaration. fn parse_item_fn(&mut self, unsafety: Unsafety, - mut asyncness: Spanned, + asyncness: Spanned, constness: Spanned, abi: Abi) -> PResult<'a, ItemInfo> { let (ident, mut generics) = self.parse_fn_header()?; let allow_c_variadic = abi == Abi::C && unsafety == Unsafety::Unsafe; - let mut decl = self.parse_fn_decl(allow_c_variadic)?; + let decl = self.parse_fn_decl(allow_c_variadic)?; generics.where_clause = self.parse_where_clause()?; let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; - self.construct_async_arguments(&mut asyncness, &mut decl); let header = FnHeader { unsafety, asyncness, constness, abi }; Ok((ident, ItemKind::Fn(decl, header, generics, body), Some(inner_attrs))) } @@ -5849,14 +5844,13 @@ impl<'a> Parser<'a> { Ok((Ident::invalid(), vec![], ast::Generics::default(), ast::ImplItemKind::Macro(mac))) } else { - let (constness, unsafety, mut asyncness, abi) = self.parse_fn_front_matter()?; + let (constness, unsafety, asyncness, abi) = self.parse_fn_front_matter()?; let ident = self.parse_ident()?; let mut generics = self.parse_generics()?; - let mut decl = self.parse_fn_decl_with_self(|p| { + let decl = self.parse_fn_decl_with_self(|p| { p.parse_arg_general(true, true, false) })?; generics.where_clause = self.parse_where_clause()?; - self.construct_async_arguments(&mut asyncness, &mut decl); *at_end = true; let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; let header = ast::FnHeader { abi, unsafety, constness, asyncness }; @@ -7218,7 +7212,6 @@ impl<'a> Parser<'a> { respan(async_span, IsAsync::Async { closure_id: ast::DUMMY_NODE_ID, return_impl_trait_id: ast::DUMMY_NODE_ID, - arguments: Vec::new(), }), respan(fn_span, Constness::NotConst), Abi::Rust)?; @@ -7849,116 +7842,6 @@ impl<'a> Parser<'a> { Applicability::MaybeIncorrect, ).emit(); } - - /// When lowering a `async fn` to the HIR, we need to move all of the arguments of the function - /// into the generated closure so that they are dropped when the future is polled and not when - /// it is created. - /// - /// The arguments of the function are replaced in HIR lowering with the arguments created by - /// this function and the statements created here are inserted at the top of the closure body. - fn construct_async_arguments(&mut self, asyncness: &mut Spanned, decl: &mut FnDecl) { - // FIXME(davidtwco): This function should really live in the HIR lowering but because - // the types constructed here need to be used in parts of resolve so that the correct - // locals are considered upvars, it is currently easier for it to live here in the parser, - // where it can be constructed once. - if let IsAsync::Async { ref mut arguments, .. } = asyncness.node { - for (index, input) in decl.inputs.iter_mut().enumerate() { - let id = ast::DUMMY_NODE_ID; - let span = input.pat.span; - let desugared_span = self.sess.source_map() - .mark_span_with_reason(CompilerDesugaringKind::Async, span, None); - - // Construct a name for our temporary argument. - let name = format!("__arg{}", index); - let ident = Ident::from_str(&name).gensym(); - - // Check if this is a ident pattern, if so, we can optimize and avoid adding a - // `let = __argN;` statement, instead just adding a `let = ;` - // statement. - let (binding_mode, ident, is_simple_pattern) = match input.pat.node { - PatKind::Ident(binding_mode @ BindingMode::ByValue(_), ident, _) => { - // Simple patterns like this don't have a generated argument, but they are - // moved into the closure with a statement, so any `mut` bindings on the - // argument will be unused. This binding mode can't be removed, because - // this would affect the input to procedural macros, but they can have - // their span marked as being the result of a compiler desugaring so - // that they aren't linted against. - input.pat.span = desugared_span; - - (binding_mode, ident, true) - } - _ => (BindingMode::ByValue(Mutability::Mutable), ident, false), - }; - - // Construct an argument representing `__argN: ` to replace the argument of the - // async function if it isn't a simple pattern. - let arg = if is_simple_pattern { - None - } else { - Some(Arg { - ty: input.ty.clone(), - id, - pat: P(Pat { - id, - node: PatKind::Ident( - BindingMode::ByValue(Mutability::Immutable), ident, None, - ), - span: desugared_span, - }), - source: ArgSource::AsyncFn(input.pat.clone()), - }) - }; - - // Construct a `let __argN = __argN;` statement to insert at the top of the - // async closure. This makes sure that the argument is captured by the closure and - // that the drop order is correct. - let move_local = Local { - pat: P(Pat { - id, - node: PatKind::Ident(binding_mode, ident, None), - span: desugared_span, - }), - // We explicitly do not specify the type for this statement. When the user's - // argument type is `impl Trait` then this would require the - // `impl_trait_in_bindings` feature to also be present for that same type to - // be valid in this binding. At the time of writing (13 Mar 19), - // `impl_trait_in_bindings` is not stable. - ty: None, - init: Some(P(Expr { - id, - node: ExprKind::Path(None, ast::Path { - span, - segments: vec![PathSegment { ident, id, args: None }], - }), - span, - attrs: ThinVec::new(), - })), - id, - span, - attrs: ThinVec::new(), - source: LocalSource::AsyncFn, - }; - - // Construct a `let = __argN;` statement to insert at the top of the - // async closure if this isn't a simple pattern. - let pat_stmt = if is_simple_pattern { - None - } else { - Some(Stmt { - id, - node: StmtKind::Local(P(Local { - pat: input.pat.clone(), - ..move_local.clone() - })), - span, - }) - }; - - let move_stmt = Stmt { id, node: StmtKind::Local(P(move_local)), span }; - arguments.push(AsyncArgument { ident, arg, pat_stmt, move_stmt }); - } - } - } } pub fn emit_unclosed_delims(unclosed_delims: &mut Vec, handler: &errors::Handler) { diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index cf546332c2c9d..b81dc53ef6836 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -357,7 +357,7 @@ pub fn vis_to_string(v: &ast::Visibility) -> String { } pub fn fun_to_string(decl: &ast::FnDecl, - header: &ast::FnHeader, + header: ast::FnHeader, name: ast::Ident, generics: &ast::Generics) -> String { @@ -1040,7 +1040,7 @@ impl<'a> State<'a> { match item.node { ast::ForeignItemKind::Fn(ref decl, ref generics) => { self.head("")?; - self.print_fn(decl, &ast::FnHeader::default(), + self.print_fn(decl, ast::FnHeader::default(), Some(item.ident), generics, &item.vis)?; self.end()?; // end head-ibox @@ -1170,7 +1170,7 @@ impl<'a> State<'a> { self.s.word(";")?; self.end()?; // end the outer cbox } - ast::ItemKind::Fn(ref decl, ref header, ref param_names, ref body) => { + ast::ItemKind::Fn(ref decl, header, ref param_names, ref body) => { self.head("")?; self.print_fn( decl, @@ -1522,7 +1522,7 @@ impl<'a> State<'a> { vis: &ast::Visibility) -> io::Result<()> { self.print_fn(&m.decl, - &m.header, + m.header, Some(ident), &generics, vis) @@ -2113,7 +2113,7 @@ impl<'a> State<'a> { self.bclose_(expr.span, INDENT_UNIT)?; } ast::ExprKind::Closure( - capture_clause, ref asyncness, movability, ref decl, ref body, _) => { + capture_clause, asyncness, movability, ref decl, ref body, _) => { self.print_movability(movability)?; self.print_asyncness(asyncness)?; self.print_capture_clause(capture_clause)?; @@ -2710,7 +2710,7 @@ impl<'a> State<'a> { pub fn print_fn(&mut self, decl: &ast::FnDecl, - header: &ast::FnHeader, + header: ast::FnHeader, name: Option, generics: &ast::Generics, vis: &ast::Visibility) -> io::Result<()> { @@ -2765,7 +2765,8 @@ impl<'a> State<'a> { } } - pub fn print_asyncness(&mut self, asyncness: &ast::IsAsync) -> io::Result<()> { + pub fn print_asyncness(&mut self, asyncness: ast::IsAsync) + -> io::Result<()> { if asyncness.is_async() { self.word_nbsp("async")?; } @@ -3037,7 +3038,7 @@ impl<'a> State<'a> { span: syntax_pos::DUMMY_SP, }; self.print_fn(decl, - &ast::FnHeader { unsafety, abi, ..ast::FnHeader::default() }, + ast::FnHeader { unsafety, abi, ..ast::FnHeader::default() }, name, &generics, &source_map::dummy_spanned(ast::VisibilityKind::Inherited))?; @@ -3100,7 +3101,7 @@ impl<'a> State<'a> { } pub fn print_fn_header_info(&mut self, - header: &ast::FnHeader, + header: ast::FnHeader, vis: &ast::Visibility) -> io::Result<()> { self.s.word(visibility_qualified(vis, ""))?; @@ -3109,7 +3110,7 @@ impl<'a> State<'a> { ast::Constness::Const => self.word_nbsp("const")? } - self.print_asyncness(&header.asyncness.node)?; + self.print_asyncness(header.asyncness.node)?; self.print_unsafety(header.unsafety)?; if header.abi != Abi::Rust { @@ -3158,7 +3159,7 @@ mod tests { assert_eq!( fun_to_string( &decl, - &ast::FnHeader { + ast::FnHeader { unsafety: ast::Unsafety::Normal, constness: source_map::dummy_spanned(ast::Constness::NotConst), asyncness: source_map::dummy_spanned(ast::IsAsync::NotAsync), diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 4e096d68235b5..eb516b5c7c62f 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -544,9 +544,6 @@ pub fn walk_fn_ret_ty<'a, V: Visitor<'a>>(visitor: &mut V, ret_ty: &'a FunctionR pub fn walk_fn_decl<'a, V: Visitor<'a>>(visitor: &mut V, function_declaration: &'a FnDecl) { for argument in &function_declaration.inputs { visitor.visit_pat(&argument.pat); - if let ArgSource::AsyncFn(pat) = &argument.source { - visitor.visit_pat(pat); - } visitor.visit_ty(&argument.ty) } visitor.visit_fn_ret_ty(&function_declaration.output) diff --git a/src/libsyntax_ext/deriving/debug.rs b/src/libsyntax_ext/deriving/debug.rs index dec4c2dfc3b5e..44ddbb98809b4 100644 --- a/src/libsyntax_ext/deriving/debug.rs +++ b/src/libsyntax_ext/deriving/debug.rs @@ -129,7 +129,6 @@ fn stmt_let_undescore(cx: &mut ExtCtxt<'_>, sp: Span, expr: P) -> ast id: ast::DUMMY_NODE_ID, span: sp, attrs: ThinVec::new(), - source: ast::LocalSource::Normal, }); ast::Stmt { id: ast::DUMMY_NODE_ID, From 32771071e8d6731e2ff747de04aabe9a4d499b24 Mon Sep 17 00:00:00 2001 From: David Wood Date: Fri, 31 May 2019 15:50:06 +0100 Subject: [PATCH 19/30] syntax/rustc: move `mark_span_with_reason` back. --- src/librustc/hir/lowering.rs | 51 +++++++++++++++++++++++++----------- src/libsyntax/source_map.rs | 21 --------------- 2 files changed, 35 insertions(+), 37 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index a61bdeb829915..df0a23c1b8671 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -50,6 +50,7 @@ use errors::Applicability; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::thin_vec::ThinVec; +use rustc_data_structures::sync::Lrc; use std::collections::{BTreeSet, BTreeMap}; use std::mem; @@ -58,17 +59,17 @@ use syntax::attr; use syntax::ast; use syntax::ast::*; use syntax::errors; -use syntax::ext::hygiene::Mark; +use syntax::ext::hygiene::{Mark, SyntaxContext}; use syntax::print::pprust; use syntax::ptr::P; -use syntax::source_map::{respan, CompilerDesugaringKind, Spanned}; +use syntax::source_map::{self, respan, CompilerDesugaringKind, Spanned}; use syntax::source_map::CompilerDesugaringKind::IfTemporary; use syntax::std_inject; use syntax::symbol::{kw, sym, Symbol}; use syntax::tokenstream::{TokenStream, TokenTree}; use syntax::parse::token::Token; use syntax::visit::{self, Visitor}; -use syntax_pos::Span; +use syntax_pos::{edition, Span}; const HIR_ID_COUNTER_LOCKED: u32 = 0xFFFFFFFF; @@ -829,6 +830,27 @@ impl<'a> LoweringContext<'a> { self.sess.diagnostic() } + /// Reuses the span but adds information like the kind of the desugaring and features that are + /// allowed inside this span. + fn mark_span_with_reason( + &self, + reason: CompilerDesugaringKind, + span: Span, + allow_internal_unstable: Option>, + ) -> Span { + let mark = Mark::fresh(Mark::root()); + mark.set_expn_info(source_map::ExpnInfo { + call_site: span, + def_site: Some(span), + format: source_map::CompilerDesugaring(reason), + allow_internal_unstable, + allow_internal_unsafe: false, + local_inner_macros: false, + edition: edition::Edition::from_session(), + }); + span.with_ctxt(SyntaxContext::empty().apply_mark(mark)) + } + fn with_anonymous_lifetime_mode( &mut self, anonymous_lifetime_mode: AnonymousLifetimeMode, @@ -1128,7 +1150,7 @@ impl<'a> LoweringContext<'a> { attrs: ThinVec::new(), }; - let unstable_span = self.sess.source_map().mark_span_with_reason( + let unstable_span = self.mark_span_with_reason( CompilerDesugaringKind::Async, span, Some(vec![sym::gen_future].into()), @@ -1535,7 +1557,7 @@ impl<'a> LoweringContext<'a> { // desugaring that explicitly states that we don't want to track that. // Not tracking it makes lints in rustc and clippy very fragile as // frequently opened issues show. - let exist_ty_span = self.sess.source_map().mark_span_with_reason( + let exist_ty_span = self.mark_span_with_reason( CompilerDesugaringKind::ExistentialReturnType, span, None, @@ -2395,7 +2417,7 @@ impl<'a> LoweringContext<'a> { ) -> hir::FunctionRetTy { let span = output.span(); - let exist_ty_span = self.sess.source_map().mark_span_with_reason( + let exist_ty_span = self.mark_span_with_reason( CompilerDesugaringKind::Async, span, None, @@ -4038,10 +4060,7 @@ impl<'a> LoweringContext<'a> { let else_arm = self.arm(hir_vec![else_pat], P(else_expr)); // Lower condition: - let span_block = self - .sess - .source_map() - .mark_span_with_reason(IfTemporary, cond.span, None); + let span_block = self.mark_span_with_reason(IfTemporary, cond.span, None); let cond = self.lower_expr(cond); // Wrap in a construct equivalent to `{ let _t = $cond; _t }` to preserve drop // semantics since `if cond { ... }` don't let temporaries live outside of `cond`. @@ -4071,7 +4090,7 @@ impl<'a> LoweringContext<'a> { }), ExprKind::TryBlock(ref body) => { self.with_catch_scope(body.id, |this| { - let unstable_span = this.sess.source_map().mark_span_with_reason( + let unstable_span = this.mark_span_with_reason( CompilerDesugaringKind::TryBlock, body.span, Some(vec![sym::try_trait].into()), @@ -4503,7 +4522,7 @@ impl<'a> LoweringContext<'a> { // expand let mut head = self.lower_expr(head); let head_sp = head.span; - let desugared_span = self.sess.source_map().mark_span_with_reason( + let desugared_span = self.mark_span_with_reason( CompilerDesugaringKind::ForLoop, head_sp, None, @@ -4657,13 +4676,13 @@ impl<'a> LoweringContext<'a> { // return Try::from_error(From::from(err)), // } - let unstable_span = self.sess.source_map().mark_span_with_reason( + let unstable_span = self.mark_span_with_reason( CompilerDesugaringKind::QuestionMark, e.span, Some(vec![sym::try_trait].into()), ); let try_span = self.sess.source_map().end_point(e.span); - let try_span = self.sess.source_map().mark_span_with_reason( + let try_span = self.mark_span_with_reason( CompilerDesugaringKind::QuestionMark, try_span, Some(vec![sym::try_trait].into()), @@ -5460,12 +5479,12 @@ impl<'a> LoweringContext<'a> { err.emit(); return hir::ExprKind::Err; } - let span = self.sess.source_map().mark_span_with_reason( + let span = self.mark_span_with_reason( CompilerDesugaringKind::Await, await_span, None, ); - let gen_future_span = self.sess.source_map().mark_span_with_reason( + let gen_future_span = self.mark_span_with_reason( CompilerDesugaringKind::Await, await_span, Some(vec![sym::gen_future].into()), diff --git a/src/libsyntax/source_map.rs b/src/libsyntax/source_map.rs index 4b6893b242337..a21d2df416206 100644 --- a/src/libsyntax/source_map.rs +++ b/src/libsyntax/source_map.rs @@ -935,27 +935,6 @@ impl SourceMap { None } - - /// Reuses the span but adds information like the kind of the desugaring and features that are - /// allowed inside this span. - pub fn mark_span_with_reason( - &self, - reason: hygiene::CompilerDesugaringKind, - span: Span, - allow_internal_unstable: Option>, - ) -> Span { - let mark = Mark::fresh(Mark::root()); - mark.set_expn_info(ExpnInfo { - call_site: span, - def_site: Some(span), - format: CompilerDesugaring(reason), - allow_internal_unstable, - allow_internal_unsafe: false, - local_inner_macros: false, - edition: edition::Edition::from_session(), - }); - span.with_ctxt(SyntaxContext::empty().apply_mark(mark)) - } } impl SourceMapper for SourceMap { From 1e5f496143aabf1d4d158d99b73afee7b00f0650 Mon Sep 17 00:00:00 2001 From: David Wood Date: Wed, 29 May 2019 19:28:51 +0300 Subject: [PATCH 20/30] rustc: async fn drop order lowering in HIR This commit re-implements the async fn drop order lowering changes so that it all takes place in HIR lowering, building atop the work done by `@eddyb` to refactor `Res::Upvar`. Previously, this types involved in the lowering were constructed in libsyntax as they had to be used during name resolution and HIR lowering. This was awful because none of that logic should have existed in libsyntax. This commit also changes `ArgSource` to keep a `HirId` to the original argument pattern rather than a cloned copy of the pattern. --- src/librustc/hir/intravisit.rs | 10 - src/librustc/hir/lowering.rs | 294 ++++++++++++++---- src/librustc/hir/map/mod.rs | 13 + src/librustc/hir/mod.rs | 14 +- .../nice_region_error/different_lifetimes.rs | 6 +- .../nice_region_error/named_anon_conflict.rs | 3 +- src/librustc/middle/resolve_lifetime.rs | 3 +- src/librustc_mir/build/mod.rs | 66 ++-- src/librustc_privacy/lib.rs | 20 -- src/librustc_typeck/check/mod.rs | 10 - src/librustc_typeck/check/writeback.rs | 10 - src/librustdoc/clean/mod.rs | 3 +- src/test/ui/async-await/issues/issue-61187.rs | 9 + .../ui/async-await/issues/issue-61187.stderr | 11 + 14 files changed, 317 insertions(+), 155 deletions(-) create mode 100644 src/test/ui/async-await/issues/issue-61187.rs create mode 100644 src/test/ui/async-await/issues/issue-61187.stderr diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 8000666044a1a..9cf365addca9b 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -262,9 +262,6 @@ pub trait Visitor<'v> : Sized { fn visit_pat(&mut self, p: &'v Pat) { walk_pat(self, p) } - fn visit_argument_source(&mut self, s: &'v ArgSource) { - walk_argument_source(self, s) - } fn visit_anon_const(&mut self, c: &'v AnonConst) { walk_anon_const(self, c) } @@ -402,17 +399,10 @@ pub fn walk_body<'v, V: Visitor<'v>>(visitor: &mut V, body: &'v Body) { for argument in &body.arguments { visitor.visit_id(argument.hir_id); visitor.visit_pat(&argument.pat); - visitor.visit_argument_source(&argument.source); } visitor.visit_expr(&body.value); } -pub fn walk_argument_source<'v, V: Visitor<'v>>(visitor: &mut V, source: &'v ArgSource) { - if let ArgSource::AsyncFn(pat) = source { - visitor.visit_pat(pat); - } -} - pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local) { // Intentionally visiting the expr first - the initialization expr // dominates the local's definition. diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index df0a23c1b8671..e82b3df855035 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -781,7 +781,7 @@ impl<'a> LoweringContext<'a> { }) } - fn record_body(&mut self, value: hir::Expr, arguments: HirVec) -> hir::BodyId { + fn record_body(&mut self, arguments: HirVec, value: hir::Expr) -> hir::BodyId { if self.is_generator && self.is_async_body { span_err!( self.sess, @@ -1121,27 +1121,21 @@ impl<'a> LoweringContext<'a> { span: Span, body: impl FnOnce(&mut LoweringContext<'_>) -> hir::Expr, ) -> hir::ExprKind { - let prev_is_generator = mem::replace(&mut self.is_generator, false); - let prev_is_async_body = mem::replace(&mut self.is_async_body, true); + let capture_clause = self.lower_capture_clause(capture_clause); let output = match ret_ty { Some(ty) => FunctionRetTy::Ty(P(ty.clone())), None => FunctionRetTy::Default(span), }; - let decl = FnDecl { + let ast_decl = FnDecl { inputs: vec![], output, c_variadic: false }; - // Lower the arguments before the body otherwise the body will call `lower_res` expecting - // the argument to have been assigned an id already. - let arguments = self.lower_args(Some(&decl)); - let body_expr = body(self); - let body_id = self.record_body(body_expr, arguments); - self.is_generator = prev_is_generator; - self.is_async_body = prev_is_async_body; - - let capture_clause = self.lower_capture_clause(capture_clause); - let decl = self.lower_fn_decl(&decl, None, /* impl trait allowed */ false, None); + let decl = self.lower_fn_decl(&ast_decl, None, /* impl trait allowed */ false, None); + let body_id = self.lower_fn_body(&ast_decl, |this| { + this.is_async_body = true; + body(this) + }); let generator = hir::Expr { hir_id: self.lower_node_id(closure_node_id), node: hir::ExprKind::Closure(capture_clause, decl, body_id, span, @@ -1160,18 +1154,32 @@ impl<'a> LoweringContext<'a> { hir::ExprKind::Call(P(gen_future), hir_vec![generator]) } - fn lower_body(&mut self, decl: Option<&FnDecl>, f: F) -> hir::BodyId - where - F: FnOnce(&mut LoweringContext<'_>) -> hir::Expr, - { - let prev_generator = mem::replace(&mut self.is_generator, false); - let prev_async = mem::replace(&mut self.is_async_body, false); - let arguments = self.lower_args(decl); - let result = f(self); - let r = self.record_body(result, arguments); - self.is_generator = prev_generator; - self.is_async_body = prev_async; - return r; + fn lower_body( + &mut self, + f: impl FnOnce(&mut LoweringContext<'_>) -> (HirVec, hir::Expr), + ) -> hir::BodyId { + let prev_is_generator = mem::replace(&mut self.is_generator, false); + let prev_is_async_body = mem::replace(&mut self.is_async_body, false); + let (arguments, result) = f(self); + let body_id = self.record_body(arguments, result); + self.is_generator = prev_is_generator; + self.is_async_body = prev_is_async_body; + body_id + } + + fn lower_fn_body( + &mut self, + decl: &FnDecl, + body: impl FnOnce(&mut LoweringContext<'_>) -> hir::Expr, + ) -> hir::BodyId { + self.lower_body(|this| ( + decl.inputs.iter().map(|x| this.lower_arg(x)).collect(), + body(this), + )) + } + + fn lower_const_body(&mut self, expr: &Expr) -> hir::BodyId { + self.lower_body(|this| (hir_vec![], this.lower_expr(expr))) } fn with_loop_scope(&mut self, loop_id: NodeId, f: F) -> T @@ -2273,10 +2281,6 @@ impl<'a> LoweringContext<'a> { } } - fn lower_args(&mut self, decl: Option<&FnDecl>) -> HirVec { - decl.map_or(hir_vec![], |decl| decl.inputs.iter().map(|x| self.lower_arg(x)).collect()) - } - fn lower_arg(&mut self, arg: &Arg) -> hir::Arg { hir::Arg { hir_id: self.lower_node_id(arg.id), @@ -2980,11 +2984,14 @@ impl<'a> LoweringContext<'a> { bounds.iter().map(|bound| self.lower_param_bound(bound, itctx.reborrow())).collect() } - fn lower_block(&mut self, b: &Block, targeted_by_break: bool) -> P { + fn lower_block_with_stmts( + &mut self, + b: &Block, + targeted_by_break: bool, + mut stmts: Vec, + ) -> P { let mut expr = None; - let mut stmts = vec![]; - for (index, stmt) in b.stmts.iter().enumerate() { if index == b.stmts.len() - 1 { if let StmtKind::Expr(ref e) = stmt.node { @@ -3007,25 +3014,177 @@ impl<'a> LoweringContext<'a> { }) } - fn lower_async_body( + fn lower_block(&mut self, b: &Block, targeted_by_break: bool) -> P { + self.lower_block_with_stmts(b, targeted_by_break, vec![]) + } + + fn lower_maybe_async_body( &mut self, decl: &FnDecl, asyncness: IsAsync, body: &Block, ) -> hir::BodyId { - self.lower_body(Some(&decl), |this| { - if let IsAsync::Async { closure_id, .. } = asyncness { - let async_expr = this.make_async_expr( - CaptureBy::Value, closure_id, None, body.span, - |this| { - let body = this.lower_block(&body, false); - this.expr_block(body, ThinVec::new()) - }); - this.expr(body.span, async_expr, ThinVec::new()) - } else { + let closure_id = match asyncness { + IsAsync::Async { closure_id, .. } => closure_id, + IsAsync::NotAsync => return self.lower_fn_body(&decl, |this| { let body = this.lower_block(body, false); this.expr_block(body, ThinVec::new()) + }), + }; + + self.lower_body(|this| { + let mut arguments: Vec = Vec::new(); + let mut statements: Vec<(hir::Stmt, Option)> = Vec::new(); + + // Async function arguments are lowered into the closure body so that they are + // captured and so that the drop order matches the equivalent non-async functions. + // + // async fn foo(: , : , : ) { + // async move { + // } + // } + // + // // ...becomes... + // fn foo(__arg0: , __arg1: , __arg2: ) { + // async move { + // let __arg2 = __arg2; + // let = __arg2; + // let __arg1 = __arg1; + // let = __arg1; + // let __arg0 = __arg0; + // let = __arg0; + // } + // } + // + // If `` is a simple ident, then it is lowered to a single + // `let = ;` statement as an optimization. + for (index, argument) in decl.inputs.iter().enumerate() { + let argument = this.lower_arg(argument); + let span = argument.pat.span; + + // Check if this is a binding pattern, if so, we can optimize and avoid adding a + // `let = __argN;` statement. In this case, we do not rename the argument. + let (ident, is_simple_argument) = match argument.pat.node { + hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, ident, _) => + (ident, true), + _ => { + // Replace the ident for bindings that aren't simple. + let name = format!("__arg{}", index); + let ident = Ident::from_str(&name); + + (ident, false) + }, + }; + + // Construct an argument representing `__argN: ` to replace the argument of the + // async function. + // + // If this is the simple case, this argument will end up being the same as the + // original argument, but with a different pattern id. + let new_argument_id = this.next_id(); + let desugared_span = + this.mark_span_with_reason(CompilerDesugaringKind::Async, span, None); + let new_argument = hir::Arg { + hir_id: argument.hir_id, + pat: P(hir::Pat { + hir_id: new_argument_id, + node: hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, + new_argument_id, ident, None), + span: desugared_span, + }), + source: hir::ArgSource::AsyncFn(argument.pat.hir_id), + }; + + let construct_stmt = |this: &mut LoweringContext<'_>, pat: P, + init_pat_id: hir::HirId| { + hir::Stmt { + hir_id: this.next_id(), + node: hir::StmtKind::Local(P(hir::Local { + pat, + // We explicitly do not specify the type for any statements. When the + // user's argument type is `impl Trait` then this would require the + // `impl_trait_in_bindings` feature to also be present for that same + // type to be valid in this binding. At the time of writing (13 Mar 19), + // `impl_trait_in_bindings` is not stable. + ty: None, + init: Some(P(hir::Expr { + span, + node: hir::ExprKind::Path(hir::QPath::Resolved(None, P(hir::Path { + span, + res: Res::Local(init_pat_id), + segments: hir_vec![ hir::PathSegment::from_ident(ident) ], + }))), + attrs: ThinVec::new(), + hir_id: this.next_id(), + })), + hir_id: this.next_id(), + span: desugared_span, + attrs: ThinVec::new(), + source: hir::LocalSource::AsyncFn, + })), + span: desugared_span, + } + }; + + let new_statements = if is_simple_argument { + // If this is the simple case, then we only insert one statement that is + // `let = ;`. We re-use the original argument's pattern so that + // `HirId`s are densely assigned. + (construct_stmt(this, argument.pat, new_argument_id), None) + } else { + // If this is not the simple case, then we construct two statements: + // + // ``` + // let __argN = __argN; + // let = __argN; + // ``` + // + // The first statement moves the argument into the closure and thus ensures + // that the drop order is correct. + // + // The second statement creates the bindings that the user wrote. + + // Construct the `let mut __argN = __argN;` statement. It must be a mut binding + // because the user may have specified a `ref mut` binding in the next + // statement. + let hir_id = this.next_id(); + let move_stmt = construct_stmt( + this, + P(hir::Pat { + hir_id, + node: hir::PatKind::Binding(hir::BindingAnnotation::Mutable, + hir_id, ident, None), + span: desugared_span, + }), + new_argument_id, + ); + + // Construct the `let = __argN;` statement. We re-use the original + // argument's pattern so that `HirId`s are densely assigned. + let pattern_stmt = construct_stmt(this, argument.pat, hir_id); + (move_stmt, Some(pattern_stmt)) + }; + + arguments.push(new_argument); + statements.push(new_statements); } + + let async_expr = this.make_async_expr( + CaptureBy::Value, closure_id, None, body.span, + |this| { + let mut stmts = vec![]; + for (move_stmt, pattern_stmt) in statements.drain(..) { + // Insert the `let __argN = __argN` statement first. + stmts.push(move_stmt); + // Then insert the `let = __argN` statement, if there is one. + if let Some(pattern_stmt) = pattern_stmt { + stmts.push(pattern_stmt); + } + } + let body = this.lower_block_with_stmts(body, false, stmts); + this.expr_block(body, ThinVec::new()) + }); + (HirVec::from(arguments), this.expr(body.span, async_expr, ThinVec::new())) }) } @@ -3049,7 +3208,6 @@ impl<'a> LoweringContext<'a> { self.lower_use_tree(use_tree, &prefix, id, vis, ident, attrs) } ItemKind::Static(ref t, m, ref e) => { - let value = self.lower_body(None, |this| this.lower_expr(e)); hir::ItemKind::Static( self.lower_ty( t, @@ -3060,11 +3218,10 @@ impl<'a> LoweringContext<'a> { } ), self.lower_mutability(m), - value, + self.lower_const_body(e), ) } ItemKind::Const(ref t, ref e) => { - let value = self.lower_body(None, |this| this.lower_expr(e)); hir::ItemKind::Const( self.lower_ty( t, @@ -3074,29 +3231,31 @@ impl<'a> LoweringContext<'a> { ImplTraitContext::Disallowed(ImplTraitPosition::Binding) } ), - value + self.lower_const_body(e) ) } ItemKind::Fn(ref decl, header, ref generics, ref body) => { let fn_def_id = self.resolver.definitions().local_def_id(id); self.with_new_scopes(|this| { + this.current_item = Some(ident.span); + // Note: we don't need to change the return type from `T` to // `impl Future` here because lower_body // only cares about the input argument patterns in the function // declaration (decl), not the return types. - let body_id = this.lower_async_body(decl, header.asyncness.node, body); + let body_id = this.lower_maybe_async_body(&decl, header.asyncness.node, body); + let (generics, fn_decl) = this.add_in_band_defs( generics, fn_def_id, AnonymousLifetimeMode::PassThrough, |this, idty| this.lower_fn_decl( - decl, + &decl, Some((fn_def_id, idty)), true, header.asyncness.node.opt_return_id() ), ); - this.current_item = Some(ident.span); hir::ItemKind::Fn( fn_decl, @@ -3478,7 +3637,7 @@ impl<'a> LoweringContext<'a> { self.lower_ty(ty, ImplTraitContext::disallowed()), default .as_ref() - .map(|x| self.lower_body(None, |this| this.lower_expr(x))), + .map(|x| self.lower_const_body(x)), ), ), TraitItemKind::Method(ref sig, None) => { @@ -3493,7 +3652,7 @@ impl<'a> LoweringContext<'a> { (generics, hir::TraitItemKind::Method(sig, hir::TraitMethod::Required(names))) } TraitItemKind::Method(ref sig, Some(ref body)) => { - let body_id = self.lower_body(Some(&sig.decl), |this| { + let body_id = self.lower_fn_body(&sig.decl, |this| { let body = this.lower_block(body, false); this.expr_block(body, ThinVec::new()) }); @@ -3557,18 +3716,18 @@ impl<'a> LoweringContext<'a> { let impl_item_def_id = self.resolver.definitions().local_def_id(i.id); let (generics, node) = match i.node { - ImplItemKind::Const(ref ty, ref expr) => { - let body_id = self.lower_body(None, |this| this.lower_expr(expr)); - ( - self.lower_generics(&i.generics, ImplTraitContext::disallowed()), - hir::ImplItemKind::Const( - self.lower_ty(ty, ImplTraitContext::disallowed()), - body_id, - ), - ) - } + ImplItemKind::Const(ref ty, ref expr) => ( + self.lower_generics(&i.generics, ImplTraitContext::disallowed()), + hir::ImplItemKind::Const( + self.lower_ty(ty, ImplTraitContext::disallowed()), + self.lower_const_body(expr), + ), + ), ImplItemKind::Method(ref sig, ref body) => { - let body_id = self.lower_async_body(&sig.decl, sig.header.asyncness.node, body); + self.current_item = Some(i.span); + let body_id = self.lower_maybe_async_body( + &sig.decl, sig.header.asyncness.node, body + ); let impl_trait_return_allow = !self.is_in_trait_impl; let (generics, sig) = self.lower_method_sig( &i.generics, @@ -3577,7 +3736,6 @@ impl<'a> LoweringContext<'a> { impl_trait_return_allow, sig.header.asyncness.node.opt_return_id(), ); - self.current_item = Some(i.span); (generics, hir::ImplItemKind::Method(sig, body_id)) } @@ -3973,7 +4131,7 @@ impl<'a> LoweringContext<'a> { self.with_new_scopes(|this| { hir::AnonConst { hir_id: this.lower_node_id(c.id), - body: this.lower_body(None, |this| this.lower_expr(&c.value)), + body: this.lower_const_body(&c.value), } }) } @@ -4161,7 +4319,7 @@ impl<'a> LoweringContext<'a> { // Transform `async |x: u8| -> X { ... }` into // `|x: u8| future_from_generator(|| -> X { ... })`. - let body_id = this.lower_body(Some(&outer_decl), |this| { + let body_id = this.lower_fn_body(&outer_decl, |this| { let async_ret_ty = if let FunctionRetTy::Ty(ty) = &decl.output { Some(&**ty) } else { None }; @@ -4187,7 +4345,7 @@ impl<'a> LoweringContext<'a> { self.with_new_scopes(|this| { this.current_item = Some(fn_decl_span); let mut is_generator = false; - let body_id = this.lower_body(Some(decl), |this| { + let body_id = this.lower_fn_body(decl, |this| { let e = this.lower_expr(body); is_generator = this.is_generator; e diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 75799a1903174..2d3de5af9927f 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -699,6 +699,19 @@ impl<'hir> Map<'hir> { } } + /// Returns the `HirId` of this pattern, or, if this is an `async fn` desugaring, the `HirId` + /// of the original pattern that the user wrote. + pub fn original_pat_of_argument(&self, arg: &'hir Arg) -> &'hir Pat { + match &arg.source { + ArgSource::Normal => &*arg.pat, + ArgSource::AsyncFn(hir_id) => match self.find_by_hir_id(*hir_id) { + Some(Node::Pat(pat)) | Some(Node::Binding(pat)) => &pat, + Some(Node::Local(local)) => &*local.pat, + x => bug!("ArgSource::AsyncFn HirId not a pattern/binding/local: {:?}", x), + }, + } + } + pub fn is_const_scope(&self, hir_id: HirId) -> bool { self.walk_parent_nodes(hir_id, |node| match *node { Node::Item(Item { node: ItemKind::Const(_, _), .. }) => true, diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 210c0c9225a3d..817c4cb540f67 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -1932,23 +1932,13 @@ pub struct Arg { pub source: ArgSource, } -impl Arg { - /// Returns the pattern representing the original binding for this argument. - pub fn original_pat(&self) -> &P { - match &self.source { - ArgSource::Normal => &self.pat, - ArgSource::AsyncFn(pat) => &pat, - } - } -} - /// Represents the source of an argument in a function header. #[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] pub enum ArgSource { /// Argument as specified by the user. Normal, - /// Generated argument from `async fn` lowering, contains the original binding pattern. - AsyncFn(P), + /// Generated argument from `async fn` lowering, `HirId` is the original pattern. + AsyncFn(HirId), } /// Represents the header (not the body) of a function declaration. diff --git a/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs b/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs index 944cc8a8b1999..46785f7ada1fe 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs @@ -86,12 +86,14 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { let sub_is_ret_type = self.is_return_type_anon(scope_def_id_sub, bregion_sub, ty_fndecl_sub); - let span_label_var1 = match anon_arg_sup.original_pat().simple_ident() { + let arg_sup_pat = self.tcx().hir().original_pat_of_argument(anon_arg_sup); + let span_label_var1 = match arg_sup_pat.simple_ident() { Some(simple_ident) => format!(" from `{}`", simple_ident), None => String::new(), }; - let span_label_var2 = match anon_arg_sub.original_pat().simple_ident() { + let arg_sub_pat = self.tcx().hir().original_pat_of_argument(anon_arg_sub); + let span_label_var2 = match arg_sub_pat.simple_ident() { Some(simple_ident) => format!(" into `{}`", simple_ident), None => String::new(), }; diff --git a/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs b/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs index 2d7587b11b6f8..1eb2af2bd5818 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs @@ -95,7 +95,8 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { } } - let (error_var, span_label_var) = match arg.original_pat().simple_ident() { + let arg_pat = self.tcx().hir().original_pat_of_argument(arg); + let (error_var, span_label_var) = match arg_pat.simple_ident() { Some(simple_ident) => ( format!("the type of `{}`", simple_ident), format!("the type of `{}`", simple_ident), diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 593a09b6866db..f48da4762b768 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -2416,7 +2416,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { let help_name = if let Some(body) = parent { let arg = &self.tcx.hir().body(body).arguments[index]; - format!("`{}`", self.tcx.hir().hir_to_pretty_string(arg.original_pat().hir_id)) + let original_pat = self.tcx.hir().original_pat_of_argument(arg); + format!("`{}`", self.tcx.hir().hir_to_pretty_string(original_pat.hir_id)) } else { format!("argument {}", index + 1) }; diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 123b46cb04820..a5d92d6c88f99 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -84,11 +84,23 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Body<' // HACK(eddyb) Avoid having RustCall on closures, // as it adds unnecessary (and wrong) auto-tupling. abi = Abi::Rust; - Some(ArgInfo(liberated_closure_env_ty(tcx, id, body_id), None, None, None)) + Some(ArgInfo { + ty: liberated_closure_env_ty(tcx, id, body_id), + span: None, + pattern: None, + user_pattern: None, + self_kind: None, + }) } ty::Generator(..) => { let gen_ty = tcx.body_tables(body_id).node_type(id); - Some(ArgInfo(gen_ty, None, None, None)) + Some(ArgInfo { + ty: gen_ty, + span: None, + pattern: None, + user_pattern: None, + self_kind: None, + }) } _ => None, }; @@ -126,7 +138,15 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Body<' opt_ty_info = None; self_arg = None; } - ArgInfo(fn_sig.inputs()[index], opt_ty_info, Some(&*arg.pat), self_arg) + + let original_pat = tcx.hir().original_pat_of_argument(arg); + ArgInfo { + ty: fn_sig.inputs()[index], + span: opt_ty_info, + pattern: Some(&*arg.pat), + user_pattern: Some(&original_pat), + self_kind: self_arg, + } }); let arguments = implicit_argument.into_iter().chain(explicit_arguments); @@ -614,10 +634,13 @@ fn should_abort_on_panic<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, /////////////////////////////////////////////////////////////////////////// /// the main entry point for building MIR for a function -struct ArgInfo<'gcx>(Ty<'gcx>, - Option, - Option<&'gcx hir::Pat>, - Option); +struct ArgInfo<'gcx> { + ty: Ty<'gcx>, + span: Option, + pattern: Option<&'gcx hir::Pat>, + user_pattern: Option<&'gcx hir::Pat>, + self_kind: Option, +} fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, fn_id: hir::HirId, @@ -878,26 +901,23 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { -> BlockAnd<()> { // Allocate locals for the function arguments - for &ArgInfo(ty, _, pattern, _) in arguments.iter() { + for &ArgInfo { ty, span: _, pattern, user_pattern, self_kind: _ } in arguments.iter() { // If this is a simple binding pattern, give the local a name for // debuginfo and so that error reporting knows that this is a user // variable. For any other pattern the pattern introduces new // variables which will be named instead. - let mut name = None; - if let Some(pat) = pattern { + let (name, span) = if let Some(pat) = user_pattern { match pat.node { hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, ident, _) - | hir::PatKind::Binding(hir::BindingAnnotation::Mutable, _, ident, _) => { - name = Some(ident.name); - } - _ => (), + | hir::PatKind::Binding(hir::BindingAnnotation::Mutable, _, ident, _) => + (Some(ident.name), pat.span), + _ => (None, pattern.map_or(self.fn_span, |pat| pat.span)) } - } - - let source_info = SourceInfo { - scope: OUTERMOST_SOURCE_SCOPE, - span: pattern.map_or(self.fn_span, |pat| pat.span) + } else { + (None, self.fn_span) }; + + let source_info = SourceInfo { scope: OUTERMOST_SOURCE_SCOPE, span, }; self.local_decls.push(LocalDecl { mutability: Mutability::Mut, ty, @@ -917,7 +937,13 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // Function arguments always get the first Local indices after the return place let local = Local::new(index + 1); let place = Place::Base(PlaceBase::Local(local)); - let &ArgInfo(ty, opt_ty_info, pattern, ref self_binding) = arg_info; + let &ArgInfo { + ty, + span: opt_ty_info, + pattern, + user_pattern: _, + self_kind: ref self_binding + } = arg_info; // Make sure we drop (parts of) the argument even when not matched on. self.schedule_drop( diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 20e18d60f076b..f084d3b9f28c3 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -948,16 +948,6 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> { intravisit::walk_pat(self, pat); } - - fn visit_argument_source(&mut self, s: &'tcx hir::ArgSource) { - match s { - // Don't visit the pattern in `ArgSource::AsyncFn`, it contains a pattern which has - // a `NodeId` w/out a type, as it is only used for getting the name of the original - // pattern for diagnostics where only an `hir::Arg` is present. - hir::ArgSource::AsyncFn(..) => {}, - _ => intravisit::walk_argument_source(self, s), - } - } } //////////////////////////////////////////////////////////////////////////////////////////// @@ -1147,16 +1137,6 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { intravisit::walk_pat(self, pattern); } - fn visit_argument_source(&mut self, s: &'tcx hir::ArgSource) { - match s { - // Don't visit the pattern in `ArgSource::AsyncFn`, it contains a pattern which has - // a `NodeId` w/out a type, as it is only used for getting the name of the original - // pattern for diagnostics where only an `hir::Arg` is present. - hir::ArgSource::AsyncFn(..) => {}, - _ => intravisit::walk_argument_source(self, s), - } - } - fn visit_local(&mut self, local: &'tcx hir::Local) { if let Some(ref init) = local.init { if self.check_expr_pat_type(init.hir_id, init.span) { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 82d198f0b78f7..3ada80b3e8b70 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1009,16 +1009,6 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for GatherLocalsVisitor<'a, 'gcx, 'tcx> { // Don't descend into the bodies of nested closures fn visit_fn(&mut self, _: intravisit::FnKind<'gcx>, _: &'gcx hir::FnDecl, _: hir::BodyId, _: Span, _: hir::HirId) { } - - fn visit_argument_source(&mut self, s: &'gcx hir::ArgSource) { - match s { - // Don't visit the pattern in `ArgSource::AsyncFn`, it contains a pattern which has - // a `NodeId` w/out a type, as it is only used for getting the name of the original - // pattern for diagnostics where only an `hir::Arg` is present. - hir::ArgSource::AsyncFn(..) => {}, - _ => intravisit::walk_argument_source(self, s), - } - } } /// When `check_fn` is invoked on a generator (i.e., a body that diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index a535f776dfe60..6f8682e64671c 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -311,16 +311,6 @@ impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> { let ty = self.resolve(&ty, &hir_ty.span); self.write_ty_to_tables(hir_ty.hir_id, ty); } - - fn visit_argument_source(&mut self, s: &'gcx hir::ArgSource) { - match s { - // Don't visit the pattern in `ArgSource::AsyncFn`, it contains a pattern which has - // a `NodeId` w/out a type, as it is only used for getting the name of the original - // pattern for diagnostics where only an `hir::Arg` is present. - hir::ArgSource::AsyncFn(..) => {}, - _ => intravisit::walk_argument_source(self, s), - } - } } impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index e68ad6a7c3b4b..319adea6b8682 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2018,8 +2018,9 @@ impl<'a> Clean for (&'a [hir::Ty], hir::BodyId) { Arguments { values: self.0.iter().enumerate().map(|(i, ty)| { + let original_pat = cx.tcx.hir().original_pat_of_argument(&body.arguments[i]); Argument { - name: name_from_pat(&body.arguments[i].original_pat()), + name: name_from_pat(original_pat), type_: ty.clean(cx), } }).collect() diff --git a/src/test/ui/async-await/issues/issue-61187.rs b/src/test/ui/async-await/issues/issue-61187.rs new file mode 100644 index 0000000000000..8b939b43b8bd4 --- /dev/null +++ b/src/test/ui/async-await/issues/issue-61187.rs @@ -0,0 +1,9 @@ +// edition:2018 +#![feature(async_await)] + +fn main() { +} + +async fn response(data: Vec) { + data.reverse(); //~ ERROR E0596 +} diff --git a/src/test/ui/async-await/issues/issue-61187.stderr b/src/test/ui/async-await/issues/issue-61187.stderr new file mode 100644 index 0000000000000..a03142263202e --- /dev/null +++ b/src/test/ui/async-await/issues/issue-61187.stderr @@ -0,0 +1,11 @@ +error[E0596]: cannot borrow `data` as mutable, as it is not declared as mutable + --> $DIR/issue-61187.rs:8:5 + | +LL | async fn response(data: Vec) { + | ---- help: consider changing this to be mutable: `mut data` +LL | data.reverse(); + | ^^^^ cannot borrow as mutable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. From 80df64b7d4a7718d4c5ece9c627e95cfd6084bce Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Mon, 3 Jun 2019 11:54:36 +0200 Subject: [PATCH 21/30] ci: retry s3 upload on azure if it fails --- .azure-pipelines/steps/run.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.azure-pipelines/steps/run.yml b/.azure-pipelines/steps/run.yml index e7c6235a50444..cfa28a6a1d70f 100644 --- a/.azure-pipelines/steps/run.yml +++ b/.azure-pipelines/steps/run.yml @@ -118,6 +118,7 @@ steps: # bucket. - bash: | set -e + source src/ci/shared.sh if [ "$AGENT_OS" = "Linux" ]; then rm -rf obj/build/dist/doc upload_dir=obj/build/dist @@ -130,7 +131,7 @@ steps: if [ "$DEPLOY_ALT" == "1" ]; then deploy_dir=rustc-builds-alt fi - aws s3 cp --no-progress --recursive --acl public-read ./$upload_dir s3://$DEPLOY_BUCKET/$deploy_dir/$BUILD_SOURCEVERSION + retry aws s3 cp --no-progress --recursive --acl public-read ./$upload_dir s3://$DEPLOY_BUCKET/$deploy_dir/$BUILD_SOURCEVERSION env: AWS_SECRET_ACCESS_KEY: $(AWS_SECRET_ACCESS_KEY) condition: and(succeeded(), or(eq(variables.DEPLOY, '1'), eq(variables.DEPLOY_ALT, '1'))) From 5e3b41e0cb7f8acef84afe3e9d464e67e7b2c891 Mon Sep 17 00:00:00 2001 From: David Wood Date: Sun, 2 Jun 2019 19:03:17 +0100 Subject: [PATCH 22/30] rustc: remove `HirId` from `ArgSource::AsyncFn` This commit removes the `HirId` from `ArgSource::AsyncFn`, relying on the fact that only `simple_ident` is used in each of the locations that previously took the original pattern from the `ArgSource::AsyncFn`. --- src/librustc/hir/lowering.rs | 2 +- src/librustc/hir/map/mod.rs | 13 ---- src/librustc/hir/mod.rs | 4 +- .../nice_region_error/different_lifetimes.rs | 6 +- .../nice_region_error/named_anon_conflict.rs | 3 +- src/librustc/middle/resolve_lifetime.rs | 8 +-- src/librustc_mir/build/mod.rs | 60 +++++-------------- src/librustdoc/clean/mod.rs | 3 +- .../underscore-lifetime-binders.stderr | 2 +- 9 files changed, 27 insertions(+), 74 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index e82b3df855035..d6d8b60f21f27 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -3092,7 +3092,7 @@ impl<'a> LoweringContext<'a> { new_argument_id, ident, None), span: desugared_span, }), - source: hir::ArgSource::AsyncFn(argument.pat.hir_id), + source: hir::ArgSource::AsyncFn, }; let construct_stmt = |this: &mut LoweringContext<'_>, pat: P, diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 2d3de5af9927f..75799a1903174 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -699,19 +699,6 @@ impl<'hir> Map<'hir> { } } - /// Returns the `HirId` of this pattern, or, if this is an `async fn` desugaring, the `HirId` - /// of the original pattern that the user wrote. - pub fn original_pat_of_argument(&self, arg: &'hir Arg) -> &'hir Pat { - match &arg.source { - ArgSource::Normal => &*arg.pat, - ArgSource::AsyncFn(hir_id) => match self.find_by_hir_id(*hir_id) { - Some(Node::Pat(pat)) | Some(Node::Binding(pat)) => &pat, - Some(Node::Local(local)) => &*local.pat, - x => bug!("ArgSource::AsyncFn HirId not a pattern/binding/local: {:?}", x), - }, - } - } - pub fn is_const_scope(&self, hir_id: HirId) -> bool { self.walk_parent_nodes(hir_id, |node| match *node { Node::Item(Item { node: ItemKind::Const(_, _), .. }) => true, diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 817c4cb540f67..eb338482eba91 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -1937,8 +1937,8 @@ pub struct Arg { pub enum ArgSource { /// Argument as specified by the user. Normal, - /// Generated argument from `async fn` lowering, `HirId` is the original pattern. - AsyncFn(HirId), + /// Generated argument from `async fn` lowering. + AsyncFn, } /// Represents the header (not the body) of a function declaration. diff --git a/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs b/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs index 46785f7ada1fe..ecdcb4bbf114a 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs @@ -86,14 +86,12 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { let sub_is_ret_type = self.is_return_type_anon(scope_def_id_sub, bregion_sub, ty_fndecl_sub); - let arg_sup_pat = self.tcx().hir().original_pat_of_argument(anon_arg_sup); - let span_label_var1 = match arg_sup_pat.simple_ident() { + let span_label_var1 = match anon_arg_sup.pat.simple_ident() { Some(simple_ident) => format!(" from `{}`", simple_ident), None => String::new(), }; - let arg_sub_pat = self.tcx().hir().original_pat_of_argument(anon_arg_sub); - let span_label_var2 = match arg_sub_pat.simple_ident() { + let span_label_var2 = match anon_arg_sub.pat.simple_ident() { Some(simple_ident) => format!(" into `{}`", simple_ident), None => String::new(), }; diff --git a/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs b/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs index 1eb2af2bd5818..0efc124e31fee 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs @@ -95,8 +95,7 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { } } - let arg_pat = self.tcx().hir().original_pat_of_argument(arg); - let (error_var, span_label_var) = match arg_pat.simple_ident() { + let (error_var, span_label_var) = match arg.pat.simple_ident() { Some(simple_ident) => ( format!("the type of `{}`", simple_ident), format!("the type of `{}`", simple_ident), diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index f48da4762b768..7c57c50595bc8 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -2414,10 +2414,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { have_bound_regions, } = info; - let help_name = if let Some(body) = parent { - let arg = &self.tcx.hir().body(body).arguments[index]; - let original_pat = self.tcx.hir().original_pat_of_argument(arg); - format!("`{}`", self.tcx.hir().hir_to_pretty_string(original_pat.hir_id)) + let help_name = if let Some(ident) = parent.and_then(|body| { + self.tcx.hir().body(body).arguments[index].pat.simple_ident() + }) { + format!("`{}`", ident) } else { format!("argument {}", index + 1) }; diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index a5d92d6c88f99..91106ebd77e07 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -84,23 +84,11 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Body<' // HACK(eddyb) Avoid having RustCall on closures, // as it adds unnecessary (and wrong) auto-tupling. abi = Abi::Rust; - Some(ArgInfo { - ty: liberated_closure_env_ty(tcx, id, body_id), - span: None, - pattern: None, - user_pattern: None, - self_kind: None, - }) + Some(ArgInfo(liberated_closure_env_ty(tcx, id, body_id), None, None, None)) } ty::Generator(..) => { let gen_ty = tcx.body_tables(body_id).node_type(id); - Some(ArgInfo { - ty: gen_ty, - span: None, - pattern: None, - user_pattern: None, - self_kind: None, - }) + Some(ArgInfo(gen_ty, None, None, None)) } _ => None, }; @@ -139,14 +127,7 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Body<' self_arg = None; } - let original_pat = tcx.hir().original_pat_of_argument(arg); - ArgInfo { - ty: fn_sig.inputs()[index], - span: opt_ty_info, - pattern: Some(&*arg.pat), - user_pattern: Some(&original_pat), - self_kind: self_arg, - } + ArgInfo(fn_sig.inputs()[index], opt_ty_info, Some(&*arg.pat), self_arg) }); let arguments = implicit_argument.into_iter().chain(explicit_arguments); @@ -634,13 +615,7 @@ fn should_abort_on_panic<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, /////////////////////////////////////////////////////////////////////////// /// the main entry point for building MIR for a function -struct ArgInfo<'gcx> { - ty: Ty<'gcx>, - span: Option, - pattern: Option<&'gcx hir::Pat>, - user_pattern: Option<&'gcx hir::Pat>, - self_kind: Option, -} +struct ArgInfo<'gcx>(Ty<'gcx>, Option, Option<&'gcx hir::Pat>, Option); fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, fn_id: hir::HirId, @@ -901,18 +876,13 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { -> BlockAnd<()> { // Allocate locals for the function arguments - for &ArgInfo { ty, span: _, pattern, user_pattern, self_kind: _ } in arguments.iter() { + for &ArgInfo(ty, _, pattern, _) in arguments.iter() { // If this is a simple binding pattern, give the local a name for // debuginfo and so that error reporting knows that this is a user // variable. For any other pattern the pattern introduces new // variables which will be named instead. - let (name, span) = if let Some(pat) = user_pattern { - match pat.node { - hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, ident, _) - | hir::PatKind::Binding(hir::BindingAnnotation::Mutable, _, ident, _) => - (Some(ident.name), pat.span), - _ => (None, pattern.map_or(self.fn_span, |pat| pat.span)) - } + let (name, span) = if let Some(pat) = pattern { + (pat.simple_ident().map(|ident| ident.name), pat.span) } else { (None, self.fn_span) }; @@ -937,13 +907,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // Function arguments always get the first Local indices after the return place let local = Local::new(index + 1); let place = Place::Base(PlaceBase::Local(local)); - let &ArgInfo { - ty, - span: opt_ty_info, - pattern, - user_pattern: _, - self_kind: ref self_binding - } = arg_info; + let &ArgInfo(ty, opt_ty_info, pattern, ref self_binding) = arg_info; // Make sure we drop (parts of) the argument even when not matched on. self.schedule_drop( @@ -958,7 +922,13 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { match *pattern.kind { // Don't introduce extra copies for simple bindings - PatternKind::Binding { mutability, var, mode: BindingMode::ByValue, .. } => { + PatternKind::Binding { + mutability, + var, + mode: BindingMode::ByValue, + subpattern: None, + .. + } => { self.local_decls[local].mutability = mutability; self.local_decls[local].is_user_variable = if let Some(kind) = self_binding { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 319adea6b8682..0c00b3b20b5b3 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2018,9 +2018,8 @@ impl<'a> Clean for (&'a [hir::Ty], hir::BodyId) { Arguments { values: self.0.iter().enumerate().map(|(i, ty)| { - let original_pat = cx.tcx.hir().original_pat_of_argument(&body.arguments[i]); Argument { - name: name_from_pat(original_pat), + name: name_from_pat(&body.arguments[i].pat), type_: ty.clean(cx), } }).collect() diff --git a/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr b/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr index 654f4285f655f..ef9e7e39df0bc 100644 --- a/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr +++ b/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr @@ -30,7 +30,7 @@ error[E0106]: missing lifetime specifier LL | fn foo2(_: &'_ u8, y: &'_ u8) -> &'_ u8 { y } | ^^ expected lifetime parameter | - = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `_` or `y` + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or `y` error: aborting due to 5 previous errors From 3ebe9ab5e7bb71e3dfc87bc556f3b0c37d4fb83a Mon Sep 17 00:00:00 2001 From: David Wood Date: Sun, 2 Jun 2019 19:59:49 +0100 Subject: [PATCH 23/30] rustc: use lowering helpers This commit changes the lowering to stop creating HIR statements, expressions and patterns directly and instead uses the pre-existing helper functions. --- src/librustc/hir/lowering.rs | 83 ++++++++++++------------------------ 1 file changed, 28 insertions(+), 55 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index d6d8b60f21f27..e9a86f708eff2 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -3039,12 +3039,15 @@ impl<'a> LoweringContext<'a> { // Async function arguments are lowered into the closure body so that they are // captured and so that the drop order matches the equivalent non-async functions. // + // from: + // // async fn foo(: , : , : ) { // async move { // } // } // - // // ...becomes... + // into: + // // fn foo(__arg0: , __arg1: , __arg2: ) { // async move { // let __arg2 = __arg2; @@ -3076,61 +3079,29 @@ impl<'a> LoweringContext<'a> { }, }; + let desugared_span = + this.mark_span_with_reason(CompilerDesugaringKind::Async, span, None); + // Construct an argument representing `__argN: ` to replace the argument of the // async function. // // If this is the simple case, this argument will end up being the same as the // original argument, but with a different pattern id. - let new_argument_id = this.next_id(); - let desugared_span = - this.mark_span_with_reason(CompilerDesugaringKind::Async, span, None); + let (new_argument_pat, new_argument_id) = this.pat_ident(desugared_span, ident); let new_argument = hir::Arg { hir_id: argument.hir_id, - pat: P(hir::Pat { - hir_id: new_argument_id, - node: hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, - new_argument_id, ident, None), - span: desugared_span, - }), - source: hir::ArgSource::AsyncFn, - }; - - let construct_stmt = |this: &mut LoweringContext<'_>, pat: P, - init_pat_id: hir::HirId| { - hir::Stmt { - hir_id: this.next_id(), - node: hir::StmtKind::Local(P(hir::Local { - pat, - // We explicitly do not specify the type for any statements. When the - // user's argument type is `impl Trait` then this would require the - // `impl_trait_in_bindings` feature to also be present for that same - // type to be valid in this binding. At the time of writing (13 Mar 19), - // `impl_trait_in_bindings` is not stable. - ty: None, - init: Some(P(hir::Expr { - span, - node: hir::ExprKind::Path(hir::QPath::Resolved(None, P(hir::Path { - span, - res: Res::Local(init_pat_id), - segments: hir_vec![ hir::PathSegment::from_ident(ident) ], - }))), - attrs: ThinVec::new(), - hir_id: this.next_id(), - })), - hir_id: this.next_id(), - span: desugared_span, - attrs: ThinVec::new(), - source: hir::LocalSource::AsyncFn, - })), - span: desugared_span, - } + pat: new_argument_pat, + source: hir::ArgSource::AsyncFn }; let new_statements = if is_simple_argument { // If this is the simple case, then we only insert one statement that is // `let = ;`. We re-use the original argument's pattern so that // `HirId`s are densely assigned. - (construct_stmt(this, argument.pat, new_argument_id), None) + let expr = this.expr_ident(desugared_span, ident, new_argument_id); + let stmt = this.stmt_let_pat( + desugared_span, Some(P(expr)), argument.pat, hir::LocalSource::AsyncFn); + (stmt, None) } else { // If this is not the simple case, then we construct two statements: // @@ -3147,21 +3118,19 @@ impl<'a> LoweringContext<'a> { // Construct the `let mut __argN = __argN;` statement. It must be a mut binding // because the user may have specified a `ref mut` binding in the next // statement. - let hir_id = this.next_id(); - let move_stmt = construct_stmt( - this, - P(hir::Pat { - hir_id, - node: hir::PatKind::Binding(hir::BindingAnnotation::Mutable, - hir_id, ident, None), - span: desugared_span, - }), - new_argument_id, - ); + let (move_pat, move_id) = this.pat_ident_binding_mode( + desugared_span, ident, hir::BindingAnnotation::Mutable); + let move_expr = this.expr_ident(desugared_span, ident, new_argument_id); + let move_stmt = this.stmt_let_pat( + desugared_span, Some(P(move_expr)), move_pat, hir::LocalSource::AsyncFn); // Construct the `let = __argN;` statement. We re-use the original // argument's pattern so that `HirId`s are densely assigned. - let pattern_stmt = construct_stmt(this, argument.pat, hir_id); + let pattern_expr = this.expr_ident(desugared_span, ident, move_id); + let pattern_stmt = this.stmt_let_pat( + desugared_span, Some(P(pattern_expr)), argument.pat, + hir::LocalSource::AsyncFn); + (move_stmt, Some(pattern_stmt)) }; @@ -5251,6 +5220,10 @@ impl<'a> LoweringContext<'a> { } } + fn arg(&mut self, hir_id: hir::HirId, pat: P, source: hir::ArgSource) -> hir::Arg { + hir::Arg { hir_id, pat, source } + } + fn stmt(&mut self, span: Span, node: hir::StmtKind) -> hir::Stmt { hir::Stmt { span, node, hir_id: self.next_id() } } From 3c7e0eb5472592a8d429527858636b27efeee021 Mon Sep 17 00:00:00 2001 From: David Wood Date: Mon, 3 Jun 2019 10:14:27 +0100 Subject: [PATCH 24/30] rustc: construct statement vector directly This commit simplifies the previous logic to construct the statement vector directly rather than constructing a `Vec` of `(hir::Stmt, Option)` first. --- src/librustc/hir/lowering.rs | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index e9a86f708eff2..ab7a854112661 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -3034,7 +3034,7 @@ impl<'a> LoweringContext<'a> { self.lower_body(|this| { let mut arguments: Vec = Vec::new(); - let mut statements: Vec<(hir::Stmt, Option)> = Vec::new(); + let mut statements: Vec = Vec::new(); // Async function arguments are lowered into the closure body so that they are // captured and so that the drop order matches the equivalent non-async functions. @@ -3094,14 +3094,14 @@ impl<'a> LoweringContext<'a> { source: hir::ArgSource::AsyncFn }; - let new_statements = if is_simple_argument { + if is_simple_argument { // If this is the simple case, then we only insert one statement that is // `let = ;`. We re-use the original argument's pattern so that // `HirId`s are densely assigned. let expr = this.expr_ident(desugared_span, ident, new_argument_id); let stmt = this.stmt_let_pat( desugared_span, Some(P(expr)), argument.pat, hir::LocalSource::AsyncFn); - (stmt, None) + statements.push(stmt); } else { // If this is not the simple case, then we construct two statements: // @@ -3131,26 +3131,17 @@ impl<'a> LoweringContext<'a> { desugared_span, Some(P(pattern_expr)), argument.pat, hir::LocalSource::AsyncFn); - (move_stmt, Some(pattern_stmt)) + statements.push(move_stmt); + statements.push(pattern_stmt); }; arguments.push(new_argument); - statements.push(new_statements); } let async_expr = this.make_async_expr( CaptureBy::Value, closure_id, None, body.span, |this| { - let mut stmts = vec![]; - for (move_stmt, pattern_stmt) in statements.drain(..) { - // Insert the `let __argN = __argN` statement first. - stmts.push(move_stmt); - // Then insert the `let = __argN` statement, if there is one. - if let Some(pattern_stmt) = pattern_stmt { - stmts.push(pattern_stmt); - } - } - let body = this.lower_block_with_stmts(body, false, stmts); + let body = this.lower_block_with_stmts(body, false, statements); this.expr_block(body, ThinVec::new()) }); (HirVec::from(arguments), this.expr(body.span, async_expr, ThinVec::new())) @@ -5220,10 +5211,6 @@ impl<'a> LoweringContext<'a> { } } - fn arg(&mut self, hir_id: hir::HirId, pat: P, source: hir::ArgSource) -> hir::Arg { - hir::Arg { hir_id, pat, source } - } - fn stmt(&mut self, span: Span, node: hir::StmtKind) -> hir::Stmt { hir::Stmt { span, node, hir_id: self.next_id() } } From 2bb92aa02ff98e13970602e7a7f9555050f1dbe7 Mon Sep 17 00:00:00 2001 From: David Wood Date: Mon, 3 Jun 2019 11:36:19 +0100 Subject: [PATCH 25/30] rustc: remove `ArgSource` `ArgSource` is no longer used anywhere, so it can be removed. --- src/librustc/hir/lowering.rs | 2 -- src/librustc/hir/mod.rs | 10 ---------- 2 files changed, 12 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index ab7a854112661..14a6e93341e32 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -2285,7 +2285,6 @@ impl<'a> LoweringContext<'a> { hir::Arg { hir_id: self.lower_node_id(arg.id), pat: self.lower_pat(&arg.pat), - source: hir::ArgSource::Normal, } } @@ -3091,7 +3090,6 @@ impl<'a> LoweringContext<'a> { let new_argument = hir::Arg { hir_id: argument.hir_id, pat: new_argument_pat, - source: hir::ArgSource::AsyncFn }; if is_simple_argument { diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index eb338482eba91..65fc56f2c4878 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -1929,16 +1929,6 @@ pub struct InlineAsm { pub struct Arg { pub pat: P, pub hir_id: HirId, - pub source: ArgSource, -} - -/// Represents the source of an argument in a function header. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] -pub enum ArgSource { - /// Argument as specified by the user. - Normal, - /// Generated argument from `async fn` lowering. - AsyncFn, } /// Represents the header (not the body) of a function declaration. From b87bad7e364c3b5544dd73ae71cd04b05e0c8eb5 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 3 Jun 2019 07:46:08 -0700 Subject: [PATCH 26/30] ci: Reenable step timings on AppVeyor This was accidentally regressed in #60777 by accident, and we've stopped printing out step timings on AppVeyor recently reducing the ability for us to track build times over time! --- src/ci/shared.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ci/shared.sh b/src/ci/shared.sh index 1e667fca5875a..323d53f2bec85 100644 --- a/src/ci/shared.sh +++ b/src/ci/shared.sh @@ -35,6 +35,8 @@ function isOSX { function getCIBranch { if [ "$TRAVIS" = "true" ]; then echo "$TRAVIS_BRANCH" + elif [ "$APPVEYOR" = "True" ]; then + echo "$APPVEYOR_REPO_BRANCH" else echo "$BUILD_SOURCEBRANCHNAME" fi; From 242056cadf2073325cc8b8edea9dd2960db99e93 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Mon, 3 Jun 2019 11:53:09 -0600 Subject: [PATCH 27/30] Do not panic in tidy on unbalanced parentheses in cfg's --- src/tools/tidy/src/pal.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/tools/tidy/src/pal.rs b/src/tools/tidy/src/pal.rs index 837be69f7cadd..d4a6cf73bf98c 100644 --- a/src/tools/tidy/src/pal.rs +++ b/src/tools/tidy/src/pal.rs @@ -204,7 +204,7 @@ fn parse_cfgs<'a>(contents: &'a str) -> Vec<(usize, &'a str)> { succeeds_non_ident && preceeds_whitespace_and_paren }); - cfgs.map(|i| { + cfgs.flat_map(|i| { let mut depth = 0; let contents_from = &contents[i..]; for (j, byte) in contents_from.bytes().enumerate() { @@ -215,13 +215,15 @@ fn parse_cfgs<'a>(contents: &'a str) -> Vec<(usize, &'a str)> { b')' => { depth -= 1; if depth == 0 { - return (i, &contents_from[..=j]); + return Some((i, &contents_from[..=j])); } } _ => { } } } - unreachable!() + // if the parentheses are unbalanced just ignore this cfg -- it'll be caught when attempting + // to run the compiler, and there's no real reason to lint it separately here + None }).collect() } From 41dd21a9bc5a8e69b5d2fd5d158c8f87a97d3e58 Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 3 Jun 2019 19:54:28 +0100 Subject: [PATCH 28/30] Add a regression test for #53457 --- src/test/ui/impl-trait/issue-53457.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 src/test/ui/impl-trait/issue-53457.rs diff --git a/src/test/ui/impl-trait/issue-53457.rs b/src/test/ui/impl-trait/issue-53457.rs new file mode 100644 index 0000000000000..3f6a4fb278715 --- /dev/null +++ b/src/test/ui/impl-trait/issue-53457.rs @@ -0,0 +1,15 @@ +// run-pass + +#![feature(existential_type)] + +existential type X: Clone; + +fn bar(f: F) -> F { + f +} + +fn foo() -> X { + bar(|x| ()) +} + +fn main() {} From 1c6dce8b6d6b66b4a596c3aa8f798cf95f0c45d7 Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 3 Jun 2019 19:57:13 +0100 Subject: [PATCH 29/30] Add ui/impl-trait/issues folder --- .../ui/impl-trait/{ => issues}/infinite-impl-trait-issue-38064.rs | 0 .../{ => issues}/infinite-impl-trait-issue-38064.stderr | 0 .../{ => issues}/issue-21659-show-relevant-trait-impls-3.rs | 0 .../{ => issues}/issue-21659-show-relevant-trait-impls-3.stderr | 0 src/test/ui/impl-trait/{ => issues}/issue-42479.rs | 0 src/test/ui/impl-trait/{ => issues}/issue-49376.rs | 0 src/test/ui/impl-trait/{ => issues}/issue-52128.rs | 0 src/test/ui/impl-trait/{ => issues}/issue-53457.rs | 0 .../impl-trait/{ => issues}/issue-55608-captures-empty-region.rs | 0 .../ui/impl-trait/{ => issues}/issue-57464-unexpected-regions.rs | 0 .../issue-57979-deeply-nested-impl-trait-in-assoc-proj.rs | 0 .../issue-57979-deeply-nested-impl-trait-in-assoc-proj.stderr | 0 .../ui/impl-trait/{ => issues}/issue-57979-impl-trait-in-path.rs | 0 .../impl-trait/{ => issues}/issue-57979-impl-trait-in-path.stderr | 0 .../{ => issues}/issue-57979-nested-impl-trait-in-assoc-proj.rs | 0 .../issue-57979-nested-impl-trait-in-assoc-proj.stderr | 0 src/test/ui/impl-trait/{ => issues}/universal-issue-48703.rs | 0 src/test/ui/impl-trait/{ => issues}/universal-issue-48703.stderr | 0 .../{ => issues}/universal-turbofish-in-method-issue-50950.rs | 0 .../{ => issues}/universal-turbofish-in-method-issue-50950.stderr | 0 20 files changed, 0 insertions(+), 0 deletions(-) rename src/test/ui/impl-trait/{ => issues}/infinite-impl-trait-issue-38064.rs (100%) rename src/test/ui/impl-trait/{ => issues}/infinite-impl-trait-issue-38064.stderr (100%) rename src/test/ui/impl-trait/{ => issues}/issue-21659-show-relevant-trait-impls-3.rs (100%) rename src/test/ui/impl-trait/{ => issues}/issue-21659-show-relevant-trait-impls-3.stderr (100%) rename src/test/ui/impl-trait/{ => issues}/issue-42479.rs (100%) rename src/test/ui/impl-trait/{ => issues}/issue-49376.rs (100%) rename src/test/ui/impl-trait/{ => issues}/issue-52128.rs (100%) rename src/test/ui/impl-trait/{ => issues}/issue-53457.rs (100%) rename src/test/ui/impl-trait/{ => issues}/issue-55608-captures-empty-region.rs (100%) rename src/test/ui/impl-trait/{ => issues}/issue-57464-unexpected-regions.rs (100%) rename src/test/ui/impl-trait/{ => issues}/issue-57979-deeply-nested-impl-trait-in-assoc-proj.rs (100%) rename src/test/ui/impl-trait/{ => issues}/issue-57979-deeply-nested-impl-trait-in-assoc-proj.stderr (100%) rename src/test/ui/impl-trait/{ => issues}/issue-57979-impl-trait-in-path.rs (100%) rename src/test/ui/impl-trait/{ => issues}/issue-57979-impl-trait-in-path.stderr (100%) rename src/test/ui/impl-trait/{ => issues}/issue-57979-nested-impl-trait-in-assoc-proj.rs (100%) rename src/test/ui/impl-trait/{ => issues}/issue-57979-nested-impl-trait-in-assoc-proj.stderr (100%) rename src/test/ui/impl-trait/{ => issues}/universal-issue-48703.rs (100%) rename src/test/ui/impl-trait/{ => issues}/universal-issue-48703.stderr (100%) rename src/test/ui/impl-trait/{ => issues}/universal-turbofish-in-method-issue-50950.rs (100%) rename src/test/ui/impl-trait/{ => issues}/universal-turbofish-in-method-issue-50950.stderr (100%) diff --git a/src/test/ui/impl-trait/infinite-impl-trait-issue-38064.rs b/src/test/ui/impl-trait/issues/infinite-impl-trait-issue-38064.rs similarity index 100% rename from src/test/ui/impl-trait/infinite-impl-trait-issue-38064.rs rename to src/test/ui/impl-trait/issues/infinite-impl-trait-issue-38064.rs diff --git a/src/test/ui/impl-trait/infinite-impl-trait-issue-38064.stderr b/src/test/ui/impl-trait/issues/infinite-impl-trait-issue-38064.stderr similarity index 100% rename from src/test/ui/impl-trait/infinite-impl-trait-issue-38064.stderr rename to src/test/ui/impl-trait/issues/infinite-impl-trait-issue-38064.stderr diff --git a/src/test/ui/impl-trait/issue-21659-show-relevant-trait-impls-3.rs b/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.rs similarity index 100% rename from src/test/ui/impl-trait/issue-21659-show-relevant-trait-impls-3.rs rename to src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.rs diff --git a/src/test/ui/impl-trait/issue-21659-show-relevant-trait-impls-3.stderr b/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr similarity index 100% rename from src/test/ui/impl-trait/issue-21659-show-relevant-trait-impls-3.stderr rename to src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr diff --git a/src/test/ui/impl-trait/issue-42479.rs b/src/test/ui/impl-trait/issues/issue-42479.rs similarity index 100% rename from src/test/ui/impl-trait/issue-42479.rs rename to src/test/ui/impl-trait/issues/issue-42479.rs diff --git a/src/test/ui/impl-trait/issue-49376.rs b/src/test/ui/impl-trait/issues/issue-49376.rs similarity index 100% rename from src/test/ui/impl-trait/issue-49376.rs rename to src/test/ui/impl-trait/issues/issue-49376.rs diff --git a/src/test/ui/impl-trait/issue-52128.rs b/src/test/ui/impl-trait/issues/issue-52128.rs similarity index 100% rename from src/test/ui/impl-trait/issue-52128.rs rename to src/test/ui/impl-trait/issues/issue-52128.rs diff --git a/src/test/ui/impl-trait/issue-53457.rs b/src/test/ui/impl-trait/issues/issue-53457.rs similarity index 100% rename from src/test/ui/impl-trait/issue-53457.rs rename to src/test/ui/impl-trait/issues/issue-53457.rs diff --git a/src/test/ui/impl-trait/issue-55608-captures-empty-region.rs b/src/test/ui/impl-trait/issues/issue-55608-captures-empty-region.rs similarity index 100% rename from src/test/ui/impl-trait/issue-55608-captures-empty-region.rs rename to src/test/ui/impl-trait/issues/issue-55608-captures-empty-region.rs diff --git a/src/test/ui/impl-trait/issue-57464-unexpected-regions.rs b/src/test/ui/impl-trait/issues/issue-57464-unexpected-regions.rs similarity index 100% rename from src/test/ui/impl-trait/issue-57464-unexpected-regions.rs rename to src/test/ui/impl-trait/issues/issue-57464-unexpected-regions.rs diff --git a/src/test/ui/impl-trait/issue-57979-deeply-nested-impl-trait-in-assoc-proj.rs b/src/test/ui/impl-trait/issues/issue-57979-deeply-nested-impl-trait-in-assoc-proj.rs similarity index 100% rename from src/test/ui/impl-trait/issue-57979-deeply-nested-impl-trait-in-assoc-proj.rs rename to src/test/ui/impl-trait/issues/issue-57979-deeply-nested-impl-trait-in-assoc-proj.rs diff --git a/src/test/ui/impl-trait/issue-57979-deeply-nested-impl-trait-in-assoc-proj.stderr b/src/test/ui/impl-trait/issues/issue-57979-deeply-nested-impl-trait-in-assoc-proj.stderr similarity index 100% rename from src/test/ui/impl-trait/issue-57979-deeply-nested-impl-trait-in-assoc-proj.stderr rename to src/test/ui/impl-trait/issues/issue-57979-deeply-nested-impl-trait-in-assoc-proj.stderr diff --git a/src/test/ui/impl-trait/issue-57979-impl-trait-in-path.rs b/src/test/ui/impl-trait/issues/issue-57979-impl-trait-in-path.rs similarity index 100% rename from src/test/ui/impl-trait/issue-57979-impl-trait-in-path.rs rename to src/test/ui/impl-trait/issues/issue-57979-impl-trait-in-path.rs diff --git a/src/test/ui/impl-trait/issue-57979-impl-trait-in-path.stderr b/src/test/ui/impl-trait/issues/issue-57979-impl-trait-in-path.stderr similarity index 100% rename from src/test/ui/impl-trait/issue-57979-impl-trait-in-path.stderr rename to src/test/ui/impl-trait/issues/issue-57979-impl-trait-in-path.stderr diff --git a/src/test/ui/impl-trait/issue-57979-nested-impl-trait-in-assoc-proj.rs b/src/test/ui/impl-trait/issues/issue-57979-nested-impl-trait-in-assoc-proj.rs similarity index 100% rename from src/test/ui/impl-trait/issue-57979-nested-impl-trait-in-assoc-proj.rs rename to src/test/ui/impl-trait/issues/issue-57979-nested-impl-trait-in-assoc-proj.rs diff --git a/src/test/ui/impl-trait/issue-57979-nested-impl-trait-in-assoc-proj.stderr b/src/test/ui/impl-trait/issues/issue-57979-nested-impl-trait-in-assoc-proj.stderr similarity index 100% rename from src/test/ui/impl-trait/issue-57979-nested-impl-trait-in-assoc-proj.stderr rename to src/test/ui/impl-trait/issues/issue-57979-nested-impl-trait-in-assoc-proj.stderr diff --git a/src/test/ui/impl-trait/universal-issue-48703.rs b/src/test/ui/impl-trait/issues/universal-issue-48703.rs similarity index 100% rename from src/test/ui/impl-trait/universal-issue-48703.rs rename to src/test/ui/impl-trait/issues/universal-issue-48703.rs diff --git a/src/test/ui/impl-trait/universal-issue-48703.stderr b/src/test/ui/impl-trait/issues/universal-issue-48703.stderr similarity index 100% rename from src/test/ui/impl-trait/universal-issue-48703.stderr rename to src/test/ui/impl-trait/issues/universal-issue-48703.stderr diff --git a/src/test/ui/impl-trait/universal-turbofish-in-method-issue-50950.rs b/src/test/ui/impl-trait/issues/universal-turbofish-in-method-issue-50950.rs similarity index 100% rename from src/test/ui/impl-trait/universal-turbofish-in-method-issue-50950.rs rename to src/test/ui/impl-trait/issues/universal-turbofish-in-method-issue-50950.rs diff --git a/src/test/ui/impl-trait/universal-turbofish-in-method-issue-50950.stderr b/src/test/ui/impl-trait/issues/universal-turbofish-in-method-issue-50950.stderr similarity index 100% rename from src/test/ui/impl-trait/universal-turbofish-in-method-issue-50950.stderr rename to src/test/ui/impl-trait/issues/universal-turbofish-in-method-issue-50950.stderr From 5ce3c8137b4d29481038d4b322f6db28d946d648 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Mon, 3 Jun 2019 12:14:10 -0600 Subject: [PATCH 30/30] Treat 0 as special value for codegen-units-std Fixes #57669 --- src/bootstrap/config.rs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index d618654b129af..edeb07fda1d59 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -11,7 +11,6 @@ use std::process; use std::cmp; use build_helper::t; -use num_cpus; use toml; use serde::Deserialize; use crate::cache::{INTERNER, Interned}; @@ -401,7 +400,7 @@ impl Config { config.rustc_error_format = flags.rustc_error_format; config.on_fail = flags.on_fail; config.stage = flags.stage; - config.jobs = flags.jobs; + config.jobs = flags.jobs.map(threads_from_config); config.cmd = flags.cmd; config.incremental = flags.incremental; config.dry_run = flags.dry_run; @@ -583,13 +582,8 @@ impl Config { set(&mut config.rust_codegen_backends_dir, rust.codegen_backends_dir.clone()); - match rust.codegen_units { - Some(0) => config.rust_codegen_units = Some(num_cpus::get() as u32), - Some(n) => config.rust_codegen_units = Some(n), - None => {} - } - - config.rust_codegen_units_std = rust.codegen_units_std; + config.rust_codegen_units = rust.codegen_units.map(threads_from_config); + config.rust_codegen_units_std = rust.codegen_units_std.map(threads_from_config); } if let Some(ref t) = toml.target { @@ -688,3 +682,10 @@ fn set(field: &mut T, val: Option) { *field = v; } } + +fn threads_from_config(v: u32) -> u32 { + match v { + 0 => num_cpus::get() as u32, + n => n, + } +}