From d2d89b10de394b4a1d5e2491dfffd3d65d1741b3 Mon Sep 17 00:00:00 2001 From: Sean McArthur Date: Thu, 16 May 2019 17:09:04 -0700 Subject: [PATCH 01/20] error: remove StringError from Debug output Seeing `StringError("something something")` in debug output can cause someone to think there was an error dealing with `String`s, not that the error type is just a string. So, remove that noise. --- src/libstd/error.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/libstd/error.rs b/src/libstd/error.rs index 7cb830e751a77..9424e059a14fd 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -300,7 +300,6 @@ impl From for Box { /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) /// ``` fn from(err: String) -> Box { - #[derive(Debug)] struct StringError(String); impl Error for StringError { @@ -313,6 +312,13 @@ impl From for Box { } } + // Purposefully skip printing "StringError(..)" + impl Debug for StringError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + Debug::fmt(&self.0, f) + } + } + Box::new(StringError(err)) } } From 642e8d4434c4f6214a908eea0019b3185323431f Mon Sep 17 00:00:00 2001 From: Jason Shirk Date: Tue, 28 May 2019 22:57:12 -0700 Subject: [PATCH 02/20] Speed up Azure CI installing Windows dependencies There is known issue where PowerShell is unreasonably slow downloading files due to an issue with rendering the progress bar, see: https://github.com/PowerShell/PowerShell/issues/2138 That issue is fixed in PowerShell Core (available in Azure Pipelines as pwsh.exe) but it can also be worked around by setting: $ProgressPreference = 'SilentlyContinue' --- .azure-pipelines/steps/install-clang.yml | 2 +- .azure-pipelines/steps/install-sccache.yml | 2 +- .azure-pipelines/steps/install-windows-build-deps.yml | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.azure-pipelines/steps/install-clang.yml b/.azure-pipelines/steps/install-clang.yml index 26a223282cd87..7a662c498f4b5 100644 --- a/.azure-pipelines/steps/install-clang.yml +++ b/.azure-pipelines/steps/install-clang.yml @@ -27,7 +27,7 @@ steps: # Original downloaded here came from # http://releases.llvm.org/7.0.0/LLVM-7.0.0-win64.exe - script: | - powershell -Command "iwr -outf %TEMP%\LLVM-7.0.0-win64.exe https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/LLVM-7.0.0-win64.exe" + powershell -Command "$ProgressPreference = 'SilentlyContinue'; iwr -outf %TEMP%\LLVM-7.0.0-win64.exe https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/LLVM-7.0.0-win64.exe" set CLANG_DIR=%CD%\citools\clang-rust %TEMP%\LLVM-7.0.0-win64.exe /S /NCRC /D=%CLANG_DIR% set RUST_CONFIGURE_ARGS=%RUST_CONFIGURE_ARGS% --set llvm.clang-cl=%CLANG_DIR%\bin\clang-cl.exe diff --git a/.azure-pipelines/steps/install-sccache.yml b/.azure-pipelines/steps/install-sccache.yml index 39f58002a7358..8f80c955f7e49 100644 --- a/.azure-pipelines/steps/install-sccache.yml +++ b/.azure-pipelines/steps/install-sccache.yml @@ -9,7 +9,7 @@ steps: - script: | md sccache - powershell -Command "iwr -outf sccache\sccache.exe https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2018-04-26-sccache-x86_64-pc-windows-msvc" + powershell -Command "$ProgressPreference = 'SilentlyContinue'; iwr -outf sccache\sccache.exe https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2018-04-26-sccache-x86_64-pc-windows-msvc" echo ##vso[task.prependpath]%CD%\sccache displayName: Install sccache (Windows) condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) diff --git a/.azure-pipelines/steps/install-windows-build-deps.yml b/.azure-pipelines/steps/install-windows-build-deps.yml index 037c8daa2a80a..0e9c0b99b46f1 100644 --- a/.azure-pipelines/steps/install-windows-build-deps.yml +++ b/.azure-pipelines/steps/install-windows-build-deps.yml @@ -54,9 +54,9 @@ steps: # Note that we don't literally overwrite the gdb.exe binary because it appears # to just use gdborig.exe, so that's the binary we deal with instead. - script: | - powershell -Command "iwr -outf %MINGW_ARCHIVE% %MINGW_URL%/%MINGW_ARCHIVE%" + powershell -Command "$ProgressPreference = 'SilentlyContinue'; iwr -outf %MINGW_ARCHIVE% %MINGW_URL%/%MINGW_ARCHIVE%" 7z x -y %MINGW_ARCHIVE% > nul - powershell -Command "iwr -outf 2017-04-20-%MSYS_BITS%bit-gdborig.exe %MINGW_URL%/2017-04-20-%MSYS_BITS%bit-gdborig.exe" + powershell -Command "$ProgressPreference = 'SilentlyContinue'; iwr -outf 2017-04-20-%MSYS_BITS%bit-gdborig.exe %MINGW_URL%/2017-04-20-%MSYS_BITS%bit-gdborig.exe" mv 2017-04-20-%MSYS_BITS%bit-gdborig.exe %MINGW_DIR%\bin\gdborig.exe echo ##vso[task.prependpath]%CD%\%MINGW_DIR%\bin condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT'), ne(variables['MINGW_URL'],'')) @@ -81,7 +81,7 @@ steps: # Note that this is originally from the github releases patch of Ninja - script: | md ninja - powershell -Command "iwr -outf 2017-03-15-ninja-win.zip https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2017-03-15-ninja-win.zip" + powershell -Command "$ProgressPreference = 'SilentlyContinue'; iwr -outf 2017-03-15-ninja-win.zip https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2017-03-15-ninja-win.zip" 7z x -oninja 2017-03-15-ninja-win.zip del 2017-03-15-ninja-win.zip set RUST_CONFIGURE_ARGS=%RUST_CONFIGURE_ARGS% --enable-ninja From 07864a6fd16811a6797296f0bf9551954b71603e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 25 May 2019 13:48:56 +0200 Subject: [PATCH 03/20] cache tag for vtable; fn_alloc's don't have a stack nor tag --- src/librustc_mir/interpret/cast.rs | 4 ++-- src/librustc_mir/interpret/eval_context.rs | 7 +++++-- src/librustc_mir/interpret/memory.rs | 5 +++-- src/librustc_mir/interpret/traits.rs | 8 ++++---- 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs index 76b11ac2fe646..f1e23655741fc 100644 --- a/src/librustc_mir/interpret/cast.rs +++ b/src/librustc_mir/interpret/cast.rs @@ -86,7 +86,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> def_id, substs, ).ok_or_else(|| InterpError::TooGeneric.into()); - let fn_ptr = self.memory.create_fn_alloc(instance?).with_default_tag(); + let fn_ptr = self.memory.create_fn_alloc(instance?); self.write_scalar(Scalar::Ptr(fn_ptr.into()), dest)?; } _ => bug!("reify fn pointer on {:?}", src.layout.ty), @@ -115,7 +115,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> substs, ty::ClosureKind::FnOnce, ); - let fn_ptr = self.memory.create_fn_alloc(instance).with_default_tag(); + let fn_ptr = self.memory.create_fn_alloc(instance); let val = Immediate::Scalar(Scalar::Ptr(fn_ptr.into()).into()); self.write_immediate(val, dest)?; } diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index d3cbd2bcc03a5..1ed04c013eee3 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -15,7 +15,7 @@ use rustc::ty::query::TyCtxtAt; use rustc_data_structures::indexed_vec::IndexVec; use rustc::mir::interpret::{ ErrorHandled, - GlobalId, Scalar, FrameInfo, AllocId, + GlobalId, Scalar, Pointer, FrameInfo, AllocId, EvalResult, InterpError, truncate, sign_extend, }; @@ -43,7 +43,10 @@ pub struct InterpretCx<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'a, 'mir, 'tcx>> { pub(crate) stack: Vec>, /// A cache for deduplicating vtables - pub(super) vtables: FxHashMap<(Ty<'tcx>, Option>), AllocId>, + pub(super) vtables: FxHashMap< + (Ty<'tcx>, Option>), + Pointer + >, } /// A stack frame. diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 65a3b04c8b152..98fb8ff1d79b0 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -108,8 +108,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { } } - pub fn create_fn_alloc(&mut self, instance: Instance<'tcx>) -> Pointer { - Pointer::from(self.tcx.alloc_map.lock().create_fn_alloc(instance)) + pub fn create_fn_alloc(&mut self, instance: Instance<'tcx>) -> Pointer { + // Default tag is okay because anyway you cannot access memory with this. + Pointer::from(self.tcx.alloc_map.lock().create_fn_alloc(instance)).with_default_tag() } pub fn allocate_static_bytes(&mut self, bytes: &[u8]) -> Pointer { diff --git a/src/librustc_mir/interpret/traits.rs b/src/librustc_mir/interpret/traits.rs index 4eb79cf56fcf2..208bba60bf2f2 100644 --- a/src/librustc_mir/interpret/traits.rs +++ b/src/librustc_mir/interpret/traits.rs @@ -25,7 +25,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> // always use the same vtable for the same (Type, Trait) combination. // That's not what happens in rustc, but emulating per-crate deduplication // does not sound like it actually makes anything any better. - return Ok(Pointer::from(vtable).with_default_tag()); + return Ok(vtable); } let methods = if let Some(poly_trait_ref) = poly_trait_ref { @@ -56,7 +56,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> let tcx = &*self.tcx; let drop = crate::monomorphize::resolve_drop_in_place(*tcx, ty); - let drop = self.memory.create_fn_alloc(drop).with_default_tag(); + let drop = self.memory.create_fn_alloc(drop); // no need to do any alignment checks on the memory accesses below, because we know the // allocation is correctly aligned as we created it above. Also we're only offsetting by // multiples of `ptr_align`, which means that it will stay aligned to `ptr_align`. @@ -83,7 +83,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> def_id, substs, ).ok_or_else(|| InterpError::TooGeneric)?; - let fn_ptr = self.memory.create_fn_alloc(instance).with_default_tag(); + let fn_ptr = self.memory.create_fn_alloc(instance); let method_ptr = vtable.offset(ptr_size * (3 + i as u64), self)?; self.memory .get_mut(method_ptr.alloc_id)? @@ -92,7 +92,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> } self.memory.mark_immutable(vtable.alloc_id)?; - assert!(self.vtables.insert((ty, poly_trait_ref), vtable.alloc_id).is_none()); + assert!(self.vtables.insert((ty, poly_trait_ref), vtable).is_none()); Ok(vtable) } From a218be9a2e65435224e315d6b5500163de2387d9 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 28 May 2019 10:44:46 +0200 Subject: [PATCH 04/20] no longer assume that there is a default tag: give the machine the chance to tag all allocations --- src/librustc/mir/interpret/allocation.rs | 15 +-- src/librustc/mir/interpret/pointer.rs | 7 -- src/librustc/mir/interpret/value.rs | 27 +---- src/librustc/ty/context.rs | 2 +- src/librustc_mir/const_eval.rs | 28 ++--- src/librustc_mir/hair/constant.rs | 4 +- src/librustc_mir/interpret/eval_context.rs | 10 +- src/librustc_mir/interpret/machine.rs | 64 +++++------ src/librustc_mir/interpret/memory.rs | 124 +++++++++++++-------- src/librustc_mir/interpret/operand.rs | 96 ++++++---------- src/librustc_mir/interpret/place.rs | 36 +++--- 11 files changed, 192 insertions(+), 221 deletions(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index 9549a5af5af5c..5c7cf31985d6e 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -110,9 +110,10 @@ pub trait AllocationExtra: ::std::fmt::Debug + Clone { // For Tag=() and no extra state, we have is a trivial implementation. impl AllocationExtra<()> for () { } -impl Allocation { +// The constructors are all without extra; the extra gets added by a machine hook later. +impl Allocation { /// Creates a read-only allocation initialized by the given bytes - pub fn from_bytes(slice: &[u8], align: Align, extra: Extra) -> Self { + pub fn from_bytes(slice: &[u8], align: Align) -> Self { let undef_mask = UndefMask::new(Size::from_bytes(slice.len() as u64), true); Self { bytes: slice.to_owned(), @@ -120,15 +121,15 @@ impl Allocation { undef_mask, align, mutability: Mutability::Immutable, - extra, + extra: (), } } - pub fn from_byte_aligned_bytes(slice: &[u8], extra: Extra) -> Self { - Allocation::from_bytes(slice, Align::from_bytes(1).unwrap(), extra) + pub fn from_byte_aligned_bytes(slice: &[u8]) -> Self { + Allocation::from_bytes(slice, Align::from_bytes(1).unwrap()) } - pub fn undef(size: Size, align: Align, extra: Extra) -> Self { + pub fn undef(size: Size, align: Align) -> Self { assert_eq!(size.bytes() as usize as u64, size.bytes()); Allocation { bytes: vec![0; size.bytes() as usize], @@ -136,7 +137,7 @@ impl Allocation { undef_mask: UndefMask::new(size, false), align, mutability: Mutability::Mutable, - extra, + extra: (), } } } diff --git a/src/librustc/mir/interpret/pointer.rs b/src/librustc/mir/interpret/pointer.rs index 9e71399d4fdf7..4aa83a79d52b8 100644 --- a/src/librustc/mir/interpret/pointer.rs +++ b/src/librustc/mir/interpret/pointer.rs @@ -116,13 +116,6 @@ impl<'tcx> Pointer<()> { { Pointer::new_with_tag(self.alloc_id, self.offset, tag) } - - #[inline(always)] - pub fn with_default_tag(self) -> Pointer - where Tag: Default - { - self.with_tag(Tag::default()) - } } impl<'tcx, Tag> Pointer { diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs index 21792b847db77..1c24f5c116cce 100644 --- a/src/librustc/mir/interpret/value.rs +++ b/src/librustc/mir/interpret/value.rs @@ -140,23 +140,18 @@ impl<'tcx> Scalar<()> { #[inline] pub fn with_tag(self, new_tag: Tag) -> Scalar { + // Used by `MemPlace::replace_tag` match self { Scalar::Ptr(ptr) => Scalar::Ptr(ptr.with_tag(new_tag)), Scalar::Raw { data, size } => Scalar::Raw { data, size }, } } - - #[inline(always)] - pub fn with_default_tag(self) -> Scalar - where Tag: Default - { - self.with_tag(Tag::default()) - } } impl<'tcx, Tag> Scalar { #[inline] pub fn erase_tag(self) -> Scalar { + // Used by error reporting code to avoid having the error type depend on `Tag` match self { Scalar::Ptr(ptr) => Scalar::Ptr(ptr.erase_tag()), Scalar::Raw { data, size } => Scalar::Raw { data, size }, @@ -476,27 +471,11 @@ impl fmt::Display for ScalarMaybeUndef { } } -impl<'tcx> ScalarMaybeUndef<()> { - #[inline] - pub fn with_tag(self, new_tag: Tag) -> ScalarMaybeUndef { - match self { - ScalarMaybeUndef::Scalar(s) => ScalarMaybeUndef::Scalar(s.with_tag(new_tag)), - ScalarMaybeUndef::Undef => ScalarMaybeUndef::Undef, - } - } - - #[inline(always)] - pub fn with_default_tag(self) -> ScalarMaybeUndef - where Tag: Default - { - self.with_tag(Tag::default()) - } -} - impl<'tcx, Tag> ScalarMaybeUndef { #[inline] pub fn erase_tag(self) -> ScalarMaybeUndef { + // Used by error reporting code to avoid having the error type depend on `Tag` match self { ScalarMaybeUndef::Scalar(s) => ScalarMaybeUndef::Scalar(s.erase_tag()), ScalarMaybeUndef::Undef => ScalarMaybeUndef::Undef, diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index ff218911ffb81..c23a9a88c1baa 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1189,7 +1189,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// Allocates a byte or string literal for `mir::interpret`, read-only pub fn allocate_bytes(self, bytes: &[u8]) -> interpret::AllocId { // create an allocation that just contains these bytes - let alloc = interpret::Allocation::from_byte_aligned_bytes(bytes, ()); + let alloc = interpret::Allocation::from_byte_aligned_bytes(bytes); let alloc = self.intern_const_alloc(alloc); self.alloc_map.lock().allocate(alloc) } diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 0637c7b058882..ab4e7f59a11ad 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -12,7 +12,7 @@ use rustc::hir::def_id::DefId; use rustc::mir::interpret::{ConstEvalErr, ErrorHandled}; use rustc::mir; use rustc::ty::{self, TyCtxt, query::TyCtxtAt}; -use rustc::ty::layout::{self, LayoutOf, VariantIdx, Size}; +use rustc::ty::layout::{self, LayoutOf, VariantIdx}; use rustc::ty::subst::Subst; use rustc::traits::Reveal; use rustc::util::common::ErrorReported; @@ -116,7 +116,7 @@ fn op_to_const<'tcx>( ptr.offset.bytes(), ), Scalar::Raw { .. } => ( - ecx.tcx.intern_const_alloc(Allocation::from_byte_aligned_bytes(b"", ())), + ecx.tcx.intern_const_alloc(Allocation::from_byte_aligned_bytes(b"")), 0, ), }; @@ -395,27 +395,27 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx> fn find_foreign_static( _def_id: DefId, _tcx: TyCtxtAt<'a, 'tcx, 'tcx>, - _memory_extra: &(), ) -> EvalResult<'tcx, Cow<'tcx, Allocation>> { err!(ReadForeignStatic) } #[inline(always)] - fn adjust_static_allocation<'b>( - alloc: &'b Allocation, + fn tag_allocation<'b>( + _id: AllocId, + alloc: Cow<'b, Allocation>, + _kind: Option>, _memory_extra: &(), - ) -> Cow<'b, Allocation> { - // We do not use a tag so we can just cheaply forward the reference - Cow::Borrowed(alloc) + ) -> (Cow<'b, Allocation>, Self::PointerTag) { + // We do not use a tag so we can just cheaply forward the allocation + (alloc, ()) } #[inline(always)] - fn new_allocation( - _size: Size, - _extra: &Self::MemoryExtra, - _kind: MemoryKind, - ) -> (Self::AllocExtra, Self::PointerTag) { - ((), ()) + fn tag_static_base_pointer( + _id: AllocId, + _memory_extra: &(), + ) -> Self::PointerTag { + () } fn box_alloc( diff --git a/src/librustc_mir/hair/constant.rs b/src/librustc_mir/hair/constant.rs index 69df36348a69e..a5be55d16d488 100644 --- a/src/librustc_mir/hair/constant.rs +++ b/src/librustc_mir/hair/constant.rs @@ -30,13 +30,13 @@ crate fn lit_to_const<'a, 'gcx, 'tcx>( let lit = match *lit { LitKind::Str(ref s, _) => { let s = s.as_str(); - let allocation = Allocation::from_byte_aligned_bytes(s.as_bytes(), ()); + let allocation = Allocation::from_byte_aligned_bytes(s.as_bytes()); let allocation = tcx.intern_const_alloc(allocation); ConstValue::Slice { data: allocation, start: 0, end: s.len() } }, LitKind::Err(ref s) => { let s = s.as_str(); - let allocation = Allocation::from_byte_aligned_bytes(s.as_bytes(), ()); + let allocation = Allocation::from_byte_aligned_bytes(s.as_bytes()); let allocation = tcx.intern_const_alloc(allocation); return Ok(tcx.mk_const(ty::Const { val: ConstValue::Slice{ data: allocation, start: 0, end: s.len() }, diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 1ed04c013eee3..594802a03410c 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -225,6 +225,11 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tc &mut self.memory } + #[inline(always)] + pub fn tag_static_base_pointer(&self, ptr: Pointer) -> Pointer { + self.memory.tag_static_base_pointer(ptr) + } + #[inline(always)] pub fn stack(&self) -> &[Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>] { &self.stack @@ -363,11 +368,6 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tc } } - pub fn str_to_immediate(&mut self, s: &str) -> EvalResult<'tcx, Immediate> { - let ptr = self.memory.allocate_static_bytes(s.as_bytes()).with_default_tag(); - Ok(Immediate::new_slice(Scalar::Ptr(ptr), s.len() as u64, self)) - } - /// Returns the actual dynamic size and alignment of the place at the given type. /// Only the "meta" (metadata) part of the place matters. /// This can fail to provide an answer for extern types. diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index 873c2d2ec6088..7bf92711766a0 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -5,13 +5,13 @@ use std::borrow::{Borrow, Cow}; use std::hash::Hash; -use rustc::hir::{self, def_id::DefId}; +use rustc::hir::def_id::DefId; use rustc::mir; -use rustc::ty::{self, query::TyCtxtAt, layout::Size}; +use rustc::ty::{self, query::TyCtxtAt}; use super::{ Allocation, AllocId, EvalResult, Scalar, AllocationExtra, - InterpretCx, PlaceTy, MPlaceTy, OpTy, ImmTy, MemoryKind, + InterpretCx, PlaceTy, OpTy, ImmTy, MemoryKind, }; /// Whether this kind of memory is allowed to leak @@ -65,7 +65,7 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized { /// Tag tracked alongside every pointer. This is used to implement "Stacked Borrows" /// . /// The `default()` is used for pointers to consts, statics, vtables and functions. - type PointerTag: ::std::fmt::Debug + Default + Copy + Eq + Hash + 'static; + type PointerTag: ::std::fmt::Debug + Copy + Eq + Hash + 'static; /// Extra data stored in every call frame. type FrameExtra; @@ -90,7 +90,7 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized { /// The memory kind to use for copied statics -- or None if statics should not be mutated /// and thus any such attempt will cause a `ModifiedStatic` error to be raised. /// Statics are copied under two circumstances: When they are mutated, and when - /// `static_with_default_tag` or `find_foreign_static` (see below) returns an owned allocation + /// `tag_allocation` or `find_foreign_static` (see below) returns an owned allocation /// that is added to the memory so that the work is not done twice. const STATIC_KIND: Option; @@ -133,11 +133,12 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized { /// This will only be called once per static and machine; the result is cached in /// the machine memory. (This relies on `AllocMap::get_or` being able to add the /// owned allocation to the map even when the map is shared.) + /// + /// This allocation will then be fed to `tag_allocation` to initialize the "extra" state. fn find_foreign_static( def_id: DefId, tcx: TyCtxtAt<'a, 'tcx, 'tcx>, - memory_extra: &Self::MemoryExtra, - ) -> EvalResult<'tcx, Cow<'tcx, Allocation>>; + ) -> EvalResult<'tcx, Cow<'tcx, Allocation>>; /// Called for all binary operations on integer(-like) types when one operand is a pointer /// value, and for the `Offset` operation that is inherently about pointers. @@ -156,36 +157,37 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized { dest: PlaceTy<'tcx, Self::PointerTag>, ) -> EvalResult<'tcx>; - /// Called to turn an allocation obtained from the `tcx` into one that has - /// the right type for this machine. + /// Called to initialize the "extra" state of an allocation and make the pointers + /// it contains (in relocations) tagged. The way we construct allocations is + /// to always first construct it without extra and then add the extra. + /// This keeps uniform code paths for handling both allocations created by CTFE + /// for statics, and allocations ceated by Miri during evaluation. + /// + /// `kind` is the kind of the allocation being tagged; it can be `None` when + /// it's a static and `STATIC_KIND` is `None`. /// /// This should avoid copying if no work has to be done! If this returns an owned /// allocation (because a copy had to be done to add tags or metadata), machine memory will /// cache the result. (This relies on `AllocMap::get_or` being able to add the /// owned allocation to the map even when the map is shared.) - fn adjust_static_allocation<'b>( - alloc: &'b Allocation, + /// + /// The tag returned must be the same as the one returned by `tag_base_pointer`. + fn tag_allocation<'b>( + id: AllocId, + alloc: Cow<'b, Allocation>, + kind: Option>, memory_extra: &Self::MemoryExtra, - ) -> Cow<'b, Allocation>; - - /// Computes the extra state and the tag for a new allocation. - fn new_allocation( - size: Size, - extra: &Self::MemoryExtra, - kind: MemoryKind, - ) -> (Self::AllocExtra, Self::PointerTag); - - /// Executed when evaluating the `*` operator: Following a reference. - /// This has the chance to adjust the tag. It should not change anything else! - /// `mutability` can be `None` in case a raw ptr is being dereferenced. - #[inline] - fn tag_dereference( - _ecx: &InterpretCx<'a, 'mir, 'tcx, Self>, - place: MPlaceTy<'tcx, Self::PointerTag>, - _mutability: Option, - ) -> EvalResult<'tcx, Scalar> { - Ok(place.ptr) - } + ) -> (Cow<'b, Allocation>, Self::PointerTag); + + /// Return the "base" tag for the given static allocation: the one that is used for direct + /// accesses to this static/const/fn allocation. + /// + /// Be aware that requesting the `Allocation` for that `id` will lead to cycles + /// for cyclic statics! + fn tag_static_base_pointer( + id: AllocId, + memory_extra: &Self::MemoryExtra, + ) -> Self::PointerTag; /// Executes a retagging operation #[inline] diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 98fb8ff1d79b0..d121a924cfbd9 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -108,33 +108,44 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { } } + #[inline] + pub fn tag_static_base_pointer(&self, ptr: Pointer) -> Pointer { + ptr.with_tag(M::tag_static_base_pointer(ptr.alloc_id, &self.extra)) + } + pub fn create_fn_alloc(&mut self, instance: Instance<'tcx>) -> Pointer { - // Default tag is okay because anyway you cannot access memory with this. - Pointer::from(self.tcx.alloc_map.lock().create_fn_alloc(instance)).with_default_tag() + let id = self.tcx.alloc_map.lock().create_fn_alloc(instance); + self.tag_static_base_pointer(Pointer::from(id)) } - pub fn allocate_static_bytes(&mut self, bytes: &[u8]) -> Pointer { - Pointer::from(self.tcx.allocate_bytes(bytes)) + pub fn allocate( + &mut self, + size: Size, + align: Align, + kind: MemoryKind, + ) -> Pointer { + let alloc = Allocation::undef(size, align); + self.allocate_with(alloc, kind) } - pub fn allocate_with( + pub fn allocate_static_bytes( &mut self, - alloc: Allocation, + bytes: &[u8], kind: MemoryKind, - ) -> AllocId { - let id = self.tcx.alloc_map.lock().reserve(); - self.alloc_map.insert(id, (kind, alloc)); - id + ) -> Pointer { + let alloc = Allocation::from_byte_aligned_bytes(bytes); + self.allocate_with(alloc, kind) } - pub fn allocate( + pub fn allocate_with( &mut self, - size: Size, - align: Align, + alloc: Allocation, kind: MemoryKind, ) -> Pointer { - let (extra, tag) = M::new_allocation(size, &self.extra, kind); - Pointer::from(self.allocate_with(Allocation::undef(size, align, extra), kind)).with_tag(tag) + let id = self.tcx.alloc_map.lock().reserve(); + let (alloc, tag) = M::tag_allocation(id, Cow::Owned(alloc), Some(kind), &self.extra); + self.alloc_map.insert(id, (kind, alloc.into_owned())); + Pointer::from(id).with_tag(tag) } pub fn reallocate( @@ -306,53 +317,70 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { /// This attempts to return a reference to an existing allocation if /// one can be found in `tcx`. That, however, is only possible if `tcx` and /// this machine use the same pointer tag, so it is indirected through - /// `M::static_with_default_tag`. + /// `M::tag_allocation`. + /// + /// Notice that every static has two `AllocId` that will resolve to the same + /// thing here: one maps to `AllocKind::Static`, this is the "lazy" ID, + /// and the other one is maps to `AllocKind::Memory`, this is returned by + /// `const_eval_raw` and it is the "resolved" ID. + /// The resolved ID is never used by the interpreted progrma, it is hidden. + /// The `AllocKind::Memory` branch here is still reachable though; when a static + /// contains a reference to memory that was created during its evaluation (i.e., not to + /// another static), those inner references only exist in "resolved" from. fn get_static_alloc( id: AllocId, tcx: TyCtxtAt<'a, 'tcx, 'tcx>, memory_extra: &M::MemoryExtra, ) -> EvalResult<'tcx, Cow<'tcx, Allocation>> { let alloc = tcx.alloc_map.lock().get(id); - let def_id = match alloc { + let alloc = match alloc { Some(AllocKind::Memory(mem)) => { - // We got tcx memory. Let the machine figure out whether and how to - // turn that into memory with the right pointer tag. - return Ok(M::adjust_static_allocation(mem, memory_extra)) + Cow::Borrowed(mem) } Some(AllocKind::Function(..)) => { return err!(DerefFunctionPointer) } - Some(AllocKind::Static(did)) => { - did - } None => return err!(DanglingPointerDeref), - }; - // We got a "lazy" static that has not been computed yet, do some work - trace!("static_alloc: Need to compute {:?}", def_id); - if tcx.is_foreign_item(def_id) { - return M::find_foreign_static(def_id, tcx, memory_extra); - } - let instance = Instance::mono(tcx.tcx, def_id); - let gid = GlobalId { - instance, - promoted: None, - }; - // use the raw query here to break validation cycles. Later uses of the static will call the - // full query anyway - tcx.const_eval_raw(ty::ParamEnv::reveal_all().and(gid)).map_err(|err| { - // no need to report anything, the const_eval call takes care of that for statics - assert!(tcx.is_static(def_id)); - match err { - ErrorHandled::Reported => InterpError::ReferencedConstant.into(), - ErrorHandled::TooGeneric => InterpError::TooGeneric.into(), + Some(AllocKind::Static(def_id)) => { + // We got a "lazy" static that has not been computed yet. + if tcx.is_foreign_item(def_id) { + trace!("static_alloc: foreign item {:?}", def_id); + M::find_foreign_static(def_id, tcx)? + } else { + trace!("static_alloc: Need to compute {:?}", def_id); + let instance = Instance::mono(tcx.tcx, def_id); + let gid = GlobalId { + instance, + promoted: None, + }; + // use the raw query here to break validation cycles. Later uses of the static + // will call the full query anyway + let raw_const = tcx.const_eval_raw(ty::ParamEnv::reveal_all().and(gid)) + .map_err(|err| { + // no need to report anything, the const_eval call takes care of that + // for statics + assert!(tcx.is_static(def_id)); + match err { + ErrorHandled::Reported => InterpError::ReferencedConstant, + ErrorHandled::TooGeneric => InterpError::TooGeneric, + } + })?; + // Make sure we use the ID of the resolved memory, not the lazy one! + let id = raw_const.alloc_id; + let allocation = tcx.alloc_map.lock().unwrap_memory(id); + Cow::Borrowed(allocation) + } } - }).map(|raw_const| { - let allocation = tcx.alloc_map.lock().unwrap_memory(raw_const.alloc_id); - // We got tcx memory. Let the machine figure out whether and how to - // turn that into memory with the right pointer tag. - M::adjust_static_allocation(allocation, memory_extra) - }) + }; + // We got tcx memory. Let the machine figure out whether and how to + // turn that into memory with the right pointer tag. + Ok(M::tag_allocation( + id, // always use the ID we got as input, not the "hidden" one. + alloc, + M::STATIC_KIND.map(MemoryKind::Machine), + memory_extra + ).0) } pub fn get(&self, id: AllocId) -> EvalResult<'tcx, &Allocation> { diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 289379f34a9a3..5583552263d4b 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -37,16 +37,6 @@ impl<'tcx, Tag> Immediate { Immediate::Scalar(ScalarMaybeUndef::Scalar(val)) } - #[inline] - pub fn erase_tag(self) -> Immediate - { - match self { - Immediate::Scalar(x) => Immediate::Scalar(x.erase_tag()), - Immediate::ScalarPair(x, y) => - Immediate::ScalarPair(x.erase_tag(), y.erase_tag()), - } - } - pub fn new_slice( val: Scalar, len: u64, @@ -130,15 +120,6 @@ pub enum Operand { } impl Operand { - #[inline] - pub fn erase_tag(self) -> Operand - { - match self { - Operand::Immediate(x) => Operand::Immediate(x.erase_tag()), - Operand::Indirect(x) => Operand::Indirect(x.erase_tag()), - } - } - #[inline] pub fn to_mem_place(self) -> MemPlace where Tag: ::std::fmt::Debug @@ -209,18 +190,6 @@ impl<'tcx, Tag: Copy> ImmTy<'tcx, Tag> } } -impl<'tcx, Tag> OpTy<'tcx, Tag> -{ - #[inline] - pub fn erase_tag(self) -> OpTy<'tcx> - { - OpTy { - op: self.op.erase_tag(), - layout: self.layout, - } - } -} - // Use the existing layout if given (but sanity check in debug mode), // or compute the layout. #[inline(always)] @@ -537,44 +506,53 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> val: &'tcx ty::Const<'tcx>, layout: Option>, ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> { - let op = match val.val { + let tag_scalar = |scalar| match scalar { + Scalar::Ptr(ptr) => Scalar::Ptr(self.tag_static_base_pointer(ptr)), + Scalar::Bits { bits, size } => Scalar::Bits { bits, size }, + }; + // Early-return cases. + match val.val { ConstValue::Param(_) => return err!(TooGeneric), - ConstValue::Infer(_) | ConstValue::Placeholder(_) => bug!(), - ConstValue::ByRef(ptr, alloc) => { - // We rely on mutability being set correctly in that allocation to prevent writes - // where none should happen -- and for `static mut`, we copy on demand anyway. - Operand::Indirect( - MemPlace::from_ptr(ptr.with_default_tag(), alloc.align) - ) - }, - ConstValue::Slice { data, start, end } => - Operand::Immediate(Immediate::ScalarPair( - Scalar::from(Pointer::new( - self.tcx.alloc_map.lock().allocate(data), - Size::from_bytes(start as u64), - )).with_default_tag().into(), - Scalar::from_uint( - (end - start) as u64, - self.tcx.data_layout.pointer_size, - ).with_default_tag().into(), - )), - ConstValue::Scalar(x) => - Operand::Immediate(Immediate::Scalar(x.with_default_tag().into())), ConstValue::Unevaluated(def_id, substs) => { let instance = self.resolve(def_id, substs)?; return Ok(OpTy::from(self.const_eval_raw(GlobalId { instance, promoted: None, })?)); - }, - }; + } + _ => {} + } + // Other cases need layout. let layout = from_known_layout(layout, || { self.layout_of(self.monomorphize(val.ty)?) })?; - Ok(OpTy { - op, - layout, - }) + let op = match val.val { + ConstValue::ByRef(ptr, _alloc) => { + // We rely on mutability being set correctly in that allocation to prevent writes + // where none should happen -- and for `static mut`, we copy on demand anyway. + let ptr = self.tag_static_base_pointer(ptr); + Operand::Indirect(MemPlace::from_ptr(ptr, layout.align.abi)) + }, + ConstValue::Scalar(x) => + Operand::Immediate(Immediate::Scalar(tag_scalar(x).into())), + ConstValue::Slice { data, start, end } => { + let ptr = Pointer::new( + self.tcx.alloc_map.lock().allocate(data), + Size::from_bytes(start as u64), // offset: `start` + ); + Operand::Immediate(Immediate::new_slice( + self.tag_static_base_pointer(ptr).into(), + (end - start) as u64, // len: `end - start` + self, + )) + } + ConstValue::Param(..) | + ConstValue::Infer(..) | + ConstValue::Placeholder(..) | + ConstValue::Unevaluated(..) => + bug!("eval_const_to_op: Unexpected ConstValue {:?}", val), + }; + Ok(OpTy { op, layout }) } /// Read discriminant, return the runtime value as well as the variant index. diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 0ae4e90b7c24d..84783adcf9f5e 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -5,7 +5,6 @@ use std::convert::TryFrom; use std::hash::Hash; -use rustc::hir; use rustc::mir; use rustc::mir::interpret::truncate; use rustc::ty::{self, Ty}; @@ -294,7 +293,7 @@ impl<'tcx, Tag: ::std::fmt::Debug> PlaceTy<'tcx, Tag> { impl<'a, 'mir, 'tcx, Tag, M> InterpretCx<'a, 'mir, 'tcx, M> where // FIXME: Working around https://github.com/rust-lang/rust/issues/54385 - Tag: ::std::fmt::Debug+Default+Copy+Eq+Hash+'static, + Tag: ::std::fmt::Debug + Copy + Eq + Hash + 'static, M: Machine<'a, 'mir, 'tcx, PointerTag=Tag>, // FIXME: Working around https://github.com/rust-lang/rust/issues/24159 M::MemoryMap: AllocMap, Allocation)>, @@ -325,25 +324,13 @@ where // Take an operand, representing a pointer, and dereference it to a place -- that // will always be a MemPlace. Lives in `place.rs` because it creates a place. - // This calls the "deref" machine hook, and counts as a deref as far as - // Stacked Borrows is concerned. pub fn deref_operand( &self, src: OpTy<'tcx, M::PointerTag>, ) -> EvalResult<'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)?; - // Pointer tag tracking might want to adjust the tag. - let mutbl = match val.layout.ty.sty { - // `builtin_deref` considers boxes immutable, that's useless for our purposes - ty::Ref(_, _, mutbl) => Some(mutbl), - ty::Adt(def, _) if def.is_box() => Some(hir::MutMutable), - ty::RawPtr(_) => None, - _ => bug!("Unexpected pointer type {}", val.layout.ty), - }; - place.mplace.ptr = M::tag_dereference(self, place, mutbl)?; - Ok(place) + self.ref_to_mplace(val) } /// Offset a pointer to project to a field. Unlike place_field, this is always @@ -587,18 +574,23 @@ where promoted: None }; // Just create a lazy reference, so we can support recursive statics. - // tcx takes are of assigning every static one and only one unique AllocId. + // tcx takes care of assigning every static one and only one unique AllocId. // When the data here is ever actually used, memory will notice, // and it knows how to deal with alloc_id that are present in the // global table but not in its local memory: It calls back into tcx through // a query, triggering the CTFE machinery to actually turn this lazy reference // into a bunch of bytes. IOW, statics are evaluated with CTFE even when // this InterpretCx uses another Machine (e.g., in miri). This is what we - // want! This way, computing statics works concistently between codegen + // want! This way, computing statics works consistently between codegen // and miri: They use the same query to eventually obtain a `ty::Const` // and use that for further computation. - let alloc = self.tcx.alloc_map.lock().intern_static(cid.instance.def_id()); - MPlaceTy::from_aligned_ptr(Pointer::from(alloc).with_default_tag(), layout) + // + // Notice that statics have *two* AllocIds: the lazy one, and the resolved + // one. Here we make sure that the interpreted program never sees the + // resolved ID. Also see the doc comment of `Memory::get_static_alloc`. + let alloc_id = self.tcx.alloc_map.lock().intern_static(cid.instance.def_id()); + let ptr = self.tag_static_base_pointer(Pointer::from(alloc_id)); + MPlaceTy::from_aligned_ptr(ptr, layout) } }) } @@ -1032,11 +1024,9 @@ where ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> { // This must be an allocation in `tcx` assert!(self.tcx.alloc_map.lock().get(raw.alloc_id).is_some()); + let ptr = self.tag_static_base_pointer(Pointer::from(raw.alloc_id)); let layout = self.layout_of(raw.ty)?; - Ok(MPlaceTy::from_aligned_ptr( - Pointer::new(raw.alloc_id, Size::ZERO).with_default_tag(), - layout, - )) + Ok(MPlaceTy::from_aligned_ptr(ptr, layout)) } /// Turn a place with a `dyn Trait` type into a place with the actual dynamic type. From 19c4cfd213dc57c2a495eef630dfe0a94415dd60 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 28 May 2019 19:08:14 +0200 Subject: [PATCH 05/20] fix comments --- src/librustc_mir/interpret/machine.rs | 3 ++- src/librustc_mir/interpret/memory.rs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index 7bf92711766a0..fa0750fa82aa9 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -171,7 +171,8 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized { /// cache the result. (This relies on `AllocMap::get_or` being able to add the /// owned allocation to the map even when the map is shared.) /// - /// The tag returned must be the same as the one returned by `tag_base_pointer`. + /// For static allocations, the tag returned must be the same as the one returned by + /// `tag_static_base_pointer`. fn tag_allocation<'b>( id: AllocId, alloc: Cow<'b, Allocation>, diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index d121a924cfbd9..cf72934fd4965 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -326,7 +326,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { /// The resolved ID is never used by the interpreted progrma, it is hidden. /// The `AllocKind::Memory` branch here is still reachable though; when a static /// contains a reference to memory that was created during its evaluation (i.e., not to - /// another static), those inner references only exist in "resolved" from. + /// another static), those inner references only exist in "resolved" form. fn get_static_alloc( id: AllocId, tcx: TyCtxtAt<'a, 'tcx, 'tcx>, From c60435003ce6f6497221d303a61727701433926e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 29 May 2019 10:59:16 +0200 Subject: [PATCH 06/20] fix rebase fallout --- src/librustc_mir/interpret/operand.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 5583552263d4b..8ede4a723c897 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -508,7 +508,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> { let tag_scalar = |scalar| match scalar { Scalar::Ptr(ptr) => Scalar::Ptr(self.tag_static_base_pointer(ptr)), - Scalar::Bits { bits, size } => Scalar::Bits { bits, size }, + Scalar::Raw { data, size } => Scalar::Raw { data, size }, }; // Early-return cases. match val.val { From 66cc1b72d47041ce74bcaa99915eec95042d165c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 29 May 2019 11:51:43 +0200 Subject: [PATCH 07/20] turn comments into doc-comments --- src/librustc/mir/interpret/value.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs index 1c24f5c116cce..b8d6c12244631 100644 --- a/src/librustc/mir/interpret/value.rs +++ b/src/librustc/mir/interpret/value.rs @@ -138,9 +138,11 @@ impl<'tcx> Scalar<()> { "Scalar value {:#x} exceeds size of {} bytes", data, size); } + /// Tag this scalar with `new_tag` if it is a pointer, leave it unchanged otherwise. + /// + /// Used by `MemPlace::replace_tag`. #[inline] pub fn with_tag(self, new_tag: Tag) -> Scalar { - // Used by `MemPlace::replace_tag` match self { Scalar::Ptr(ptr) => Scalar::Ptr(ptr.with_tag(new_tag)), Scalar::Raw { data, size } => Scalar::Raw { data, size }, @@ -149,9 +151,11 @@ impl<'tcx> Scalar<()> { } impl<'tcx, Tag> Scalar { + /// Erase the tag from the scalar, if any. + /// + /// Used by error reporting code to avoid having the error type depend on `Tag`. #[inline] pub fn erase_tag(self) -> Scalar { - // Used by error reporting code to avoid having the error type depend on `Tag` match self { Scalar::Ptr(ptr) => Scalar::Ptr(ptr.erase_tag()), Scalar::Raw { data, size } => Scalar::Raw { data, size }, @@ -472,10 +476,12 @@ impl fmt::Display for ScalarMaybeUndef { } impl<'tcx, Tag> ScalarMaybeUndef { + /// Erase the tag from the scalar, if any. + /// + /// Used by error reporting code to avoid having the error type depend on `Tag`. #[inline] pub fn erase_tag(self) -> ScalarMaybeUndef { - // Used by error reporting code to avoid having the error type depend on `Tag` match self { ScalarMaybeUndef::Scalar(s) => ScalarMaybeUndef::Scalar(s.erase_tag()), ScalarMaybeUndef::Undef => ScalarMaybeUndef::Undef, From b073599929ab8dbd71369c01f8bde35d9574df16 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 29 May 2019 11:52:14 +0200 Subject: [PATCH 08/20] fix indentation --- src/librustc_mir/interpret/eval_context.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 594802a03410c..a6153bf055d60 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -44,9 +44,9 @@ pub struct InterpretCx<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'a, 'mir, 'tcx>> { /// A cache for deduplicating vtables pub(super) vtables: FxHashMap< - (Ty<'tcx>, Option>), - Pointer - >, + (Ty<'tcx>, Option>), + Pointer + >, } /// A stack frame. From 1a7ce022a6ce303944bb9b0a7d8b3c68f6cf8a14 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 29 May 2019 14:49:02 +0200 Subject: [PATCH 09/20] FIXME --- src/librustc_mir/interpret/operand.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 8ede4a723c897..538e53699fd1c 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -512,7 +512,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> }; // Early-return cases. match val.val { - ConstValue::Param(_) => return err!(TooGeneric), + ConstValue::Param(_) => return err!(TooGeneric), // FIXME(oli-obk): try to monomorphize ConstValue::Unevaluated(def_id, substs) => { let instance = self.resolve(def_id, substs)?; return Ok(OpTy::from(self.const_eval_raw(GlobalId { From 5a8f6db4858e75cf6bac6c89a4ba578f30e9c85f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 29 May 2019 15:16:18 +0200 Subject: [PATCH 10/20] update comments --- src/librustc_mir/interpret/operand.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 538e53699fd1c..83c26110cd218 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -529,13 +529,15 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> let op = match val.val { ConstValue::ByRef(ptr, _alloc) => { // We rely on mutability being set correctly in that allocation to prevent writes - // where none should happen -- and for `static mut`, we copy on demand anyway. + // where none should happen. let ptr = self.tag_static_base_pointer(ptr); Operand::Indirect(MemPlace::from_ptr(ptr, layout.align.abi)) }, ConstValue::Scalar(x) => Operand::Immediate(Immediate::Scalar(tag_scalar(x).into())), ConstValue::Slice { data, start, end } => { + // We rely on mutability being set correctly in `data` to prevent writes + // where none should happen. let ptr = Pointer::new( self.tcx.alloc_map.lock().allocate(data), Size::from_bytes(start as u64), // offset: `start` From bf0da6c6ce77b43add5a391f4d5090ad6b4c444e Mon Sep 17 00:00:00 2001 From: memoryruins Date: Thu, 30 May 2019 04:13:55 -0400 Subject: [PATCH 11/20] Set ellipsis_inclusive_range_patterns lint to warn --- src/librustc_lint/builtin.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index d184c671bbaf8..434a1498a1c93 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -1275,7 +1275,7 @@ declare_lint_pass!( declare_lint! { pub ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, - Allow, + Warn, "`...` range patterns are deprecated" } From e18885e21ff3e5abaaf702c9f2109323e2e5a659 Mon Sep 17 00:00:00 2001 From: memoryruins Date: Thu, 30 May 2019 06:20:30 -0400 Subject: [PATCH 12/20] Update ui and run-pass for ellipsis_inclusive_range_patterns lint --- .../associated-const-range-match-patterns.rs | 14 +++++ src/test/run-pass/binding/pat-ranges.rs | 6 +++ src/test/run-pass/inc-range-pat.rs | 2 + .../issue-15881-model-lexer-dotdotdot.rs | 1 + .../mir/mir_build_match_comparisons.rs | 2 +- .../ui/lint/issue-54538-unused-parens-lint.rs | 28 ++++++++-- .../issue-54538-unused-parens-lint.stderr | 52 ++++++++++++++++--- .../ui/match/match-range-fail-dominate.rs | 18 +++---- .../ui/match/match-range-fail-dominate.stderr | 14 ++--- src/test/ui/nll/issue-57960.rs | 6 +-- 10 files changed, 112 insertions(+), 31 deletions(-) diff --git a/src/test/run-pass/associated-consts/associated-const-range-match-patterns.rs b/src/test/run-pass/associated-consts/associated-const-range-match-patterns.rs index 4801369cfd1a8..5276869a702ee 100644 --- a/src/test/run-pass/associated-consts/associated-const-range-match-patterns.rs +++ b/src/test/run-pass/associated-consts/associated-const-range-match-patterns.rs @@ -1,5 +1,6 @@ // run-pass #![allow(dead_code, unreachable_patterns)] +#![allow(ellipsis_inclusive_range_patterns)] struct Foo; @@ -23,4 +24,17 @@ fn main() { ::NUM ... ::NUM => true, _ => false, }); + + assert!(match 2 { + Foo::NUM ..= 3 => true, + _ => false, + }); + assert!(match 0 { + -1 ..= ::NUM => true, + _ => false, + }); + assert!(match 1 { + ::NUM ..= ::NUM => true, + _ => false, + }); } diff --git a/src/test/run-pass/binding/pat-ranges.rs b/src/test/run-pass/binding/pat-ranges.rs index b3729a79615a6..19b3045784f86 100644 --- a/src/test/run-pass/binding/pat-ranges.rs +++ b/src/test/run-pass/binding/pat-ranges.rs @@ -1,6 +1,8 @@ // run-pass // Parsing of range patterns +#![allow(ellipsis_inclusive_range_patterns)] + const NUM1: i32 = 10; mod m { @@ -11,4 +13,8 @@ fn main() { if let NUM1 ... m::NUM2 = 10 {} else { panic!() } if let ::NUM1 ... ::m::NUM2 = 11 {} else { panic!() } if let -13 ... -10 = 12 { panic!() } else {} + + if let NUM1 ..= m::NUM2 = 10 {} else { panic!() } + if let ::NUM1 ..= ::m::NUM2 = 11 {} else { panic!() } + if let -13 ..= -10 = 12 { panic!() } else {} } diff --git a/src/test/run-pass/inc-range-pat.rs b/src/test/run-pass/inc-range-pat.rs index 6bf857a11f816..a648ff17492ee 100644 --- a/src/test/run-pass/inc-range-pat.rs +++ b/src/test/run-pass/inc-range-pat.rs @@ -1,5 +1,7 @@ // Test old and new syntax for inclusive range patterns. +#![allow(ellipsis_inclusive_range_patterns)] + fn main() { assert!(match 42 { 0 ... 100 => true, _ => false }); assert!(match 42 { 0 ..= 100 => true, _ => false }); diff --git a/src/test/run-pass/issues/issue-15881-model-lexer-dotdotdot.rs b/src/test/run-pass/issues/issue-15881-model-lexer-dotdotdot.rs index 2470e37e1820b..dee7f25d7bb3a 100644 --- a/src/test/run-pass/issues/issue-15881-model-lexer-dotdotdot.rs +++ b/src/test/run-pass/issues/issue-15881-model-lexer-dotdotdot.rs @@ -1,5 +1,6 @@ // run-pass #![allow(illegal_floating_point_literal_pattern)] // FIXME #41620 +#![allow(ellipsis_inclusive_range_patterns)] // regression test for the model lexer handling the DOTDOTDOT syntax (#15877) diff --git a/src/test/run-pass/mir/mir_build_match_comparisons.rs b/src/test/run-pass/mir/mir_build_match_comparisons.rs index 8913009f69156..04570055763a9 100644 --- a/src/test/run-pass/mir/mir_build_match_comparisons.rs +++ b/src/test/run-pass/mir/mir_build_match_comparisons.rs @@ -2,7 +2,7 @@ #![allow(dead_code)] fn test1(x: i8) -> i32 { match x { - 1...10 => 0, + 1..=10 => 0, _ => 1, } } diff --git a/src/test/ui/lint/issue-54538-unused-parens-lint.rs b/src/test/ui/lint/issue-54538-unused-parens-lint.rs index 6ca53816e3c6b..3a52996195c0d 100644 --- a/src/test/ui/lint/issue-54538-unused-parens-lint.rs +++ b/src/test/ui/lint/issue-54538-unused-parens-lint.rs @@ -1,10 +1,32 @@ // compile-pass +#![allow(ellipsis_inclusive_range_patterns)] #![allow(unreachable_patterns)] #![allow(unused_variables)] #![warn(unused_parens)] fn main() { + match 1 { + (_) => {} //~ WARNING: unnecessary parentheses around pattern + (y) => {} //~ WARNING: unnecessary parentheses around pattern + (ref r) => {} //~ WARNING: unnecessary parentheses around pattern + (e @ 1...2) => {} //~ WARNING: unnecessary parentheses around outer pattern + (1...2) => {} // Non ambiguous range pattern should not warn + e @ (3...4) => {} // Non ambiguous range pattern should not warn + } + + match &1 { + (e @ &(1...2)) => {} //~ WARNING: unnecessary parentheses around outer pattern + &(_) => {} //~ WARNING: unnecessary parentheses around pattern + e @ &(1...2) => {} // Ambiguous range pattern should not warn + &(1...2) => {} // Ambiguous range pattern should not warn + } + + match &1 { + e @ &(1...2) | e @ &(3...4) => {} // Complex ambiguous pattern should not warn + &_ => {} + } + match 1 { (_) => {} //~ WARNING: unnecessary parentheses around pattern (y) => {} //~ WARNING: unnecessary parentheses around pattern @@ -15,14 +37,14 @@ fn main() { } match &1 { - (e @ &(1...2)) => {} //~ WARNING: unnecessary parentheses around outer pattern + (e @ &(1..=2)) => {} //~ WARNING: unnecessary parentheses around outer pattern &(_) => {} //~ WARNING: unnecessary parentheses around pattern - e @ &(1...2) => {} // Ambiguous range pattern should not warn + e @ &(1..=2) => {} // Ambiguous range pattern should not warn &(1..=2) => {} // Ambiguous range pattern should not warn } match &1 { - e @ &(1...2) | e @ &(3..=4) => {} // Complex ambiguous pattern should not warn + e @ &(1..=2) | e @ &(3..=4) => {} // Complex ambiguous pattern should not warn &_ => {} } } diff --git a/src/test/ui/lint/issue-54538-unused-parens-lint.stderr b/src/test/ui/lint/issue-54538-unused-parens-lint.stderr index 3cf321b072f40..3b312198952a5 100644 --- a/src/test/ui/lint/issue-54538-unused-parens-lint.stderr +++ b/src/test/ui/lint/issue-54538-unused-parens-lint.stderr @@ -1,41 +1,77 @@ warning: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:9:9 + --> $DIR/issue-54538-unused-parens-lint.rs:10:9 | LL | (_) => {} | ^^^ help: remove these parentheses | note: lint level defined here - --> $DIR/issue-54538-unused-parens-lint.rs:5:9 + --> $DIR/issue-54538-unused-parens-lint.rs:6:9 | LL | #![warn(unused_parens)] | ^^^^^^^^^^^^^ warning: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:10:9 + --> $DIR/issue-54538-unused-parens-lint.rs:11:9 | LL | (y) => {} | ^^^ help: remove these parentheses warning: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:11:9 + --> $DIR/issue-54538-unused-parens-lint.rs:12:9 | LL | (ref r) => {} | ^^^^^^^ help: remove these parentheses warning: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:12:9 + --> $DIR/issue-54538-unused-parens-lint.rs:13:9 | -LL | (e @ 1..=2) => {} +LL | (e @ 1...2) => {} | ^^^^^^^^^^^ help: remove these parentheses warning: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:18:9 + --> $DIR/issue-54538-unused-parens-lint.rs:19:9 | LL | (e @ &(1...2)) => {} | ^^^^^^^^^^^^^^ help: remove these parentheses warning: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:19:10 + --> $DIR/issue-54538-unused-parens-lint.rs:20:10 + | +LL | &(_) => {} + | ^^^ help: remove these parentheses + +warning: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:31:9 + | +LL | (_) => {} + | ^^^ help: remove these parentheses + +warning: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:32:9 + | +LL | (y) => {} + | ^^^ help: remove these parentheses + +warning: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:33:9 + | +LL | (ref r) => {} + | ^^^^^^^ help: remove these parentheses + +warning: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:34:9 + | +LL | (e @ 1..=2) => {} + | ^^^^^^^^^^^ help: remove these parentheses + +warning: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:40:9 + | +LL | (e @ &(1..=2)) => {} + | ^^^^^^^^^^^^^^ help: remove these parentheses + +warning: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:41:10 | LL | &(_) => {} | ^^^ help: remove these parentheses diff --git a/src/test/ui/match/match-range-fail-dominate.rs b/src/test/ui/match/match-range-fail-dominate.rs index 99069183e4eda..a0cc773d20edd 100644 --- a/src/test/ui/match/match-range-fail-dominate.rs +++ b/src/test/ui/match/match-range-fail-dominate.rs @@ -8,31 +8,31 @@ fn main() { match 5 { - 1 ... 10 => { } - 5 ... 6 => { } + 1 ..= 10 => { } + 5 ..= 6 => { } _ => {} }; match 5 { - 3 ... 6 => { } - 4 ... 6 => { } + 3 ..= 6 => { } + 4 ..= 6 => { } _ => {} }; match 5 { - 4 ... 6 => { } - 4 ... 6 => { } + 4 ..= 6 => { } + 4 ..= 6 => { } _ => {} }; match 'c' { - 'A' ... 'z' => {} - 'a' ... 'z' => {} + 'A' ..= 'z' => {} + 'a' ..= 'z' => {} _ => {} }; match 1.0f64 { - 0.01f64 ... 6.5f64 => {} + 0.01f64 ..= 6.5f64 => {} 0.02f64 => {} _ => {} }; diff --git a/src/test/ui/match/match-range-fail-dominate.stderr b/src/test/ui/match/match-range-fail-dominate.stderr index 0f5ab7fff3840..f481e56c85e56 100644 --- a/src/test/ui/match/match-range-fail-dominate.stderr +++ b/src/test/ui/match/match-range-fail-dominate.stderr @@ -1,7 +1,7 @@ error: unreachable pattern --> $DIR/match-range-fail-dominate.rs:12:7 | -LL | 5 ... 6 => { } +LL | 5 ..= 6 => { } | ^^^^^^^ | note: lint level defined here @@ -13,25 +13,25 @@ LL | #![deny(unreachable_patterns)] error: unreachable pattern --> $DIR/match-range-fail-dominate.rs:18:7 | -LL | 4 ... 6 => { } +LL | 4 ..= 6 => { } | ^^^^^^^ error: unreachable pattern --> $DIR/match-range-fail-dominate.rs:24:7 | -LL | 4 ... 6 => { } +LL | 4 ..= 6 => { } | ^^^^^^^ error: unreachable pattern --> $DIR/match-range-fail-dominate.rs:30:7 | -LL | 'a' ... 'z' => {} +LL | 'a' ..= 'z' => {} | ^^^^^^^^^^^ warning: floating-point types cannot be used in patterns --> $DIR/match-range-fail-dominate.rs:35:7 | -LL | 0.01f64 ... 6.5f64 => {} +LL | 0.01f64 ..= 6.5f64 => {} | ^^^^^^^ | = note: #[warn(illegal_floating_point_literal_pattern)] on by default @@ -41,7 +41,7 @@ LL | 0.01f64 ... 6.5f64 => {} warning: floating-point types cannot be used in patterns --> $DIR/match-range-fail-dominate.rs:35:19 | -LL | 0.01f64 ... 6.5f64 => {} +LL | 0.01f64 ..= 6.5f64 => {} | ^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -65,7 +65,7 @@ LL | 0.02f64 => {} warning: floating-point types cannot be used in patterns --> $DIR/match-range-fail-dominate.rs:35:7 | -LL | 0.01f64 ... 6.5f64 => {} +LL | 0.01f64 ..= 6.5f64 => {} | ^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! diff --git a/src/test/ui/nll/issue-57960.rs b/src/test/ui/nll/issue-57960.rs index 0b52e46c45989..1399694a79b6a 100644 --- a/src/test/ui/nll/issue-57960.rs +++ b/src/test/ui/nll/issue-57960.rs @@ -27,9 +27,9 @@ impl Range for ThreeDigits { fn digits(x: u8) -> u32 { match x { - OneDigit::FIRST...OneDigit::LAST => 1, - TwoDigits::FIRST...TwoDigits::LAST => 2, - ThreeDigits::FIRST...ThreeDigits::LAST => 3, + OneDigit::FIRST..=OneDigit::LAST => 1, + TwoDigits::FIRST..=TwoDigits::LAST => 2, + ThreeDigits::FIRST..=ThreeDigits::LAST => 3, _ => unreachable!(), } } From 3ffab36462e9da9842ffc6ab538be198fa8c0e18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Miku=C5=82a?= Date: Thu, 30 May 2019 13:59:12 +0200 Subject: [PATCH 13/20] Migrate unstable-book to MdBook2 --- src/bootstrap/doc.rs | 2 +- src/doc/unstable-book/src/language-features/asm.md | 2 +- .../src/language-features/box-patterns.md | 2 +- .../unstable-book/src/language-features/box-syntax.md | 2 +- .../unstable-book/src/language-features/global-asm.md | 2 +- .../unstable-book/src/language-features/lang-items.md | 2 +- .../src/language-features/non-ascii-idents.md | 2 +- .../src/language-features/plugin-registrar.md | 2 +- src/doc/unstable-book/src/language-features/plugin.md | 10 +++++----- .../src/language-features/unboxed-closures.md | 2 +- .../unstable-book/src/library-features/fn-traits.md | 2 +- src/doc/unstable-book/src/library-features/fnbox.md | 2 +- src/doc/unstable-book/src/the-unstable-book.md | 2 +- 13 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 12bdfa5691dc7..b98a6b5e1814b 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -134,7 +134,7 @@ impl Step for UnstableBook { target: self.target, name: INTERNER.intern_str("unstable-book"), src: builder.md_doc_out(self.target), - version: RustbookVersion::MdBook1, + version: RustbookVersion::MdBook2, }) } } diff --git a/src/doc/unstable-book/src/language-features/asm.md b/src/doc/unstable-book/src/language-features/asm.md index f22095fe5de2e..2a1b6397781f9 100644 --- a/src/doc/unstable-book/src/language-features/asm.md +++ b/src/doc/unstable-book/src/language-features/asm.md @@ -190,4 +190,4 @@ constraints, etc. [llvm-docs]: http://llvm.org/docs/LangRef.html#inline-assembler-expressions If you need more power and don't mind losing some of the niceties of -`asm!`, check out [global_asm](language-features/global-asm.html). +`asm!`, check out [global_asm](global-asm.md). diff --git a/src/doc/unstable-book/src/language-features/box-patterns.md b/src/doc/unstable-book/src/language-features/box-patterns.md index 0896627acae1b..bf0819ec920b7 100644 --- a/src/doc/unstable-book/src/language-features/box-patterns.md +++ b/src/doc/unstable-book/src/language-features/box-patterns.md @@ -4,7 +4,7 @@ The tracking issue for this feature is: [#29641] [#29641]: https://github.com/rust-lang/rust/issues/29641 -See also [`box_syntax`](language-features/box-syntax.html) +See also [`box_syntax`](box-syntax.md) ------------------------ diff --git a/src/doc/unstable-book/src/language-features/box-syntax.md b/src/doc/unstable-book/src/language-features/box-syntax.md index 414dc48e557d3..9569974d22ca2 100644 --- a/src/doc/unstable-book/src/language-features/box-syntax.md +++ b/src/doc/unstable-book/src/language-features/box-syntax.md @@ -4,7 +4,7 @@ The tracking issue for this feature is: [#49733] [#49733]: https://github.com/rust-lang/rust/issues/49733 -See also [`box_patterns`](language-features/box-patterns.html) +See also [`box_patterns`](box-patterns.md) ------------------------ diff --git a/src/doc/unstable-book/src/language-features/global-asm.md b/src/doc/unstable-book/src/language-features/global-asm.md index f1ef74a63b513..bc55fe80fa64c 100644 --- a/src/doc/unstable-book/src/language-features/global-asm.md +++ b/src/doc/unstable-book/src/language-features/global-asm.md @@ -75,4 +75,4 @@ usages and placed the larger, single usage in the crate root. If you don't need quite as much power and flexibility as `global_asm!` provides, and you don't mind restricting your inline assembly to `fn` bodies only, you might try the -[asm](language-features/asm.html) feature instead. +[asm](asm.md) feature instead. diff --git a/src/doc/unstable-book/src/language-features/lang-items.md b/src/doc/unstable-book/src/language-features/lang-items.md index b16739b4743a9..3ee024c6b5883 100644 --- a/src/doc/unstable-book/src/language-features/lang-items.md +++ b/src/doc/unstable-book/src/language-features/lang-items.md @@ -192,7 +192,7 @@ such as "```undefined reference to `__rust_probestack'```". Using this crate also requires enabling the library feature `compiler_builtins_lib`. You can read more about this [here][compiler-builtins-lib]. -[compiler-builtins-lib]: library-features/compiler-builtins-lib.html +[compiler-builtins-lib]: ../library-features/compiler-builtins-lib.md ## More about the language items diff --git a/src/doc/unstable-book/src/language-features/non-ascii-idents.md b/src/doc/unstable-book/src/language-features/non-ascii-idents.md index 46957c00bf95c..22dae0c89a6ff 100644 --- a/src/doc/unstable-book/src/language-features/non-ascii-idents.md +++ b/src/doc/unstable-book/src/language-features/non-ascii-idents.md @@ -45,4 +45,4 @@ that does _not_ occur in the set of [strict keywords]. [`XID_start`]: http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5B%3AXID_Start%3A%5D&abb=on&g=&i= [`XID_continue`]: http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5B%3AXID_Continue%3A%5D&abb=on&g=&i= -[strict keywords]: ../reference/keywords.html#strict-keywords +[strict keywords]: ../../reference/keywords.md#strict-keywords diff --git a/src/doc/unstable-book/src/language-features/plugin-registrar.md b/src/doc/unstable-book/src/language-features/plugin-registrar.md index b16e2ac2d221c..bf5dd81d735af 100644 --- a/src/doc/unstable-book/src/language-features/plugin-registrar.md +++ b/src/doc/unstable-book/src/language-features/plugin-registrar.md @@ -8,6 +8,6 @@ This feature is part of "compiler plugins." It will often be used with the [`plugin`] and `rustc_private` features as well. For more details, see their docs. -[`plugin`]: language-features/plugin.html +[`plugin`]: plugin.md ------------------------ diff --git a/src/doc/unstable-book/src/language-features/plugin.md b/src/doc/unstable-book/src/language-features/plugin.md index 49fe7c9e994fe..43fffd680372f 100644 --- a/src/doc/unstable-book/src/language-features/plugin.md +++ b/src/doc/unstable-book/src/language-features/plugin.md @@ -8,7 +8,7 @@ The tracking issue for this feature is: [#29597] This feature is part of "compiler plugins." It will often be used with the [`plugin_registrar`] and `rustc_private` features. -[`plugin_registrar`]: language-features/plugin-registrar.html +[`plugin_registrar`]: plugin-registrar.md ------------------------ @@ -39,7 +39,7 @@ of a library. Plugins can extend Rust's syntax in various ways. One kind of syntax extension is the procedural macro. These are invoked the same way as [ordinary -macros](../book/macros.html), but the expansion is performed by arbitrary Rust +macros](../../book/macros.md), but the expansion is performed by arbitrary Rust code that manipulates syntax trees at compile time. @@ -130,7 +130,7 @@ The advantages over a simple `fn(&str) -> u32` are: a way to define new literal syntax for any data type. In addition to procedural macros, you can define new -[`derive`](../reference/attributes/derive.html)-like attributes and other kinds +[`derive`](../../reference/attributes/derive.md)-like attributes and other kinds of extensions. See `Registry::register_syntax_extension` and the `SyntaxExtension` enum. For a more involved macro example, see [`regex_macros`](https://github.com/rust-lang/regex/blob/master/regex_macros/src/lib.rs). @@ -174,7 +174,7 @@ quasiquote as an ordinary plugin library. # Lint plugins Plugins can extend [Rust's lint -infrastructure](../reference/attributes/diagnostics.html#lint-check-attributes) with +infrastructure](../../reference/attributes/diagnostics.md#lint-check-attributes) with additional checks for code style, safety, etc. Now let's write a plugin [`lint_plugin_test.rs`](https://github.com/rust-lang/rust/blob/master/src/test/ui-fulldeps/auxiliary/lint_plugin_test.rs) that warns about any item named `lintme`. @@ -253,7 +253,7 @@ mostly use the same infrastructure as lint plugins, and provide examples of how to access type information. Lints defined by plugins are controlled by the usual [attributes and compiler -flags](../reference/attributes/diagnostics.html#lint-check-attributes), e.g. +flags](../../reference/attributes/diagnostics.md#lint-check-attributes), e.g. `#[allow(test_lint)]` or `-A test-lint`. These identifiers are derived from the first argument to `declare_lint!`, with appropriate case and punctuation conversion. diff --git a/src/doc/unstable-book/src/language-features/unboxed-closures.md b/src/doc/unstable-book/src/language-features/unboxed-closures.md index d845c99a88a69..71003fba00ba2 100644 --- a/src/doc/unstable-book/src/language-features/unboxed-closures.md +++ b/src/doc/unstable-book/src/language-features/unboxed-closures.md @@ -2,7 +2,7 @@ The tracking issue for this feature is [#29625] -See Also: [`fn_traits`](library-features/fn-traits.html) +See Also: [`fn_traits`](../library-features/fn-traits.md) [#29625]: https://github.com/rust-lang/rust/issues/29625 diff --git a/src/doc/unstable-book/src/library-features/fn-traits.md b/src/doc/unstable-book/src/library-features/fn-traits.md index 72a3f36c10b69..29a8aecee6c2f 100644 --- a/src/doc/unstable-book/src/library-features/fn-traits.md +++ b/src/doc/unstable-book/src/library-features/fn-traits.md @@ -2,7 +2,7 @@ The tracking issue for this feature is [#29625] -See Also: [`unboxed_closures`](language-features/unboxed-closures.html) +See Also: [`unboxed_closures`](../language-features/unboxed-closures.md) [#29625]: https://github.com/rust-lang/rust/issues/29625 diff --git a/src/doc/unstable-book/src/library-features/fnbox.md b/src/doc/unstable-book/src/library-features/fnbox.md index cb3386b715211..97e32cc0acb12 100644 --- a/src/doc/unstable-book/src/library-features/fnbox.md +++ b/src/doc/unstable-book/src/library-features/fnbox.md @@ -27,6 +27,6 @@ impl Fn for &F where F: Fn + ?Sized {} Before the introduction of [`unsized_locals`][unsized_locals], we had been unable to provide the former impls. That means, unlike `&dyn Fn()` or `&mut dyn FnMut()` we could not use `Box` at that time. -[unsized_locals]: language-features/unsized-locals.html +[unsized_locals]: ../language-features/unsized-locals.md `FnBox()` is an alternative approach to `Box` is delegated to `FnBox::call_box` which doesn't need unsized locals. As we now have `Box` working, the `fnbox` feature is going to be removed. diff --git a/src/doc/unstable-book/src/the-unstable-book.md b/src/doc/unstable-book/src/the-unstable-book.md index 604b449f16379..554c52c3c9c27 100644 --- a/src/doc/unstable-book/src/the-unstable-book.md +++ b/src/doc/unstable-book/src/the-unstable-book.md @@ -14,7 +14,7 @@ fn main() { The `box_syntax` feature [has a chapter][box] describing how to use it. -[box]: language-features/box-syntax.html +[box]: language-features/box-syntax.md Because this documentation relates to unstable features, we make no guarantees that what is contained here is accurate or up to date. It's developed on a From 5f929be1624fdf6fc49cb36eac54db5e6b38e275 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Miku=C5=82a?= Date: Thu, 30 May 2019 14:22:33 +0200 Subject: [PATCH 14/20] Migrate rustdoc book to MdBook2 --- src/bootstrap/doc.rs | 2 +- src/doc/rustdoc/src/command-line-arguments.md | 8 ++++---- src/doc/rustdoc/src/passes.md | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index b98a6b5e1814b..5cd9f99d12108 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -66,7 +66,7 @@ book!( Reference, "src/doc/reference", "reference", RustbookVersion::MdBook1; RustByExample, "src/doc/rust-by-example", "rust-by-example", RustbookVersion::MdBook1; RustcBook, "src/doc/rustc", "rustc", RustbookVersion::MdBook1; - RustdocBook, "src/doc/rustdoc", "rustdoc", RustbookVersion::MdBook1; + RustdocBook, "src/doc/rustdoc", "rustdoc", RustbookVersion::MdBook2; ); #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] diff --git a/src/doc/rustdoc/src/command-line-arguments.md b/src/doc/rustdoc/src/command-line-arguments.md index aba485f752ab2..b21defaedc313 100644 --- a/src/doc/rustdoc/src/command-line-arguments.md +++ b/src/doc/rustdoc/src/command-line-arguments.md @@ -178,7 +178,7 @@ $ rustdoc src/lib.rs --passes strip-priv-imports An argument of "list" will print a list of possible "rustdoc passes", and other arguments will be the name of which passes to run in addition to the defaults. -For more details on passes, see [the chapter on them](passes.html). +For more details on passes, see [the chapter on them](passes.md). See also `--no-defaults`. @@ -194,7 +194,7 @@ By default, `rustdoc` will run several passes over your code. This removes those defaults, allowing you to use `--passes` to specify exactly which passes you want. -For more details on passes, see [the chapter on them](passes.html). +For more details on passes, see [the chapter on them](passes.md). See also `--passes`. @@ -207,7 +207,7 @@ $ rustdoc src/lib.rs --test ``` This flag will run your code examples as tests. For more, see [the chapter -on documentation tests](documentation-tests.html). +on documentation tests](documentation-tests.md). See also `--test-args`. @@ -220,7 +220,7 @@ $ rustdoc src/lib.rs --test --test-args ignored ``` This flag will pass options to the test runner when running documentation tests. -For more, see [the chapter on documentation tests](documentation-tests.html). +For more, see [the chapter on documentation tests](documentation-tests.md). See also `--test`. diff --git a/src/doc/rustdoc/src/passes.md b/src/doc/rustdoc/src/passes.md index 615b3dca199f1..12d4ea205b31e 100644 --- a/src/doc/rustdoc/src/passes.md +++ b/src/doc/rustdoc/src/passes.md @@ -5,8 +5,8 @@ Rustdoc has a concept called "passes". These are transformations that In addition to the passes below, check out the docs for these flags: -* [`--passes`](command-line-arguments.html#a--passes-add-more-rustdoc-passes) -* [`--no-defaults`](command-line-arguments.html#a--no-defaults-dont-run-default-passes) +* [`--passes`](command-line-arguments.md#--passes-add-more-rustdoc-passes) +* [`--no-defaults`](command-line-arguments.md#--no-defaults-dont-run-default-passes) ## Default passes From dacf19cb5922f92aaa9ffca085656018ce4ffe0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Miku=C5=82a?= Date: Thu, 30 May 2019 14:30:59 +0200 Subject: [PATCH 15/20] Migrate nomicon book to MdBook2 --- src/bootstrap/doc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 5cd9f99d12108..2a3577a3d2044 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -62,7 +62,7 @@ macro_rules! book { book!( EditionGuide, "src/doc/edition-guide", "edition-guide", RustbookVersion::MdBook2; EmbeddedBook, "src/doc/embedded-book", "embedded-book", RustbookVersion::MdBook2; - Nomicon, "src/doc/nomicon", "nomicon", RustbookVersion::MdBook1; + Nomicon, "src/doc/nomicon", "nomicon", RustbookVersion::MdBook2; Reference, "src/doc/reference", "reference", RustbookVersion::MdBook1; RustByExample, "src/doc/rust-by-example", "rust-by-example", RustbookVersion::MdBook1; RustcBook, "src/doc/rustc", "rustc", RustbookVersion::MdBook1; From 436c9bee79d34b5d6637f87e415d90bd82029236 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 30 May 2019 19:06:23 +0200 Subject: [PATCH 16/20] Fix links in Deref documentation --- src/libcore/ops/deref.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libcore/ops/deref.rs b/src/libcore/ops/deref.rs index e44a6c4d2a0e9..ce0d3fd01f78f 100644 --- a/src/libcore/ops/deref.rs +++ b/src/libcore/ops/deref.rs @@ -23,9 +23,9 @@ /// * Values of type `&T` are coerced to values of type `&U` /// * `T` implicitly implements all the (immutable) methods of the type `U`. /// -/// For more details, visit [the chapter in *The Rust Programming Language*] -/// [book] as well as the reference sections on [the dereference operator] -/// [ref-deref-op], [method resolution] and [type coercions]. +/// For more details, visit [the chapter in *The Rust Programming Language*][book] +/// as well as the reference sections on [the dereference operator][ref-deref-op], +/// [method resolution] and [type coercions]. /// /// [book]: ../../book/ch15-02-deref.html /// [`DerefMut`]: trait.DerefMut.html @@ -113,9 +113,9 @@ impl Deref for &mut T { /// * Values of type `&mut T` are coerced to values of type `&mut U` /// * `T` implicitly implements all the (mutable) methods of the type `U`. /// -/// For more details, visit [the chapter in *The Rust Programming Language*] -/// [book] as well as the reference sections on [the dereference operator] -/// [ref-deref-op], [method resolution] and [type coercions]. +/// For more details, visit [the chapter in *The Rust Programming Language*][book] +/// as well as the reference sections on [the dereference operator][ref-deref-op], +/// [method resolution] and [type coercions]. /// /// [book]: ../../book/ch15-02-deref.html /// [`Deref`]: trait.Deref.html From 0c35c699d43ba24943bb8f38986f84c4be676dc3 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Thu, 30 May 2019 18:00:17 +0000 Subject: [PATCH 17/20] Stabilize iter_nth_back feature --- src/liballoc/lib.rs | 1 - src/libcore/iter/traits/double_ended.rs | 5 +---- src/libcore/tests/lib.rs | 1 - 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index d90036eaf49b8..bfc008e14a486 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -112,7 +112,6 @@ #![feature(maybe_uninit_extra, maybe_uninit_slice, maybe_uninit_array)] #![feature(alloc_layout_extra)] #![feature(try_trait)] -#![feature(iter_nth_back)] // Allow testing this library diff --git a/src/libcore/iter/traits/double_ended.rs b/src/libcore/iter/traits/double_ended.rs index 06de95c082724..2c1aeb5690a58 100644 --- a/src/libcore/iter/traits/double_ended.rs +++ b/src/libcore/iter/traits/double_ended.rs @@ -88,7 +88,6 @@ pub trait DoubleEndedIterator: Iterator { /// Basic usage: /// /// ``` - /// #![feature(iter_nth_back)] /// let a = [1, 2, 3]; /// assert_eq!(a.iter().nth_back(2), Some(&1)); /// ``` @@ -96,7 +95,6 @@ pub trait DoubleEndedIterator: Iterator { /// Calling `nth_back()` multiple times doesn't rewind the iterator: /// /// ``` - /// #![feature(iter_nth_back)] /// let a = [1, 2, 3]; /// /// let mut iter = a.iter(); @@ -108,12 +106,11 @@ pub trait DoubleEndedIterator: Iterator { /// Returning `None` if there are less than `n + 1` elements: /// /// ``` - /// #![feature(iter_nth_back)] /// let a = [1, 2, 3]; /// assert_eq!(a.iter().nth_back(10), None); /// ``` #[inline] - #[unstable(feature = "iter_nth_back", issue = "56995")] + #[stable(feature = "iter_nth_back", since = "1.37.0")] fn nth_back(&mut self, mut n: usize) -> Option { for x in self.rev() { if n == 0 { return Some(x) } diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index c617596aba801..0dba2bed62c93 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -10,7 +10,6 @@ #![feature(fmt_internals)] #![feature(hashmap_internals)] #![feature(is_sorted)] -#![feature(iter_nth_back)] #![feature(iter_once_with)] #![feature(pattern)] #![feature(range_is_empty)] From 0fdd4191adb998991742c7f63f49b1a6c4e4ec3d Mon Sep 17 00:00:00 2001 From: varkor Date: Thu, 30 May 2019 19:55:43 +0100 Subject: [PATCH 18/20] Add regression test for const generics ICE Co-Authored-By: Mazdak Farrokhzad --- .../const-generic-array-wrapper.rs | 18 ++++++++++++++++++ .../const-generic-array-wrapper.stderr | 6 ++++++ 2 files changed, 24 insertions(+) create mode 100644 src/test/ui/const-generics/const-generic-array-wrapper.rs create mode 100644 src/test/ui/const-generics/const-generic-array-wrapper.stderr diff --git a/src/test/ui/const-generics/const-generic-array-wrapper.rs b/src/test/ui/const-generics/const-generic-array-wrapper.rs new file mode 100644 index 0000000000000..adffe32d67a30 --- /dev/null +++ b/src/test/ui/const-generics/const-generic-array-wrapper.rs @@ -0,0 +1,18 @@ +// run-pass + +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +struct Foo([T; {N}]); + +impl Foo { + fn foo(&self) -> usize { + {N} + } +} + +fn main() { + let foo = Foo([0u32; 21]); + assert_eq!(foo.0, [0u32; 21]); + assert_eq!(foo.foo(), 21); +} diff --git a/src/test/ui/const-generics/const-generic-array-wrapper.stderr b/src/test/ui/const-generics/const-generic-array-wrapper.stderr new file mode 100644 index 0000000000000..f92e11d47ed37 --- /dev/null +++ b/src/test/ui/const-generics/const-generic-array-wrapper.stderr @@ -0,0 +1,6 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/const-generic-array-wrapper.rs:3:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + From 66aa18bb44d04b5e0371c4bab240100ad80faebb Mon Sep 17 00:00:00 2001 From: Christian Vallentin Date: Thu, 30 May 2019 21:29:32 +0200 Subject: [PATCH 19/20] Fixed lifetime misspelling --- src/librustc_codegen_ssa/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_codegen_ssa/README.md b/src/librustc_codegen_ssa/README.md index 9e1d429180367..11fac239edf12 100644 --- a/src/librustc_codegen_ssa/README.md +++ b/src/librustc_codegen_ssa/README.md @@ -26,7 +26,7 @@ While the LLVM-specific code will be left in `rustc_codegen_llvm`, all the new t @irinagpopa started to parametrize the types of `rustc_codegen_llvm` by a generic `Value` type, implemented in LLVM by a reference `&'ll Value`. This work has been extended to all structures inside the `mir` folder and elsewhere, as well as for LLVM's `BasicBlock` and `Type` types. -The two most important structures for the LLVM codegen are `CodegenCx` and `Builder`. They are parametrized by multiple liftime parameters and the type for `Value`. +The two most important structures for the LLVM codegen are `CodegenCx` and `Builder`. They are parametrized by multiple lifetime parameters and the type for `Value`. ```rust struct CodegenCx<'ll, 'tcx: 'll> { From 4c5eb8ecfc1accda036053d50c8c44b3c5eebb3b Mon Sep 17 00:00:00 2001 From: Janusz Marcinkiewicz Date: Thu, 30 May 2019 22:41:09 +0200 Subject: [PATCH 20/20] Explicitly suggest 'type_ascription' feature --- src/libsyntax/parse/diagnostics.rs | 4 ++-- src/test/ui/issues/issue-22644.stderr | 2 +- src/test/ui/issues/issue-34255-1.stderr | 2 +- src/test/ui/lifetime_starts_expressions.stderr | 2 +- src/test/ui/parser/recover-from-bad-variant.stderr | 2 +- .../ui/type/type-ascription-instead-of-statement-end.stderr | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/libsyntax/parse/diagnostics.rs b/src/libsyntax/parse/diagnostics.rs index b3d49524d7668..2e4d4c091398e 100644 --- a/src/libsyntax/parse/diagnostics.rs +++ b/src/libsyntax/parse/diagnostics.rs @@ -858,8 +858,8 @@ impl<'a> Parser<'a> { Applicability::MaybeIncorrect, ); } else { - err.note("type ascription is a nightly-only feature that lets \ - you annotate an expression with a type: `: `") + err.note("#![feature(type_ascription)] lets you annotate an \ + expression with a type: `: `") .span_note( lhs_span, "this expression expects an ascribed type after the colon", diff --git a/src/test/ui/issues/issue-22644.stderr b/src/test/ui/issues/issue-22644.stderr index a28ea0d09f8f0..cf36953546549 100644 --- a/src/test/ui/issues/issue-22644.stderr +++ b/src/test/ui/issues/issue-22644.stderr @@ -89,7 +89,7 @@ error: expected type, found `4` LL | println!("{}", a: &mut 4); | ^ expecting a type here because of type ascription | - = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `: ` + = note: #![feature(type_ascription)] lets you annotate an expression with a type: `: ` note: this expression expects an ascribed type after the colon --> $DIR/issue-22644.rs:34:20 | diff --git a/src/test/ui/issues/issue-34255-1.stderr b/src/test/ui/issues/issue-34255-1.stderr index 7899c8d30f1dd..01f3953777017 100644 --- a/src/test/ui/issues/issue-34255-1.stderr +++ b/src/test/ui/issues/issue-34255-1.stderr @@ -4,7 +4,7 @@ error: expected type, found `42` LL | Test::Drill(field: 42); | ^^ expecting a type here because of type ascription | - = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `: ` + = note: #![feature(type_ascription)] lets you annotate an expression with a type: `: ` note: this expression expects an ascribed type after the colon --> $DIR/issue-34255-1.rs:8:17 | diff --git a/src/test/ui/lifetime_starts_expressions.stderr b/src/test/ui/lifetime_starts_expressions.stderr index cb5a52a3e081a..8ae8018c2ff25 100644 --- a/src/test/ui/lifetime_starts_expressions.stderr +++ b/src/test/ui/lifetime_starts_expressions.stderr @@ -14,7 +14,7 @@ error: expected type, found keyword `loop` LL | loop { break 'label: loop { break 'label 42; }; } | ^^^^ expecting a type here because of type ascription | - = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `: ` + = note: #![feature(type_ascription)] lets you annotate an expression with a type: `: ` note: this expression expects an ascribed type after the colon --> $DIR/lifetime_starts_expressions.rs:6:12 | diff --git a/src/test/ui/parser/recover-from-bad-variant.stderr b/src/test/ui/parser/recover-from-bad-variant.stderr index 1eba6d7d52877..150d74f07428d 100644 --- a/src/test/ui/parser/recover-from-bad-variant.stderr +++ b/src/test/ui/parser/recover-from-bad-variant.stderr @@ -4,7 +4,7 @@ error: expected type, found `3` LL | let x = Enum::Foo(a: 3, b: 4); | ^ expecting a type here because of type ascription | - = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `: ` + = note: #![feature(type_ascription)] lets you annotate an expression with a type: `: ` note: this expression expects an ascribed type after the colon --> $DIR/recover-from-bad-variant.rs:7:23 | diff --git a/src/test/ui/type/type-ascription-instead-of-statement-end.stderr b/src/test/ui/type/type-ascription-instead-of-statement-end.stderr index 2084cbcce4f62..4929922c83fe6 100644 --- a/src/test/ui/type/type-ascription-instead-of-statement-end.stderr +++ b/src/test/ui/type/type-ascription-instead-of-statement-end.stderr @@ -12,7 +12,7 @@ error: expected type, found `0` LL | println!("test"): 0; | ^ expecting a type here because of type ascription | - = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `: ` + = note: #![feature(type_ascription)] lets you annotate an expression with a type: `: ` note: this expression expects an ascribed type after the colon --> $DIR/type-ascription-instead-of-statement-end.rs:9:5 |