From 3b229f144160067409dd9d321748ab7ae77bd99c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 27 Jul 2019 11:02:52 +0200 Subject: [PATCH 01/35] check that ptr is valid already when doing Deref, not only when doing the access --- src/librustc_mir/interpret/place.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 8fe882934dfb5..e90fc28a521b6 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -304,7 +304,16 @@ where ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> { let val = self.read_immediate(src)?; trace!("deref to {} on {:?}", val.layout.ty, *val); - self.ref_to_mplace(val) + let mut place = self.ref_to_mplace(val)?; + let (size, align) = self.size_and_align_of_mplace(place)? + .unwrap_or((place.layout.size, place.layout.align.abi)); + assert!(place.mplace.align <= align, "dynamic alignment less strict than static one?"); + place.mplace.align = align; // maximally strict checking + // When dereferencing a pointer, it must be non-NULL, aligned, and live. + if let Some(ptr) = self.check_mplace_access(place, Some(size))? { + place.mplace.ptr = ptr.into(); + } + Ok(place) } /// Check if the given place is good for memory access with the given From 5800bec22363615fe7a3b55b8e15a28dc51f687b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 28 Jul 2019 12:10:29 +0200 Subject: [PATCH 02/35] discourage use of ref_to_mplace --- src/librustc_mir/interpret/place.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index e90fc28a521b6..d0670f64ed8da 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -277,6 +277,10 @@ where { /// Take a value, which represents a (thin or fat) reference, and make it a place. /// Alignment is just based on the type. This is the inverse of `MemPlace::to_ref()`. + /// + /// Only call this if you are sure the place is "valid" (aligned and inbounds), or do not + /// want to ever use the place for memory access! + /// Generally prefer `deref_operand`. pub fn ref_to_mplace( &self, val: ImmTy<'tcx, M::PointerTag>, From 3677c5be56168508fea082e1651c774e34600ca8 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 28 Jul 2019 12:29:20 +0200 Subject: [PATCH 03/35] the alignment checks on access can no longer fail now --- src/librustc_mir/interpret/operand.rs | 4 +++- src/librustc_mir/interpret/place.rs | 10 +++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 1816171d7b127..974481a993c67 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -238,7 +238,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { return Ok(None); } - let ptr = match self.check_mplace_access(mplace, None)? { + let ptr = match self.check_mplace_access(mplace, None) + .expect("places should be checked on creation") + { Some(ptr) => ptr, None => return Ok(Some(ImmTy { // zero-sized type imm: Immediate::Scalar(Scalar::zst().into()), diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index d0670f64ed8da..1588ed35b13f2 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -763,7 +763,9 @@ where // to handle padding properly, which is only correct if we never look at this data with the // wrong type. - let ptr = match self.check_mplace_access(dest, None)? { + let ptr = match self.check_mplace_access(dest, None) + .expect("places should be checked on creation") + { Some(ptr) => ptr, None => return Ok(()), // zero-sized access }; @@ -866,8 +868,10 @@ where }); assert_eq!(src.meta, dest.meta, "Can only copy between equally-sized instances"); - let src = self.check_mplace_access(src, Some(size))?; - let dest = self.check_mplace_access(dest, Some(size))?; + let src = self.check_mplace_access(src, Some(size)) + .expect("places should be checked on creation"); + let dest = self.check_mplace_access(dest, Some(size)) + .expect("places should be checked on creation"); let (src_ptr, dest_ptr) = match (src, dest) { (Some(src_ptr), Some(dest_ptr)) => (src_ptr, dest_ptr), (None, None) => return Ok(()), // zero-sized copy From e4c39e1bc28185cc85511baa4bd4fd8b2fe29aa1 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 28 Jul 2019 14:19:13 +0200 Subject: [PATCH 04/35] better name for check_in_alloc --- src/librustc/mir/interpret/pointer.rs | 5 ++++- src/librustc_mir/interpret/memory.rs | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/librustc/mir/interpret/pointer.rs b/src/librustc/mir/interpret/pointer.rs index 0e3b8459115e3..fceae75d72421 100644 --- a/src/librustc/mir/interpret/pointer.rs +++ b/src/librustc/mir/interpret/pointer.rs @@ -191,8 +191,11 @@ impl<'tcx, Tag> Pointer { Pointer { alloc_id: self.alloc_id, offset: self.offset, tag: () } } + /// Test if the pointer is "inbounds" of an allocation of the given size. + /// A pointer is "inbounds" even if its offset is equal to the size; this is + /// a "one-past-the-end" pointer. #[inline(always)] - pub fn check_in_alloc( + pub fn check_inbounds_alloc( self, allocation_size: Size, msg: CheckInAllocMsg, diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 4575784ac3703..ad1ec5a11ed6c 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -357,7 +357,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // It is sufficient to check this for the end pointer. The addition // checks for overflow. let end_ptr = ptr.offset(size, self)?; - end_ptr.check_in_alloc(allocation_size, CheckInAllocMsg::MemoryAccessTest)?; + end_ptr.check_inbounds_alloc(allocation_size, CheckInAllocMsg::MemoryAccessTest)?; // Test align. Check this last; if both bounds and alignment are violated // we want the error to be about the bounds. if alloc_align.bytes() < align.bytes() { @@ -387,7 +387,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { ) -> bool { let (size, _align) = self.get_size_and_align(ptr.alloc_id, AllocCheck::MaybeDead) .expect("alloc info with MaybeDead cannot fail"); - ptr.check_in_alloc(size, CheckInAllocMsg::NullPointerTest).is_err() + ptr.check_inbounds_alloc(size, CheckInAllocMsg::NullPointerTest).is_err() } } From 388d99d3a555e8c47c9465b896966298d11dc43f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 28 Jul 2019 14:25:04 +0200 Subject: [PATCH 05/35] fix tests --- src/test/ui/consts/const-eval/ub-nonnull.rs | 7 +++-- .../ui/consts/const-eval/ub-nonnull.stderr | 29 +++++++++++-------- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/src/test/ui/consts/const-eval/ub-nonnull.rs b/src/test/ui/consts/const-eval/ub-nonnull.rs index bcbb4358aec03..431ff356ade19 100644 --- a/src/test/ui/consts/const-eval/ub-nonnull.rs +++ b/src/test/ui/consts/const-eval/ub-nonnull.rs @@ -11,10 +11,11 @@ const NON_NULL_PTR: NonNull = unsafe { mem::transmute(&1) }; const NULL_PTR: NonNull = unsafe { mem::transmute(0usize) }; //~^ ERROR it is undefined behavior to use this value +#[deny(const_err)] // this triggers a `const_err` so validation does not even happen const OUT_OF_BOUNDS_PTR: NonNull = { unsafe { -//~^ ERROR it is undefined behavior to use this value - let ptr: &(u8, u8, u8) = mem::transmute(&0u8); // &0 gets promoted so it does not dangle - let out_of_bounds_ptr = &ptr.2; // use address-of-field for pointer arithmetic + let ptr: &[u8; 256] = mem::transmute(&0u8); // &0 gets promoted so it does not dangle + // Use address-of-element for pointer arithmetic. This could wrap around to NULL! + let out_of_bounds_ptr = &ptr[255]; //~ ERROR any use of this value will cause an error mem::transmute(out_of_bounds_ptr) } }; diff --git a/src/test/ui/consts/const-eval/ub-nonnull.stderr b/src/test/ui/consts/const-eval/ub-nonnull.stderr index 2f9423fed3530..7b3c97e5fbf96 100644 --- a/src/test/ui/consts/const-eval/ub-nonnull.stderr +++ b/src/test/ui/consts/const-eval/ub-nonnull.stderr @@ -6,21 +6,26 @@ LL | const NULL_PTR: NonNull = unsafe { mem::transmute(0usize) }; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior -error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-nonnull.rs:14:1 +error: any use of this value will cause an error + --> $DIR/ub-nonnull.rs:18:29 | LL | / const OUT_OF_BOUNDS_PTR: NonNull = { unsafe { -LL | | -LL | | let ptr: &(u8, u8, u8) = mem::transmute(&0u8); // &0 gets promoted so it does not dangle -LL | | let out_of_bounds_ptr = &ptr.2; // use address-of-field for pointer arithmetic +LL | | let ptr: &[u8; 256] = mem::transmute(&0u8); // &0 gets promoted so it does not dangle +LL | | // Use address-of-element for pointer arithmetic. This could wrap around to NULL! +LL | | let out_of_bounds_ptr = &ptr[255]; + | | ^^^^^^^^^ Memory access failed: pointer must be in-bounds at offset 256, but is outside bounds of allocation 6 which has size 1 LL | | mem::transmute(out_of_bounds_ptr) LL | | } }; - | |____^ type validation failed: encountered a potentially NULL pointer, but expected something that cannot possibly fail to be greater or equal to 1 + | |____- | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior +note: lint level defined here + --> $DIR/ub-nonnull.rs:14:8 + | +LL | #[deny(const_err)] // this triggers a `const_err` so validation does not even happen + | ^^^^^^^^^ error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-nonnull.rs:21:1 + --> $DIR/ub-nonnull.rs:22:1 | LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1 @@ -28,7 +33,7 @@ LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-nonnull.rs:23:1 + --> $DIR/ub-nonnull.rs:24:1 | LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1 @@ -36,7 +41,7 @@ LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-nonnull.rs:30:1 + --> $DIR/ub-nonnull.rs:31:1 | LL | const UNINIT: NonZeroU8 = unsafe { Transmute { uninit: () }.out }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected something greater or equal to 1 @@ -44,7 +49,7 @@ LL | const UNINIT: NonZeroU8 = unsafe { Transmute { uninit: () }.out }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-nonnull.rs:38:1 + --> $DIR/ub-nonnull.rs:39:1 | LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 42, but expected something in the range 10..=30 @@ -52,7 +57,7 @@ LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-nonnull.rs:44:1 + --> $DIR/ub-nonnull.rs:45:1 | LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 20, but expected something less or equal to 10, or greater or equal to 30 From 74fbdb6eb8826c2a6627b666091a16691637832d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 28 Jul 2019 22:41:52 +0200 Subject: [PATCH 06/35] move 'get me the access-checked version of an mplace' into separate function --- src/librustc_mir/interpret/place.rs | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 1588ed35b13f2..d35f9127da40c 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -308,16 +308,8 @@ where ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> { let val = self.read_immediate(src)?; trace!("deref to {} on {:?}", val.layout.ty, *val); - let mut place = self.ref_to_mplace(val)?; - let (size, align) = self.size_and_align_of_mplace(place)? - .unwrap_or((place.layout.size, place.layout.align.abi)); - assert!(place.mplace.align <= align, "dynamic alignment less strict than static one?"); - place.mplace.align = align; // maximally strict checking - // When dereferencing a pointer, it must be non-NULL, aligned, and live. - if let Some(ptr) = self.check_mplace_access(place, Some(size))? { - place.mplace.ptr = ptr.into(); - } - Ok(place) + let place = self.ref_to_mplace(val)?; + self.mplace_access_checked(place) } /// Check if the given place is good for memory access with the given @@ -340,6 +332,23 @@ where self.memory.check_ptr_access(place.ptr, size, place.align) } + /// Return the "access-checked" version of this `MPlace`, where for non-ZST + /// this is definitely a `Pointer`. + pub fn mplace_access_checked( + &self, + mut place: MPlaceTy<'tcx, M::PointerTag>, + ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> { + let (size, align) = self.size_and_align_of_mplace(place)? + .unwrap_or((place.layout.size, place.layout.align.abi)); + assert!(place.mplace.align <= align, "dynamic alignment less strict than static one?"); + place.mplace.align = align; // maximally strict checking + // When dereferencing a pointer, it must be non-NULL, aligned, and live. + if let Some(ptr) = self.check_mplace_access(place, Some(size))? { + place.mplace.ptr = ptr.into(); + } + Ok(place) + } + /// Force `place.ptr` to a `Pointer`. /// Can be helpful to avoid lots of `force_ptr` calls later, if this place is used a lot. pub fn force_mplace_ptr( From 647c0e06365aa4570870e78d3b29c2a8fffc0089 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 28 Jul 2019 22:57:50 +0200 Subject: [PATCH 07/35] 'Ref' can now be sure it gets a 'Pointer' --- src/librustc_mir/interpret/step.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs index 246c90ba48e3a..e7876c9dee904 100644 --- a/src/librustc_mir/interpret/step.rs +++ b/src/librustc_mir/interpret/step.rs @@ -240,8 +240,12 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Ref(_, _, ref place) => { let src = self.eval_place(place)?; - let val = self.force_allocation(src)?; - self.write_immediate(val.to_ref(), dest)?; + let place = self.force_allocation(src)?; + if place.layout.size.bytes() > 0 { + // definitely not a ZST + assert!(place.ptr.is_ptr(), "non-ZST places should be normalized to `Pointer`"); + } + self.write_immediate(place.to_ref(), dest)?; } NullaryOp(mir::NullOp::Box, _) => { From a4af9d1ac25113362898ca598556db5eaa3d8f31 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 12 Aug 2019 07:34:08 +0200 Subject: [PATCH 08/35] parse_pat_with_range_pat: remove unnecessary assignments. --- src/libsyntax/parse/parser/pat.rs | 54 ++++++++++++++----------------- 1 file changed, 25 insertions(+), 29 deletions(-) diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index 5cc428a4df1de..21b38751831b9 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -108,8 +108,7 @@ impl<'a> Parser<'a> { maybe_whole!(self, NtPat, |x| x); let lo = self.token.span; - let pat; - match self.token.kind { + let pat = match self.token.kind { token::BinOp(token::And) | token::AndAnd => { // Parse &pat / &mut pat self.expect_and()?; @@ -120,7 +119,7 @@ impl<'a> Parser<'a> { return Err(err); } let subpat = self.parse_pat_with_range_pat(false, expected)?; - pat = PatKind::Ref(subpat, mutbl); + PatKind::Ref(subpat, mutbl) } token::OpenDelim(token::Paren) => { // Parse a tuple or parenthesis pattern. @@ -128,41 +127,40 @@ impl<'a> Parser<'a> { // Here, `(pat,)` is a tuple pattern. // For backward compatibility, `(..)` is a tuple pattern as well. - pat = if fields.len() == 1 && !(trailing_comma || fields[0].is_rest()) { + if fields.len() == 1 && !(trailing_comma || fields[0].is_rest()) { PatKind::Paren(fields.into_iter().nth(0).unwrap()) } else { PatKind::Tuple(fields) - }; + } } token::OpenDelim(token::Bracket) => { // Parse `[pat, pat,...]` as a slice pattern. - let (slice, _) = self.parse_delim_comma_seq(token::Bracket, |p| p.parse_pat(None))?; - pat = PatKind::Slice(slice); + PatKind::Slice(self.parse_delim_comma_seq(token::Bracket, |p| p.parse_pat(None))?.0) } token::DotDot => { self.bump(); - pat = if self.is_pat_range_end_start() { + if self.is_pat_range_end_start() { // Parse `..42` for recovery. self.parse_pat_range_to(RangeEnd::Excluded, "..")? } else { // A rest pattern `..`. PatKind::Rest - }; + } } token::DotDotEq => { // Parse `..=42` for recovery. self.bump(); - pat = self.parse_pat_range_to(RangeEnd::Included(RangeSyntax::DotDotEq), "..=")?; + self.parse_pat_range_to(RangeEnd::Included(RangeSyntax::DotDotEq), "..=")? } token::DotDotDot => { // Parse `...42` for recovery. self.bump(); - pat = self.parse_pat_range_to(RangeEnd::Included(RangeSyntax::DotDotDot), "...")?; + self.parse_pat_range_to(RangeEnd::Included(RangeSyntax::DotDotDot), "...")? } // At this point, token != &, &&, (, [ _ => if self.eat_keyword(kw::Underscore) { // Parse _ - pat = PatKind::Wild; + PatKind::Wild } else if self.eat_keyword(kw::Mut) { // Parse mut ident @ pat / mut ref ident @ pat let mutref_span = self.prev_span.to(self.token.span); @@ -179,22 +177,20 @@ impl<'a> Parser<'a> { } else { BindingMode::ByValue(Mutability::Mutable) }; - pat = self.parse_pat_ident(binding_mode)?; + self.parse_pat_ident(binding_mode)? } else if self.eat_keyword(kw::Ref) { // Parse ref ident @ pat / ref mut ident @ pat let mutbl = self.parse_mutability(); - pat = self.parse_pat_ident(BindingMode::ByRef(mutbl))?; + self.parse_pat_ident(BindingMode::ByRef(mutbl))? } else if self.eat_keyword(kw::Box) { - // Parse box pat - let subpat = self.parse_pat_with_range_pat(false, None)?; - pat = PatKind::Box(subpat); + // Parse `box pat` + PatKind::Box(self.parse_pat_with_range_pat(false, None)?) } else if self.token.is_ident() && !self.token.is_reserved_ident() && self.parse_as_ident() { - // Parse ident @ pat + // Parse `ident @ pat` // This can give false positives and parse nullary enums, - // they are dealt with later in resolve - let binding_mode = BindingMode::ByValue(Mutability::Immutable); - pat = self.parse_pat_ident(binding_mode)?; + // they are dealt with later in resolve. + self.parse_pat_ident(BindingMode::ByValue(Mutability::Immutable))? } else if self.token.is_path_start() { // Parse pattern starting with a path let (qself, path) = if self.eat_lt() { @@ -216,7 +212,7 @@ impl<'a> Parser<'a> { delim, prior_type_ascription: self.last_type_ascription, }); - pat = PatKind::Mac(mac); + PatKind::Mac(mac) } token::DotDotDot | token::DotDotEq | token::DotDot => { let (end_kind, form) = match self.token.kind { @@ -232,7 +228,7 @@ impl<'a> Parser<'a> { let begin = self.mk_expr(span, ExprKind::Path(qself, path), ThinVec::new()); self.bump(); let end = self.parse_pat_range_end_opt(&begin, form)?; - pat = PatKind::Range(begin, end, respan(op_span, end_kind)); + PatKind::Range(begin, end, respan(op_span, end_kind)) } token::OpenDelim(token::Brace) => { if qself.is_some() { @@ -249,7 +245,7 @@ impl<'a> Parser<'a> { (vec![], true) }); self.bump(); - pat = PatKind::Struct(path, fields, etc); + PatKind::Struct(path, fields, etc) } token::OpenDelim(token::Paren) => { if qself.is_some() { @@ -260,9 +256,9 @@ impl<'a> Parser<'a> { } // Parse tuple struct or enum pattern let (fields, _) = self.parse_paren_comma_seq(|p| p.parse_pat(None))?; - pat = PatKind::TupleStruct(path, fields) + PatKind::TupleStruct(path, fields) } - _ => pat = PatKind::Path(qself, path), + _ => PatKind::Path(qself, path), } } else { // Try to parse everything else as literal with optional minus @@ -282,9 +278,9 @@ impl<'a> Parser<'a> { on a range-operator token") }; let end = self.parse_pat_range_end_opt(&begin, form)?; - pat = PatKind::Range(begin, end, respan(op_span, end_kind)) + PatKind::Range(begin, end, respan(op_span, end_kind)) } else { - pat = PatKind::Lit(begin); + PatKind::Lit(begin) } } Err(mut err) => { @@ -305,7 +301,7 @@ impl<'a> Parser<'a> { } } } - } + }; let pat = self.mk_pat(lo.to(self.prev_span), pat); let pat = self.maybe_recover_from_bad_qpath(pat, true)?; From 90793c0f126a9d5a0ffab297e9fef8bbbed6ae70 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 12 Aug 2019 07:37:08 +0200 Subject: [PATCH 09/35] extract parse_pat_deref --- src/libsyntax/parse/parser/pat.rs | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index 21b38751831b9..95678f9f7a147 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -109,18 +109,7 @@ impl<'a> Parser<'a> { let lo = self.token.span; let pat = match self.token.kind { - token::BinOp(token::And) | token::AndAnd => { - // Parse &pat / &mut pat - self.expect_and()?; - let mutbl = self.parse_mutability(); - if let token::Lifetime(name) = self.token.kind { - let mut err = self.fatal(&format!("unexpected lifetime `{}` in pattern", name)); - err.span_label(self.token.span, "unexpected lifetime"); - return Err(err); - } - let subpat = self.parse_pat_with_range_pat(false, expected)?; - PatKind::Ref(subpat, mutbl) - } + token::BinOp(token::And) | token::AndAnd => self.parse_pat_deref(expected)?, token::OpenDelim(token::Paren) => { // Parse a tuple or parenthesis pattern. let (fields, trailing_comma) = self.parse_paren_comma_seq(|p| p.parse_pat(None))?; @@ -332,6 +321,21 @@ impl<'a> Parser<'a> { Ok(pat) } + /// Parse `&pat` / `&mut pat`. + fn parse_pat_deref(&mut self, expected: Option<&'static str>) -> PResult<'a, PatKind> { + self.expect_and()?; + let mutbl = self.parse_mutability(); + + if let token::Lifetime(name) = self.token.kind { + let mut err = self.fatal(&format!("unexpected lifetime `{}` in pattern", name)); + err.span_label(self.token.span, "unexpected lifetime"); + return Err(err); + } + + let subpat = self.parse_pat_with_range_pat(false, expected)?; + Ok(PatKind::Ref(subpat, mutbl)) + } + // Helper function to decide whether to parse as ident binding // or to try to do something more complex like range patterns. fn parse_as_ident(&mut self) -> bool { From c69b3ede8a98b45633736f7a84757fe7f3b5a392 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 12 Aug 2019 07:41:50 +0200 Subject: [PATCH 10/35] extract parse_pat_tuple_or_parens --- src/libsyntax/parse/parser/pat.rs | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index 95678f9f7a147..b7e40969d3eb5 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -110,18 +110,7 @@ impl<'a> Parser<'a> { let lo = self.token.span; let pat = match self.token.kind { token::BinOp(token::And) | token::AndAnd => self.parse_pat_deref(expected)?, - token::OpenDelim(token::Paren) => { - // Parse a tuple or parenthesis pattern. - let (fields, trailing_comma) = self.parse_paren_comma_seq(|p| p.parse_pat(None))?; - - // Here, `(pat,)` is a tuple pattern. - // For backward compatibility, `(..)` is a tuple pattern as well. - if fields.len() == 1 && !(trailing_comma || fields[0].is_rest()) { - PatKind::Paren(fields.into_iter().nth(0).unwrap()) - } else { - PatKind::Tuple(fields) - } - } + token::OpenDelim(token::Paren) => self.parse_pat_tuple_or_parens()?, token::OpenDelim(token::Bracket) => { // Parse `[pat, pat,...]` as a slice pattern. PatKind::Slice(self.parse_delim_comma_seq(token::Bracket, |p| p.parse_pat(None))?.0) @@ -336,6 +325,19 @@ impl<'a> Parser<'a> { Ok(PatKind::Ref(subpat, mutbl)) } + /// Parse a tuple or parenthesis pattern. + fn parse_pat_tuple_or_parens(&mut self) -> PResult<'a, PatKind> { + let (fields, trailing_comma) = self.parse_paren_comma_seq(|p| p.parse_pat(None))?; + + // Here, `(pat,)` is a tuple pattern. + // For backward compatibility, `(..)` is a tuple pattern as well. + Ok(if fields.len() == 1 && !(trailing_comma || fields[0].is_rest()) { + PatKind::Paren(fields.into_iter().nth(0).unwrap()) + } else { + PatKind::Tuple(fields) + }) + } + // Helper function to decide whether to parse as ident binding // or to try to do something more complex like range patterns. fn parse_as_ident(&mut self) -> bool { From 3b651330e0ff4090f18fc834486a8f0a9aa62748 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 12 Aug 2019 07:45:55 +0200 Subject: [PATCH 11/35] extract recover_pat_ident_mut_first --- src/libsyntax/parse/parser/pat.rs | 36 +++++++++++++++++-------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index b7e40969d3eb5..1b6baf09d816b 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -140,22 +140,7 @@ impl<'a> Parser<'a> { // Parse _ PatKind::Wild } else if self.eat_keyword(kw::Mut) { - // Parse mut ident @ pat / mut ref ident @ pat - let mutref_span = self.prev_span.to(self.token.span); - let binding_mode = if self.eat_keyword(kw::Ref) { - self.diagnostic() - .struct_span_err(mutref_span, "the order of `mut` and `ref` is incorrect") - .span_suggestion( - mutref_span, - "try switching the order", - "ref mut".into(), - Applicability::MachineApplicable - ).emit(); - BindingMode::ByRef(Mutability::Mutable) - } else { - BindingMode::ByValue(Mutability::Mutable) - }; - self.parse_pat_ident(binding_mode)? + self.recover_pat_ident_mut_first()? } else if self.eat_keyword(kw::Ref) { // Parse ref ident @ pat / ref mut ident @ pat let mutbl = self.parse_mutability(); @@ -338,6 +323,25 @@ impl<'a> Parser<'a> { }) } + // Recover on `mut ref? ident @ pat` and suggest that the order of `mut` and `ref` is incorrect. + fn recover_pat_ident_mut_first(&mut self) -> PResult<'a, PatKind> { + let mutref_span = self.prev_span.to(self.token.span); + let binding_mode = if self.eat_keyword(kw::Ref) { + self.struct_span_err(mutref_span, "the order of `mut` and `ref` is incorrect") + .span_suggestion( + mutref_span, + "try switching the order", + "ref mut".into(), + Applicability::MachineApplicable + ) + .emit(); + BindingMode::ByRef(Mutability::Mutable) + } else { + BindingMode::ByValue(Mutability::Mutable) + }; + self.parse_pat_ident(binding_mode) + } + // Helper function to decide whether to parse as ident binding // or to try to do something more complex like range patterns. fn parse_as_ident(&mut self) -> bool { From 231da7e044255286ba92675e89ca168a4932452c Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 12 Aug 2019 08:16:04 +0200 Subject: [PATCH 12/35] extract ban_pat_range_if_ambiguous --- src/libsyntax/parse/parser/pat.rs | 45 +++++++++++++++++-------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index 1b6baf09d816b..7c7dad1fd94b8 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -270,31 +270,36 @@ impl<'a> Parser<'a> { let pat = self.maybe_recover_from_bad_qpath(pat, true)?; if !allow_range_pat { - match pat.node { - PatKind::Range( - _, _, Spanned { node: RangeEnd::Included(RangeSyntax::DotDotDot), .. } - ) => {}, - PatKind::Range(..) => { - let mut err = self.struct_span_err( - pat.span, - "the range pattern here has ambiguous interpretation", - ); - err.span_suggestion( - pat.span, - "add parentheses to clarify the precedence", - format!("({})", pprust::pat_to_string(&pat)), - // "ambiguous interpretation" implies that we have to be guessing - Applicability::MaybeIncorrect - ); - return Err(err); - } - _ => {} - } + self.ban_pat_range_if_ambiguous(&pat)? } Ok(pat) } + /// Ban a range pattern if it has an ambiguous interpretation. + fn ban_pat_range_if_ambiguous(&self, pat: &Pat) -> PResult<'a, ()> { + match pat.node { + PatKind::Range( + .., Spanned { node: RangeEnd::Included(RangeSyntax::DotDotDot), .. } + ) => return Ok(()), + PatKind::Range(..) => {} + _ => return Ok(()), + } + + let mut err = self.struct_span_err( + pat.span, + "the range pattern here has ambiguous interpretation", + ); + err.span_suggestion( + pat.span, + "add parentheses to clarify the precedence", + format!("({})", pprust::pat_to_string(&pat)), + // "ambiguous interpretation" implies that we have to be guessing + Applicability::MaybeIncorrect + ); + Err(err) + } + /// Parse `&pat` / `&mut pat`. fn parse_pat_deref(&mut self, expected: Option<&'static str>) -> PResult<'a, PatKind> { self.expect_and()?; From e32bd69d0f7443bf76af4a8129fc43b381e5afaa Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 12 Aug 2019 08:27:01 +0200 Subject: [PATCH 13/35] extract parse_pat_mac_invoc --- src/libsyntax/parse/parser/pat.rs | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index 7c7dad1fd94b8..40dfa86834f1c 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -3,7 +3,7 @@ use super::{Parser, PResult, PathStyle}; use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole}; use crate::ptr::P; use crate::ast::{self, Attribute, Pat, PatKind, FieldPat, RangeEnd, RangeSyntax, Mac_}; -use crate::ast::{BindingMode, Ident, Mutability, Expr, ExprKind}; +use crate::ast::{BindingMode, Ident, Mutability, Path, Expr, ExprKind}; use crate::parse::token::{self}; use crate::print::pprust; use crate::source_map::{respan, Span, Spanned}; @@ -165,18 +165,7 @@ impl<'a> Parser<'a> { (None, self.parse_path(PathStyle::Expr)?) }; match self.token.kind { - token::Not if qself.is_none() => { - // Parse macro invocation - self.bump(); - let (delim, tts) = self.expect_delimited_token_tree()?; - let mac = respan(lo.to(self.prev_span), Mac_ { - path, - tts, - delim, - prior_type_ascription: self.last_type_ascription, - }); - PatKind::Mac(mac) - } + token::Not if qself.is_none() => self.parse_pat_mac_invoc(lo, path)?, token::DotDotDot | token::DotDotEq | token::DotDot => { let (end_kind, form) = match self.token.kind { token::DotDot => (RangeEnd::Excluded, ".."), @@ -328,7 +317,8 @@ impl<'a> Parser<'a> { }) } - // Recover on `mut ref? ident @ pat` and suggest that the order of `mut` and `ref` is incorrect. + /// Recover on `mut ref? ident @ pat` and suggest + /// that the order of `mut` and `ref` is incorrect. fn recover_pat_ident_mut_first(&mut self) -> PResult<'a, PatKind> { let mutref_span = self.prev_span.to(self.token.span); let binding_mode = if self.eat_keyword(kw::Ref) { @@ -347,6 +337,19 @@ impl<'a> Parser<'a> { self.parse_pat_ident(binding_mode) } + /// Parse macro invocation + fn parse_pat_mac_invoc(&mut self, lo: Span, path: Path) -> PResult<'a, PatKind> { + self.bump(); + let (delim, tts) = self.expect_delimited_token_tree()?; + let mac = respan(lo.to(self.prev_span), Mac_ { + path, + tts, + delim, + prior_type_ascription: self.last_type_ascription, + }); + Ok(PatKind::Mac(mac)) + } + // Helper function to decide whether to parse as ident binding // or to try to do something more complex like range patterns. fn parse_as_ident(&mut self) -> bool { From e6f980f9b804acb42e72ba4b071320ca9e7f22e0 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 12 Aug 2019 08:35:24 +0200 Subject: [PATCH 14/35] extract parse_pat_range_starting_with_path --- src/libsyntax/parse/parser/pat.rs | 40 +++++++++++++++++++------------ 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index 40dfa86834f1c..5c53a497ff475 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -3,7 +3,7 @@ use super::{Parser, PResult, PathStyle}; use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole}; use crate::ptr::P; use crate::ast::{self, Attribute, Pat, PatKind, FieldPat, RangeEnd, RangeSyntax, Mac_}; -use crate::ast::{BindingMode, Ident, Mutability, Path, Expr, ExprKind}; +use crate::ast::{BindingMode, Ident, Mutability, Path, QSelf, Expr, ExprKind}; use crate::parse::token::{self}; use crate::print::pprust; use crate::source_map::{respan, Span, Spanned}; @@ -167,20 +167,7 @@ impl<'a> Parser<'a> { match self.token.kind { token::Not if qself.is_none() => self.parse_pat_mac_invoc(lo, path)?, token::DotDotDot | token::DotDotEq | token::DotDot => { - let (end_kind, form) = match self.token.kind { - token::DotDot => (RangeEnd::Excluded, ".."), - token::DotDotDot => (RangeEnd::Included(RangeSyntax::DotDotDot), "..."), - token::DotDotEq => (RangeEnd::Included(RangeSyntax::DotDotEq), "..="), - _ => panic!("can only parse `..`/`...`/`..=` for ranges \ - (checked above)"), - }; - let op_span = self.token.span; - // Parse range - let span = lo.to(self.prev_span); - let begin = self.mk_expr(span, ExprKind::Path(qself, path), ThinVec::new()); - self.bump(); - let end = self.parse_pat_range_end_opt(&begin, form)?; - PatKind::Range(begin, end, respan(op_span, end_kind)) + self.parse_pat_range_starting_with_path(lo, qself, path)? } token::OpenDelim(token::Brace) => { if qself.is_some() { @@ -350,6 +337,29 @@ impl<'a> Parser<'a> { Ok(PatKind::Mac(mac)) } + /// Parse a range pattern `$path $form $end?` where `$form = ".." | "..." | "..=" ;`. + /// The `$path` has already been parsed and the next token is the `$form`. + fn parse_pat_range_starting_with_path( + &mut self, + lo: Span, + qself: Option, + path: Path + ) -> PResult<'a, PatKind> { + let (end_kind, form) = match self.token.kind { + token::DotDot => (RangeEnd::Excluded, ".."), + token::DotDotDot => (RangeEnd::Included(RangeSyntax::DotDotDot), "..."), + token::DotDotEq => (RangeEnd::Included(RangeSyntax::DotDotEq), "..="), + _ => panic!("can only parse `..`/`...`/`..=` for ranges (checked above)"), + }; + let op_span = self.token.span; + // Parse range + let span = lo.to(self.prev_span); + let begin = self.mk_expr(span, ExprKind::Path(qself, path), ThinVec::new()); + self.bump(); + let end = self.parse_pat_range_end_opt(&begin, form)?; + Ok(PatKind::Range(begin, end, respan(op_span, end_kind))) + } + // Helper function to decide whether to parse as ident binding // or to try to do something more complex like range patterns. fn parse_as_ident(&mut self) -> bool { From 49740b792ddf1bc6d98445b8955b2ebfb742772b Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 12 Aug 2019 09:01:08 +0200 Subject: [PATCH 15/35] extract parse_pat_range_starting_with_lit --- src/libsyntax/parse/parser/pat.rs | 41 ++++++++++++++++--------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index 5c53a497ff475..b821d9da3548f 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -202,26 +202,10 @@ impl<'a> Parser<'a> { } else { // Try to parse everything else as literal with optional minus match self.parse_literal_maybe_minus() { - Ok(begin) => { - let op_span = self.token.span; - if self.check(&token::DotDot) || self.check(&token::DotDotEq) || - self.check(&token::DotDotDot) { - let (end_kind, form) = if self.eat(&token::DotDotDot) { - (RangeEnd::Included(RangeSyntax::DotDotDot), "...") - } else if self.eat(&token::DotDotEq) { - (RangeEnd::Included(RangeSyntax::DotDotEq), "..=") - } else if self.eat(&token::DotDot) { - (RangeEnd::Excluded, "..") - } else { - panic!("impossible case: we already matched \ - on a range-operator token") - }; - let end = self.parse_pat_range_end_opt(&begin, form)?; - PatKind::Range(begin, end, respan(op_span, end_kind)) - } else { - PatKind::Lit(begin) - } - } + Ok(begin) if self.check(&token::DotDot) || self.check(&token::DotDotEq) + || self.check(&token::DotDotDot) + => self.parse_pat_range_starting_with_lit(begin)?, + Ok(begin) => PatKind::Lit(begin), Err(mut err) => { self.cancel(&mut err); let expected = expected.unwrap_or("pattern"); @@ -360,6 +344,23 @@ impl<'a> Parser<'a> { Ok(PatKind::Range(begin, end, respan(op_span, end_kind))) } + /// Parse a range pattern `$literal $form $end?` where `$form = ".." | "..." | "..=" ;`. + /// The `$path` has already been parsed and the next token is the `$form`. + fn parse_pat_range_starting_with_lit(&mut self, begin: P) -> PResult<'a, PatKind> { + let op_span = self.token.span; + let (end_kind, form) = if self.eat(&token::DotDotDot) { + (RangeEnd::Included(RangeSyntax::DotDotDot), "...") + } else if self.eat(&token::DotDotEq) { + (RangeEnd::Included(RangeSyntax::DotDotEq), "..=") + } else if self.eat(&token::DotDot) { + (RangeEnd::Excluded, "..") + } else { + panic!("impossible case: we already matched on a range-operator token") + }; + let end = self.parse_pat_range_end_opt(&begin, form)?; + Ok(PatKind::Range(begin, end, respan(op_span, end_kind))) + } + // Helper function to decide whether to parse as ident binding // or to try to do something more complex like range patterns. fn parse_as_ident(&mut self) -> bool { From 37f37a5df1b4873ab2a4562fca04dc6454817429 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 12 Aug 2019 09:28:30 +0200 Subject: [PATCH 16/35] parser/pat: minor misc cleanup --- src/libsyntax/parse/parser/pat.rs | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index b821d9da3548f..b7a60a2a4fe80 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -202,9 +202,13 @@ impl<'a> Parser<'a> { } else { // Try to parse everything else as literal with optional minus match self.parse_literal_maybe_minus() { - Ok(begin) if self.check(&token::DotDot) || self.check(&token::DotDotEq) - || self.check(&token::DotDotDot) - => self.parse_pat_range_starting_with_lit(begin)?, + Ok(begin) + if self.check(&token::DotDot) + || self.check(&token::DotDotEq) + || self.check(&token::DotDotDot) => + { + self.parse_pat_range_starting_with_lit(begin)? + } Ok(begin) => PatKind::Lit(begin), Err(mut err) => { self.cancel(&mut err); @@ -446,11 +450,9 @@ impl<'a> Parser<'a> { } /// Parses `ident` or `ident @ pat`. - /// used by the copy foo and ref foo patterns to give a good + /// Used by the copy foo and ref foo patterns to give a good /// error message when parsing mistakes like `ref foo(a, b)`. - fn parse_pat_ident(&mut self, - binding_mode: ast::BindingMode) - -> PResult<'a, PatKind> { + fn parse_pat_ident(&mut self, binding_mode: BindingMode) -> PResult<'a, PatKind> { let ident = self.parse_ident()?; let sub = if self.eat(&token::At) { Some(self.parse_pat(Some("binding pattern"))?) @@ -458,16 +460,16 @@ impl<'a> Parser<'a> { None }; - // just to be friendly, if they write something like - // ref Some(i) - // we end up here with ( as the current token. This shortly - // leads to a parse error. Note that if there is no explicit + // Just to be friendly, if they write something like `ref Some(i)`, + // we end up here with `(` as the current token. + // This shortly leads to a parse error. Note that if there is no explicit // binding mode then we do not end up here, because the lookahead - // will direct us over to parse_enum_variant() + // will direct us over to `parse_enum_variant()`. if self.token == token::OpenDelim(token::Paren) { return Err(self.span_fatal( self.prev_span, - "expected identifier, found enum pattern")) + "expected identifier, found enum pattern", + )) } Ok(PatKind::Ident(binding_mode, ident, sub)) From ddf734deb2c48247e06603262145aec3eedbb315 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 12 Aug 2019 11:39:44 +0200 Subject: [PATCH 17/35] extract fatal_unexpected_non_pat --- src/libsyntax/parse/parser/pat.rs | 38 ++++++++++++++++++------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index b7a60a2a4fe80..49090a57f62a1 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -210,22 +210,7 @@ impl<'a> Parser<'a> { self.parse_pat_range_starting_with_lit(begin)? } Ok(begin) => PatKind::Lit(begin), - Err(mut err) => { - self.cancel(&mut err); - let expected = expected.unwrap_or("pattern"); - let msg = format!( - "expected {}, found {}", - expected, - self.this_token_descr(), - ); - let mut err = self.fatal(&msg); - err.span_label(self.token.span, format!("expected {}", expected)); - let sp = self.sess.source_map().start_point(self.token.span); - if let Some(sp) = self.sess.ambiguous_block_expr_parse.borrow().get(&sp) { - self.sess.expr_parentheses_needed(&mut err, *sp, None); - } - return Err(err); - } + Err(err) => return self.fatal_unexpected_non_pat(err, expected), } } }; @@ -365,6 +350,27 @@ impl<'a> Parser<'a> { Ok(PatKind::Range(begin, end, respan(op_span, end_kind))) } + fn fatal_unexpected_non_pat( + &mut self, + mut err: DiagnosticBuilder<'a>, + expected: Option<&'static str>, + ) -> PResult<'a, P> { + self.cancel(&mut err); + + let expected = expected.unwrap_or("pattern"); + let msg = format!("expected {}, found {}", expected, self.this_token_descr()); + + let mut err = self.fatal(&msg); + err.span_label(self.token.span, format!("expected {}", expected)); + + let sp = self.sess.source_map().start_point(self.token.span); + if let Some(sp) = self.sess.ambiguous_block_expr_parse.borrow().get(&sp) { + self.sess.expr_parentheses_needed(&mut err, *sp, None); + } + + Err(err) + } + // Helper function to decide whether to parse as ident binding // or to try to do something more complex like range patterns. fn parse_as_ident(&mut self) -> bool { From c8fc4c106cfb7594dedf3372e33959e9b859c228 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 12 Aug 2019 12:27:43 +0200 Subject: [PATCH 18/35] extract parse_pat_{tuple_}struct + recover_one_fewer_dotdot --- src/libsyntax/parse/parser/pat.rs | 90 +++++++++++++++++-------------- 1 file changed, 51 insertions(+), 39 deletions(-) diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index 49090a57f62a1..53f4d0998c3e1 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -169,34 +169,8 @@ impl<'a> Parser<'a> { token::DotDotDot | token::DotDotEq | token::DotDot => { self.parse_pat_range_starting_with_path(lo, qself, path)? } - token::OpenDelim(token::Brace) => { - if qself.is_some() { - let msg = "unexpected `{` after qualified path"; - let mut err = self.fatal(msg); - err.span_label(self.token.span, msg); - return Err(err); - } - // Parse struct pattern - self.bump(); - let (fields, etc) = self.parse_pat_fields().unwrap_or_else(|mut e| { - e.emit(); - self.recover_stmt(); - (vec![], true) - }); - self.bump(); - PatKind::Struct(path, fields, etc) - } - token::OpenDelim(token::Paren) => { - if qself.is_some() { - let msg = "unexpected `(` after qualified path"; - let mut err = self.fatal(msg); - err.span_label(self.token.span, msg); - return Err(err); - } - // Parse tuple struct or enum pattern - let (fields, _) = self.parse_paren_comma_seq(|p| p.parse_pat(None))?; - PatKind::TupleStruct(path, fields) - } + token::OpenDelim(token::Brace) => self.parse_pat_struct(qself, path)?, + token::OpenDelim(token::Paren) => self.parse_pat_tuple_struct(qself, path)?, _ => PatKind::Path(qself, path), } } else { @@ -481,6 +455,37 @@ impl<'a> Parser<'a> { Ok(PatKind::Ident(binding_mode, ident, sub)) } + /// Parse a struct ("record") pattern (e.g. `Foo { ... }` or `Foo::Bar { ... }`). + fn parse_pat_struct(&mut self, qself: Option, path: Path) -> PResult<'a, PatKind> { + if qself.is_some() { + let msg = "unexpected `{` after qualified path"; + let mut err = self.fatal(msg); + err.span_label(self.token.span, msg); + return Err(err); + } + + self.bump(); + let (fields, etc) = self.parse_pat_fields().unwrap_or_else(|mut e| { + e.emit(); + self.recover_stmt(); + (vec![], true) + }); + self.bump(); + Ok(PatKind::Struct(path, fields, etc)) + } + + /// Parse tuple struct or tuple variant pattern (e.g. `Foo(...)` or `Foo::Bar(...)`). + fn parse_pat_tuple_struct(&mut self, qself: Option, path: Path) -> PResult<'a, PatKind> { + if qself.is_some() { + let msg = "unexpected `(` after qualified path"; + let mut err = self.fatal(msg); + err.span_label(self.token.span, msg); + return Err(err); + } + let (fields, _) = self.parse_paren_comma_seq(|p| p.parse_pat(None))?; + Ok(PatKind::TupleStruct(path, fields)) + } + /// Parses the fields of a struct-like pattern. fn parse_pat_fields(&mut self) -> PResult<'a, (Vec>, bool)> { let mut fields = Vec::new(); @@ -515,17 +520,7 @@ impl<'a> Parser<'a> { etc = true; let mut etc_sp = self.token.span; - if self.token == token::DotDotDot { // Issue #46718 - // Accept `...` as if it were `..` to avoid further errors - self.struct_span_err(self.token.span, "expected field pattern, found `...`") - .span_suggestion( - self.token.span, - "to omit remaining fields, use one fewer `.`", - "..".to_owned(), - Applicability::MachineApplicable - ) - .emit(); - } + self.recover_one_fewer_dotdot(); self.bump(); // `..` || `...` if self.token == token::CloseDelim(token::Brace) { @@ -607,6 +602,23 @@ impl<'a> Parser<'a> { return Ok((fields, etc)); } + /// Recover on `...` as if it were `..` to avoid further errors. + /// See issue #46718. + fn recover_one_fewer_dotdot(&self) { + if self.token != token::DotDotDot { + return; + } + + self.struct_span_err(self.token.span, "expected field pattern, found `...`") + .span_suggestion( + self.token.span, + "to omit remaining fields, use one fewer `.`", + "..".to_owned(), + Applicability::MachineApplicable + ) + .emit(); + } + fn parse_pat_field( &mut self, lo: Span, From 71415ef9bd697a49db34742172aacb792ce8d116 Mon Sep 17 00:00:00 2001 From: nathanwhit Date: Thu, 25 Jul 2019 11:51:05 -0400 Subject: [PATCH 19/35] Parse excess semicolons as empty stmts for linting --- src/libsyntax/parse/parser/stmt.rs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/libsyntax/parse/parser/stmt.rs b/src/libsyntax/parse/parser/stmt.rs index f182edcbff437..750d8fbbddc00 100644 --- a/src/libsyntax/parse/parser/stmt.rs +++ b/src/libsyntax/parse/parser/stmt.rs @@ -167,7 +167,22 @@ impl<'a> Parser<'a> { if self.token == token::Semi { unused_attrs(&attrs, self); self.bump(); - return Ok(None); + let mut last_semi = lo; + while self.token == token::Semi { + last_semi = self.token.span; + self.bump(); + } + // We are encoding a string of semicolons as an + // an empty tuple that spans the excess semicolons + // to preserve this info until the lint stage + return Ok(Some(Stmt { + id: ast::DUMMY_NODE_ID, + span: lo.to(last_semi), + node: StmtKind::Semi(self.mk_expr(lo.to(last_semi), + ExprKind::Tup(Vec::new()), + ThinVec::new() + )), + })); } if self.token == token::CloseDelim(token::Brace) { From 2f6cb5f75e080d7886129bd9fa2dbc9ee52b20ac Mon Sep 17 00:00:00 2001 From: Nathan Date: Tue, 30 Jul 2019 13:48:39 -0400 Subject: [PATCH 20/35] Add lint for excess trailing semicolons --- src/librustc_lint/lib.rs | 3 ++ src/librustc_lint/redundant_semicolon.rs | 52 ++++++++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 src/librustc_lint/redundant_semicolon.rs diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 3a540fdf4b91f..fc416be8eeb50 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -24,6 +24,7 @@ extern crate rustc; mod error_codes; mod nonstandard_style; +mod redundant_semicolon; pub mod builtin; mod types; mod unused; @@ -55,6 +56,7 @@ use session::Session; use lint::LintId; use lint::FutureIncompatibleInfo; +use redundant_semicolon::*; use nonstandard_style::*; use builtin::*; use types::*; @@ -98,6 +100,7 @@ macro_rules! early_lint_passes { WhileTrue: WhileTrue, NonAsciiIdents: NonAsciiIdents, IncompleteFeatures: IncompleteFeatures, + RedundantSemicolon: RedundantSemicolon, ]); ) } diff --git a/src/librustc_lint/redundant_semicolon.rs b/src/librustc_lint/redundant_semicolon.rs new file mode 100644 index 0000000000000..7c9df3578b59c --- /dev/null +++ b/src/librustc_lint/redundant_semicolon.rs @@ -0,0 +1,52 @@ +use crate::lint::{EarlyLintPass, LintPass, EarlyContext, LintArray, LintContext}; +use syntax::ast::{Stmt, StmtKind, ExprKind}; +use syntax::errors::Applicability; + +declare_lint! { + pub REDUNDANT_SEMICOLON, + Warn, + "detects unnecessary trailing semicolons" +} + +declare_lint_pass!(RedundantSemicolon => [REDUNDANT_SEMICOLON]); + +impl EarlyLintPass for RedundantSemicolon { + fn check_stmt(&mut self, cx: &EarlyContext<'_>, stmt: &Stmt) { + if let StmtKind::Semi(expr) = &stmt.node { + if let ExprKind::Tup(ref v) = &expr.node { + if v.is_empty() { + // Strings of excess semicolons are encoded as empty tuple expressions + // during the parsing stage, so we check for empty tuple expressions + // which span only semicolons + if let Ok(source_str) = cx.sess().source_map().span_to_snippet(stmt.span) { + if source_str.chars().all(|c| c == ';') { + let multiple = (stmt.span.hi() - stmt.span.lo()).0 > 1; + let msg = if multiple { + "unnecessary trailing semicolons" + } else { + "unnecessary trailing semicolon" + }; + let mut err = cx.struct_span_lint( + REDUNDANT_SEMICOLON, + stmt.span, + &msg + ); + let suggest_msg = if multiple { + "remove these semicolons" + } else { + "remove this semicolon" + }; + err.span_suggestion( + stmt.span, + &suggest_msg, + String::new(), + Applicability::MaybeIncorrect + ); + err.emit(); + } + } + } + } + } + } +} From 76a134524295a04ed5f336265239ef5f39d089de Mon Sep 17 00:00:00 2001 From: Nathan Date: Tue, 30 Jul 2019 13:52:32 -0400 Subject: [PATCH 21/35] Update tests for excess semicolon lint --- src/test/ui/block-expr-precedence.stderr | 8 ++++++++ .../issue-46836-identifier-not-instead-of-negation.stderr | 5 ++++- src/test/ui/parser/doc-before-semi.rs | 2 ++ src/test/ui/parser/doc-before-semi.stderr | 8 ++++++++ src/test/ui/proc-macro/span-preservation.rs | 2 +- src/test/ui/proc-macro/span-preservation.stderr | 2 +- 6 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/block-expr-precedence.stderr diff --git a/src/test/ui/block-expr-precedence.stderr b/src/test/ui/block-expr-precedence.stderr new file mode 100644 index 0000000000000..1307b5d6ddd82 --- /dev/null +++ b/src/test/ui/block-expr-precedence.stderr @@ -0,0 +1,8 @@ +warning: unnecessary trailing semicolons + --> $DIR/block-expr-precedence.rs:60:21 + | +LL | if (true) { 12; };;; -num; + | ^^ help: remove these semicolons + | + = note: `#[warn(redundant_semicolon)]` on by default + diff --git a/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr b/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr index f1c93d5463767..f5edbe2a3af53 100644 --- a/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr +++ b/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr @@ -28,7 +28,10 @@ error: expected `{`, found `;` LL | if not // lack of braces is [sic] | -- this `if` statement has a condition, but no block LL | println!("Then when?"); - | ^ expected `{` + | ^ + | | + | expected `{` + | help: try placing this code inside a block: `{ ; }` error: unexpected `2` after identifier --> $DIR/issue-46836-identifier-not-instead-of-negation.rs:26:24 diff --git a/src/test/ui/parser/doc-before-semi.rs b/src/test/ui/parser/doc-before-semi.rs index 405a7e1e2a33b..c3f478fe42077 100644 --- a/src/test/ui/parser/doc-before-semi.rs +++ b/src/test/ui/parser/doc-before-semi.rs @@ -3,4 +3,6 @@ fn main() { //~^ ERROR found a documentation comment that doesn't document anything //~| HELP maybe a comment was intended ; + //~^ WARNING unnecessary trailing semicolon + //~| HELP remove this semicolon } diff --git a/src/test/ui/parser/doc-before-semi.stderr b/src/test/ui/parser/doc-before-semi.stderr index e6bade18d0a2d..b9ac30b09b2f8 100644 --- a/src/test/ui/parser/doc-before-semi.stderr +++ b/src/test/ui/parser/doc-before-semi.stderr @@ -6,6 +6,14 @@ LL | /// hi | = help: doc comments must come before what they document, maybe a comment was intended with `//`? +warning: unnecessary trailing semicolon + --> $DIR/doc-before-semi.rs:5:5 + | +LL | ; + | ^ help: remove this semicolon + | + = note: `#[warn(redundant_semicolon)]` on by default + error: aborting due to previous error For more information about this error, try `rustc --explain E0585`. diff --git a/src/test/ui/proc-macro/span-preservation.rs b/src/test/ui/proc-macro/span-preservation.rs index 0a82d28e9e544..55835cb88f4e3 100644 --- a/src/test/ui/proc-macro/span-preservation.rs +++ b/src/test/ui/proc-macro/span-preservation.rs @@ -9,7 +9,7 @@ extern crate test_macros; #[recollect_attr] fn a() { - let x: usize = "hello";;;;; //~ ERROR mismatched types + let x: usize = "hello"; //~ ERROR mismatched types } #[recollect_attr] diff --git a/src/test/ui/proc-macro/span-preservation.stderr b/src/test/ui/proc-macro/span-preservation.stderr index cf03deee7e445..0290f4b2cc982 100644 --- a/src/test/ui/proc-macro/span-preservation.stderr +++ b/src/test/ui/proc-macro/span-preservation.stderr @@ -6,7 +6,7 @@ error[E0308]: mismatched types error[E0308]: mismatched types --> $DIR/span-preservation.rs:12:20 | -LL | let x: usize = "hello";;;;; +LL | let x: usize = "hello"; | ^^^^^^^ expected usize, found reference | = note: expected type `usize` From c0375973350865ad2e1b84801c8778123832cbad Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Mon, 12 Aug 2019 18:15:13 +0300 Subject: [PATCH 22/35] Remove redundant `ty` fields from `mir::Constant` and `hair::pattern::PatternRange`. --- src/librustc/mir/mod.rs | 5 +-- src/librustc/mir/tcx.rs | 2 +- src/librustc/mir/visit.rs | 2 - src/librustc_codegen_ssa/mir/analyze.rs | 2 +- src/librustc_codegen_ssa/mir/block.rs | 2 +- src/librustc_codegen_ssa/mir/operand.rs | 2 +- .../borrow_check/nll/type_check/mod.rs | 44 ++----------------- src/librustc_mir/build/expr/as_constant.rs | 1 - src/librustc_mir/build/expr/as_rvalue.rs | 4 +- src/librustc_mir/build/expr/into.rs | 2 - src/librustc_mir/build/matches/simplify.rs | 4 +- src/librustc_mir/build/matches/test.rs | 23 +++++----- src/librustc_mir/build/misc.rs | 5 +-- src/librustc_mir/hair/cx/mod.rs | 4 +- src/librustc_mir/hair/pattern/_match.rs | 19 ++++---- src/librustc_mir/hair/pattern/mod.rs | 19 ++------ src/librustc_mir/shim.rs | 3 -- src/librustc_mir/transform/const_prop.rs | 1 - src/librustc_mir/transform/elaborate_drops.rs | 1 - src/librustc_mir/transform/generator.rs | 1 - src/librustc_mir/transform/inline.rs | 2 +- src/librustc_mir/transform/instcombine.rs | 3 +- src/librustc_mir/transform/qualify_consts.rs | 4 +- src/librustc_mir/transform/rustc_peek.rs | 2 +- src/librustc_mir/util/elaborate_drops.rs | 1 - src/librustc_mir/util/pretty.rs | 3 +- 26 files changed, 46 insertions(+), 115 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 1e2ec08301cf9..119114485ffbd 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2197,7 +2197,6 @@ impl<'tcx> Operand<'tcx> { let ty = tcx.type_of(def_id).subst(tcx, substs); Operand::Constant(box Constant { span, - ty, user_ty: None, literal: ty::Const::zero_sized(tcx, ty), }) @@ -2476,7 +2475,6 @@ impl<'tcx> Debug for Rvalue<'tcx> { #[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)] pub struct Constant<'tcx> { pub span: Span, - pub ty: Ty<'tcx>, /// Optional user-given type: for something like /// `collect::>`, this would be present and would @@ -3385,12 +3383,11 @@ impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> { fn super_fold_with>(&self, folder: &mut F) -> Self { Constant { span: self.span.clone(), - ty: self.ty.fold_with(folder), user_ty: self.user_ty.fold_with(folder), literal: self.literal.fold_with(folder), } } fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.ty.visit_with(visitor) || self.literal.visit_with(visitor) + self.literal.visit_with(visitor) } } diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index f8889380b2abf..e9f7636ba85ae 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -252,7 +252,7 @@ impl<'tcx> Operand<'tcx> { match self { &Operand::Copy(ref l) | &Operand::Move(ref l) => l.ty(local_decls, tcx).ty, - &Operand::Constant(ref c) => c.ty, + &Operand::Constant(ref c) => c.literal.ty, } } } diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index ee4ecb6762c96..2d16e7bcc8371 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -782,13 +782,11 @@ macro_rules! make_mir_visitor { location: Location) { let Constant { span, - ty, user_ty, literal, } = constant; self.visit_span(span); - self.visit_ty(ty, TyContext::Location(location)); drop(user_ty); // no visit method for this self.visit_const(literal, location); } diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs index cc0c733c22410..e63f1b91dd7d5 100644 --- a/src/librustc_codegen_ssa/mir/analyze.rs +++ b/src/librustc_codegen_ssa/mir/analyze.rs @@ -221,7 +221,7 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx> mir::TerminatorKind::Call { func: mir::Operand::Constant(ref c), ref args, .. - } => match c.ty.sty { + } => match c.literal.ty.sty { ty::FnDef(did, _) => Some((did, args)), _ => None, }, diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index ce98979cc0c64..dbce5ce4896a7 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -651,7 +651,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let (llval, ty) = self.simd_shuffle_indices( &bx, constant.span, - constant.ty, + constant.literal.ty, c, ); return OperandRef { diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs index 5e5804b72657b..254b73da44261 100644 --- a/src/librustc_codegen_ssa/mir/operand.rs +++ b/src/librustc_codegen_ssa/mir/operand.rs @@ -466,7 +466,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } mir::Operand::Constant(ref constant) => { - let ty = self.monomorphize(&constant.ty); self.eval_mir_constant(constant) .map(|c| OperandRef::from_const(bx, c)) .unwrap_or_else(|err| { @@ -481,6 +480,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // the above error (or silence it under some conditions) will not cause UB bx.abort(); // We've errored, so we don't have to produce working code. + let ty = self.monomorphize(&constant.literal.ty); let layout = bx.cx().layout_of(ty); bx.load_operand(PlaceRef::new_sized( bx.cx().const_undef(bx.cx().type_ptr_to(bx.cx().backend_type(layout))), diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 70d6c15d8e2a7..9ff0c6ca6a546 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -272,12 +272,11 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) { self.super_constant(constant, location); - self.sanitize_constant(constant, location); - self.sanitize_type(constant, constant.ty); + self.sanitize_type(constant, constant.literal.ty); if let Some(annotation_index) = constant.user_ty { if let Err(terr) = self.cx.relate_type_and_user_type( - constant.ty, + constant.literal.ty, ty::Variance::Invariant, &UserTypeProjection { base: annotation_index, projs: vec![], }, location.to_locations(), @@ -289,7 +288,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { constant, "bad constant user type {:?} vs {:?}: {:?}", annotation, - constant.ty, + constant.literal.ty, terr, ); } @@ -299,7 +298,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { location.to_locations(), ConstraintCategory::Boring, self.cx.param_env.and(type_op::ascribe_user_type::AscribeUserType::new( - constant.ty, def_id, UserSubsts { substs, user_self_ty: None }, + constant.literal.ty, def_id, UserSubsts { substs, user_self_ty: None }, )), ) { span_mirbug!( @@ -403,41 +402,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { } } - /// Checks that the constant's `ty` field matches up with what would be - /// expected from its literal. Unevaluated constants and well-formed - /// constraints are checked by `visit_constant`. - fn sanitize_constant(&mut self, constant: &Constant<'tcx>, location: Location) { - debug!( - "sanitize_constant(constant={:?}, location={:?})", - constant, location - ); - - let literal = constant.literal; - - if let ConstValue::Unevaluated(..) = literal.val { - return; - } - - debug!("sanitize_constant: expected_ty={:?}", literal.ty); - - if let Err(terr) = self.cx.eq_types( - literal.ty, - constant.ty, - location.to_locations(), - ConstraintCategory::Boring, - ) { - span_mirbug!( - self, - constant, - "constant {:?} should have type {:?} but has {:?} ({:?})", - constant, - literal.ty, - constant.ty, - terr, - ); - } - } - /// Checks that the types internal to the `place` match up with /// what would be expected. fn sanitize_place( diff --git a/src/librustc_mir/build/expr/as_constant.rs b/src/librustc_mir/build/expr/as_constant.rs index 5197981a85cb8..ec936f801c308 100644 --- a/src/librustc_mir/build/expr/as_constant.rs +++ b/src/librustc_mir/build/expr/as_constant.rs @@ -40,7 +40,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }); Constant { span, - ty, user_ty, literal, } diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index ec061e7453577..1a186fa932ddb 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -591,7 +591,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let n = (!0u128) >> (128 - bits); let literal = ty::Const::from_bits(self.hir.tcx(), n, param_ty); - self.literal_operand(span, ty, literal) + self.literal_operand(span, literal) } // Helper to get the minimum value of the appropriate type @@ -602,6 +602,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let n = 1 << (bits - 1); let literal = ty::Const::from_bits(self.hir.tcx(), n, param_ty); - self.literal_operand(span, ty, literal) + self.literal_operand(span, literal) } } diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index 02ab53fe8c1b1..889861b856748 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -114,7 +114,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { destination, Constant { span: expr_span, - ty: this.hir.bool_ty(), user_ty: None, literal: this.hir.true_literal(), }, @@ -126,7 +125,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { destination, Constant { span: expr_span, - ty: this.hir.bool_ty(), user_ty: None, literal: this.hir.false_literal(), }, diff --git a/src/librustc_mir/build/matches/simplify.rs b/src/librustc_mir/build/matches/simplify.rs index d9b748f71f011..3473155a3ea3e 100644 --- a/src/librustc_mir/build/matches/simplify.rs +++ b/src/librustc_mir/build/matches/simplify.rs @@ -108,8 +108,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Err(match_pair) } - PatternKind::Range(PatternRange { lo, hi, ty, end }) => { - let (range, bias) = match ty.sty { + PatternKind::Range(PatternRange { lo, hi, end }) => { + let (range, bias) = match lo.ty.sty { ty::Char => { (Some(('\u{0000}' as u128, '\u{10FFFF}' as u128, Size::from_bits(32))), 0) } diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs index 1c93abd40ded2..b8ca67663ae2d 100644 --- a/src/librustc_mir/build/matches/test.rs +++ b/src/librustc_mir/build/matches/test.rs @@ -63,7 +63,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } PatternKind::Range(range) => { - assert!(range.ty == match_pair.pattern.ty); Test { span: match_pair.pattern.span, kind: TestKind::Range(range), @@ -270,8 +269,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ); } else { if let [success, fail] = *make_target_blocks(self) { + let expect = self.literal_operand(test.span, value); let val = Operand::Copy(place.clone()); - let expect = self.literal_operand(test.span, ty, value); self.compare(block, success, fail, source_info, BinOp::Eq, expect, val); } else { bug!("`TestKind::Eq` should have two target blocks"); @@ -279,13 +278,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - TestKind::Range(PatternRange { ref lo, ref hi, ty, ref end }) => { + TestKind::Range(PatternRange { ref lo, ref hi, ref end }) => { let lower_bound_success = self.cfg.start_new_block(); let target_blocks = make_target_blocks(self); // Test `val` by computing `lo <= val && val <= hi`, using primitive comparisons. - let lo = self.literal_operand(test.span, ty, lo); - let hi = self.literal_operand(test.span, ty, hi); + let lo = self.literal_operand(test.span, lo); + let hi = self.literal_operand(test.span, hi); let val = Operand::Copy(place.clone()); if let [success, fail] = *target_blocks { @@ -387,7 +386,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ) { use rustc::middle::lang_items::EqTraitLangItem; - let mut expect = self.literal_operand(source_info.span, value.ty, value); + let mut expect = self.literal_operand(source_info.span, value); let mut val = Operand::Copy(place.clone()); // If we're using `b"..."` as a pattern, we need to insert an @@ -440,7 +439,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }; let eq_def_id = self.hir.tcx().require_lang_item(EqTraitLangItem); - let (mty, method) = self.hir.trait_method(eq_def_id, sym::eq, deref_ty, &[deref_ty.into()]); + let method = self.hir.trait_method(eq_def_id, sym::eq, deref_ty, &[deref_ty.into()]); let bool_ty = self.hir.bool_ty(); let eq_result = self.temp(bool_ty, source_info.span); @@ -449,7 +448,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.cfg.terminate(block, source_info, TerminatorKind::Call { func: Operand::Constant(box Constant { span: source_info.span, - ty: mty, // FIXME(#54571): This constant comes from user input (a // constant in a pattern). Are there forms where users can add @@ -656,8 +654,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let tcx = self.hir.tcx(); - let lo = compare_const_vals(tcx, test.lo, pat.hi, self.hir.param_env, test.ty)?; - let hi = compare_const_vals(tcx, test.hi, pat.lo, self.hir.param_env, test.ty)?; + let test_ty = test.lo.ty; + let lo = compare_const_vals(tcx, test.lo, pat.hi, self.hir.param_env, test_ty)?; + let hi = compare_const_vals(tcx, test.hi, pat.lo, self.hir.param_env, test_ty)?; match (test.end, pat.end, lo, hi) { // pat < test @@ -774,8 +773,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let tcx = self.hir.tcx(); - let a = compare_const_vals(tcx, range.lo, value, self.hir.param_env, range.ty)?; - let b = compare_const_vals(tcx, value, range.hi, self.hir.param_env, range.ty)?; + let a = compare_const_vals(tcx, range.lo, value, self.hir.param_env, range.lo.ty)?; + let b = compare_const_vals(tcx, value, range.hi, self.hir.param_env, range.lo.ty)?; match (b, range.end) { (Less, _) | diff --git a/src/librustc_mir/build/misc.rs b/src/librustc_mir/build/misc.rs index 56025eeaaa922..d038310dd4454 100644 --- a/src/librustc_mir/build/misc.rs +++ b/src/librustc_mir/build/misc.rs @@ -26,12 +26,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// without any user type annotation. pub fn literal_operand(&mut self, span: Span, - ty: Ty<'tcx>, literal: &'tcx ty::Const<'tcx>) -> Operand<'tcx> { let constant = box Constant { span, - ty, user_ty: None, literal, }; @@ -47,7 +45,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { pub fn zero_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> { let literal = ty::Const::from_bits(self.hir.tcx(), 0, ty::ParamEnv::empty().and(ty)); - self.literal_operand(span, ty, literal) + self.literal_operand(span, literal) } pub fn push_usize(&mut self, @@ -61,7 +59,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block, source_info, &temp, Constant { span: source_info.span, - ty: self.hir.usize_ty(), user_ty: None, literal: self.hir.usize_literal(value), }); diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index 3d9349df5bedb..740dc2011cab1 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -170,13 +170,13 @@ impl<'a, 'tcx> Cx<'a, 'tcx> { method_name: Symbol, self_ty: Ty<'tcx>, params: &[Kind<'tcx>]) - -> (Ty<'tcx>, &'tcx ty::Const<'tcx>) { + -> &'tcx ty::Const<'tcx> { let substs = self.tcx.mk_substs_trait(self_ty, params); for item in self.tcx.associated_items(trait_def_id) { if item.kind == ty::AssocKind::Method && item.ident.name == method_name { let method_ty = self.tcx.type_of(item.def_id); let method_ty = method_ty.subst(self.tcx, substs); - return (method_ty, ty::Const::zero_sized(self.tcx, method_ty)); + return ty::Const::zero_sized(self.tcx, method_ty); } } diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index 8a3d904e77579..1833ee30624bb 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -609,7 +609,6 @@ impl<'tcx> Witness<'tcx> { ConstantRange(lo, hi, ty, end) => PatternKind::Range(PatternRange { lo: ty::Const::from_bits(cx.tcx, lo, ty::ParamEnv::empty().and(ty)), hi: ty::Const::from_bits(cx.tcx, hi, ty::ParamEnv::empty().and(ty)), - ty, end, }), _ => PatternKind::Wild, @@ -880,10 +879,10 @@ impl<'tcx> IntRange<'tcx> { let range = loop { match pat.kind { box PatternKind::Constant { value } => break ConstantValue(value), - box PatternKind::Range(PatternRange { lo, hi, ty, end }) => break ConstantRange( - lo.eval_bits(tcx, param_env, ty), - hi.eval_bits(tcx, param_env, ty), - ty, + box PatternKind::Range(PatternRange { lo, hi, end }) => break ConstantRange( + lo.eval_bits(tcx, param_env, lo.ty), + hi.eval_bits(tcx, param_env, hi.ty), + lo.ty, end, ), box PatternKind::AscribeUserType { ref subpattern, .. } => { @@ -1339,11 +1338,11 @@ fn pat_constructors<'tcx>(cx: &mut MatchCheckCtxt<'_, 'tcx>, Some(vec![Variant(adt_def.variants[variant_index].def_id)]) } PatternKind::Constant { value } => Some(vec![ConstantValue(value)]), - PatternKind::Range(PatternRange { lo, hi, ty, end }) => + PatternKind::Range(PatternRange { lo, hi, end }) => Some(vec![ConstantRange( - lo.eval_bits(cx.tcx, cx.param_env, ty), - hi.eval_bits(cx.tcx, cx.param_env, ty), - ty, + lo.eval_bits(cx.tcx, cx.param_env, lo.ty), + hi.eval_bits(cx.tcx, cx.param_env, hi.ty), + lo.ty, end, )]), PatternKind::Array { .. } => match pcx.ty.sty { @@ -1656,7 +1655,7 @@ fn constructor_covered_by_range<'tcx>( ) -> Result { let (from, to, end, ty) = match pat.kind { box PatternKind::Constant { value } => (value, value, RangeEnd::Included, value.ty), - box PatternKind::Range(PatternRange { lo, hi, end, ty }) => (lo, hi, end, ty), + box PatternKind::Range(PatternRange { lo, hi, end }) => (lo, hi, end, lo.ty), _ => bug!("`constructor_covered_by_range` called with {:?}", pat), }; trace!("constructor_covered_by_range {:#?}, {:#?}, {:#?}, {}", ctor, from, to, ty); diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 5ecfb84b63236..c43bd765d2aab 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -181,7 +181,6 @@ pub enum PatternKind<'tcx> { pub struct PatternRange<'tcx> { pub lo: &'tcx ty::Const<'tcx>, pub hi: &'tcx ty::Const<'tcx>, - pub ty: Ty<'tcx>, pub end: RangeEnd, } @@ -296,7 +295,7 @@ impl<'tcx> fmt::Display for Pattern<'tcx> { PatternKind::Constant { value } => { write!(f, "{}", value) } - PatternKind::Range(PatternRange { lo, hi, ty: _, end }) => { + PatternKind::Range(PatternRange { lo, hi, end }) => { write!(f, "{}", lo)?; match end { RangeEnd::Included => write!(f, "..=")?, @@ -451,7 +450,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { ); match (end, cmp) { (RangeEnd::Excluded, Some(Ordering::Less)) => - PatternKind::Range(PatternRange { lo, hi, ty, end }), + PatternKind::Range(PatternRange { lo, hi, end }), (RangeEnd::Excluded, _) => { span_err!( self.tcx.sess, @@ -465,7 +464,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { PatternKind::Constant { value: lo } } (RangeEnd::Included, Some(Ordering::Less)) => { - PatternKind::Range(PatternRange { lo, hi, ty, end }) + PatternKind::Range(PatternRange { lo, hi, end }) } (RangeEnd::Included, _) => { let mut err = struct_span_err!( @@ -1416,17 +1415,7 @@ impl<'tcx> PatternFoldable<'tcx> for PatternKind<'tcx> { } => PatternKind::Constant { value, }, - PatternKind::Range(PatternRange { - lo, - hi, - ty, - end, - }) => PatternKind::Range(PatternRange { - lo, - hi, - ty: ty.fold_with(folder), - end, - }), + PatternKind::Range(range) => PatternKind::Range(range), PatternKind::Slice { ref prefix, ref slice, diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 33447eba7492a..063e779637158 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -445,7 +445,6 @@ impl CloneShimBuilder<'tcx> { let func_ty = tcx.mk_fn_def(self.def_id, substs); let func = Operand::Constant(box Constant { span: self.span, - ty: func_ty, user_ty: None, literal: ty::Const::zero_sized(tcx, func_ty), }); @@ -505,7 +504,6 @@ impl CloneShimBuilder<'tcx> { fn make_usize(&self, value: u64) -> Box> { box Constant { span: self.span, - ty: self.tcx.types.usize, user_ty: None, literal: ty::Const::from_usize(self.tcx, value), } @@ -745,7 +743,6 @@ fn build_call_shim<'tcx>( let ty = tcx.type_of(def_id); (Operand::Constant(box Constant { span, - ty, user_ty: None, literal: ty::Const::zero_sized(tcx, ty), }), diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 38d26d0ba50a4..c3c432d606644 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -539,7 +539,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { Operand::Constant(Box::new( Constant { span, - ty, user_ty: None, literal: self.tcx.mk_const(*ty::Const::from_scalar( self.tcx, diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs index 0a021d9b8fa06..4480d1e0a05b8 100644 --- a/src/librustc_mir/transform/elaborate_drops.rs +++ b/src/librustc_mir/transform/elaborate_drops.rs @@ -527,7 +527,6 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { fn constant_bool(&self, span: Span, val: bool) -> Rvalue<'tcx> { Rvalue::Use(Operand::Constant(Box::new(Constant { span, - ty: self.tcx.types.bool, user_ty: None, literal: ty::Const::from_bool(self.tcx, val), }))) diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index 94bb70e10aa53..f694188024031 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -975,7 +975,6 @@ fn insert_panic_block<'tcx>( let term = TerminatorKind::Assert { cond: Operand::Constant(box Constant { span: body.span, - ty: tcx.types.bool, user_ty: None, literal: ty::Const::from_bool(tcx, false), }), diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 40cb1fbdc57fa..bc7bd39be488e 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -328,7 +328,7 @@ impl Inliner<'tcx> { } TerminatorKind::Call {func: Operand::Constant(ref f), .. } => { - if let ty::FnDef(def_id, _) = f.ty.sty { + if let ty::FnDef(def_id, _) = f.literal.ty.sty { // Don't give intrinsics the extra penalty for calls let f = tcx.fn_sig(def_id); if f.abi() == Abi::RustIntrinsic || f.abi() == Abi::PlatformIntrinsic { diff --git a/src/librustc_mir/transform/instcombine.rs b/src/librustc_mir/transform/instcombine.rs index 5542926503693..b2d063a1f4e10 100644 --- a/src/librustc_mir/transform/instcombine.rs +++ b/src/librustc_mir/transform/instcombine.rs @@ -97,8 +97,7 @@ impl Visitor<'tcx> for OptimizationFinder<'b, 'tcx> { let place_ty = place.ty(&self.body.local_decls, self.tcx).ty; if let ty::Array(_, len) = place_ty.sty { let span = self.body.source_info(location).span; - let ty = self.tcx.types.usize; - let constant = Constant { span, ty, literal: len, user_ty: None }; + let constant = Constant { span, literal: len, user_ty: None }; self.optimizations.arrays_lengths.insert(location, constant); } } diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index dcfc80968f31c..0eed43b10868e 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -249,7 +249,7 @@ trait Qualif { if let ConstValue::Unevaluated(def_id, _) = constant.literal.val { // Don't peek inside trait associated constants. if cx.tcx.trait_of_item(def_id).is_some() { - Self::in_any_value_of_ty(cx, constant.ty).unwrap_or(false) + Self::in_any_value_of_ty(cx, constant.literal.ty).unwrap_or(false) } else { let (bits, _) = cx.tcx.at(constant.span).mir_const_qualif(def_id); @@ -258,7 +258,7 @@ trait Qualif { // Just in case the type is more specific than // the definition, e.g., impl associated const // with type parameters, take it into account. - qualif && Self::mask_for_ty(cx, constant.ty) + qualif && Self::mask_for_ty(cx, constant.literal.ty) } } else { false diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs index 7fe8480c819e6..598de3a77e61c 100644 --- a/src/librustc_mir/transform/rustc_peek.rs +++ b/src/librustc_mir/transform/rustc_peek.rs @@ -224,7 +224,7 @@ fn is_rustc_peek<'a, 'tcx>( if let Some(mir::Terminator { ref kind, source_info, .. }) = *terminator { if let mir::TerminatorKind::Call { func: ref oper, ref args, .. } = *kind { if let mir::Operand::Constant(ref func) = *oper { - if let ty::FnDef(def_id, _) = func.ty.sty { + if let ty::FnDef(def_id, _) = func.literal.ty.sty { let abi = tcx.fn_sig(def_id).abi(); let name = tcx.item_name(def_id); if abi == Abi::RustIntrinsic && name == sym::rustc_peek { diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index 52fd645e38e22..c5561a1ae0d15 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -970,7 +970,6 @@ where fn constant_usize(&self, val: u16) -> Operand<'tcx> { Operand::Constant(box Constant { span: self.source_info.span, - ty: self.tcx().types.usize, user_ty: None, literal: ty::Const::from_usize(self.tcx(), val.into()), }) diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs index 68880fc345ae2..ac2701971dfd5 100644 --- a/src/librustc_mir/util/pretty.rs +++ b/src/librustc_mir/util/pretty.rs @@ -397,10 +397,9 @@ impl ExtraComments<'tcx> { impl Visitor<'tcx> for ExtraComments<'tcx> { fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) { self.super_constant(constant, location); - let Constant { span, ty, user_ty, literal } = constant; + let Constant { span, user_ty, literal } = constant; self.push("mir::Constant"); self.push(&format!("+ span: {:?}", span)); - self.push(&format!("+ ty: {:?}", ty)); if let Some(user_ty) = user_ty { self.push(&format!("+ user_ty: {:?}", user_ty)); } From 2882bee06520b754d7b302769014507aa54ed744 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Mon, 12 Aug 2019 18:15:45 +0300 Subject: [PATCH 23/35] rustc_mir: add sanity asserts for the types of `ty::Const`s. --- src/librustc_mir/build/expr/as_constant.rs | 1 + src/librustc_mir/build/matches/test.rs | 3 +++ src/librustc_mir/hair/pattern/mod.rs | 2 ++ 3 files changed, 6 insertions(+) diff --git a/src/librustc_mir/build/expr/as_constant.rs b/src/librustc_mir/build/expr/as_constant.rs index ec936f801c308..39bdc871d83c6 100644 --- a/src/librustc_mir/build/expr/as_constant.rs +++ b/src/librustc_mir/build/expr/as_constant.rs @@ -38,6 +38,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { inferred_ty: ty, }) }); + assert_eq!(literal.ty, ty); Constant { span, user_ty, diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs index b8ca67663ae2d..65e92d422b022 100644 --- a/src/librustc_mir/build/matches/test.rs +++ b/src/librustc_mir/build/matches/test.rs @@ -63,6 +63,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } PatternKind::Range(range) => { + assert_eq!(range.lo.ty, match_pair.pattern.ty); + assert_eq!(range.hi.ty, match_pair.pattern.ty); Test { span: match_pair.pattern.span, kind: TestKind::Range(range), @@ -269,6 +271,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ); } else { if let [success, fail] = *make_target_blocks(self) { + assert_eq!(value.ty, ty); let expect = self.literal_operand(test.span, value); let val = Operand::Copy(place.clone()); self.compare(block, success, fail, source_info, BinOp::Eq, expect, val); diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index c43bd765d2aab..b1eda0c559c90 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -441,6 +441,8 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { let mut kind = match (lo, hi) { (PatternKind::Constant { value: lo }, PatternKind::Constant { value: hi }) => { + assert_eq!(lo.ty, ty); + assert_eq!(hi.ty, ty); let cmp = compare_const_vals( self.tcx, lo, From 22127b159d80ab138bd3e60a4fcee006ff648ca0 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Mon, 12 Aug 2019 18:26:02 +0300 Subject: [PATCH 24/35] rustc_mir: use the right type for associated const literals. --- src/librustc_mir/hair/cx/expr.rs | 2 +- src/test/ui/dropck/dropck_trait_cycle_checked.stderr | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 1c6a743155ee4..a33d7207ed4e1 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -927,7 +927,7 @@ fn convert_path_expr<'a, 'tcx>( ExprKind::Literal { literal: cx.tcx.mk_const(ty::Const { val: ConstValue::Unevaluated(def_id, substs), - ty: cx.tcx.type_of(def_id), + ty: cx.tables().node_type(expr.hir_id), }), user_ty, } diff --git a/src/test/ui/dropck/dropck_trait_cycle_checked.stderr b/src/test/ui/dropck/dropck_trait_cycle_checked.stderr index 1e779208e58a5..dc3fbed593b79 100644 --- a/src/test/ui/dropck/dropck_trait_cycle_checked.stderr +++ b/src/test/ui/dropck/dropck_trait_cycle_checked.stderr @@ -2,7 +2,7 @@ error[E0597]: `o2` does not live long enough --> $DIR/dropck_trait_cycle_checked.rs:111:13 | LL | let (o1, o2, o3): (Box, Box, Box) = (O::new(), O::new(), O::new()); - | -------- cast requires that `o2` is borrowed for `'static` + | -------- cast requires that `o2` is borrowed for `'static` LL | o1.set0(&o2); | ^^^ borrowed value does not live long enough ... @@ -13,7 +13,7 @@ error[E0597]: `o3` does not live long enough --> $DIR/dropck_trait_cycle_checked.rs:112:13 | LL | let (o1, o2, o3): (Box, Box, Box) = (O::new(), O::new(), O::new()); - | -------- cast requires that `o3` is borrowed for `'static` + | -------- cast requires that `o3` is borrowed for `'static` LL | o1.set0(&o2); LL | o1.set1(&o3); | ^^^ borrowed value does not live long enough @@ -37,7 +37,7 @@ error[E0597]: `o3` does not live long enough --> $DIR/dropck_trait_cycle_checked.rs:114:13 | LL | let (o1, o2, o3): (Box, Box, Box) = (O::new(), O::new(), O::new()); - | -------- cast requires that `o3` is borrowed for `'static` + | -------- cast requires that `o3` is borrowed for `'static` ... LL | o2.set1(&o3); | ^^^ borrowed value does not live long enough @@ -49,7 +49,7 @@ error[E0597]: `o1` does not live long enough --> $DIR/dropck_trait_cycle_checked.rs:115:13 | LL | let (o1, o2, o3): (Box, Box, Box) = (O::new(), O::new(), O::new()); - | -------- cast requires that `o1` is borrowed for `'static` + | -------- cast requires that `o1` is borrowed for `'static` ... LL | o3.set0(&o1); | ^^^ borrowed value does not live long enough @@ -61,7 +61,7 @@ error[E0597]: `o2` does not live long enough --> $DIR/dropck_trait_cycle_checked.rs:116:13 | LL | let (o1, o2, o3): (Box, Box, Box) = (O::new(), O::new(), O::new()); - | -------- cast requires that `o2` is borrowed for `'static` + | -------- cast requires that `o2` is borrowed for `'static` ... LL | o3.set1(&o2); | ^^^ borrowed value does not live long enough From d30f4817ba956186333b5f01f572209932ce7394 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Mon, 12 Aug 2019 18:56:10 +0300 Subject: [PATCH 25/35] Fix indentation nit in src/librustc/mir/mod.rs. Co-Authored-By: bjorn3 --- src/librustc/mir/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 119114485ffbd..11701a6637744 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -3388,6 +3388,6 @@ impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> { } } fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.literal.visit_with(visitor) + self.literal.visit_with(visitor) } } From e9b3a0176440fa1696c730b55d82e68e8e6c41f6 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sun, 11 Aug 2019 12:55:31 -0400 Subject: [PATCH 26/35] Bump to 1.39 --- src/bootstrap/channel.rs | 2 +- src/stage0.txt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/bootstrap/channel.rs b/src/bootstrap/channel.rs index 8e8d8f5e787a7..caa4843da4d36 100644 --- a/src/bootstrap/channel.rs +++ b/src/bootstrap/channel.rs @@ -13,7 +13,7 @@ use build_helper::output; use crate::Build; // The version number -pub const CFG_RELEASE_NUM: &str = "1.38.0"; +pub const CFG_RELEASE_NUM: &str = "1.39.0"; pub struct GitInfo { inner: Option, diff --git a/src/stage0.txt b/src/stage0.txt index 14d65bef8f6dd..1a9e64a1862c9 100644 --- a/src/stage0.txt +++ b/src/stage0.txt @@ -12,7 +12,7 @@ # source tarball for a stable release you'll likely see `1.x.0` for rustc and # `0.x.0` for Cargo where they were released on `date`. -date: 2019-07-04 +date: 2019-08-13 rustc: beta cargo: beta @@ -25,7 +25,7 @@ cargo: beta # # This means that there's a small window of time (a few days) where artifacts # are downloaded from dev-static.rust-lang.org instead of static.rust-lang.org. -# In order to ease this transition we have an extra key which is in the +# In order to ease this transition we have an extra key which is in the # configuration file below. When uncommented this will instruct the bootstrap.py # script to download from dev-static.rust-lang.org. # From 376636e51719588edba82fc284328e14ce1f2d74 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 13 Aug 2019 20:51:54 +0300 Subject: [PATCH 27/35] syntax: Remove `DummyResult::expn_only` --- src/libsyntax/ext/base.rs | 39 +++++--------------------------- src/libsyntax_ext/asm.rs | 4 ++-- src/libsyntax_ext/assert.rs | 2 +- src/libsyntax_ext/cfg.rs | 2 +- src/libsyntax_ext/concat.rs | 8 +++---- src/libsyntax_ext/env.rs | 14 ++++++------ src/libsyntax_ext/format.rs | 2 +- src/libsyntax_ext/source_util.rs | 10 ++++---- 8 files changed, 27 insertions(+), 54 deletions(-) diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 7f4feff6be670..11544d43ac3e3 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -405,7 +405,6 @@ impl MacResult for MacEager { /// after hitting errors. #[derive(Copy, Clone)] pub struct DummyResult { - expr_only: bool, is_error: bool, span: Span, } @@ -416,21 +415,12 @@ impl DummyResult { /// Use this as a return value after hitting any errors and /// calling `span_err`. pub fn any(span: Span) -> Box { - Box::new(DummyResult { expr_only: false, is_error: true, span }) + Box::new(DummyResult { is_error: true, span }) } /// Same as `any`, but must be a valid fragment, not error. pub fn any_valid(span: Span) -> Box { - Box::new(DummyResult { expr_only: false, is_error: false, span }) - } - - /// Creates a default MacResult that can only be an expression. - /// - /// Use this for macros that must expand to an expression, so even - /// if an error is encountered internally, the user will receive - /// an error that they also used it in the wrong place. - pub fn expr(span: Span) -> Box { - Box::new(DummyResult { expr_only: true, is_error: true, span }) + Box::new(DummyResult { is_error: false, span }) } /// A plain dummy expression. @@ -472,36 +462,19 @@ impl MacResult for DummyResult { } fn make_items(self: Box) -> Option; 1]>> { - // this code needs a comment... why not always just return the Some() ? - if self.expr_only { - None - } else { - Some(SmallVec::new()) - } + Some(SmallVec::new()) } fn make_impl_items(self: Box) -> Option> { - if self.expr_only { - None - } else { - Some(SmallVec::new()) - } + Some(SmallVec::new()) } fn make_trait_items(self: Box) -> Option> { - if self.expr_only { - None - } else { - Some(SmallVec::new()) - } + Some(SmallVec::new()) } fn make_foreign_items(self: Box) -> Option> { - if self.expr_only { - None - } else { - Some(SmallVec::new()) - } + Some(SmallVec::new()) } fn make_stmts(self: Box) -> Option> { diff --git a/src/libsyntax_ext/asm.rs b/src/libsyntax_ext/asm.rs index c1c2732605c46..950166f9260e2 100644 --- a/src/libsyntax_ext/asm.rs +++ b/src/libsyntax_ext/asm.rs @@ -47,10 +47,10 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt<'_>, -> Box { let mut inline_asm = match parse_inline_asm(cx, sp, tts) { Ok(Some(inline_asm)) => inline_asm, - Ok(None) => return DummyResult::expr(sp), + Ok(None) => return DummyResult::any(sp), Err(mut err) => { err.emit(); - return DummyResult::expr(sp); + return DummyResult::any(sp); } }; diff --git a/src/libsyntax_ext/assert.rs b/src/libsyntax_ext/assert.rs index d7571f43eddd0..e3ef39075e236 100644 --- a/src/libsyntax_ext/assert.rs +++ b/src/libsyntax_ext/assert.rs @@ -20,7 +20,7 @@ pub fn expand_assert<'cx>( Ok(assert) => assert, Err(mut err) => { err.emit(); - return DummyResult::expr(sp); + return DummyResult::any(sp); } }; diff --git a/src/libsyntax_ext/cfg.rs b/src/libsyntax_ext/cfg.rs index 84830e6ddda1a..0e52c1af9086f 100644 --- a/src/libsyntax_ext/cfg.rs +++ b/src/libsyntax_ext/cfg.rs @@ -25,7 +25,7 @@ pub fn expand_cfg( } Err(mut err) => { err.emit(); - DummyResult::expr(sp) + DummyResult::any(sp) } } } diff --git a/src/libsyntax_ext/concat.rs b/src/libsyntax_ext/concat.rs index f1d079eb05379..4cd17531a4500 100644 --- a/src/libsyntax_ext/concat.rs +++ b/src/libsyntax_ext/concat.rs @@ -1,5 +1,5 @@ use syntax::ast; -use syntax::ext::base; +use syntax::ext::base::{self, DummyResult}; use syntax::symbol::Symbol; use syntax::tokenstream; @@ -12,7 +12,7 @@ pub fn expand_syntax_ext( ) -> Box { let es = match base::get_exprs_from_tts(cx, sp, tts) { Some(e) => e, - None => return base::DummyResult::expr(sp), + None => return DummyResult::any(sp), }; let mut accumulator = String::new(); let mut missing_literal = vec![]; @@ -55,9 +55,9 @@ pub fn expand_syntax_ext( let mut err = cx.struct_span_err(missing_literal, "expected a literal"); err.note("only literals (like `\"foo\"`, `42` and `3.14`) can be passed to `concat!()`"); err.emit(); - return base::DummyResult::expr(sp); + return DummyResult::any(sp); } else if has_errors { - return base::DummyResult::expr(sp); + return DummyResult::any(sp); } let sp = sp.apply_mark(cx.current_expansion.id); base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&accumulator))) diff --git a/src/libsyntax_ext/env.rs b/src/libsyntax_ext/env.rs index 39fc90decc92a..442f27c782185 100644 --- a/src/libsyntax_ext/env.rs +++ b/src/libsyntax_ext/env.rs @@ -16,7 +16,7 @@ pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt<'_>, tts: &[tokenstream::TokenTree]) -> Box { let var = match get_single_str_from_tts(cx, sp, tts, "option_env!") { - None => return DummyResult::expr(sp), + None => return DummyResult::any(sp), Some(v) => v, }; @@ -50,21 +50,21 @@ pub fn expand_env<'cx>(cx: &'cx mut ExtCtxt<'_>, let mut exprs = match get_exprs_from_tts(cx, sp, tts) { Some(ref exprs) if exprs.is_empty() => { cx.span_err(sp, "env! takes 1 or 2 arguments"); - return DummyResult::expr(sp); + return DummyResult::any(sp); } - None => return DummyResult::expr(sp), + None => return DummyResult::any(sp), Some(exprs) => exprs.into_iter(), }; let var = match expr_to_string(cx, exprs.next().unwrap(), "expected string literal") { - None => return DummyResult::expr(sp), + None => return DummyResult::any(sp), Some((v, _style)) => v, }; let msg = match exprs.next() { None => Symbol::intern(&format!("environment variable `{}` not defined", var)), Some(second) => { match expr_to_string(cx, second, "expected string literal") { - None => return DummyResult::expr(sp), + None => return DummyResult::any(sp), Some((s, _style)) => s, } } @@ -72,13 +72,13 @@ pub fn expand_env<'cx>(cx: &'cx mut ExtCtxt<'_>, if exprs.next().is_some() { cx.span_err(sp, "env! takes 1 or 2 arguments"); - return DummyResult::expr(sp); + return DummyResult::any(sp); } let e = match env::var(&*var.as_str()) { Err(_) => { cx.span_err(sp, &msg.as_str()); - return DummyResult::expr(sp); + return DummyResult::any(sp); } Ok(s) => cx.expr_str(sp, Symbol::intern(&s)), }; diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index 2ae13b66e2853..d699b3b1a90c2 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -805,7 +805,7 @@ fn expand_format_args_impl<'cx>( } Err(mut err) => { err.emit(); - DummyResult::expr(sp) + DummyResult::any(sp) } } } diff --git a/src/libsyntax_ext/source_util.rs b/src/libsyntax_ext/source_util.rs index 2c8d53a231550..cbc01b48afd03 100644 --- a/src/libsyntax_ext/source_util.rs +++ b/src/libsyntax_ext/source_util.rs @@ -111,7 +111,7 @@ pub fn expand_include_str(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::To -> Box { let file = match get_single_str_from_tts(cx, sp, tts, "include_str!") { Some(f) => f, - None => return DummyResult::expr(sp) + None => return DummyResult::any(sp) }; let file = cx.resolve_path(file, sp); match fs::read_to_string(&file) { @@ -126,11 +126,11 @@ pub fn expand_include_str(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::To }, Err(ref e) if e.kind() == ErrorKind::InvalidData => { cx.span_err(sp, &format!("{} wasn't a utf-8 file", file.display())); - DummyResult::expr(sp) + DummyResult::any(sp) } Err(e) => { cx.span_err(sp, &format!("couldn't read {}: {}", file.display(), e)); - DummyResult::expr(sp) + DummyResult::any(sp) } } } @@ -139,7 +139,7 @@ pub fn expand_include_bytes(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream:: -> Box { let file = match get_single_str_from_tts(cx, sp, tts, "include_bytes!") { Some(f) => f, - None => return DummyResult::expr(sp) + None => return DummyResult::any(sp) }; let file = cx.resolve_path(file, sp); match fs::read(&file) { @@ -158,7 +158,7 @@ pub fn expand_include_bytes(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream:: }, Err(e) => { cx.span_err(sp, &format!("couldn't read {}: {}", file.display(), e)); - DummyResult::expr(sp) + DummyResult::any(sp) } } } From 0d29142aad9554a23f0881be95110ad96365bfcf Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 14 Aug 2019 01:59:14 +0300 Subject: [PATCH 28/35] expand: `expand_fragment` -> `fully_expand_fragment` --- src/libsyntax/ext/expand.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 9a3195b1165b1..21cf232ecc34a 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -118,13 +118,13 @@ macro_rules! ast_fragments { impl<'a, 'b> MutVisitor for MacroExpander<'a, 'b> { fn filter_map_expr(&mut self, expr: P) -> Option> { - self.expand_fragment(AstFragment::OptExpr(Some(expr))).make_opt_expr() + self.fully_expand_fragment(AstFragment::OptExpr(Some(expr))).make_opt_expr() } $($(fn $mut_visit_ast(&mut self, ast: &mut $AstTy) { - visit_clobber(ast, |ast| self.expand_fragment(AstFragment::$Kind(ast)).$make_ast()); + visit_clobber(ast, |ast| self.fully_expand_fragment(AstFragment::$Kind(ast)).$make_ast()); })?)* $($(fn $flat_map_ast_elt(&mut self, ast_elt: <$AstTy as IntoIterator>::Item) -> $AstTy { - self.expand_fragment(AstFragment::$Kind(smallvec![ast_elt])).$make_ast() + self.fully_expand_fragment(AstFragment::$Kind(smallvec![ast_elt])).$make_ast() })?)* } @@ -265,7 +265,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { tokens: None, })]); - match self.expand_fragment(krate_item).make_items().pop().map(P::into_inner) { + match self.fully_expand_fragment(krate_item).make_items().pop().map(P::into_inner) { Some(ast::Item { attrs, node: ast::ItemKind::Mod(module), .. }) => { krate.attrs = attrs; krate.module = module; @@ -285,8 +285,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> { krate } - // Fully expand all macro invocations in this AST fragment. - fn expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragment { + // Recursively expand all macro invocations in this AST fragment. + fn fully_expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragment { let orig_expansion_data = self.cx.current_expansion.clone(); self.cx.current_expansion.depth = 0; From d416ebeb6ee265c980778df9bc4d84dc4a7b8580 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 14 Aug 2019 02:30:09 +0300 Subject: [PATCH 29/35] expand: Unimplement `MutVisitor` on `MacroExpander` Each call to `fully_expand_fragment` is something unique, interesting, and requiring attention. It represents a "root" of expansion and its use means that something unusual is happening, like eager expansion or expansion performed outside of the primary expansion pass. So, it shouldn't be hide under a generic visitor call. Also, from all the implemented visitor methods only two were actually used. --- src/libsyntax/ext/base.rs | 14 +++++++++---- src/libsyntax/ext/expand.rs | 14 +------------ src/libsyntax_ext/proc_macro_harness.rs | 9 +++++---- src/libsyntax_ext/test_harness.rs | 27 ++++++++++++++----------- 4 files changed, 31 insertions(+), 33 deletions(-) diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 7f4feff6be670..532de05eea214 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -947,8 +947,10 @@ pub fn expr_to_spanned_string<'a>( // Update `expr.span`'s ctxt now in case expr is an `include!` macro invocation. expr.span = expr.span.apply_mark(cx.current_expansion.id); - // we want to be able to handle e.g., `concat!("foo", "bar")` - cx.expander().visit_expr(&mut expr); + // Perform eager expansion on the expression. + // We want to be able to handle e.g., `concat!("foo", "bar")`. + let expr = cx.expander().fully_expand_fragment(AstFragment::Expr(expr)).make_expr(); + Err(match expr.node { ast::ExprKind::Lit(ref l) => match l.node { ast::LitKind::Str(s, style) => return Ok(respan(expr.span, (s, style))), @@ -1013,8 +1015,12 @@ pub fn get_exprs_from_tts(cx: &mut ExtCtxt<'_>, let mut p = cx.new_parser_from_tts(tts); let mut es = Vec::new(); while p.token != token::Eof { - let mut expr = panictry!(p.parse_expr()); - cx.expander().visit_expr(&mut expr); + let expr = panictry!(p.parse_expr()); + + // Perform eager expansion on the expression. + // We want to be able to handle e.g., `concat!("foo", "bar")`. + let expr = cx.expander().fully_expand_fragment(AstFragment::Expr(expr)).make_expr(); + es.push(expr); if p.eat(&token::Comma) { continue; diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 21cf232ecc34a..402b42dfbc80d 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -116,18 +116,6 @@ macro_rules! ast_fragments { } } - impl<'a, 'b> MutVisitor for MacroExpander<'a, 'b> { - fn filter_map_expr(&mut self, expr: P) -> Option> { - self.fully_expand_fragment(AstFragment::OptExpr(Some(expr))).make_opt_expr() - } - $($(fn $mut_visit_ast(&mut self, ast: &mut $AstTy) { - visit_clobber(ast, |ast| self.fully_expand_fragment(AstFragment::$Kind(ast)).$make_ast()); - })?)* - $($(fn $flat_map_ast_elt(&mut self, ast_elt: <$AstTy as IntoIterator>::Item) -> $AstTy { - self.fully_expand_fragment(AstFragment::$Kind(smallvec![ast_elt])).$make_ast() - })?)* - } - impl<'a> MacResult for crate::ext::tt::macro_rules::ParserAnyMacro<'a> { $(fn $make_ast(self: Box>) -> Option<$AstTy> { @@ -286,7 +274,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } // Recursively expand all macro invocations in this AST fragment. - fn fully_expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragment { + pub fn fully_expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragment { let orig_expansion_data = self.cx.current_expansion.clone(); self.cx.current_expansion.depth = 0; diff --git a/src/libsyntax_ext/proc_macro_harness.rs b/src/libsyntax_ext/proc_macro_harness.rs index 7913a7442edc7..70325539f301f 100644 --- a/src/libsyntax_ext/proc_macro_harness.rs +++ b/src/libsyntax_ext/proc_macro_harness.rs @@ -1,18 +1,17 @@ use std::mem; +use smallvec::smallvec; use syntax::ast::{self, Ident}; use syntax::attr; use syntax::source_map::{ExpnInfo, ExpnKind, respan}; use syntax::ext::base::{ExtCtxt, MacroKind}; -use syntax::ext::expand::ExpansionConfig; +use syntax::ext::expand::{AstFragment, ExpansionConfig}; use syntax::ext::hygiene::ExpnId; use syntax::ext::proc_macro::is_proc_macro_attr; -use syntax::mut_visit::MutVisitor; use syntax::parse::ParseSess; use syntax::ptr::P; use syntax::symbol::{kw, sym}; use syntax::visit::{self, Visitor}; - use syntax_pos::{Span, DUMMY_SP}; struct ProcMacroDerive { @@ -409,5 +408,7 @@ fn mk_decls( i }); - cx.monotonic_expander().flat_map_item(module).pop().unwrap() + // Integrate the new module into existing module structures. + let module = AstFragment::Items(smallvec![module]); + cx.monotonic_expander().fully_expand_fragment(module).make_items().pop().unwrap() } diff --git a/src/libsyntax_ext/test_harness.rs b/src/libsyntax_ext/test_harness.rs index eec8a3f802343..0267637e54062 100644 --- a/src/libsyntax_ext/test_harness.rs +++ b/src/libsyntax_ext/test_harness.rs @@ -6,7 +6,7 @@ use syntax::ast::{self, Ident}; use syntax::attr; use syntax::entry::{self, EntryPointType}; use syntax::ext::base::{ExtCtxt, Resolver}; -use syntax::ext::expand::ExpansionConfig; +use syntax::ext::expand::{AstFragment, ExpansionConfig}; use syntax::ext::hygiene::{ExpnId, MacroKind}; use syntax::feature_gate::Features; use syntax::mut_visit::{*, ExpectOne}; @@ -74,12 +74,7 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> { noop_visit_crate(c, self); // Create a main function to run our tests - let test_main = { - let unresolved = mk_main(&mut self.cx); - self.cx.ext_cx.monotonic_expander().flat_map_item(unresolved).pop().unwrap() - }; - - c.module.items.push(test_main); + c.module.items.push(mk_main(&mut self.cx)); } fn flat_map_item(&mut self, i: P) -> SmallVec<[P; 1]> { @@ -216,7 +211,7 @@ fn mk_reexport_mod(cx: &mut TestCtxt<'_>, let name = Ident::from_str("__test_reexports").gensym(); let parent = if parent == ast::DUMMY_NODE_ID { ast::CRATE_NODE_ID } else { parent }; cx.ext_cx.current_expansion.id = cx.ext_cx.resolver.get_module_scope(parent); - let it = cx.ext_cx.monotonic_expander().flat_map_item(P(ast::Item { + let module = P(ast::Item { ident: name, attrs: Vec::new(), id: ast::DUMMY_NODE_ID, @@ -224,9 +219,14 @@ fn mk_reexport_mod(cx: &mut TestCtxt<'_>, vis: dummy_spanned(ast::VisibilityKind::Public), span: DUMMY_SP, tokens: None, - })).pop().unwrap(); + }); - (it, name) + // Integrate the new module into existing module structures. + let module = AstFragment::Items(smallvec![module]); + let module = + cx.ext_cx.monotonic_expander().fully_expand_fragment(module).make_items().pop().unwrap(); + + (module, name) } /// Crawl over the crate, inserting test reexports and the test main function @@ -321,7 +321,7 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P { None => Ident::from_str_and_span("main", sp).gensym(), }; - P(ast::Item { + let main = P(ast::Item { ident: main_id, attrs: vec![main_attr], id: ast::DUMMY_NODE_ID, @@ -329,8 +329,11 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P { vis: dummy_spanned(ast::VisibilityKind::Public), span: sp, tokens: None, - }) + }); + // Integrate the new item into existing module structures. + let main = AstFragment::Items(smallvec![main]); + cx.ext_cx.monotonic_expander().fully_expand_fragment(main).make_items().pop().unwrap() } fn path_name_i(idents: &[Ident]) -> String { From 9348af8396c961f8bb79cc360c091d74ea4ba34a Mon Sep 17 00:00:00 2001 From: Caio Date: Tue, 13 Aug 2019 22:22:51 -0300 Subject: [PATCH 30/35] Add NodeId for Arm, Field and FieldPat --- src/libsyntax/ast.rs | 3 +++ src/libsyntax/ext/build.rs | 2 ++ src/libsyntax/mut_visit.rs | 12 +++++++++--- src/libsyntax/parse/parser/expr.rs | 3 +++ src/libsyntax/parse/parser/pat.rs | 1 + src/libsyntax_ext/deriving/generic/mod.rs | 1 + 6 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 052eb55b40811..aadf7ec5588b4 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -608,6 +608,7 @@ pub struct FieldPat { pub pat: P, pub is_shorthand: bool, pub attrs: ThinVec, + pub id: NodeId, } #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)] @@ -925,6 +926,7 @@ pub struct Arm { pub guard: Option>, pub body: P, pub span: Span, + pub id: NodeId, } #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] @@ -934,6 +936,7 @@ pub struct Field { pub span: Span, pub is_shorthand: bool, pub attrs: ThinVec, + pub id: NodeId, } pub type SpannedIdent = Spanned; diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 22962499a2b75..aab782d612e1b 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -403,6 +403,7 @@ impl<'a> ExtCtxt<'a> { span, is_shorthand: false, attrs: ThinVec::new(), + id: ast::DUMMY_NODE_ID, } } pub fn expr_struct( @@ -612,6 +613,7 @@ impl<'a> ExtCtxt<'a> { guard: None, body: expr, span, + id: ast::DUMMY_NODE_ID, } } diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index be04c6a76b06d..f910aaaf8fa7b 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -383,10 +383,11 @@ pub fn noop_visit_use_tree(use_tree: &mut UseTree, vis: &mut T) { } pub fn noop_visit_arm( - Arm { attrs, pats, guard, body, span }: &mut Arm, + Arm { attrs, pats, guard, body, span, id }: &mut Arm, vis: &mut T, ) { visit_attrs(attrs, vis); + vis.visit_id(id); visit_vec(pats, |pat| vis.visit_pat(pat)); visit_opt(guard, |guard| vis.visit_expr(guard)); vis.visit_expr(body); @@ -808,9 +809,10 @@ pub fn noop_visit_struct_field(f: &mut StructField, visitor: &mut } pub fn noop_visit_field(f: &mut Field, vis: &mut T) { - let Field { ident, expr, span, is_shorthand: _, attrs } = f; + let Field { ident, expr, span, is_shorthand: _, attrs, id } = f; vis.visit_ident(ident); vis.visit_expr(expr); + vis.visit_id(id); vis.visit_span(span); visit_thin_attrs(attrs, vis); } @@ -1040,8 +1042,12 @@ pub fn noop_visit_pat(pat: &mut P, vis: &mut T) { } PatKind::Struct(path, fields, _etc) => { vis.visit_path(path); - for Spanned { node: FieldPat { ident, pat, is_shorthand: _, attrs }, span } in fields { + for Spanned { + node: FieldPat { ident, pat, is_shorthand: _, attrs, id }, + span + } in fields { vis.visit_ident(ident); + vis.visit_id(id); vis.visit_pat(pat); visit_thin_attrs(attrs, vis); vis.visit_span(span); diff --git a/src/libsyntax/parse/parser/expr.rs b/src/libsyntax/parse/parser/expr.rs index 4432c1329cbfe..823dca2c9e765 100644 --- a/src/libsyntax/parse/parser/expr.rs +++ b/src/libsyntax/parse/parser/expr.rs @@ -1444,6 +1444,7 @@ impl<'a> Parser<'a> { guard, body: expr, span: lo.to(hi), + id: ast::DUMMY_NODE_ID, }) } @@ -1599,6 +1600,7 @@ impl<'a> Parser<'a> { expr: self.mk_expr(self.token.span, ExprKind::Err, ThinVec::new()), is_shorthand: false, attrs: ThinVec::new(), + id: ast::DUMMY_NODE_ID, }); } } @@ -1684,6 +1686,7 @@ impl<'a> Parser<'a> { expr, is_shorthand, attrs: attrs.into(), + id: ast::DUMMY_NODE_ID, }) } diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index 5cc428a4df1de..5a1b41645099b 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -620,6 +620,7 @@ impl<'a> Parser<'a> { pat: subpat, is_shorthand, attrs: attrs.into(), + id: ast::DUMMY_NODE_ID, } }) } diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index 7e6d9126c8740..b21a6e7bc78a0 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -1613,6 +1613,7 @@ impl<'a> TraitDef<'a> { source_map::Spanned { span: pat.span.with_ctxt(self.span.ctxt()), node: ast::FieldPat { + id: ast::DUMMY_NODE_ID, ident: ident.unwrap(), pat, is_shorthand: false, From 2601c864878412814134f417b7a738e5ee8898f2 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sun, 11 Aug 2019 12:55:14 -0400 Subject: [PATCH 31/35] Handle cfg(bootstrap) throughout --- src/bootstrap/bin/rustc.rs | 5 +-- src/bootstrap/builder.rs | 2 +- src/liballoc/collections/btree/node.rs | 6 ++-- src/liballoc/lib.rs | 6 ++-- src/libcore/any.rs | 5 --- src/libcore/char/methods.rs | 14 ++------ src/libcore/clone.rs | 1 - src/libcore/cmp.rs | 4 --- src/libcore/default.rs | 1 - src/libcore/fmt/mod.rs | 2 -- src/libcore/hash/mod.rs | 2 -- src/libcore/lib.rs | 4 +-- src/libcore/macros.rs | 35 ------------------- src/libcore/marker.rs | 1 - src/libcore/mem/maybe_uninit.rs | 2 +- src/libcore/mem/mod.rs | 4 +-- src/libcore/prelude/v1.rs | 4 --- src/librustc/lint/context.rs | 4 +-- src/librustc/lint/internal.rs | 2 +- src/librustc/ty/codec.rs | 4 +-- src/librustc/ty/context.rs | 6 ++-- src/librustc/ty/flags.rs | 4 +-- src/librustc/ty/mod.rs | 2 +- src/librustc/ty/sty.rs | 2 +- src/librustc_data_structures/lib.rs | 2 +- src/librustc_macros/src/lib.rs | 2 +- src/librustc_target/abi/mod.rs | 19 ++++------ src/librustc_typeck/check/mod.rs | 4 +-- src/libstd/lib.rs | 5 ++- src/libstd/os/raw/mod.rs | 48 +++++++++----------------- src/libstd/prelude/v1.rs | 18 ---------- src/libstd/sync/mod.rs | 1 - src/libstd/sys/cloudabi/mod.rs | 2 +- src/libunwind/build.rs | 8 ++--- src/libunwind/libunwind.rs | 10 +++--- src/test/ui/lint/lint-qualification.rs | 2 +- 36 files changed, 64 insertions(+), 179 deletions(-) diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index 54b689fb062a5..04a3dea5c8791 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -132,10 +132,7 @@ fn main() { cmd.arg("-Dwarnings"); cmd.arg("-Drust_2018_idioms"); cmd.arg("-Dunused_lifetimes"); - // cfg(not(bootstrap)): Remove this during the next stage 0 compiler update. - // `-Drustc::internal` is a new feature and `rustc_version` mis-reports the `stage`. - let cfg_not_bootstrap = stage != "0" && crate_name != Some("rustc_version"); - if cfg_not_bootstrap && use_internal_lints(crate_name) { + if use_internal_lints(crate_name) { cmd.arg("-Zunstable-options"); cmd.arg("-Drustc::internal"); } diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index e54c9360baece..9e4cd5ebca749 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -145,7 +145,7 @@ impl StepDescription { only_hosts: S::ONLY_HOSTS, should_run: S::should_run, make_run: S::make_run, - name: unsafe { ::std::intrinsics::type_name::() }, + name: std::any::type_name::(), } } diff --git a/src/liballoc/collections/btree/node.rs b/src/liballoc/collections/btree/node.rs index e067096f0c780..0b5a271dbea95 100644 --- a/src/liballoc/collections/btree/node.rs +++ b/src/liballoc/collections/btree/node.rs @@ -106,8 +106,8 @@ impl LeafNode { LeafNode { // As a general policy, we leave fields uninitialized if they can be, as this should // be both slightly faster and easier to track in Valgrind. - keys: uninit_array![_; CAPACITY], - vals: uninit_array![_; CAPACITY], + keys: [MaybeUninit::UNINIT; CAPACITY], + vals: [MaybeUninit::UNINIT; CAPACITY], parent: ptr::null(), parent_idx: MaybeUninit::uninit(), len: 0 @@ -159,7 +159,7 @@ impl InternalNode { unsafe fn new() -> Self { InternalNode { data: LeafNode::new(), - edges: uninit_array![_; 2*B], + edges: [MaybeUninit::UNINIT; 2*B] } } } diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index a1936b36ac6bf..7421beddd9574 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -69,7 +69,7 @@ #![warn(missing_debug_implementations)] #![deny(intra_doc_link_resolution_failure)] // rustdoc is run without -D warnings #![allow(explicit_outlives_requirements)] -#![cfg_attr(not(bootstrap), allow(incomplete_features))] +#![allow(incomplete_features)] #![cfg_attr(not(test), feature(generator_trait))] #![cfg_attr(test, feature(test))] @@ -84,7 +84,7 @@ #![feature(coerce_unsized)] #![feature(const_generic_impls_guard)] #![feature(const_generics)] -#![cfg_attr(not(bootstrap), feature(const_in_array_repeat_expressions))] +#![feature(const_in_array_repeat_expressions)] #![feature(dispatch_from_dyn)] #![feature(core_intrinsics)] #![feature(dropck_eyepatch)] @@ -118,7 +118,7 @@ #![feature(rustc_const_unstable)] #![feature(const_vec_new)] #![feature(slice_partition_dedup)] -#![feature(maybe_uninit_extra, maybe_uninit_slice, maybe_uninit_array)] +#![feature(maybe_uninit_extra, maybe_uninit_slice)] #![feature(alloc_layout_extra)] #![feature(try_trait)] #![feature(mem_take)] diff --git a/src/libcore/any.rs b/src/libcore/any.rs index 078091a9b5475..e8a0a88f12a7e 100644 --- a/src/libcore/any.rs +++ b/src/libcore/any.rs @@ -470,10 +470,5 @@ impl TypeId { #[stable(feature = "type_name", since = "1.38.0")] #[rustc_const_unstable(feature = "const_type_name")] pub const fn type_name() -> &'static str { - #[cfg(bootstrap)] - unsafe { - intrinsics::type_name::() - } - #[cfg(not(bootstrap))] intrinsics::type_name::() } diff --git a/src/libcore/char/methods.rs b/src/libcore/char/methods.rs index aa834db2b9b3e..e91bf53c5b418 100644 --- a/src/libcore/char/methods.rs +++ b/src/libcore/char/methods.rs @@ -553,12 +553,7 @@ impl char { /// `XID_Start` is a Unicode Derived Property specified in /// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications), /// mostly similar to `ID_Start` but modified for closure under `NFKx`. - #[cfg_attr(bootstrap, - unstable(feature = "rustc_private", - reason = "mainly needed for compiler internals", - issue = "27812"))] - #[cfg_attr(not(bootstrap), - unstable(feature = "unicode_internals", issue = "0"))] + #[unstable(feature = "unicode_internals", issue = "0")] pub fn is_xid_start(self) -> bool { derived_property::XID_Start(self) } @@ -569,12 +564,7 @@ impl char { /// `XID_Continue` is a Unicode Derived Property specified in /// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications), /// mostly similar to `ID_Continue` but modified for closure under NFKx. - #[cfg_attr(bootstrap, - unstable(feature = "rustc_private", - reason = "mainly needed for compiler internals", - issue = "27812"))] - #[cfg_attr(not(bootstrap), - unstable(feature = "unicode_internals", issue = "0"))] + #[unstable(feature = "unicode_internals", issue = "0")] #[inline] pub fn is_xid_continue(self) -> bool { derived_property::XID_Continue(self) diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs index 0c99356390bda..ec22a7ccfe4c3 100644 --- a/src/libcore/clone.rs +++ b/src/libcore/clone.rs @@ -134,7 +134,6 @@ pub trait Clone : Sized { } /// Derive macro generating an impl of the trait `Clone`. -#[cfg(not(bootstrap))] #[rustc_builtin_macro] #[rustc_macro_transparency = "semitransparent"] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 38a52d97da212..b802216036b93 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -201,7 +201,6 @@ pub trait PartialEq { } /// Derive macro generating an impl of the trait `PartialEq`. -#[cfg(not(bootstrap))] #[rustc_builtin_macro] #[rustc_macro_transparency = "semitransparent"] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] @@ -265,7 +264,6 @@ pub trait Eq: PartialEq { } /// Derive macro generating an impl of the trait `Eq`. -#[cfg(not(bootstrap))] #[rustc_builtin_macro] #[rustc_macro_transparency = "semitransparent"] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] @@ -617,7 +615,6 @@ pub trait Ord: Eq + PartialOrd { } /// Derive macro generating an impl of the trait `Ord`. -#[cfg(not(bootstrap))] #[rustc_builtin_macro] #[rustc_macro_transparency = "semitransparent"] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] @@ -867,7 +864,6 @@ pub trait PartialOrd: PartialEq { } /// Derive macro generating an impl of the trait `PartialOrd`. -#[cfg(not(bootstrap))] #[rustc_builtin_macro] #[rustc_macro_transparency = "semitransparent"] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] diff --git a/src/libcore/default.rs b/src/libcore/default.rs index 8d95e9de15849..9b1616ccce448 100644 --- a/src/libcore/default.rs +++ b/src/libcore/default.rs @@ -116,7 +116,6 @@ pub trait Default: Sized { } /// Derive macro generating an impl of the trait `Default`. -#[cfg(not(bootstrap))] #[rustc_builtin_macro] #[rustc_macro_transparency = "semitransparent"] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 0ea01d4b84a2c..d5fae9e740136 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -546,7 +546,6 @@ pub trait Debug { } // Separate module to reexport the macro `Debug` from prelude without the trait `Debug`. -#[cfg(not(bootstrap))] pub(crate) mod macros { /// Derive macro generating an impl of the trait `Debug`. #[rustc_builtin_macro] @@ -555,7 +554,6 @@ pub(crate) mod macros { #[allow_internal_unstable(core_intrinsics)] pub macro Debug($item:item) { /* compiler built-in */ } } -#[cfg(not(bootstrap))] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[doc(inline)] pub use macros::Debug; diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs index c4cbf40a93a15..40b827b878782 100644 --- a/src/libcore/hash/mod.rs +++ b/src/libcore/hash/mod.rs @@ -199,7 +199,6 @@ pub trait Hash { } // Separate module to reexport the macro `Hash` from prelude without the trait `Hash`. -#[cfg(not(bootstrap))] pub(crate) mod macros { /// Derive macro generating an impl of the trait `Hash`. #[rustc_builtin_macro] @@ -208,7 +207,6 @@ pub(crate) mod macros { #[allow_internal_unstable(core_intrinsics)] pub macro Hash($item:item) { /* compiler built-in */ } } -#[cfg(not(bootstrap))] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[doc(inline)] pub use macros::Hash; diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 678ff7687921b..c168d5c8a2eac 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -63,7 +63,7 @@ #![warn(missing_debug_implementations)] #![deny(intra_doc_link_resolution_failure)] // rustdoc is run without -D warnings #![allow(explicit_outlives_requirements)] -#![cfg_attr(not(bootstrap), allow(incomplete_features))] +#![allow(incomplete_features)] #![feature(allow_internal_unstable)] #![feature(arbitrary_self_types)] @@ -129,7 +129,7 @@ #![feature(structural_match)] #![feature(abi_unadjusted)] #![feature(adx_target_feature)] -#![feature(maybe_uninit_slice, maybe_uninit_array)] +#![feature(maybe_uninit_slice)] #![feature(external_doc)] #![feature(mem_take)] #![feature(associated_type_bounds)] diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index f9dc53874acb1..bbed95167161d 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -635,46 +635,11 @@ macro_rules! todo { ($($arg:tt)+) => (panic!("not yet implemented: {}", format_args!($($arg)+))); } -/// Creates an array of [`MaybeUninit`]. -/// -/// This macro constructs an uninitialized array of the type `[MaybeUninit; N]`. -/// It exists solely because bootstrap does not yet support const array-init expressions. -/// -/// [`MaybeUninit`]: mem/union.MaybeUninit.html -// FIXME: Remove both versions of this macro once bootstrap is 1.38. -#[macro_export] -#[unstable(feature = "maybe_uninit_array", issue = "53491")] -#[cfg(bootstrap)] -macro_rules! uninit_array { - // This `assume_init` is safe because an array of `MaybeUninit` does not - // require initialization. - ($t:ty; $size:expr) => (unsafe { - MaybeUninit::<[MaybeUninit<$t>; $size]>::uninit().assume_init() - }); -} - -/// Creates an array of [`MaybeUninit`]. -/// -/// This macro constructs an uninitialized array of the type `[MaybeUninit; N]`. -/// It exists solely because bootstrap does not yet support const array-init expressions. -/// -/// [`MaybeUninit`]: mem/union.MaybeUninit.html -// FIXME: Just inline this version of the macro once bootstrap is 1.38. -#[macro_export] -#[unstable(feature = "maybe_uninit_array", issue = "53491")] -#[cfg(not(bootstrap))] -macro_rules! uninit_array { - ($t:ty; $size:expr) => ( - [MaybeUninit::<$t>::UNINIT; $size] - ); -} - /// Definitions of built-in macros. /// /// Most of the macro properties (stability, visibility, etc.) are taken from the source code here, /// with exception of expansion functions transforming macro inputs into outputs, /// those functions are provided by the compiler. -#[cfg(not(bootstrap))] pub(crate) mod builtin { /// Causes compilation to fail with the given error message when encountered. diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index 78a273611650c..3befd421b0125 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -289,7 +289,6 @@ pub trait Copy : Clone { } /// Derive macro generating an impl of the trait `Copy`. -#[cfg(not(bootstrap))] #[rustc_builtin_macro] #[rustc_macro_transparency = "semitransparent"] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] diff --git a/src/libcore/mem/maybe_uninit.rs b/src/libcore/mem/maybe_uninit.rs index 1bbea02e0c7c9..49711607262df 100644 --- a/src/libcore/mem/maybe_uninit.rs +++ b/src/libcore/mem/maybe_uninit.rs @@ -213,7 +213,7 @@ use crate::mem::ManuallyDrop; #[allow(missing_debug_implementations)] #[stable(feature = "maybe_uninit", since = "1.36.0")] // Lang item so we can wrap other types in it. This is useful for generators. -#[cfg_attr(not(bootstrap), lang = "maybe_uninit")] +#[lang = "maybe_uninit"] #[derive(Copy)] #[repr(transparent)] pub union MaybeUninit { diff --git a/src/libcore/mem/mod.rs b/src/libcore/mem/mod.rs index 2534400b8334f..87ec05a243d36 100644 --- a/src/libcore/mem/mod.rs +++ b/src/libcore/mem/mod.rs @@ -453,7 +453,7 @@ pub const fn needs_drop() -> bool { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(bootstrap, allow(deprecated_in_future))] +#[allow(deprecated_in_future)] #[allow(deprecated)] pub unsafe fn zeroed() -> T { intrinsics::panic_if_uninhabited::(); @@ -481,7 +481,7 @@ pub unsafe fn zeroed() -> T { #[inline] #[rustc_deprecated(since = "1.39.0", reason = "use `mem::MaybeUninit` instead")] #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(bootstrap, allow(deprecated_in_future))] +#[allow(deprecated_in_future)] #[allow(deprecated)] pub unsafe fn uninitialized() -> T { intrinsics::panic_if_uninhabited::(); diff --git a/src/libcore/prelude/v1.rs b/src/libcore/prelude/v1.rs index 84cf85f339c99..762403790403d 100644 --- a/src/libcore/prelude/v1.rs +++ b/src/libcore/prelude/v1.rs @@ -46,16 +46,13 @@ pub use crate::option::Option::{self, Some, None}; pub use crate::result::Result::{self, Ok, Err}; // Re-exported built-in macros -#[cfg(not(bootstrap))] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[doc(no_inline)] pub use crate::fmt::macros::Debug; -#[cfg(not(bootstrap))] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[doc(no_inline)] pub use crate::hash::macros::Hash; -#[cfg(not(bootstrap))] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[doc(no_inline)] pub use crate::{ @@ -83,7 +80,6 @@ pub use crate::{ trace_macros, }; -#[cfg(not(bootstrap))] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow(deprecated)] #[doc(no_inline)] diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index de812410e8bd8..3584a12829018 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -1355,7 +1355,7 @@ struct LateLintPassObjects<'a> { lints: &'a mut [LateLintPassObject], } -#[cfg_attr(not(bootstrap), allow(rustc::lint_pass_impl_without_macro))] +#[allow(rustc::lint_pass_impl_without_macro)] impl LintPass for LateLintPassObjects<'_> { fn name(&self) -> &'static str { panic!() @@ -1525,7 +1525,7 @@ struct EarlyLintPassObjects<'a> { lints: &'a mut [EarlyLintPassObject], } -#[cfg_attr(not(bootstrap), allow(rustc::lint_pass_impl_without_macro))] +#[allow(rustc::lint_pass_impl_without_macro)] impl LintPass for EarlyLintPassObjects<'_> { fn name(&self) -> &'static str { panic!() diff --git a/src/librustc/lint/internal.rs b/src/librustc/lint/internal.rs index 0b514f5927d30..dea1cc6601b04 100644 --- a/src/librustc/lint/internal.rs +++ b/src/librustc/lint/internal.rs @@ -23,7 +23,7 @@ pub struct DefaultHashTypes { impl DefaultHashTypes { // we are allowed to use `HashMap` and `HashSet` as identifiers for implementing the lint itself - #[cfg_attr(not(bootstrap), allow(rustc::default_hash_types))] + #[allow(rustc::default_hash_types)] pub fn new() -> Self { let mut map = FxHashMap::default(); map.insert(sym::HashMap, sym::FxHashMap); diff --git a/src/librustc/ty/codec.rs b/src/librustc/ty/codec.rs index e3c6eca02d554..1ddc6780aca89 100644 --- a/src/librustc/ty/codec.rs +++ b/src/librustc/ty/codec.rs @@ -27,7 +27,7 @@ pub trait EncodableWithShorthand: Clone + Eq + Hash { fn variant(&self) -> &Self::Variant; } -#[cfg_attr(not(bootstrap), allow(rustc::usage_of_ty_tykind))] +#[allow(rustc::usage_of_ty_tykind)] impl<'tcx> EncodableWithShorthand for Ty<'tcx> { type Variant = ty::TyKind<'tcx>; fn variant(&self) -> &Self::Variant { @@ -160,7 +160,7 @@ where Ok(decoder.map_encoded_cnum_to_current(cnum)) } -#[cfg_attr(not(bootstrap), allow(rustc::usage_of_ty_tykind))] +#[allow(rustc::usage_of_ty_tykind)] #[inline] pub fn decode_ty(decoder: &mut D) -> Result, D::Error> where diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index ef74d9e5b2899..d504ba4dfe086 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -130,7 +130,7 @@ impl<'tcx> CtxtInterners<'tcx> { } /// Intern a type - #[cfg_attr(not(bootstrap), allow(rustc::usage_of_ty_tykind))] + #[allow(rustc::usage_of_ty_tykind)] #[inline(never)] fn intern_ty(&self, st: TyKind<'tcx> @@ -2076,7 +2076,7 @@ impl<'tcx> Hash for Interned<'tcx, TyS<'tcx>> { } } -#[cfg_attr(not(bootstrap), allow(rustc::usage_of_ty_tykind))] +#[allow(rustc::usage_of_ty_tykind)] impl<'tcx> Borrow> for Interned<'tcx, TyS<'tcx>> { fn borrow<'a>(&'a self) -> &'a TyKind<'tcx> { &self.0.sty @@ -2291,7 +2291,7 @@ impl<'tcx> TyCtxt<'tcx> { self.mk_fn_ptr(converted_sig) } - #[cfg_attr(not(bootstrap), allow(rustc::usage_of_ty_tykind))] + #[allow(rustc::usage_of_ty_tykind)] #[inline] pub fn mk_ty(&self, st: TyKind<'tcx>) -> Ty<'tcx> { self.interners.intern_ty(st) diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index 411b18e043a20..9119505acd174 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -18,7 +18,7 @@ impl FlagComputation { } } - #[cfg_attr(not(bootstrap), allow(rustc::usage_of_ty_tykind))] + #[allow(rustc::usage_of_ty_tykind)] pub fn for_sty(st: &ty::TyKind<'_>) -> FlagComputation { let mut result = FlagComputation::new(); result.add_sty(st); @@ -62,7 +62,7 @@ impl FlagComputation { } // otherwise, this binder captures nothing } - #[cfg_attr(not(bootstrap), allow(rustc::usage_of_ty_tykind))] + #[allow(rustc::usage_of_ty_tykind)] fn add_sty(&mut self, st: &ty::TyKind<'_>) { match st { &ty::Bool | diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 9d563e290de96..a8ff36a394657 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -483,7 +483,7 @@ bitflags! { } } -#[cfg_attr(not(bootstrap), allow(rustc::usage_of_ty_tykind))] +#[allow(rustc::usage_of_ty_tykind)] pub struct TyS<'tcx> { pub sty: TyKind<'tcx>, pub flags: TypeFlags, diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 129ea9b5b674a..42e367b851825 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -1,6 +1,6 @@ //! This module contains `TyKind` and its major components. -#![cfg_attr(not(bootstrap), allow(rustc::usage_of_ty_tykind))] +#![allow(rustc::usage_of_ty_tykind)] use crate::hir; use crate::hir::def_id::DefId; diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index 9f103437d368e..f7593501959c7 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -27,7 +27,7 @@ #![cfg_attr(unix, feature(libc))] -#![cfg_attr(not(bootstrap), allow(rustc::default_hash_types))] +#![allow(rustc::default_hash_types)] #[macro_use] extern crate log; diff --git a/src/librustc_macros/src/lib.rs b/src/librustc_macros/src/lib.rs index 85e2247ebd7e3..3d3a020ef0c8e 100644 --- a/src/librustc_macros/src/lib.rs +++ b/src/librustc_macros/src/lib.rs @@ -1,5 +1,5 @@ #![feature(proc_macro_hygiene)] -#![cfg_attr(not(bootstrap), allow(rustc::default_hash_types))] +#![allow(rustc::default_hash_types)] #![recursion_limit="128"] diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index dd7ae742a63c6..dafa866117681 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -114,26 +114,20 @@ impl TargetDataLayout { [p] if p.starts_with("P") => { dl.instruction_address_space = parse_address_space(&p[1..], "P")? } - // FIXME: Ping cfg(bootstrap) -- Use `ref a @ ..` with new bootstrap compiler. - ["a", ..] => { - let a = &spec_parts[1..]; // FIXME inline into pattern. + ["a", ref a @ ..] => { dl.aggregate_align = align(a, "a")? } - ["f32", ..] => { - let a = &spec_parts[1..]; // FIXME inline into pattern. + ["f32", ref a @ ..] => { dl.f32_align = align(a, "f32")? } - ["f64", ..] => { - let a = &spec_parts[1..]; // FIXME inline into pattern. + ["f64", ref a @ ..] => { dl.f64_align = align(a, "f64")? } - [p @ "p", s, ..] | [p @ "p0", s, ..] => { - let a = &spec_parts[2..]; // FIXME inline into pattern. + [p @ "p", s, ref a @ ..] | [p @ "p0", s, ref a @ ..] => { dl.pointer_size = size(s, p)?; dl.pointer_align = align(a, p)?; } - [s, ..] if s.starts_with("i") => { - let a = &spec_parts[1..]; // FIXME inline into pattern. + [s, ref a @ ..] if s.starts_with("i") => { let bits = match s[1..].parse::() { Ok(bits) => bits, Err(_) => { @@ -157,8 +151,7 @@ impl TargetDataLayout { dl.i128_align = a; } } - [s, ..] if s.starts_with("v") => { - let a = &spec_parts[1..]; // FIXME inline into pattern. + [s, ref a @ ..] if s.starts_with("v") => { let v_size = size(&s[1..], "v")?; let a = align(a, s)?; if let Some(v) = dl.vector_align.iter_mut().find(|v| v.0 == v_size) { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 4fb28db6e94fa..daad2f28fdade 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1834,9 +1834,7 @@ fn bad_variant_count<'tcx>(tcx: TyCtxt<'tcx>, adt: &'tcx ty::AdtDef, sp: Span, d ); let mut err = struct_span_err!(tcx.sess, sp, E0731, "transparent enum {}", msg); err.span_label(sp, &msg); - if let &[.., ref end] = &variant_spans[..] { - // FIXME: Ping cfg(bootstrap) -- Use `ref start @ ..` with new bootstrap compiler. - let start = &variant_spans[..variant_spans.len() - 1]; + if let &[ref start @ .., ref end] = &variant_spans[..] { for variant_span in start { err.span_label(*variant_span, ""); } diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index ba80d1b70049a..1f48315d3f8db 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -228,7 +228,7 @@ // std is implemented with unstable features, many of which are internal // compiler details that will never be stable // NB: the following list is sorted to minimize merge conflicts. -#![cfg_attr(not(bootstrap), feature(__rust_unstable_column))] +#![feature(__rust_unstable_column)] #![feature(alloc_error_handler)] #![feature(alloc_layout_extra)] #![feature(allocator_api)] @@ -513,7 +513,7 @@ pub use std_detect::detect; // Re-export macros defined in libcore. #[stable(feature = "rust1", since = "1.0.0")] -#[allow(deprecated_in_future)] +#[allow(deprecated, deprecated_in_future)] pub use core::{ // Stable assert_eq, @@ -531,7 +531,6 @@ pub use core::{ }; // Re-export built-in macros defined through libcore. -#[cfg(not(bootstrap))] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] pub use core::{ // Stable diff --git a/src/libstd/os/raw/mod.rs b/src/libstd/os/raw/mod.rs index 0761c50f4b229..611a1709c8d91 100644 --- a/src/libstd/os/raw/mod.rs +++ b/src/libstd/os/raw/mod.rs @@ -8,8 +8,7 @@ #![stable(feature = "raw_os", since = "1.1.0")] -#[cfg_attr(bootstrap, doc(include = "os/raw/char.md"))] -#[cfg_attr(not(bootstrap), doc(include = "char.md"))] +#[doc(include = "char.md")] #[cfg(any(all(target_os = "linux", any(target_arch = "aarch64", target_arch = "arm", target_arch = "hexagon", @@ -33,8 +32,7 @@ target_arch = "powerpc")), all(target_os = "fuchsia", target_arch = "aarch64")))] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = u8; -#[cfg_attr(bootstrap, doc(include = "os/raw/char.md"))] -#[cfg_attr(not(bootstrap), doc(include = "char.md"))] +#[doc(include = "char.md")] #[cfg(not(any(all(target_os = "linux", any(target_arch = "aarch64", target_arch = "arm", target_arch = "hexagon", @@ -58,51 +56,37 @@ target_arch = "powerpc")), all(target_os = "fuchsia", target_arch = "aarch64"))))] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = i8; -#[cfg_attr(bootstrap, doc(include = "os/raw/schar.md"))] -#[cfg_attr(not(bootstrap), doc(include = "schar.md"))] +#[doc(include = "schar.md")] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_schar = i8; -#[cfg_attr(bootstrap, doc(include = "os/raw/uchar.md"))] -#[cfg_attr(not(bootstrap), doc(include = "uchar.md"))] +#[doc(include = "uchar.md")] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_uchar = u8; -#[cfg_attr(bootstrap, doc(include = "os/raw/short.md"))] -#[cfg_attr(not(bootstrap), doc(include = "short.md"))] +#[doc(include = "short.md")] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_short = i16; -#[cfg_attr(bootstrap, doc(include = "os/raw/ushort.md"))] -#[cfg_attr(not(bootstrap), doc(include = "ushort.md"))] +#[doc(include = "ushort.md")] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_ushort = u16; -#[cfg_attr(bootstrap, doc(include = "os/raw/int.md"))] -#[cfg_attr(not(bootstrap), doc(include = "int.md"))] +#[doc(include = "int.md")] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_int = i32; -#[cfg_attr(bootstrap, doc(include = "os/raw/uint.md"))] -#[cfg_attr(not(bootstrap), doc(include = "uint.md"))] +#[doc(include = "uint.md")] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_uint = u32; -#[cfg_attr(bootstrap, doc(include = "os/raw/long.md"))] -#[cfg_attr(not(bootstrap), doc(include = "long.md"))] +#[doc(include = "long.md")] #[cfg(any(target_pointer_width = "32", windows))] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_long = i32; -#[cfg_attr(bootstrap, doc(include = "os/raw/ulong.md"))] -#[cfg_attr(not(bootstrap), doc(include = "ulong.md"))] +#[doc(include = "ulong.md")] #[cfg(any(target_pointer_width = "32", windows))] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_ulong = u32; -#[cfg_attr(bootstrap, doc(include = "os/raw/long.md"))] -#[cfg_attr(not(bootstrap), doc(include = "long.md"))] +#[doc(include = "long.md")] #[cfg(all(target_pointer_width = "64", not(windows)))] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_long = i64; -#[cfg_attr(bootstrap, doc(include = "os/raw/ulong.md"))] -#[cfg_attr(not(bootstrap), doc(include = "ulong.md"))] +#[doc(include = "ulong.md")] #[cfg(all(target_pointer_width = "64", not(windows)))] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_ulong = u64; -#[cfg_attr(bootstrap, doc(include = "os/raw/longlong.md"))] -#[cfg_attr(not(bootstrap), doc(include = "longlong.md"))] +#[doc(include = "longlong.md")] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_longlong = i64; -#[cfg_attr(bootstrap, doc(include = "os/raw/ulonglong.md"))] -#[cfg_attr(not(bootstrap), doc(include = "ulonglong.md"))] +#[doc(include = "ulonglong.md")] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_ulonglong = u64; -#[cfg_attr(bootstrap, doc(include = "os/raw/float.md"))] -#[cfg_attr(not(bootstrap), doc(include = "float.md"))] +#[doc(include = "float.md")] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_float = f32; -#[cfg_attr(bootstrap, doc(include = "os/raw/double.md"))] -#[cfg_attr(not(bootstrap), doc(include = "double.md"))] +#[doc(include = "double.md")] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_double = f64; #[stable(feature = "raw_os", since = "1.1.0")] diff --git a/src/libstd/prelude/v1.rs b/src/libstd/prelude/v1.rs index 1c61f21f7df4e..752c6202ee489 100644 --- a/src/libstd/prelude/v1.rs +++ b/src/libstd/prelude/v1.rs @@ -7,10 +7,6 @@ #![stable(feature = "rust1", since = "1.0.0")] // Re-exported core operators -#[cfg(bootstrap)] -#[stable(feature = "rust1", since = "1.0.0")] -#[doc(no_inline)] -pub use crate::marker::Copy; #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use crate::marker::{Send, Sized, Sync, Unpin}; @@ -24,21 +20,9 @@ pub use crate::ops::{Drop, Fn, FnMut, FnOnce}; pub use crate::mem::drop; // Re-exported types and traits -#[cfg(bootstrap)] -#[stable(feature = "rust1", since = "1.0.0")] -#[doc(no_inline)] -pub use crate::clone::Clone; -#[cfg(bootstrap)] -#[stable(feature = "rust1", since = "1.0.0")] -#[doc(no_inline)] -pub use crate::cmp::{PartialEq, PartialOrd, Eq, Ord}; #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use crate::convert::{AsRef, AsMut, Into, From}; -#[cfg(bootstrap)] -#[stable(feature = "rust1", since = "1.0.0")] -#[doc(no_inline)] -pub use crate::default::Default; #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use crate::iter::{Iterator, Extend, IntoIterator}; @@ -53,7 +37,6 @@ pub use crate::option::Option::{self, Some, None}; pub use crate::result::Result::{self, Ok, Err}; // Re-exported built-in macros -#[cfg(not(bootstrap))] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[doc(no_inline)] pub use core::prelude::v1::{ @@ -83,7 +66,6 @@ pub use core::prelude::v1::{ // FIXME: Attribute and derive macros are not documented because for them rustdoc generates // dead links which fail link checker testing. -#[cfg(not(bootstrap))] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow(deprecated)] #[doc(hidden)] diff --git a/src/libstd/sync/mod.rs b/src/libstd/sync/mod.rs index e29faf18d83e5..fd6e46fd61dc5 100644 --- a/src/libstd/sync/mod.rs +++ b/src/libstd/sync/mod.rs @@ -163,7 +163,6 @@ pub use self::condvar::{Condvar, WaitTimeoutResult}; #[stable(feature = "rust1", since = "1.0.0")] pub use self::mutex::{Mutex, MutexGuard}; #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(bootstrap, allow(deprecated_in_future))] #[allow(deprecated)] pub use self::once::{Once, OnceState, ONCE_INIT}; #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/sys/cloudabi/mod.rs b/src/libstd/sys/cloudabi/mod.rs index 6e147612eb4b7..518aef4ed5e81 100644 --- a/src/libstd/sys/cloudabi/mod.rs +++ b/src/libstd/sys/cloudabi/mod.rs @@ -1,4 +1,4 @@ -#![allow(deprecated_in_future)] // mem::uninitialized; becomes `deprecated` when nightly is 1.39 +#![allow(deprecated)] // mem::uninitialized use crate::io::ErrorKind; use crate::mem; diff --git a/src/libunwind/build.rs b/src/libunwind/build.rs index da31a49ddf21f..c1b0dbc0881d3 100644 --- a/src/libunwind/build.rs +++ b/src/libunwind/build.rs @@ -4,13 +4,11 @@ fn main() { println!("cargo:rerun-if-changed=build.rs"); let target = env::var("TARGET").expect("TARGET was not set"); - // FIXME: the not(bootstrap) part is needed because of the issue addressed by #62286, - // and could be removed once that change is in beta. - if cfg!(all(not(bootstrap), feature = "llvm-libunwind")) && + if cfg!(feature = "llvm-libunwind") && (target.contains("linux") || target.contains("fuchsia")) { // Build the unwinding from libunwind C/C++ source code. - #[cfg(all(not(bootstrap), feature = "llvm-libunwind"))] + #[cfg(feature = "llvm-libunwind")] llvm_libunwind::compile(); } else if target.contains("linux") { if target.contains("musl") { @@ -46,7 +44,7 @@ fn main() { } } -#[cfg(all(not(bootstrap), feature = "llvm-libunwind"))] +#[cfg(feature = "llvm-libunwind")] mod llvm_libunwind { use std::env; use std::path::Path; diff --git a/src/libunwind/libunwind.rs b/src/libunwind/libunwind.rs index aacbfc547d472..7c9eaa51fd94e 100644 --- a/src/libunwind/libunwind.rs +++ b/src/libunwind/libunwind.rs @@ -70,7 +70,7 @@ pub enum _Unwind_Context {} pub type _Unwind_Exception_Cleanup_Fn = extern "C" fn(unwind_code: _Unwind_Reason_Code, exception: *mut _Unwind_Exception); -#[cfg_attr(all(not(bootstrap), feature = "llvm-libunwind", +#[cfg_attr(all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux")), link(name = "unwind", kind = "static"))] extern "C" { @@ -97,7 +97,7 @@ if #[cfg(all(any(target_os = "ios", target_os = "netbsd", not(target_arch = "arm } pub use _Unwind_Action::*; - #[cfg_attr(all(not(bootstrap), feature = "llvm-libunwind", + #[cfg_attr(all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux")), link(name = "unwind", kind = "static"))] extern "C" { @@ -153,7 +153,7 @@ if #[cfg(all(any(target_os = "ios", target_os = "netbsd", not(target_arch = "arm pub const UNWIND_POINTER_REG: c_int = 12; pub const UNWIND_IP_REG: c_int = 15; - #[cfg_attr(all(not(bootstrap), feature = "llvm-libunwind", + #[cfg_attr(all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux")), link(name = "unwind", kind = "static"))] extern "C" { @@ -218,7 +218,7 @@ if #[cfg(all(any(target_os = "ios", target_os = "netbsd", not(target_arch = "arm cfg_if::cfg_if! { if #[cfg(not(all(target_os = "ios", target_arch = "arm")))] { // Not 32-bit iOS - #[cfg_attr(all(not(bootstrap), feature = "llvm-libunwind", + #[cfg_attr(all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux")), link(name = "unwind", kind = "static"))] extern "C" { @@ -230,7 +230,7 @@ if #[cfg(not(all(target_os = "ios", target_arch = "arm")))] { } } else { // 32-bit iOS uses SjLj and does not provide _Unwind_Backtrace() - #[cfg_attr(all(not(bootstrap), feature = "llvm-libunwind", + #[cfg_attr(all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux")), link(name = "unwind", kind = "static"))] extern "C" { diff --git a/src/test/ui/lint/lint-qualification.rs b/src/test/ui/lint/lint-qualification.rs index 1b24191a111c2..0cace0ca0355a 100644 --- a/src/test/ui/lint/lint-qualification.rs +++ b/src/test/ui/lint/lint-qualification.rs @@ -1,5 +1,5 @@ #![deny(unused_qualifications)] -#[allow(deprecated)] +#![allow(deprecated)] mod foo { pub fn bar() {} From 6575a96198765d4fb38d9abf7d64fc817ef8e80b Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Mon, 12 Aug 2019 19:42:41 -0400 Subject: [PATCH 32/35] Disable --cfg bootstrap in libcore This is needed to permit us building core_arch which is a submodule dep (so we can't snap it to the new beta compiler). --- src/bootstrap/bin/rustc.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index 04a3dea5c8791..1436096dd6e22 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -110,7 +110,11 @@ fn main() { // Non-zero stages must all be treated uniformly to avoid problems when attempting to uplift // compiler libraries and such from stage 1 to 2. - if stage == "0" { + // + // FIXME: the fact that core here is excluded is due to core_arch from our stdarch submodule + // being broken on the beta compiler with bootstrap passed, so this is a temporary workaround + // (we've just snapped, so there are no cfg(bootstrap) related annotations in core). + if stage == "0" && crate_name != Some("core") { cmd.arg("--cfg").arg("bootstrap"); } From f7ff36dcb27b48329e9b1c12f5b78d469fafc067 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 12 Aug 2019 14:49:12 -0400 Subject: [PATCH 33/35] Update error-format to match new Cargo flags for pipelining --- src/bootstrap/bin/rustc.rs | 12 ------------ src/bootstrap/builder.rs | 3 --- src/bootstrap/compile.rs | 20 ++++++-------------- 3 files changed, 6 insertions(+), 29 deletions(-) diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index 1436096dd6e22..9c01de8aa8251 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -45,18 +45,6 @@ fn main() { } } - // Drop `--error-format json` because despite our desire for json messages - // from Cargo we don't want any from rustc itself. - if let Some(n) = args.iter().position(|n| n == "--error-format") { - args.remove(n); - args.remove(n); - } - - if let Some(s) = env::var_os("RUSTC_ERROR_FORMAT") { - args.push("--error-format".into()); - args.push(s); - } - // Detect whether or not we're a build script depending on whether --target // is passed (a bit janky...) let target = args.windows(2) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 9e4cd5ebca749..8dad5f2ef4632 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -980,9 +980,6 @@ impl<'a> Builder<'a> { if let Some(target_linker) = self.linker(target) { cargo.env("RUSTC_TARGET_LINKER", target_linker); } - if let Some(ref error_format) = self.config.rustc_error_format { - cargo.env("RUSTC_ERROR_FORMAT", error_format); - } if !(["build", "check", "clippy", "fix", "rustc"].contains(&cmd)) && want_rustdoc { cargo.env("RUSTDOC_LIBDIR", self.rustc_libdir(compiler)); } diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 4cd793adaf574..4b4b072cc1c96 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -1116,10 +1116,6 @@ pub fn run_cargo(builder: &Builder<'_>, }, .. } => (filenames, crate_types), - CargoMessage::CompilerMessage { message } => { - eprintln!("{}", message.rendered); - return; - } _ => return, }; for filename in filenames { @@ -1256,8 +1252,12 @@ pub fn stream_cargo( } // Instruct Cargo to give us json messages on stdout, critically leaving // stderr as piped so we can get those pretty colors. - cargo.arg("--message-format").arg("json") - .stdout(Stdio::piped()); + let mut message_format = String::from("json-render-diagnostics"); + if let Some(s) = &builder.config.rustc_error_format { + message_format.push_str(",json-diagnostic-"); + message_format.push_str(s); + } + cargo.arg("--message-format").arg(message_format).stdout(Stdio::piped()); for arg in tail_args { cargo.arg(arg); @@ -1310,12 +1310,4 @@ pub enum CargoMessage<'a> { BuildScriptExecuted { package_id: Cow<'a, str>, }, - CompilerMessage { - message: ClippyMessage<'a> - } -} - -#[derive(Deserialize)] -pub struct ClippyMessage<'a> { - rendered: Cow<'a, str>, } From 264640cde5ed30bdc0f3ef138472eb0de4d2f3ea Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Wed, 14 Aug 2019 18:04:33 +0200 Subject: [PATCH 34/35] move test that shouldn't be in test/run-pass/ --- src/test/{run-pass => ui}/generator/niche-in-generator.rs | 2 ++ 1 file changed, 2 insertions(+) rename src/test/{run-pass => ui}/generator/niche-in-generator.rs (95%) diff --git a/src/test/run-pass/generator/niche-in-generator.rs b/src/test/ui/generator/niche-in-generator.rs similarity index 95% rename from src/test/run-pass/generator/niche-in-generator.rs rename to src/test/ui/generator/niche-in-generator.rs index 9a644ed44a670..42bee81f524c5 100644 --- a/src/test/run-pass/generator/niche-in-generator.rs +++ b/src/test/ui/generator/niche-in-generator.rs @@ -1,5 +1,7 @@ // Test that niche finding works with captured generator upvars. +// run-pass + #![feature(generators)] use std::mem::size_of_val; From 24693d70d650b717770deb2331a50b56d1469158 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Wed, 14 Aug 2019 20:07:37 +0200 Subject: [PATCH 35/35] Adjust tracking issues for `MaybeUninit` gates --- src/libcore/mem/maybe_uninit.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libcore/mem/maybe_uninit.rs b/src/libcore/mem/maybe_uninit.rs index 1bbea02e0c7c9..c48fcfe99d290 100644 --- a/src/libcore/mem/maybe_uninit.rs +++ b/src/libcore/mem/maybe_uninit.rs @@ -312,7 +312,7 @@ impl MaybeUninit { /// without dropping it, so be careful not to use this twice unless you want to /// skip running the destructor. For your convenience, this also returns a mutable /// reference to the (now safely initialized) contents of `self`. - #[unstable(feature = "maybe_uninit_extra", issue = "53491")] + #[unstable(feature = "maybe_uninit_extra", issue = "63567")] #[inline(always)] pub fn write(&mut self, val: T) -> &mut T { unsafe { @@ -502,7 +502,7 @@ impl MaybeUninit { /// // We now created two copies of the same vector, leading to a double-free when /// // they both get dropped! /// ``` - #[unstable(feature = "maybe_uninit_extra", issue = "53491")] + #[unstable(feature = "maybe_uninit_extra", issue = "63567")] #[inline(always)] pub unsafe fn read(&self) -> T { intrinsics::panic_if_uninhabited::(); @@ -516,7 +516,7 @@ impl MaybeUninit { /// It is up to the caller to guarantee that the `MaybeUninit` really is in an initialized /// state. Calling this when the content is not yet fully initialized causes undefined /// behavior. - #[unstable(feature = "maybe_uninit_ref", issue = "53491")] + #[unstable(feature = "maybe_uninit_ref", issue = "63568")] #[inline(always)] pub unsafe fn get_ref(&self) -> &T { &*self.value @@ -532,21 +532,21 @@ impl MaybeUninit { // FIXME(#53491): We currently rely on the above being incorrect, i.e., we have references // to uninitialized data (e.g., in `libcore/fmt/float.rs`). We should make // a final decision about the rules before stabilization. - #[unstable(feature = "maybe_uninit_ref", issue = "53491")] + #[unstable(feature = "maybe_uninit_ref", issue = "63568")] #[inline(always)] pub unsafe fn get_mut(&mut self) -> &mut T { &mut *self.value } /// Gets a pointer to the first element of the array. - #[unstable(feature = "maybe_uninit_slice", issue = "53491")] + #[unstable(feature = "maybe_uninit_slice", issue = "63569")] #[inline(always)] pub fn first_ptr(this: &[MaybeUninit]) -> *const T { this as *const [MaybeUninit] as *const T } /// Gets a mutable pointer to the first element of the array. - #[unstable(feature = "maybe_uninit_slice", issue = "53491")] + #[unstable(feature = "maybe_uninit_slice", issue = "63569")] #[inline(always)] pub fn first_ptr_mut(this: &mut [MaybeUninit]) -> *mut T { this as *mut [MaybeUninit] as *mut T