From 97a6c932e02fcd7f55fdad9aef76c5619f91f481 Mon Sep 17 00:00:00 2001 From: Tim Vermeulen Date: Sun, 12 May 2019 23:55:58 +0200 Subject: [PATCH 1/9] Implement nth_back for slice::{Iter, IterMut} --- src/libcore/slice/mod.rs | 76 +++++++++++++++++++++++++++----------- src/libcore/tests/slice.rs | 13 +++++++ 2 files changed, 68 insertions(+), 21 deletions(-) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 8731f48675356..016891b29b724 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -3014,6 +3014,28 @@ macro_rules! iterator { {$( $mut_:tt )*}, {$($extra:tt)*} ) => { + // Returns the first element and moves the start of the iterator forwards by 1. + // Greatly improves performance compared to an inlined function. The iterator + // must not be empty. + macro_rules! next_unchecked { + ($self: ident) => {& $( $mut_ )* *$self.post_inc_start(1)} + } + + // Returns the last element and moves the end of the iterator backwards by 1. + // Greatly improves performance compared to an inlined function. The iterator + // must not be empty. + macro_rules! next_back_unchecked { + ($self: ident) => {& $( $mut_ )* *$self.pre_dec_end(1)} + } + + // Shrinks the iterator when T is a ZST, by moving the end of the iterator + // backwards by `n`. `n` must not exceed `self.len()`. + macro_rules! zst_shrink { + ($self: ident, $n: ident) => { + $self.end = ($self.end as * $raw_mut u8).wrapping_offset(-$n) as * $raw_mut T; + } + } + impl<'a, T> $name<'a, T> { // Helper function for creating a slice from the iterator. #[inline(always)] @@ -3023,12 +3045,11 @@ macro_rules! iterator { // Helper function for moving the start of the iterator forwards by `offset` elements, // returning the old start. - // Unsafe because the offset must be in-bounds or one-past-the-end. + // Unsafe because the offset must not exceed `self.len()`. #[inline(always)] unsafe fn post_inc_start(&mut self, offset: isize) -> * $raw_mut T { if mem::size_of::() == 0 { - // This is *reducing* the length. `ptr` never changes with ZST. - self.end = (self.end as * $raw_mut u8).wrapping_offset(-offset) as * $raw_mut T; + zst_shrink!(self, offset); self.ptr } else { let old = self.ptr; @@ -3039,11 +3060,11 @@ macro_rules! iterator { // Helper function for moving the end of the iterator backwards by `offset` elements, // returning the new end. - // Unsafe because the offset must be in-bounds or one-past-the-end. + // Unsafe because the offset must not exceed `self.len()`. #[inline(always)] unsafe fn pre_dec_end(&mut self, offset: isize) -> * $raw_mut T { if mem::size_of::() == 0 { - self.end = (self.end as * $raw_mut u8).wrapping_offset(-offset) as * $raw_mut T; + zst_shrink!(self, offset); self.ptr } else { self.end = self.end.offset(-offset); @@ -3080,7 +3101,7 @@ macro_rules! iterator { if is_empty!(self) { None } else { - Some(& $( $mut_ )* *self.post_inc_start(1)) + Some(next_unchecked!(self)) } } } @@ -3109,11 +3130,10 @@ macro_rules! iterator { } return None; } - // We are in bounds. `offset` does the right thing even for ZSTs. + // We are in bounds. `post_inc_start` does the right thing even for ZSTs. unsafe { - let elem = Some(& $( $mut_ )* *self.ptr.add(n)); - self.post_inc_start((n as isize).wrapping_add(1)); - elem + self.post_inc_start(n as isize); + Some(next_unchecked!(self)) } } @@ -3130,13 +3150,13 @@ macro_rules! iterator { let mut accum = init; unsafe { while len!(self) >= 4 { - accum = f(accum, & $( $mut_ )* *self.post_inc_start(1))?; - accum = f(accum, & $( $mut_ )* *self.post_inc_start(1))?; - accum = f(accum, & $( $mut_ )* *self.post_inc_start(1))?; - accum = f(accum, & $( $mut_ )* *self.post_inc_start(1))?; + accum = f(accum, next_unchecked!(self))?; + accum = f(accum, next_unchecked!(self))?; + accum = f(accum, next_unchecked!(self))?; + accum = f(accum, next_unchecked!(self))?; } while !is_empty!(self) { - accum = f(accum, & $( $mut_ )* *self.post_inc_start(1))?; + accum = f(accum, next_unchecked!(self))?; } } Try::from_ok(accum) @@ -3207,11 +3227,25 @@ macro_rules! iterator { if is_empty!(self) { None } else { - Some(& $( $mut_ )* *self.pre_dec_end(1)) + Some(next_back_unchecked!(self)) } } } + #[inline] + fn nth_back(&mut self, n: usize) -> Option<$elem> { + if n >= len!(self) { + // This iterator is now empty. + self.end = self.ptr; + return None; + } + // We are in bounds. `pre_dec_end` does the right thing even for ZSTs. + unsafe { + self.pre_dec_end(n as isize); + Some(next_back_unchecked!(self)) + } + } + #[inline] fn try_rfold(&mut self, init: B, mut f: F) -> R where Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try @@ -3220,14 +3254,14 @@ macro_rules! iterator { let mut accum = init; unsafe { while len!(self) >= 4 { - accum = f(accum, & $( $mut_ )* *self.pre_dec_end(1))?; - accum = f(accum, & $( $mut_ )* *self.pre_dec_end(1))?; - accum = f(accum, & $( $mut_ )* *self.pre_dec_end(1))?; - accum = f(accum, & $( $mut_ )* *self.pre_dec_end(1))?; + accum = f(accum, next_back_unchecked!(self))?; + accum = f(accum, next_back_unchecked!(self))?; + accum = f(accum, next_back_unchecked!(self))?; + accum = f(accum, next_back_unchecked!(self))?; } // inlining is_empty everywhere makes a huge performance difference while !is_empty!(self) { - accum = f(accum, & $( $mut_ )* *self.pre_dec_end(1))?; + accum = f(accum, next_back_unchecked!(self))?; } } Try::from_ok(accum) diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs index acf6b03791f01..e52879064466c 100644 --- a/src/libcore/tests/slice.rs +++ b/src/libcore/tests/slice.rs @@ -88,6 +88,19 @@ fn test_iterator_nth() { assert_eq!(iter.nth(1).unwrap(), &v[4]); } +#[test] +fn test_iterator_nth_back() { + let v: &[_] = &[0, 1, 2, 3, 4]; + for i in 0..v.len() { + assert_eq!(v.iter().nth_back(i).unwrap(), &v[v.len() - i - 1]); + } + assert_eq!(v.iter().nth_back(v.len()), None); + + let mut iter = v.iter(); + assert_eq!(iter.nth_back(2).unwrap(), &v[2]); + assert_eq!(iter.nth_back(1).unwrap(), &v[0]); +} + #[test] fn test_iterator_last() { let v: &[_] = &[0, 1, 2, 3, 4]; From e80a37558df5ac9828caccd48459fdb7be488f5b Mon Sep 17 00:00:00 2001 From: Andrea Corradi Date: Thu, 2 May 2019 14:35:43 +0000 Subject: [PATCH 2/9] Add custom nth_back for Skip --- src/libcore/iter/adapters/mod.rs | 14 +++++++++++++ src/libcore/tests/iter.rs | 34 ++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/src/libcore/iter/adapters/mod.rs b/src/libcore/iter/adapters/mod.rs index 518442efe7417..c2edcd22f953b 100644 --- a/src/libcore/iter/adapters/mod.rs +++ b/src/libcore/iter/adapters/mod.rs @@ -1509,6 +1509,20 @@ impl DoubleEndedIterator for Skip where I: DoubleEndedIterator + ExactSize } } + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + let len = self.len(); + if n < len { + self.iter.nth_back(n) + } else { + if len > 0 { + // consume the original iterator + self.iter.nth_back(len-1); + } + None + } + } + fn try_rfold(&mut self, init: Acc, mut fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try { diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index 7dfb1adad9eed..7e3190f8a20d6 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -2280,6 +2280,40 @@ fn test_skip_try_folds() { assert_eq!(iter.next_back(), Some(24)); } +#[test] +fn test_skip_nth_back() { + let xs = [0, 1, 2, 3, 4, 5]; + let mut it = xs.iter().skip(2); + assert_eq!(it.nth_back(0), Some(&5)); + assert_eq!(it.nth_back(1), Some(&3)); + assert_eq!(it.nth_back(0), Some(&2)); + assert_eq!(it.nth_back(0), None); + + let ys = [2, 3, 4, 5]; + let mut ity = ys.iter(); + let mut it = xs.iter().skip(2); + assert_eq!(it.nth_back(1), ity.nth_back(1)); + assert_eq!(it.clone().nth(0), ity.clone().nth(0)); + assert_eq!(it.nth_back(0), ity.nth_back(0)); + assert_eq!(it.clone().nth(0), ity.clone().nth(0)); + assert_eq!(it.nth_back(0), ity.nth_back(0)); + assert_eq!(it.clone().nth(0), ity.clone().nth(0)); + assert_eq!(it.nth_back(0), ity.nth_back(0)); + assert_eq!(it.clone().nth(0), ity.clone().nth(0)); + + let mut it = xs.iter().skip(2); + assert_eq!(it.nth_back(4), None); + assert_eq!(it.nth_back(0), None); + + let mut it = xs.iter(); + it.by_ref().skip(2).nth_back(3); + assert_eq!(it.next_back(), Some(&1)); + + let mut it = xs.iter(); + it.by_ref().skip(2).nth_back(10); + assert_eq!(it.next_back(), Some(&1)); +} + #[test] fn test_take_try_folds() { let f = &|acc, x| i32::checked_add(2*acc, x); From f7ecf1c54806d0a2b614510b46d1b25c178450f0 Mon Sep 17 00:00:00 2001 From: Cedric Date: Mon, 17 Jun 2019 20:04:26 +0200 Subject: [PATCH 3/9] suggest tuple struct syntax --- src/librustc_typeck/check/expr.rs | 71 +++++++++++++---------- src/test/ui/issues/issue-4736.stderr | 5 +- src/test/ui/numeric/numeric-fields.stderr | 7 ++- 3 files changed, 49 insertions(+), 34 deletions(-) diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index fa9e0d8a8578a..06d07d992427e 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -1215,38 +1215,49 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } }, ty); - // prevent all specified fields from being suggested - let skip_fields = skip_fields.iter().map(|ref x| x.ident.as_str()); - if let Some(field_name) = Self::suggest_field_name(variant, - &field.ident.as_str(), - skip_fields.collect()) { - err.span_suggestion( - field.ident.span, - "a field with a similar name exists", - field_name.to_string(), - Applicability::MaybeIncorrect, - ); - } else { - match ty.sty { - ty::Adt(adt, ..) => { - if adt.is_enum() { - err.span_label(field.ident.span, - format!("`{}::{}` does not have this field", - ty, variant.ident)); - } else { - err.span_label(field.ident.span, - format!("`{}` does not have this field", ty)); - } - let available_field_names = self.available_field_names(variant); - if !available_field_names.is_empty() { - err.note(&format!("available fields are: {}", - self.name_series_display(available_field_names))); + match variant.ctor_kind { + CtorKind::Fn => { + err.span_label(field.ident.span, "field does not exist"); + err.span_label( + field.ident.span, + format!("`{adt}` is a tuple {kind_name}, use the appropriate syntax: `{adt}(/* fields */)`", adt=ty, kind_name=kind_name) + ); + } + _ => { + // prevent all specified fields from being suggested + let skip_fields = skip_fields.iter().map(|ref x| x.ident.as_str()); + if let Some(field_name) = Self::suggest_field_name(variant, + &field.ident.as_str(), + skip_fields.collect()) { + err.span_suggestion( + field.ident.span, + "a field with a similar name exists", + field_name.to_string(), + Applicability::MaybeIncorrect, + ); + } else { + match ty.sty { + ty::Adt(adt, ..) => { + if adt.is_enum() { + err.span_label(field.ident.span, + format!("`{}::{}` does not have this field", + ty, variant.ident)); + } else { + err.span_label(field.ident.span, + format!("`{}` does not have this field", ty)); + } + let available_field_names = self.available_field_names(variant); + if !available_field_names.is_empty() { + err.note(&format!("available fields are: {}", + self.name_series_display(available_field_names))); + } + } + _ => bug!("non-ADT passed to report_unknown_field") } - } - _ => bug!("non-ADT passed to report_unknown_field") + }; } - }; - err.emit(); + } + err.emit(); } // Return an hint about the closest match in field names diff --git a/src/test/ui/issues/issue-4736.stderr b/src/test/ui/issues/issue-4736.stderr index b4ac12643bcac..557ee5593f373 100644 --- a/src/test/ui/issues/issue-4736.stderr +++ b/src/test/ui/issues/issue-4736.stderr @@ -2,7 +2,10 @@ error[E0560]: struct `NonCopyable` has no field named `p` --> $DIR/issue-4736.rs:4:26 | LL | let z = NonCopyable{ p: () }; - | ^ help: a field with a similar name exists: `0` + | ^ + | | + | field does not exist + | `NonCopyable` is a tuple struct, use the appropriate syntax: `NonCopyable(/* fields */)` error: aborting due to previous error diff --git a/src/test/ui/numeric/numeric-fields.stderr b/src/test/ui/numeric/numeric-fields.stderr index 13c18d740fc1c..fef7486b8536d 100644 --- a/src/test/ui/numeric/numeric-fields.stderr +++ b/src/test/ui/numeric/numeric-fields.stderr @@ -2,9 +2,10 @@ error[E0560]: struct `S` has no field named `0b1` --> $DIR/numeric-fields.rs:4:15 | LL | let s = S{0b1: 10, 0: 11}; - | ^^^ `S` does not have this field - | - = note: available fields are: `0`, `1` + | ^^^ + | | + | field does not exist + | `S` is a tuple struct, use the appropriate syntax: `S(/* fields */)` error[E0026]: struct `S` does not have a field named `0x1` --> $DIR/numeric-fields.rs:7:17 From 2191c1db08d21aac4d3823a497e429de283e878b Mon Sep 17 00:00:00 2001 From: Cedric Date: Tue, 18 Jun 2019 22:05:27 +0200 Subject: [PATCH 4/9] improve indentation --- src/librustc_typeck/check/expr.rs | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index 06d07d992427e..8edda805592a3 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -1218,17 +1218,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match variant.ctor_kind { CtorKind::Fn => { err.span_label(field.ident.span, "field does not exist"); - err.span_label( - field.ident.span, - format!("`{adt}` is a tuple {kind_name}, use the appropriate syntax: `{adt}(/* fields */)`", adt=ty, kind_name=kind_name) - ); + err.span_label(field.ident.span, format!( + "`{adt}` is a tuple {kind_name}, use the appropriate syntax: `{adt}(/* fields */)`", + adt=ty, + kind_name=kind_name + )); } _ => { // prevent all specified fields from being suggested let skip_fields = skip_fields.iter().map(|ref x| x.ident.as_str()); - if let Some(field_name) = Self::suggest_field_name(variant, - &field.ident.as_str(), - skip_fields.collect()) { + if let Some(field_name) = Self::suggest_field_name( + variant, + &field.ident.as_str(), + skip_fields.collect() + ) { err.span_suggestion( field.ident.span, "a field with a similar name exists", @@ -1239,12 +1242,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match ty.sty { ty::Adt(adt, ..) => { if adt.is_enum() { - err.span_label(field.ident.span, - format!("`{}::{}` does not have this field", - ty, variant.ident)); + err.span_label(field.ident.span, format!( + "`{}::{}` does not have this field", + ty, + variant.ident + )); } else { - err.span_label(field.ident.span, - format!("`{}` does not have this field", ty)); + err.span_label(field.ident.span, format!( + "`{}` does not have this field", + ty + )); } let available_field_names = self.available_field_names(variant); if !available_field_names.is_empty() { From c917ba325f3e7944eefb5e906ca0392c9b499541 Mon Sep 17 00:00:00 2001 From: Cedric Date: Wed, 19 Jun 2019 10:07:07 +0200 Subject: [PATCH 5/9] adt hint pointing to adt span --- src/librustc_typeck/check/expr.rs | 5 +++-- src/test/ui/issues/issue-4736.stderr | 7 +++---- src/test/ui/numeric/numeric-fields.stderr | 7 +++---- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index 8edda805592a3..3c31e01240317 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -1125,7 +1125,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.emit(); } else { - self.report_unknown_field(adt_ty, variant, field, ast_fields, kind_name); + self.report_unknown_field(adt_ty, variant, field, ast_fields, kind_name, span); } tcx.types.err @@ -1196,6 +1196,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { field: &hir::Field, skip_fields: &[hir::Field], kind_name: &str, + ty_span: Span ) { if variant.recovered { return; @@ -1218,7 +1219,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match variant.ctor_kind { CtorKind::Fn => { err.span_label(field.ident.span, "field does not exist"); - err.span_label(field.ident.span, format!( + err.span_label(ty_span, format!( "`{adt}` is a tuple {kind_name}, use the appropriate syntax: `{adt}(/* fields */)`", adt=ty, kind_name=kind_name diff --git a/src/test/ui/issues/issue-4736.stderr b/src/test/ui/issues/issue-4736.stderr index 557ee5593f373..6786b592d9857 100644 --- a/src/test/ui/issues/issue-4736.stderr +++ b/src/test/ui/issues/issue-4736.stderr @@ -2,10 +2,9 @@ error[E0560]: struct `NonCopyable` has no field named `p` --> $DIR/issue-4736.rs:4:26 | LL | let z = NonCopyable{ p: () }; - | ^ - | | - | field does not exist - | `NonCopyable` is a tuple struct, use the appropriate syntax: `NonCopyable(/* fields */)` + | ----------- ^ field does not exist + | | + | `NonCopyable` is a tuple struct, use the appropriate syntax: `NonCopyable(/* fields */)` error: aborting due to previous error diff --git a/src/test/ui/numeric/numeric-fields.stderr b/src/test/ui/numeric/numeric-fields.stderr index fef7486b8536d..e71af0f33ee42 100644 --- a/src/test/ui/numeric/numeric-fields.stderr +++ b/src/test/ui/numeric/numeric-fields.stderr @@ -2,10 +2,9 @@ error[E0560]: struct `S` has no field named `0b1` --> $DIR/numeric-fields.rs:4:15 | LL | let s = S{0b1: 10, 0: 11}; - | ^^^ - | | - | field does not exist - | `S` is a tuple struct, use the appropriate syntax: `S(/* fields */)` + | - ^^^ field does not exist + | | + | `S` is a tuple struct, use the appropriate syntax: `S(/* fields */)` error[E0026]: struct `S` does not have a field named `0x1` --> $DIR/numeric-fields.rs:7:17 From 70e52f84186ee017d19d26e081ab8688beee9b37 Mon Sep 17 00:00:00 2001 From: Cedric Date: Wed, 19 Jun 2019 11:09:17 +0200 Subject: [PATCH 6/9] provide variant definition on tuple struct unknow field error --- src/librustc_typeck/check/expr.rs | 4 +++- src/test/ui/issues/issue-4736.stderr | 5 ++++- src/test/ui/numeric/numeric-fields.stderr | 5 ++++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index 3c31e01240317..d659169711f2f 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -1218,9 +1218,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty); match variant.ctor_kind { CtorKind::Fn => { + err.span_label(variant.ident.span, format!("`{adt}` defined here", adt=ty)); err.span_label(field.ident.span, "field does not exist"); err.span_label(ty_span, format!( - "`{adt}` is a tuple {kind_name}, use the appropriate syntax: `{adt}(/* fields */)`", + "`{adt}` is a tuple {kind_name},\ + use the appropriate syntax: `{adt}(/* fields */)`", adt=ty, kind_name=kind_name )); diff --git a/src/test/ui/issues/issue-4736.stderr b/src/test/ui/issues/issue-4736.stderr index 6786b592d9857..557607503efab 100644 --- a/src/test/ui/issues/issue-4736.stderr +++ b/src/test/ui/issues/issue-4736.stderr @@ -1,10 +1,13 @@ error[E0560]: struct `NonCopyable` has no field named `p` --> $DIR/issue-4736.rs:4:26 | +LL | struct NonCopyable(()); + | ----------- `NonCopyable` defined here +... LL | let z = NonCopyable{ p: () }; | ----------- ^ field does not exist | | - | `NonCopyable` is a tuple struct, use the appropriate syntax: `NonCopyable(/* fields */)` + | `NonCopyable` is a tuple struct,use the appropriate syntax: `NonCopyable(/* fields */)` error: aborting due to previous error diff --git a/src/test/ui/numeric/numeric-fields.stderr b/src/test/ui/numeric/numeric-fields.stderr index e71af0f33ee42..ad1f1177f7be7 100644 --- a/src/test/ui/numeric/numeric-fields.stderr +++ b/src/test/ui/numeric/numeric-fields.stderr @@ -1,10 +1,13 @@ error[E0560]: struct `S` has no field named `0b1` --> $DIR/numeric-fields.rs:4:15 | +LL | struct S(u8, u16); + | - `S` defined here +... LL | let s = S{0b1: 10, 0: 11}; | - ^^^ field does not exist | | - | `S` is a tuple struct, use the appropriate syntax: `S(/* fields */)` + | `S` is a tuple struct,use the appropriate syntax: `S(/* fields */)` error[E0026]: struct `S` does not have a field named `0x1` --> $DIR/numeric-fields.rs:7:17 From b72b1ac062a66819cd06a3f147486678e99b4f40 Mon Sep 17 00:00:00 2001 From: Cedric Date: Wed, 19 Jun 2019 19:47:52 +0200 Subject: [PATCH 7/9] fix indentation --- src/librustc_typeck/check/expr.rs | 4 ++-- src/test/ui/issues/issue-4736.stderr | 2 +- src/test/ui/numeric/numeric-fields.stderr | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index d659169711f2f..b6e17091c06f9 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -1221,7 +1221,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.span_label(variant.ident.span, format!("`{adt}` defined here", adt=ty)); err.span_label(field.ident.span, "field does not exist"); err.span_label(ty_span, format!( - "`{adt}` is a tuple {kind_name},\ + "`{adt}` is a tuple {kind_name}, \ use the appropriate syntax: `{adt}(/* fields */)`", adt=ty, kind_name=kind_name @@ -1267,7 +1267,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; } } - err.emit(); + err.emit(); } // Return an hint about the closest match in field names diff --git a/src/test/ui/issues/issue-4736.stderr b/src/test/ui/issues/issue-4736.stderr index 557607503efab..257ec914a61ca 100644 --- a/src/test/ui/issues/issue-4736.stderr +++ b/src/test/ui/issues/issue-4736.stderr @@ -7,7 +7,7 @@ LL | struct NonCopyable(()); LL | let z = NonCopyable{ p: () }; | ----------- ^ field does not exist | | - | `NonCopyable` is a tuple struct,use the appropriate syntax: `NonCopyable(/* fields */)` + | `NonCopyable` is a tuple struct, use the appropriate syntax: `NonCopyable(/* fields */)` error: aborting due to previous error diff --git a/src/test/ui/numeric/numeric-fields.stderr b/src/test/ui/numeric/numeric-fields.stderr index ad1f1177f7be7..5202393f559c9 100644 --- a/src/test/ui/numeric/numeric-fields.stderr +++ b/src/test/ui/numeric/numeric-fields.stderr @@ -7,7 +7,7 @@ LL | struct S(u8, u16); LL | let s = S{0b1: 10, 0: 11}; | - ^^^ field does not exist | | - | `S` is a tuple struct,use the appropriate syntax: `S(/* fields */)` + | `S` is a tuple struct, use the appropriate syntax: `S(/* fields */)` error[E0026]: struct `S` does not have a field named `0x1` --> $DIR/numeric-fields.rs:7:17 From 887feeeaf7d40c25caa9532f2d9121cb79fca899 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 12 Jun 2019 11:42:58 +0300 Subject: [PATCH 8/9] rustc: replace `GenericArgs::with_generic_args` hack with a plain getter. --- src/librustc/hir/mod.rs | 18 +++--- src/librustc/hir/print.rs | 49 ++++++--------- src/librustc_typeck/astconv.rs | 106 ++++++++++++++++----------------- src/librustdoc/clean/mod.rs | 7 ++- src/libsyntax/lib.rs | 2 + src/libsyntax/ptr.rs | 11 +++- 6 files changed, 91 insertions(+), 102 deletions(-) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 527f18f57dc2e..de8c75345fee4 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -383,17 +383,13 @@ impl PathSegment { } } - // FIXME: hack required because you can't create a static - // `GenericArgs`, so you can't just return a `&GenericArgs`. - pub fn with_generic_args(&self, f: F) -> R - where F: FnOnce(&GenericArgs) -> R - { - let dummy = GenericArgs::none(); - f(if let Some(ref args) = self.args { - &args + pub fn generic_args(&self) -> &GenericArgs { + if let Some(ref args) = self.args { + args } else { - &dummy - }) + const DUMMY: &GenericArgs = &GenericArgs::none(); + DUMMY + } } } @@ -449,7 +445,7 @@ pub struct GenericArgs { } impl GenericArgs { - pub fn none() -> Self { + pub const fn none() -> Self { Self { args: HirVec::new(), bindings: HirVec::new(), diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index e1c713b537c2a..8111ac44a87ee 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -1194,12 +1194,11 @@ impl<'a> State<'a> { self.s.word(".")?; self.print_ident(segment.ident)?; - segment.with_generic_args(|generic_args| { - if !generic_args.args.is_empty() || !generic_args.bindings.is_empty() { - return self.print_generic_args(&generic_args, segment.infer_args, true); - } - Ok(()) - })?; + let generic_args = segment.generic_args(); + if !generic_args.args.is_empty() || !generic_args.bindings.is_empty() { + self.print_generic_args(generic_args, segment.infer_args, true)?; + } + self.print_call_post(base_args) } @@ -1559,11 +1558,9 @@ impl<'a> State<'a> { self.s.word("::")? } if segment.ident.name != kw::PathRoot { - self.print_ident(segment.ident)?; - segment.with_generic_args(|generic_args| { - self.print_generic_args(generic_args, segment.infer_args, - colons_before_params) - })?; + self.print_ident(segment.ident)?; + self.print_generic_args(segment.generic_args(), segment.infer_args, + colons_before_params)?; } } @@ -1572,10 +1569,8 @@ impl<'a> State<'a> { pub fn print_path_segment(&mut self, segment: &hir::PathSegment) -> io::Result<()> { if segment.ident.name != kw::PathRoot { - self.print_ident(segment.ident)?; - segment.with_generic_args(|generic_args| { - self.print_generic_args(generic_args, segment.infer_args, false) - })?; + self.print_ident(segment.ident)?; + self.print_generic_args(segment.generic_args(), segment.infer_args, false)?; } Ok(()) } @@ -1600,11 +1595,9 @@ impl<'a> State<'a> { } if segment.ident.name != kw::PathRoot { self.print_ident(segment.ident)?; - segment.with_generic_args(|generic_args| { - self.print_generic_args(generic_args, - segment.infer_args, - colons_before_params) - })?; + self.print_generic_args(segment.generic_args(), + segment.infer_args, + colons_before_params)?; } } @@ -1612,11 +1605,9 @@ impl<'a> State<'a> { self.s.word("::")?; let item_segment = path.segments.last().unwrap(); self.print_ident(item_segment.ident)?; - item_segment.with_generic_args(|generic_args| { - self.print_generic_args(generic_args, - item_segment.infer_args, - colons_before_params) - }) + self.print_generic_args(item_segment.generic_args(), + item_segment.infer_args, + colons_before_params) } hir::QPath::TypeRelative(ref qself, ref item_segment) => { self.s.word("<")?; @@ -1624,11 +1615,9 @@ impl<'a> State<'a> { self.s.word(">")?; self.s.word("::")?; self.print_ident(item_segment.ident)?; - item_segment.with_generic_args(|generic_args| { - self.print_generic_args(generic_args, - item_segment.infer_args, - colons_before_params) - }) + self.print_generic_args(item_segment.generic_args(), + item_segment.infer_args, + colons_before_params) } } } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 8236cd1f73857..b6d123c72acd8 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -191,15 +191,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { item_segment: &hir::PathSegment) -> SubstsRef<'tcx> { - let (substs, assoc_bindings, _) = item_segment.with_generic_args(|generic_args| { - self.create_substs_for_ast_path( - span, - def_id, - generic_args, - item_segment.infer_args, - None, - ) - }); + let (substs, assoc_bindings, _) = self.create_substs_for_ast_path( + span, + def_id, + item_segment.generic_args(), + item_segment.infer_args, + None, + ); assoc_bindings.first().map(|b| Self::prohibit_assoc_ty_binding(self.tcx(), b.span)); @@ -874,8 +872,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let trait_def = self.tcx().trait_def(trait_def_id); if !self.tcx().features().unboxed_closures && - trait_segment.with_generic_args(|generic_args| generic_args.parenthesized) - != trait_def.paren_sugar { + trait_segment.generic_args().parenthesized != trait_def.paren_sugar + { // For now, require that parenthetical notation be used only with `Fn()` etc. let msg = if trait_def.paren_sugar { "the precise format of `Fn`-family traits' type parameters is subject to change. \ @@ -887,13 +885,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { span, GateIssue::Language, msg); } - trait_segment.with_generic_args(|generic_args| { - self.create_substs_for_ast_path(span, - trait_def_id, - generic_args, - trait_segment.infer_args, - Some(self_ty)) - }) + self.create_substs_for_ast_path(span, + trait_def_id, + trait_segment.generic_args(), + trait_segment.infer_args, + Some(self_ty)) } fn trait_defines_associated_type_named(&self, @@ -1765,47 +1761,45 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { &self, segments: T) -> bool { let mut has_err = false; for segment in segments { - segment.with_generic_args(|generic_args| { - let (mut err_for_lt, mut err_for_ty, mut err_for_ct) = (false, false, false); - for arg in &generic_args.args { - let (span, kind) = match arg { - hir::GenericArg::Lifetime(lt) => { - if err_for_lt { continue } - err_for_lt = true; - has_err = true; - (lt.span, "lifetime") - } - hir::GenericArg::Type(ty) => { - if err_for_ty { continue } - err_for_ty = true; - has_err = true; - (ty.span, "type") - } - hir::GenericArg::Const(ct) => { - if err_for_ct { continue } - err_for_ct = true; - (ct.span, "const") - } - }; - let mut err = struct_span_err!( - self.tcx().sess, - span, - E0109, - "{} arguments are not allowed for this type", - kind, - ); - err.span_label(span, format!("{} argument not allowed", kind)); - err.emit(); - if err_for_lt && err_for_ty && err_for_ct { - break; + let (mut err_for_lt, mut err_for_ty, mut err_for_ct) = (false, false, false); + for arg in &segment.generic_args().args { + let (span, kind) = match arg { + hir::GenericArg::Lifetime(lt) => { + if err_for_lt { continue } + err_for_lt = true; + has_err = true; + (lt.span, "lifetime") } - } - for binding in &generic_args.bindings { - has_err = true; - Self::prohibit_assoc_ty_binding(self.tcx(), binding.span); + hir::GenericArg::Type(ty) => { + if err_for_ty { continue } + err_for_ty = true; + has_err = true; + (ty.span, "type") + } + hir::GenericArg::Const(ct) => { + if err_for_ct { continue } + err_for_ct = true; + (ct.span, "const") + } + }; + let mut err = struct_span_err!( + self.tcx().sess, + span, + E0109, + "{} arguments are not allowed for this type", + kind, + ); + err.span_label(span, format!("{} argument not allowed", kind)); + err.emit(); + if err_for_lt && err_for_ty && err_for_ct { break; } - }) + } + for binding in &segment.generic_args().bindings { + has_err = true; + Self::prohibit_assoc_ty_binding(self.tcx(), binding.span); + break; + } } has_err } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 4becb42d30551..9968118d2ece1 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2809,7 +2809,8 @@ impl Clean for hir::Ty { let mut ty_substs = FxHashMap::default(); let mut lt_substs = FxHashMap::default(); let mut ct_substs = FxHashMap::default(); - provided_params.with_generic_args(|generic_args| { + let generic_args = provided_params.generic_args(); + { let mut indices: GenericParamCount = Default::default(); for param in generics.params.iter() { match param.kind { @@ -2884,7 +2885,7 @@ impl Clean for hir::Ty { } } } - }); + } return cx.enter_alias(ty_substs, lt_substs, ct_substs, || ty.clean(cx)); } resolve_type(cx, path.clean(cx), self.hir_id) @@ -3537,7 +3538,7 @@ impl Clean for hir::PathSegment { fn clean(&self, cx: &DocContext<'_>) -> PathSegment { PathSegment { name: self.ident.name.clean(cx), - args: self.with_generic_args(|generic_args| generic_args.clean(cx)) + args: self.generic_args().clean(cx), } } } diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 55db8da327673..337b84247361d 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -12,6 +12,8 @@ #![deny(unused_lifetimes)] #![feature(bind_by_move_pattern_guards)] +#![feature(const_fn)] +#![feature(const_transmute)] #![feature(crate_visibility_modifier)] #![feature(label_break_value)] #![feature(nll)] diff --git a/src/libsyntax/ptr.rs b/src/libsyntax/ptr.rs index d577243fb3dcd..f0cfa5a84a827 100644 --- a/src/libsyntax/ptr.rs +++ b/src/libsyntax/ptr.rs @@ -133,8 +133,15 @@ impl Encodable for P { } impl P<[T]> { - pub fn new() -> P<[T]> { - P { ptr: Default::default() } + pub const fn new() -> P<[T]> { + // HACK(eddyb) bypass the lack of a `const fn` to create an empty `Box<[T]>` + // (as trait methods, `default` in this case, can't be `const fn` yet). + P { + ptr: unsafe { + use std::ptr::NonNull; + std::mem::transmute(NonNull::<[T; 0]>::dangling() as NonNull<[T]>) + }, + } } #[inline(never)] From 673c3fc23ad0c78fe26420b641957e4fdfea553b Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 12 Jun 2019 11:43:15 +0300 Subject: [PATCH 9/9] rustc: disallow cloning HIR nodes. --- src/librustc/hir/lowering.rs | 103 ++++---- src/librustc/hir/map/mod.rs | 10 +- src/librustc/hir/mod.rs | 170 ++++++------ src/librustc/hir/print.rs | 61 ++--- src/librustc/traits/error_reporting.rs | 4 +- .../borrow_check/conflict_errors.rs | 4 +- src/librustc_typeck/astconv.rs | 26 +- src/librustc_typeck/check/mod.rs | 14 +- src/librustc_typeck/collect.rs | 20 +- src/librustdoc/clean/mod.rs | 93 +++---- src/librustdoc/doctree.rs | 202 ++++++++------- src/librustdoc/visit_ast.rs | 243 +++++++++--------- 12 files changed, 476 insertions(+), 474 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 996af3672e8bd..c87ab68693726 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -608,15 +608,7 @@ impl<'a> LoweringContext<'a> { }); if let Some(hir_id) = item_hir_id { - let item_generics = match self.lctx.items.get(&hir_id).unwrap().node { - hir::ItemKind::Impl(_, _, _, ref generics, ..) - | hir::ItemKind::Trait(_, _, ref generics, ..) => { - generics.params.clone() - } - _ => HirVec::new(), - }; - - self.lctx.with_parent_impl_lifetime_defs(&item_generics, |this| { + self.lctx.with_parent_item_lifetime_defs(hir_id, |this| { let this = &mut ItemLowerer { lctx: this }; if let ItemKind::Impl(.., ref opt_trait_ref, _, _) = item.node { this.with_trait_impl_ref(opt_trait_ref, |this| { @@ -1054,14 +1046,22 @@ impl<'a> LoweringContext<'a> { // This should only be used with generics that have already had their // in-band lifetimes added. In practice, this means that this function is // only used when lowering a child item of a trait or impl. - fn with_parent_impl_lifetime_defs(&mut self, - params: &HirVec, + fn with_parent_item_lifetime_defs(&mut self, + parent_hir_id: hir::HirId, f: F ) -> T where F: FnOnce(&mut LoweringContext<'_>) -> T, { let old_len = self.in_scope_lifetimes.len(); - let lt_def_names = params.iter().filter_map(|param| match param.kind { + + let parent_generics = match self.items.get(&parent_hir_id).unwrap().node { + hir::ItemKind::Impl(_, _, _, ref generics, ..) + | hir::ItemKind::Trait(_, _, ref generics, ..) => { + &generics.params[..] + } + _ => &[], + }; + let lt_def_names = parent_generics.iter().filter_map(|param| match param.kind { hir::GenericParamKind::Lifetime { .. } => Some(param.name.ident().modern()), _ => None, }); @@ -1113,8 +1113,7 @@ impl<'a> LoweringContext<'a> { lowered_generics.params = lowered_generics .params - .iter() - .cloned() + .into_iter() .chain(in_band_defs) .collect(); @@ -3114,8 +3113,8 @@ impl<'a> LoweringContext<'a> { &NodeMap::default(), itctx.reborrow(), ); - let trait_ref = self.with_parent_impl_lifetime_defs( - &bound_generic_params, + let trait_ref = self.with_in_scope_lifetime_defs( + &p.bound_generic_params, |this| this.lower_trait_ref(&p.trait_ref, itctx), ); @@ -3602,8 +3601,7 @@ impl<'a> LoweringContext<'a> { // Essentially a single `use` which imports two names is desugared into // two imports. for (res, &new_node_id) in resolutions.zip([id1, id2].iter()) { - let vis = vis.clone(); - let ident = ident.clone(); + let ident = *ident; let mut path = path.clone(); for seg in &mut path.segments { seg.id = self.sess.next_node_id(); @@ -3616,19 +3614,7 @@ impl<'a> LoweringContext<'a> { let path = this.lower_path_extra(res, &path, ParamMode::Explicit, None); let item = hir::ItemKind::Use(P(path), hir::UseKind::Single); - let vis_kind = match vis.node { - hir::VisibilityKind::Public => hir::VisibilityKind::Public, - hir::VisibilityKind::Crate(sugar) => hir::VisibilityKind::Crate(sugar), - hir::VisibilityKind::Inherited => hir::VisibilityKind::Inherited, - hir::VisibilityKind::Restricted { ref path, hir_id: _ } => { - let path = this.renumber_segment_ids(path); - hir::VisibilityKind::Restricted { - path, - hir_id: this.next_id(), - } - } - }; - let vis = respan(vis.span, vis_kind); + let vis = this.rebuild_vis(&vis); this.insert_item( hir::Item { @@ -3692,8 +3678,6 @@ impl<'a> LoweringContext<'a> { for &(ref use_tree, id) in trees { let new_hir_id = self.lower_node_id(id); - let mut vis = vis.clone(); - let mut ident = ident.clone(); let mut prefix = prefix.clone(); // Give the segments new node-ids since they are being cloned. @@ -3707,6 +3691,9 @@ impl<'a> LoweringContext<'a> { // own its own names, we have to adjust the owner before // lowering the rest of the import. self.with_hir_id_owner(id, |this| { + let mut vis = this.rebuild_vis(&vis); + let mut ident = *ident; + let item = this.lower_use_tree(use_tree, &prefix, id, @@ -3714,20 +3701,6 @@ impl<'a> LoweringContext<'a> { &mut ident, attrs); - let vis_kind = match vis.node { - hir::VisibilityKind::Public => hir::VisibilityKind::Public, - hir::VisibilityKind::Crate(sugar) => hir::VisibilityKind::Crate(sugar), - hir::VisibilityKind::Inherited => hir::VisibilityKind::Inherited, - hir::VisibilityKind::Restricted { ref path, hir_id: _ } => { - let path = this.renumber_segment_ids(path); - hir::VisibilityKind::Restricted { - path: path, - hir_id: this.next_id(), - } - } - }; - let vis = respan(vis.span, vis_kind); - this.insert_item( hir::Item { hir_id: new_hir_id, @@ -3773,15 +3746,35 @@ impl<'a> LoweringContext<'a> { /// Paths like the visibility path in `pub(super) use foo::{bar, baz}` are repeated /// many times in the HIR tree; for each occurrence, we need to assign distinct /// `NodeId`s. (See, e.g., #56128.) - fn renumber_segment_ids(&mut self, path: &P) -> P { - debug!("renumber_segment_ids(path = {:?})", path); - let mut path = path.clone(); - for seg in path.segments.iter_mut() { - if seg.hir_id.is_some() { - seg.hir_id = Some(self.next_id()); - } + fn rebuild_use_path(&mut self, path: &hir::Path) -> hir::Path { + debug!("rebuild_use_path(path = {:?})", path); + let segments = path.segments.iter().map(|seg| hir::PathSegment { + ident: seg.ident, + hir_id: seg.hir_id.map(|_| self.next_id()), + res: seg.res, + args: None, + infer_args: seg.infer_args, + }).collect(); + hir::Path { + span: path.span, + res: path.res, + segments, } - path + } + + fn rebuild_vis(&mut self, vis: &hir::Visibility) -> hir::Visibility { + let vis_kind = match vis.node { + hir::VisibilityKind::Public => hir::VisibilityKind::Public, + hir::VisibilityKind::Crate(sugar) => hir::VisibilityKind::Crate(sugar), + hir::VisibilityKind::Inherited => hir::VisibilityKind::Inherited, + hir::VisibilityKind::Restricted { ref path, hir_id: _ } => { + hir::VisibilityKind::Restricted { + path: P(self.rebuild_use_path(path)), + hir_id: self.next_id(), + } + } + }; + respan(vis.span, vis_kind) } fn lower_trait_item(&mut self, i: &TraitItem) -> hir::TraitItem { diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 85c86991f489a..87da3273bd220 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -51,11 +51,11 @@ impl<'hir> Entry<'hir> { } } - fn fn_decl(&self) -> Option<&FnDecl> { + fn fn_decl(&self) -> Option<&'hir FnDecl> { match self.node { Node::Item(ref item) => { match item.node { - ItemKind::Fn(ref fn_decl, _, _, _) => Some(&fn_decl), + ItemKind::Fn(ref fn_decl, _, _, _) => Some(fn_decl), _ => None, } } @@ -76,7 +76,7 @@ impl<'hir> Entry<'hir> { Node::Expr(ref expr) => { match expr.node { - ExprKind::Closure(_, ref fn_decl, ..) => Some(&fn_decl), + ExprKind::Closure(_, ref fn_decl, ..) => Some(fn_decl), _ => None, } } @@ -412,9 +412,9 @@ impl<'hir> Map<'hir> { self.forest.krate.body(id) } - pub fn fn_decl_by_hir_id(&self, hir_id: HirId) -> Option { + pub fn fn_decl_by_hir_id(&self, hir_id: HirId) -> Option<&'hir FnDecl> { if let Some(entry) = self.find_entry(hir_id) { - entry.fn_decl().cloned() + entry.fn_decl() } else { bug!("no entry for hir_id `{}`", hir_id) } diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index de8c75345fee4..2b46170a6d232 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -155,7 +155,7 @@ pub const DUMMY_HIR_ID: HirId = HirId { pub const DUMMY_ITEM_LOCAL_ID: ItemLocalId = ItemLocalId::MAX; -#[derive(Clone, RustcEncodable, RustcDecodable, Copy, HashStable)] +#[derive(Copy, Clone, RustcEncodable, RustcDecodable, HashStable)] pub struct Lifetime { pub hir_id: HirId, pub span: Span, @@ -295,7 +295,7 @@ impl Lifetime { /// A `Path` is essentially Rust's notion of a name; for instance, /// `std::cmp::PartialEq`. It's represented as a sequence of identifiers, /// along with a bunch of supporting information. -#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)] +#[derive(RustcEncodable, RustcDecodable, HashStable)] pub struct Path { pub span: Span, /// The resolution for the path. @@ -324,7 +324,7 @@ impl fmt::Display for Path { /// A segment of a path: an identifier, an optional lifetime, and a set of /// types. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] +#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] pub struct PathSegment { /// The identifier portion of this path segment. #[stable_hasher(project(name))] @@ -393,13 +393,13 @@ impl PathSegment { } } -#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] +#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] pub struct ConstArg { pub value: AnonConst, pub span: Span, } -#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] +#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] pub enum GenericArg { Lifetime(Lifetime), Type(Ty), @@ -431,7 +431,7 @@ impl GenericArg { } } -#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] +#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] pub struct GenericArgs { /// The generic arguments for this path segment. pub args: HirVec, @@ -505,7 +505,7 @@ pub enum TraitBoundModifier { /// `typeck::collect::compute_bounds` matches these against /// the "special" built-in traits (see `middle::lang_items`) and /// detects `Copy`, `Send` and `Sync`. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] +#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] pub enum GenericBound { Trait(PolyTraitRef, TraitBoundModifier), Outlives(Lifetime), @@ -541,7 +541,7 @@ pub enum LifetimeParamKind { Error, } -#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] +#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] pub enum GenericParamKind { /// A lifetime definition (e.g., `'a: 'b + 'c + 'd`). Lifetime { @@ -556,7 +556,7 @@ pub enum GenericParamKind { } } -#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] +#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] pub struct GenericParam { pub hir_id: HirId, pub name: ParamName, @@ -576,7 +576,7 @@ pub struct GenericParamCount { /// Represents lifetimes and type parameters attached to a declaration /// of a function, enum, trait, etc. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] +#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] pub struct Generics { pub params: HirVec, pub where_clause: WhereClause, @@ -584,7 +584,7 @@ pub struct Generics { } impl Generics { - pub fn empty() -> Generics { + pub const fn empty() -> Generics { Generics { params: HirVec::new(), where_clause: WhereClause { @@ -638,7 +638,7 @@ pub enum SyntheticTyParamKind { } /// A where-clause in a definition. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] +#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] pub struct WhereClause { pub predicates: HirVec, // Only valid if predicates isn't empty. @@ -656,7 +656,7 @@ impl WhereClause { } /// A single predicate in a where-clause. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] +#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] pub enum WherePredicate { /// A type binding (e.g., `for<'c> Foo: Send + Clone + 'c`). BoundPredicate(WhereBoundPredicate), @@ -677,7 +677,7 @@ impl WherePredicate { } /// A type bound (e.g., `for<'c> Foo: Send + Clone + 'c`). -#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] +#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] pub struct WhereBoundPredicate { pub span: Span, /// Any generics from a `for` binding. @@ -689,7 +689,7 @@ pub struct WhereBoundPredicate { } /// A lifetime predicate (e.g., `'a: 'b + 'c`). -#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] +#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] pub struct WhereRegionPredicate { pub span: Span, pub lifetime: Lifetime, @@ -697,7 +697,7 @@ pub struct WhereRegionPredicate { } /// An equality predicate (e.g., `T = int`); currently unsupported. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] +#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] pub struct WhereEqPredicate { pub hir_id: HirId, pub span: Span, @@ -705,7 +705,7 @@ pub struct WhereEqPredicate { pub rhs_ty: P, } -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +#[derive(RustcEncodable, RustcDecodable, Debug)] pub struct ModuleItems { // Use BTreeSets here so items are in the same order as in the // list of all items in Crate @@ -720,7 +720,7 @@ pub struct ModuleItems { /// For more details, see the [rustc guide]. /// /// [rustc guide]: https://rust-lang.github.io/rustc-guide/hir.html -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +#[derive(RustcEncodable, RustcDecodable, Debug)] pub struct Crate { pub module: Mod, pub attrs: HirVec, @@ -815,7 +815,7 @@ impl Crate { /// A macro definition, in this crate or imported from another. /// /// Not parsed directly, but created on macro import or `macro_rules!` expansion. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] +#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] pub struct MacroDef { pub name: Name, pub vis: Visibility, @@ -829,7 +829,7 @@ pub struct MacroDef { /// A block of statements `{ .. }`, which may have a label (in this case the /// `targeted_by_break` field will be `true`) and may be `unsafe` by means of /// the `rules` being anything but `DefaultBlock`. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] +#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] pub struct Block { /// Statements in a block. pub stmts: HirVec, @@ -847,7 +847,7 @@ pub struct Block { pub targeted_by_break: bool, } -#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)] +#[derive(RustcEncodable, RustcDecodable, HashStable)] pub struct Pat { #[stable_hasher(ignore)] pub hir_id: HirId, @@ -910,7 +910,7 @@ impl Pat { /// Patterns like the fields of Foo `{ x, ref y, ref mut z }` /// are treated the same as` x: x, y: ref y, z: ref mut z`, /// except `is_shorthand` is true. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] +#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] pub struct FieldPat { #[stable_hasher(ignore)] pub hir_id: HirId, @@ -925,7 +925,7 @@ pub struct FieldPat { /// Explicit binding annotations given in the HIR for a binding. Note /// that this is not the final binding *mode* that we infer after type /// inference. -#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy, HashStable)] +#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable)] pub enum BindingAnnotation { /// No binding annotation given: this means that the final binding mode /// will depend on whether we have skipped through a `&` reference @@ -952,7 +952,7 @@ pub enum RangeEnd { Excluded, } -#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] +#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] pub enum PatKind { /// Represents a wildcard pattern (i.e., `_`). Wild, @@ -997,8 +997,8 @@ pub enum PatKind { Slice(HirVec>, Option>, HirVec>), } -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, HashStable, - RustcEncodable, RustcDecodable, Hash, Debug, Copy)] +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, HashStable, + RustcEncodable, RustcDecodable, Hash, Debug)] pub enum Mutability { MutMutable, MutImmutable, @@ -1014,7 +1014,7 @@ impl Mutability { } } -#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy, Hash, HashStable)] +#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Hash, HashStable)] pub enum BinOpKind { /// The `+` operator (addition). Add, @@ -1148,7 +1148,7 @@ impl Into for BinOpKind { pub type BinOp = Spanned; -#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy, Hash, HashStable)] +#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Hash, HashStable)] pub enum UnOp { /// The `*` operator (deferencing). UnDeref, @@ -1177,7 +1177,7 @@ impl UnOp { } /// A statement. -#[derive(Clone, RustcEncodable, RustcDecodable)] +#[derive(RustcEncodable, RustcDecodable)] pub struct Stmt { pub hir_id: HirId, pub node: StmtKind, @@ -1192,7 +1192,7 @@ impl fmt::Debug for Stmt { } /// The contents of a statement. -#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)] +#[derive(RustcEncodable, RustcDecodable, HashStable)] pub enum StmtKind { /// A local (`let`) binding. Local(P), @@ -1219,7 +1219,7 @@ impl StmtKind { } /// Represents a `let` statement (i.e., `let : = ;`). -#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] +#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] pub struct Local { pub pat: P, /// Type annotation, if any (otherwise the type will be inferred). @@ -1236,7 +1236,7 @@ pub struct Local { /// Represents a single arm of a `match` expression, e.g. /// ` (if ) => `. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] +#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] pub struct Arm { #[stable_hasher(ignore)] pub hir_id: HirId, @@ -1250,12 +1250,12 @@ pub struct Arm { pub body: P, } -#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] +#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] pub enum Guard { If(P), } -#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] +#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] pub struct Field { #[stable_hasher(ignore)] pub hir_id: HirId, @@ -1265,7 +1265,7 @@ pub struct Field { pub is_shorthand: bool, } -#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy, HashStable)] +#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable)] pub enum BlockCheckMode { DefaultBlock, UnsafeBlock(UnsafeSource), @@ -1273,7 +1273,7 @@ pub enum BlockCheckMode { PopUnsafeBlock(UnsafeSource), } -#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy, HashStable)] +#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable)] pub enum UnsafeSource { CompilerGenerated, UserProvided, @@ -1305,7 +1305,7 @@ pub struct BodyId { /// /// All bodies have an **owner**, which can be accessed via the HIR /// map using `body_owner_def_id()`. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +#[derive(RustcEncodable, RustcDecodable, Debug)] pub struct Body { pub arguments: HirVec, pub value: Expr, @@ -1379,7 +1379,7 @@ pub struct AnonConst { } /// An expression -#[derive(Clone, RustcEncodable, RustcDecodable)] +#[derive(RustcEncodable, RustcDecodable)] pub struct Expr { pub span: Span, pub node: ExprKind, @@ -1490,7 +1490,7 @@ impl fmt::Debug for Expr { } } -#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] +#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] pub enum ExprKind { /// A `box x` expression. Box(P), @@ -1598,7 +1598,7 @@ pub enum ExprKind { } /// Represents an optionally `Self`-qualified value/type path or associated extension. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] +#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] pub enum QPath { /// Path to a definition, optionally "fully-qualified" with a `Self` /// type, if the path points to an associated item in a trait. @@ -1618,7 +1618,7 @@ pub enum QPath { } /// Hints at the original code for a let statement. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy, HashStable)] +#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] pub enum LocalSource { /// A `match _ { .. }`. Normal, @@ -1640,7 +1640,7 @@ pub enum LocalSource { } /// Hints at the original code for a `match _ { .. }`. -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy, HashStable)] +#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)] pub enum MatchSource { /// A `match _ { .. }`. Normal, @@ -1664,7 +1664,7 @@ pub enum MatchSource { } /// The loop type that yielded an `ExprKind::Loop`. -#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy, HashStable)] +#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable)] pub enum LoopSource { /// A `loop { .. }` loop. Loop, @@ -1674,7 +1674,7 @@ pub enum LoopSource { ForLoop, } -#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy, HashStable)] +#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] pub enum LoopIdError { OutsideLoopScope, UnlabeledCfInWhileCondition, @@ -1692,7 +1692,7 @@ impl fmt::Display for LoopIdError { } } -#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy, HashStable)] +#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] pub struct Destination { // This is `Some(_)` iff there is an explicit user-specified `label pub label: Option