]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #62908 - fakenine:normalize_use_of_backticks_compiler_messages_p17...
authorbors <bors@rust-lang.org>
Wed, 24 Jul 2019 10:03:20 +0000 (10:03 +0000)
committerbors <bors@rust-lang.org>
Wed, 24 Jul 2019 10:03:20 +0000 (10:03 +0000)
normalize use of backticks for compiler messages in remaining modules

https://github.com/rust-lang/rust/issues/60532

100 files changed:
README.md
src/libcore/char/methods.rs
src/libcore/intrinsics.rs
src/libcore/slice/mod.rs
src/libfmt_macros/lib.rs
src/librustc/infer/lexical_region_resolve/mod.rs
src/librustc/mir/interpret/error.rs
src/librustc/mir/interpret/mod.rs
src/librustc/mir/interpret/pointer.rs
src/librustc/mir/mod.rs
src/librustc/mir/visit.rs
src/librustc_allocator/expand.rs
src/librustc_codegen_ssa/mir/analyze.rs
src/librustc_codegen_ssa/mir/block.rs
src/librustc_codegen_ssa/mir/operand.rs
src/librustc_codegen_ssa/mir/rvalue.rs
src/librustc_codegen_ssa/mir/statement.rs
src/librustc_lexer/src/lib.rs
src/librustc_lexer/src/unescape.rs [new file with mode: 0644]
src/librustc_mir/borrow_check/conflict_errors.rs
src/librustc_mir/borrow_check/error_reporting.rs
src/librustc_mir/borrow_check/mod.rs
src/librustc_mir/borrow_check/move_errors.rs
src/librustc_mir/borrow_check/mutability_errors.rs
src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
src/librustc_mir/borrow_check/nll/invalidation.rs
src/librustc_mir/borrow_check/nll/type_check/mod.rs
src/librustc_mir/borrow_check/path_utils.rs
src/librustc_mir/borrow_check/places_conflict.rs
src/librustc_mir/build/expr/as_place.rs
src/librustc_mir/build/expr/as_rvalue.rs
src/librustc_mir/build/matches/mod.rs
src/librustc_mir/dataflow/drop_flag_effects.rs
src/librustc_mir/dataflow/impls/mod.rs
src/librustc_mir/dataflow/move_paths/builder.rs
src/librustc_mir/interpret/intrinsics.rs
src/librustc_mir/interpret/operator.rs
src/librustc_mir/interpret/place.rs
src/librustc_mir/interpret/terminator.rs
src/librustc_mir/transform/add_retag.rs
src/librustc_mir/transform/const_prop.rs
src/librustc_mir/transform/elaborate_drops.rs
src/librustc_mir/transform/qualify_consts.rs
src/librustc_mir/transform/rustc_peek.rs
src/librustc_target/spec/x86_64_unknown_linux_gnux32.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/collect.rs
src/librustdoc/lib.rs
src/libsyntax/feature_gate.rs
src/libsyntax/parse/diagnostics.rs
src/libsyntax/parse/lexer/mod.rs
src/libsyntax/parse/literal.rs
src/libsyntax/parse/mod.rs
src/libsyntax/parse/parser.rs
src/libsyntax/parse/unescape.rs [deleted file]
src/libsyntax/parse/unescape_error_reporting.rs
src/libsyntax_ext/format.rs
src/libsyntax_ext/lib.rs
src/stage0.txt
src/test/ui/allocator/two-allocators.rs
src/test/ui/allocator/two-allocators.stderr
src/test/ui/codemap_tests/bad-format-args.stderr
src/test/ui/error-codes/E0121.stderr
src/test/ui/existential-type/issue-58887.rs [new file with mode: 0644]
src/test/ui/existential-type/issue-58887.stderr [new file with mode: 0644]
src/test/ui/feature-gate/rustc-private.rs [new file with mode: 0644]
src/test/ui/feature-gate/rustc-private.stderr [new file with mode: 0644]
src/test/ui/hrtb/issue-62203-hrtb-ice.rs [new file with mode: 0644]
src/test/ui/hrtb/issue-62203-hrtb-ice.stderr [new file with mode: 0644]
src/test/ui/issues/issue-22644.stderr
src/test/ui/issues/issue-34255-1.stderr
src/test/ui/issues/issue-39616.stderr
src/test/ui/issues/issue-44406.stderr
src/test/ui/lifetime_starts_expressions.stderr
src/test/ui/macros/missing-comma.stderr
src/test/ui/parser/issue-33262.stderr
src/test/ui/parser/macro/trait-object-macro-matcher.stderr
src/test/ui/parser/recover-enum2.stderr
src/test/ui/parser/recover-from-bad-variant.stderr
src/test/ui/parser/removed-syntax-mut-vec-ty.stderr
src/test/ui/parser/removed-syntax-record.stderr
src/test/ui/parser/trait-object-lifetime-parens.stderr
src/test/ui/suggestions/suggest-variants.stderr
src/test/ui/suggestions/type-ascription-instead-of-method.stderr
src/test/ui/suggestions/type-ascription-instead-of-variant.stderr
src/test/ui/type/ascription/issue-34255-1.rs [new file with mode: 0644]
src/test/ui/type/ascription/issue-34255-1.stderr [new file with mode: 0644]
src/test/ui/type/ascription/issue-47666.rs [new file with mode: 0644]
src/test/ui/type/ascription/issue-47666.stderr [new file with mode: 0644]
src/test/ui/type/ascription/issue-54516.rs [new file with mode: 0644]
src/test/ui/type/ascription/issue-54516.stderr [new file with mode: 0644]
src/test/ui/type/ascription/issue-60933.rs [new file with mode: 0644]
src/test/ui/type/ascription/issue-60933.stderr [new file with mode: 0644]
src/test/ui/type/type-ascription-instead-of-initializer.stderr
src/test/ui/type/type-ascription-instead-of-statement-end.stderr
src/test/ui/typeck/typeck_type_placeholder_item.stderr
src/test/ui/typeck/typeck_type_placeholder_item_help.rs
src/test/ui/typeck/typeck_type_placeholder_item_help.stderr
src/tools/miri

index d4bde44ff9d3c9a7031896fc9bbf77912d0e7a46..40df6a47378717da376995cc79a8f86f4c3de117 100644 (file)
--- a/README.md
+++ b/README.md
@@ -200,11 +200,11 @@ fetch snapshots, and an OS that can execute the available snapshot binaries.
 
 Snapshot binaries are currently built and tested on several platforms:
 
-| Platform / Architecture  | x86 | x86_64 |
-|--------------------------|-----|--------|
-| Windows (7, 8, 10, ...)  | ✓   | ✓      |
-| Linux (2.6.18 or later)  | ✓   | ✓      |
-| OSX (10.7 Lion or later) | ✓   | ✓      |
+| Platform / Architecture    | x86 | x86_64 |
+|----------------------------|-----|--------|
+| Windows (7, 8, 10, ...)    | ✓   | ✓      |
+| Linux (2.6.18 or later)    | ✓   | ✓      |
+| macOS (10.7 Lion or later) | ✓   | ✓      |
 
 You may find that other platforms work, but these are our officially
 supported build environments that are most likely to work.
index e843303380ad0dfd91d58cce14d828d36556de16..99f88591eea3eeca2e1a9828b00265a71e5d53e2 100644 (file)
@@ -553,10 +553,12 @@ pub fn is_alphabetic(self) -> bool {
     /// '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`.
-    #[unstable(feature = "rustc_private",
-               reason = "mainly needed for compiler internals",
-               issue = "27812")]
-    #[inline]
+    #[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"))]
     pub fn is_xid_start(self) -> bool {
         derived_property::XID_Start(self)
     }
@@ -567,9 +569,12 @@ pub fn is_xid_start(self) -> bool {
     /// '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.
-    #[unstable(feature = "rustc_private",
-               reason = "mainly needed for compiler internals",
-               issue = "27812")]
+    #[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"))]
     #[inline]
     pub fn is_xid_continue(self) -> bool {
         derived_property::XID_Continue(self)
index 56e45c3695f61830594cbaaba62ea3076b27381f..aff36aba01f9e360d2747b19cfaa87d7461695f2 100644 (file)
@@ -1333,6 +1333,7 @@ pub(crate) fn is_aligned_and_not_null<T>(ptr: *const T) -> bool {
 
 /// Checks whether the regions of memory starting at `src` and `dst` of size
 /// `count * size_of::<T>()` overlap.
+#[cfg(not(miri))] // Cannot compare with `>` across allocations in Miri
 fn overlaps<T>(src: *const T, dst: *const T, count: usize) -> bool {
     let src_usize = src as usize;
     let dst_usize = dst as usize;
@@ -1437,6 +1438,7 @@ pub unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) {
 
     debug_assert!(is_aligned_and_not_null(src), "attempt to copy from unaligned or null pointer");
     debug_assert!(is_aligned_and_not_null(dst), "attempt to copy to unaligned or null pointer");
+    #[cfg(not(miri))]
     debug_assert!(!overlaps(src, dst, count), "attempt to copy to overlapping memory");
     copy_nonoverlapping(src, dst, count)
 }
index 8c7b9cf1c5db7361e7e330740fc4b1f795e61364..e7b820e79e5cf8cc1ded819a456036b4cf1dbd04 100644 (file)
@@ -1263,6 +1263,15 @@ pub fn rsplitn_mut<F>(&mut self, n: usize, pred: F) -> RSplitNMut<'_, T, F>
     /// assert!(v.contains(&30));
     /// assert!(!v.contains(&50));
     /// ```
+    ///
+    /// If you do not have an `&T`, but just an `&U` such that `T: Borrow<U>`
+    /// (e.g. `String: Borrow<str>`), you can use `iter().any`:
+    ///
+    /// ```
+    /// let v = [String::from("hello"), String::from("world")]; // slice of `String`
+    /// assert!(v.iter().any(|e| e == "hello")); // search with `&str`
+    /// assert!(!v.iter().any(|e| e == "hi"));
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn contains(&self, x: &T) -> bool
         where T: PartialEq
index 39f130b82ed83177cc1a2332ec50f0c12f1634a4..f1c2b1fb8713363a83997e06f234f994f37a05eb 100644 (file)
@@ -13,6 +13,7 @@
 
 #![feature(nll)]
 #![feature(rustc_private)]
+#![feature(unicode_internals)]
 
 pub use Piece::*;
 pub use Position::*;
index 41d68d6e81f807c5b4fdb9f63690235a1d547d30..6282fde59cad4dadfcbe3856a1e5d84933fe9011 100644 (file)
@@ -764,16 +764,17 @@ fn region_order_key(x: &RegionAndOrigin<'_>) -> u8 {
             }
         }
 
-        span_bug!(
+        // Errors in earlier passes can yield error variables without
+        // resolution errors here; delay ICE in favor of those errors.
+        self.tcx().sess.delay_span_bug(
             self.var_infos[node_idx].origin.span(),
-            "collect_error_for_expanding_node() could not find \
-             error for var {:?} in universe {:?}, lower_bounds={:#?}, \
-             upper_bounds={:#?}",
-            node_idx,
-            node_universe,
-            lower_bounds,
-            upper_bounds
-        );
+            &format!("collect_error_for_expanding_node() could not find \
+                      error for var {:?} in universe {:?}, lower_bounds={:#?}, \
+                      upper_bounds={:#?}",
+                     node_idx,
+                     node_universe,
+                     lower_bounds,
+                     upper_bounds));
     }
 
     fn collect_concrete_regions(
index c8f42b1c604a587b2315e135ae6b51b6eb0d0676..6ab07c9679e7a0eb05472797093e737c18d0362e 100644 (file)
@@ -228,6 +228,24 @@ fn from(kind: InterpError<'tcx, u64>) -> Self {
 
 pub type AssertMessage<'tcx> = InterpError<'tcx, mir::Operand<'tcx>>;
 
+#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
+pub enum PanicMessage<O> {
+    Panic {
+        msg: Symbol,
+        line: u32,
+        col: u32,
+        file: Symbol,
+    },
+    BoundsCheck {
+        len: O,
+        index: O,
+    },
+    Overflow(mir::BinOp),
+    OverflowNeg,
+    DivisionByZero,
+    RemainderByZero,
+}
+
 #[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
 pub enum InterpError<'tcx, O> {
     /// This variant is used by machines to signal their own errors that do not
@@ -266,11 +284,6 @@ pub enum InterpError<'tcx, O> {
     Unimplemented(String),
     DerefFunctionPointer,
     ExecuteMemory,
-    BoundsCheck { len: O, index: O },
-    Overflow(mir::BinOp),
-    OverflowNeg,
-    DivisionByZero,
-    RemainderByZero,
     Intrinsic(String),
     InvalidChar(u128),
     StackFrameLimitReached,
@@ -298,12 +311,7 @@ pub enum InterpError<'tcx, O> {
     HeapAllocZeroBytes,
     HeapAllocNonPowerOfTwoAlignment(u64),
     Unreachable,
-    Panic {
-        msg: Symbol,
-        line: u32,
-        col: u32,
-        file: Symbol,
-    },
+    Panic(PanicMessage<O>),
     ReadFromReturnPointer,
     PathNotFound(Vec<String>),
     UnimplementedTraitSelection,
@@ -369,8 +377,6 @@ pub fn description(&self) -> &str {
                 "tried to dereference a function pointer",
             ExecuteMemory =>
                 "tried to treat a memory pointer as a function pointer",
-            BoundsCheck{..} =>
-                "array index out of bounds",
             Intrinsic(..) =>
                 "intrinsic failed",
             NoMirFor(..) =>
@@ -422,8 +428,32 @@ pub fn description(&self) -> &str {
                 two",
             Unreachable =>
                 "entered unreachable code",
-            Panic { .. } =>
+            Panic(PanicMessage::Panic{..}) =>
                 "the evaluated program panicked",
+            Panic(PanicMessage::BoundsCheck{..}) =>
+                "array index out of bounds",
+            Panic(PanicMessage::Overflow(mir::BinOp::Add)) =>
+                "attempt to add with overflow",
+            Panic(PanicMessage::Overflow(mir::BinOp::Sub)) =>
+                "attempt to subtract with overflow",
+            Panic(PanicMessage::Overflow(mir::BinOp::Mul)) =>
+                "attempt to multiply with overflow",
+            Panic(PanicMessage::Overflow(mir::BinOp::Div)) =>
+                "attempt to divide with overflow",
+            Panic(PanicMessage::Overflow(mir::BinOp::Rem)) =>
+                "attempt to calculate the remainder with overflow",
+            Panic(PanicMessage::OverflowNeg) =>
+                "attempt to negate with overflow",
+            Panic(PanicMessage::Overflow(mir::BinOp::Shr)) =>
+                "attempt to shift right with overflow",
+            Panic(PanicMessage::Overflow(mir::BinOp::Shl)) =>
+                "attempt to shift left with overflow",
+            Panic(PanicMessage::Overflow(op)) =>
+                bug!("{:?} cannot overflow", op),
+            Panic(PanicMessage::DivisionByZero) =>
+                "attempt to divide by zero",
+            Panic(PanicMessage::RemainderByZero) =>
+                "attempt to calculate the remainder with a divisor of zero",
             ReadFromReturnPointer =>
                 "tried to read from the return pointer",
             PathNotFound(_) =>
@@ -436,17 +466,6 @@ pub fn description(&self) -> &str {
                 "encountered overly generic constant",
             ReferencedConstant =>
                 "referenced constant has errors",
-            Overflow(mir::BinOp::Add) => "attempt to add with overflow",
-            Overflow(mir::BinOp::Sub) => "attempt to subtract with overflow",
-            Overflow(mir::BinOp::Mul) => "attempt to multiply with overflow",
-            Overflow(mir::BinOp::Div) => "attempt to divide with overflow",
-            Overflow(mir::BinOp::Rem) => "attempt to calculate the remainder with overflow",
-            OverflowNeg => "attempt to negate with overflow",
-            Overflow(mir::BinOp::Shr) => "attempt to shift right with overflow",
-            Overflow(mir::BinOp::Shl) => "attempt to shift left with overflow",
-            Overflow(op) => bug!("{:?} cannot overflow", op),
-            DivisionByZero => "attempt to divide by zero",
-            RemainderByZero => "attempt to calculate the remainder with a divisor of zero",
             GeneratorResumedAfterReturn => "generator resumed after completion",
             GeneratorResumedAfterPanic => "generator resumed after panicking",
             InfiniteLoop =>
@@ -493,8 +512,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                     callee_ty, caller_ty),
             FunctionArgCountMismatch =>
                 write!(f, "tried to call a function with incorrect number of arguments"),
-            BoundsCheck { ref len, ref index } =>
-                write!(f, "index out of bounds: the len is {:?} but the index is {:?}", len, index),
             ReallocatedWrongMemoryKind(ref old, ref new) =>
                 write!(f, "tried to reallocate memory from {} to {}", old, new),
             DeallocatedWrongMemoryKind(ref old, ref new) =>
@@ -518,8 +535,10 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                 write!(f, "incorrect alloc info: expected size {} and align {}, \
                            got size {} and align {}",
                     size.bytes(), align.bytes(), size2.bytes(), align2.bytes()),
-            Panic { ref msg, line, col, ref file } =>
+            Panic(PanicMessage::Panic { ref msg, line, col, ref file }) =>
                 write!(f, "the evaluated program panicked at '{}', {}:{}:{}", msg, file, line, col),
+            Panic(PanicMessage::BoundsCheck { ref len, ref index }) =>
+                write!(f, "index out of bounds: the len is {:?} but the index is {:?}", len, index),
             InvalidDiscriminant(val) =>
                 write!(f, "encountered invalid enum discriminant {}", val),
             Exit(code) =>
index 1b294250aa3dca3d409e104c0fa685030a3d1845..5bec64d39fa62660905b85b8e781883e57b81878 100644 (file)
@@ -12,7 +12,7 @@ macro_rules! err {
 
 pub use self::error::{
     InterpErrorInfo, InterpResult, InterpError, AssertMessage, ConstEvalErr, struct_error,
-    FrameInfo, ConstEvalRawResult, ConstEvalResult, ErrorHandled,
+    FrameInfo, ConstEvalRawResult, ConstEvalResult, ErrorHandled, PanicMessage
 };
 
 pub use self::value::{Scalar, ScalarMaybeUndef, RawConst, ConstValue};
index a17bc1f67283de750c005d46541b6b87aef0aa41..0e3b8459115e30e96c325fc62adc720eac402a29 100644 (file)
@@ -5,7 +5,7 @@
 use rustc_macros::HashStable;
 
 use super::{
-    AllocId, InterpResult,
+    AllocId, InterpResult, PanicMessage
 };
 
 /// Used by `check_in_alloc` to indicate context of check
@@ -76,13 +76,13 @@ fn overflowing_signed_offset(&self, val: u64, i: i128) -> (u64, bool) {
     #[inline]
     fn offset<'tcx>(&self, val: u64, i: u64) -> InterpResult<'tcx, u64> {
         let (res, over) = self.overflowing_offset(val, i);
-        if over { err!(Overflow(mir::BinOp::Add)) } else { Ok(res) }
+        if over { err!(Panic(PanicMessage::Overflow(mir::BinOp::Add))) } else { Ok(res) }
     }
 
     #[inline]
     fn signed_offset<'tcx>(&self, val: u64, i: i64) -> InterpResult<'tcx, u64> {
         let (res, over) = self.overflowing_signed_offset(val, i128::from(i));
-        if over { err!(Overflow(mir::BinOp::Add)) } else { Ok(res) }
+        if over { err!(Panic(PanicMessage::Overflow(mir::BinOp::Add))) } else { Ok(res) }
     }
 }
 
index d8b641fbe31f483dc1649f5aec61aa8d0dca704d..b1b6be4ae17f8424842d156d8b3c560f6623055d 100644 (file)
@@ -7,7 +7,7 @@
 use crate::hir::def::{CtorKind, Namespace};
 use crate::hir::def_id::DefId;
 use crate::hir::{self, InlineAsm as HirInlineAsm};
-use crate::mir::interpret::{ConstValue, InterpError, Scalar};
+use crate::mir::interpret::{ConstValue, PanicMessage, InterpError::Panic, Scalar};
 use crate::mir::visit::MirVisitable;
 use crate::rustc_serialize as serialize;
 use crate::ty::adjustment::PointerCast;
@@ -1931,7 +1931,7 @@ fn iterate_over2<'tcx, R>(
         iterate_over2(place_base, place_projection, &Projections::Empty, op)
     }
 
-    pub fn as_place_ref(&self) -> PlaceRef<'_, 'tcx> {
+    pub fn as_ref(&self) -> PlaceRef<'_, 'tcx> {
         PlaceRef {
             base: &self.base,
             projection: &self.projection,
@@ -3152,11 +3152,11 @@ fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
                 }
             }
             Assert { ref cond, expected, ref msg, target, cleanup } => {
-                let msg = if let InterpError::BoundsCheck { ref len, ref index } = *msg {
-                    InterpError::BoundsCheck {
+                let msg = if let Panic(PanicMessage::BoundsCheck { ref len, ref index }) = *msg {
+                    Panic(PanicMessage::BoundsCheck {
                         len: len.fold_with(folder),
                         index: index.fold_with(folder),
-                    }
+                    })
                 } else {
                     msg.clone()
                 };
@@ -3197,7 +3197,7 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
             }
             Assert { ref cond, ref msg, .. } => {
                 if cond.visit_with(visitor) {
-                    if let InterpError::BoundsCheck { ref len, ref index } = *msg {
+                    if let Panic(PanicMessage::BoundsCheck { ref len, ref index }) = *msg {
                         len.visit_with(visitor) || index.visit_with(visitor)
                     } else {
                         false
index c3a4566b5aee3834ac5d1974c26b82a80fb5abca..dca56cc526ce5b51401b1f1562e77232a7039515 100644 (file)
@@ -515,7 +515,8 @@ fn super_assert_message(&mut self,
                                     msg: & $($mutability)? AssertMessage<'tcx>,
                                     location: Location) {
                 use crate::mir::interpret::InterpError::*;
-                if let BoundsCheck { len, index } = msg {
+                use crate::mir::interpret::PanicMessage::BoundsCheck;
+                if let Panic(BoundsCheck { len, index }) = msg {
                     self.visit_operand(len, location);
                     self.visit_operand(index, location);
                 }
index 87373364c4d9e3d26753f667c03ac52d86774f84..af63fffc0f9b4074a7fd32b0f9ed733d40e6c562 100644 (file)
@@ -79,7 +79,7 @@ impl MutVisitor for ExpandAllocatorDirectives<'_> {
 
         if self.found {
             self.handler
-                .span_err(item.span, "cannot define more than one #[global_allocator]");
+                .span_err(item.span, "cannot define more than one `#[global_allocator]`");
             return smallvec![item];
         }
         self.found = true;
@@ -280,7 +280,7 @@ fn ret_ty(&self, ty: &AllocatorTy, expr: P<Expr>) -> (P<Ty>, P<Expr>) {
             AllocatorTy::Unit => (self.cx.ty(self.span, TyKind::Tup(Vec::new())), expr),
 
             AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => {
-                panic!("can't convert AllocatorTy to an output")
+                panic!("can't convert `AllocatorTy` to an output")
             }
         }
     }
index 09c346117f9d92ee14a6da3d7aefd21b872bf1ad..907689541f97884ba0d60d8e662b24a56eb31070 100644 (file)
@@ -238,7 +238,7 @@ fn visit_place(&mut self,
                    context: PlaceContext,
                    location: Location) {
         debug!("visit_place(place={:?}, context={:?})", place, context);
-        self.process_place(&place.as_place_ref(), context, location);
+        self.process_place(&place.as_ref(), context, location);
     }
 
     fn visit_local(&mut self,
index d4b434ffe809c217b8807f546991a407bab43c4c..c0a446157d35c97d45f43d822146eff9e2fe0026 100644 (file)
@@ -2,7 +2,7 @@
 use rustc::ty::{self, Ty, TypeFoldable, Instance};
 use rustc::ty::layout::{self, LayoutOf, HasTyCtxt, FnTypeExt};
 use rustc::mir::{self, Place, PlaceBase, Static, StaticKind};
-use rustc::mir::interpret::InterpError;
+use rustc::mir::interpret::{InterpError, PanicMessage};
 use rustc_target::abi::call::{ArgType, FnType, PassMode, IgnoreMode};
 use rustc_target::spec::abi::Abi;
 use crate::base;
@@ -253,7 +253,7 @@ fn codegen_return_terminator(&mut self, mut bx: Bx) {
 
             PassMode::Direct(_) | PassMode::Pair(..) => {
                 let op =
-                    self.codegen_consume(&mut bx, &mir::Place::RETURN_PLACE.as_place_ref());
+                    self.codegen_consume(&mut bx, &mir::Place::RETURN_PLACE.as_ref());
                 if let Ref(llval, _, align) = op.val {
                     bx.load(llval, align)
                 } else {
@@ -314,7 +314,7 @@ fn codegen_drop_terminator<'b>(
             return
         }
 
-        let place = self.codegen_place(&mut bx, &location.as_place_ref());
+        let place = self.codegen_place(&mut bx, &location.as_ref());
         let (args1, args2);
         let mut args = if let Some(llextra) = place.llextra {
             args2 = [place.llval, llextra];
@@ -368,7 +368,7 @@ fn codegen_assert_terminator<'b>(
         // checked operation, just a comparison with the minimum
         // value, so we have to check for the assert message.
         if !bx.check_overflow() {
-            if let mir::interpret::InterpError::OverflowNeg = *msg {
+            if let InterpError::Panic(PanicMessage::OverflowNeg) = *msg {
                 const_cond = Some(expected);
             }
         }
@@ -403,7 +403,7 @@ fn codegen_assert_terminator<'b>(
 
         // Put together the arguments to the panic entry point.
         let (lang_item, args) = match *msg {
-            InterpError::BoundsCheck { ref len, ref index } => {
+            InterpError::Panic(PanicMessage::BoundsCheck { ref len, ref index }) => {
                 let len = self.codegen_operand(&mut bx, len).immediate();
                 let index = self.codegen_operand(&mut bx, index).immediate();
 
@@ -1171,7 +1171,7 @@ fn codegen_transmute(
                 LocalRef::Place(place) => self.codegen_transmute_into(bx, src, place),
                 LocalRef::UnsizedPlace(_) => bug!("transmute must not involve unsized locals"),
                 LocalRef::Operand(None) => {
-                    let dst_layout = bx.layout_of(self.monomorphized_place_ty(&dst.as_place_ref()));
+                    let dst_layout = bx.layout_of(self.monomorphized_place_ty(&dst.as_ref()));
                     assert!(!dst_layout.ty.has_erasable_regions());
                     let place = PlaceRef::alloca(bx, dst_layout, "transmute_temp");
                     place.storage_live(bx);
@@ -1186,7 +1186,7 @@ fn codegen_transmute(
                 }
             }
         } else {
-            let dst = self.codegen_place(bx, &dst.as_place_ref());
+            let dst = self.codegen_place(bx, &dst.as_ref());
             self.codegen_transmute_into(bx, src, dst);
         }
     }
index 0f6a95c1968b8cc0da05db2d0ceab443ced761cf..302dcfcc682a3e423088ba35c6a8c219f21ef9e9 100644 (file)
@@ -462,7 +462,7 @@ pub fn codegen_operand(
         match *operand {
             mir::Operand::Copy(ref place) |
             mir::Operand::Move(ref place) => {
-                self.codegen_consume(bx, &place.as_place_ref())
+                self.codegen_consume(bx, &place.as_ref())
             }
 
             mir::Operand::Constant(ref constant) => {
index cfb7db7365802e3c8dc254ca718f19309640eb77..202cf147f1fcbcefa8fce6fe83555acd4235399a 100644 (file)
@@ -355,7 +355,7 @@ pub fn codegen_rvalue_operand(
             }
 
             mir::Rvalue::Ref(_, bk, ref place) => {
-                let cg_place = self.codegen_place(&mut bx, &place.as_place_ref());
+                let cg_place = self.codegen_place(&mut bx, &place.as_ref());
 
                 let ty = cg_place.layout.ty;
 
@@ -446,7 +446,7 @@ pub fn codegen_rvalue_operand(
 
             mir::Rvalue::Discriminant(ref place) => {
                 let discr_ty = rvalue.ty(&*self.mir, bx.tcx());
-                let discr =  self.codegen_place(&mut bx, &place.as_place_ref())
+                let discr =  self.codegen_place(&mut bx, &place.as_ref())
                     .codegen_get_discr(&mut bx, discr_ty);
                 (bx, OperandRef {
                     val: OperandValue::Immediate(discr),
@@ -527,7 +527,7 @@ fn evaluate_array_len(
             }
         }
         // use common size calculation for non zero-sized types
-        let cg_value = self.codegen_place(bx, &place.as_place_ref());
+        let cg_value = self.codegen_place(bx, &place.as_ref());
         cg_value.len(bx.cx())
     }
 
index 499cda1cf8449b02e0cc359755490cf3ea4e4f41..3717be4b4175338fb1200a4f36c999ae50bd90c3 100644 (file)
@@ -46,12 +46,12 @@ pub fn codegen_statement(
                         }
                     }
                 } else {
-                    let cg_dest = self.codegen_place(&mut bx, &place.as_place_ref());
+                    let cg_dest = self.codegen_place(&mut bx, &place.as_ref());
                     self.codegen_rvalue(bx, cg_dest, rvalue)
                 }
             }
             mir::StatementKind::SetDiscriminant{ref place, variant_index} => {
-                self.codegen_place(&mut bx, &place.as_place_ref())
+                self.codegen_place(&mut bx, &place.as_ref())
                     .codegen_set_discr(&mut bx, variant_index);
                 bx
             }
@@ -73,7 +73,7 @@ pub fn codegen_statement(
             }
             mir::StatementKind::InlineAsm(ref asm) => {
                 let outputs = asm.outputs.iter().map(|output| {
-                    self.codegen_place(&mut bx, &output.as_place_ref())
+                    self.codegen_place(&mut bx, &output.as_ref())
                 }).collect();
 
                 let input_vals = asm.inputs.iter()
index a21190ec33244a27e31f3ceb31bbdaa26bb75c26..c02abe6b89f97e51027ed6d8342cb3a4bf1790dd 100644 (file)
@@ -1,9 +1,9 @@
 // We want to be able to build this crate with a stable compiler, so feature
-// flags should optional.
-#![cfg_attr(not(feature = "unicode-xid"), feature(rustc_private))]
+// flags should be optional.
 #![cfg_attr(not(feature = "unicode-xid"), feature(unicode_internals))]
 
 mod cursor;
+pub mod unescape;
 
 use crate::cursor::{Cursor, EOF_CHAR};
 
diff --git a/src/librustc_lexer/src/unescape.rs b/src/librustc_lexer/src/unescape.rs
new file mode 100644 (file)
index 0000000..70085df
--- /dev/null
@@ -0,0 +1,602 @@
+//! Utilities for validating string and char literals and turning them into
+//! values they represent.
+
+use std::str::Chars;
+use std::ops::Range;
+
+#[derive(Debug, PartialEq, Eq)]
+pub enum EscapeError {
+    ZeroChars,
+    MoreThanOneChar,
+
+    LoneSlash,
+    InvalidEscape,
+    BareCarriageReturn,
+    BareCarriageReturnInRawString,
+    EscapeOnlyChar,
+
+    TooShortHexEscape,
+    InvalidCharInHexEscape,
+    OutOfRangeHexEscape,
+
+    NoBraceInUnicodeEscape,
+    InvalidCharInUnicodeEscape,
+    EmptyUnicodeEscape,
+    UnclosedUnicodeEscape,
+    LeadingUnderscoreUnicodeEscape,
+    OverlongUnicodeEscape,
+    LoneSurrogateUnicodeEscape,
+    OutOfRangeUnicodeEscape,
+
+    UnicodeEscapeInByte,
+    NonAsciiCharInByte,
+    NonAsciiCharInByteString,
+}
+
+/// Takes a contents of a char literal (without quotes), and returns an
+/// unescaped char or an error
+pub fn unescape_char(literal_text: &str) -> Result<char, (usize, EscapeError)> {
+    let mut chars = literal_text.chars();
+    unescape_char_or_byte(&mut chars, Mode::Char)
+        .map_err(|err| (literal_text.len() - chars.as_str().len(), err))
+}
+
+/// Takes a contents of a string literal (without quotes) and produces a
+/// sequence of escaped characters or errors.
+pub fn unescape_str<F>(literal_text: &str, callback: &mut F)
+where
+    F: FnMut(Range<usize>, Result<char, EscapeError>),
+{
+    unescape_str_or_byte_str(literal_text, Mode::Str, callback)
+}
+
+pub fn unescape_byte(literal_text: &str) -> Result<u8, (usize, EscapeError)> {
+    let mut chars = literal_text.chars();
+    unescape_char_or_byte(&mut chars, Mode::Byte)
+        .map(byte_from_char)
+        .map_err(|err| (literal_text.len() - chars.as_str().len(), err))
+}
+
+/// Takes a contents of a string literal (without quotes) and produces a
+/// sequence of escaped characters or errors.
+pub fn unescape_byte_str<F>(literal_text: &str, callback: &mut F)
+where
+    F: FnMut(Range<usize>, Result<u8, EscapeError>),
+{
+    unescape_str_or_byte_str(literal_text, Mode::ByteStr, &mut |range, char| {
+        callback(range, char.map(byte_from_char))
+    })
+}
+
+/// Takes a contents of a string literal (without quotes) and produces a
+/// sequence of characters or errors.
+/// NOTE: Raw strings do not perform any explicit character escaping, here we
+/// only translate CRLF to LF and produce errors on bare CR.
+pub fn unescape_raw_str<F>(literal_text: &str, callback: &mut F)
+where
+    F: FnMut(Range<usize>, Result<char, EscapeError>),
+{
+    unescape_raw_str_or_byte_str(literal_text, Mode::Str, callback)
+}
+
+/// Takes a contents of a string literal (without quotes) and produces a
+/// sequence of characters or errors.
+/// NOTE: Raw strings do not perform any explicit character escaping, here we
+/// only translate CRLF to LF and produce errors on bare CR.
+pub fn unescape_raw_byte_str<F>(literal_text: &str, callback: &mut F)
+where
+    F: FnMut(Range<usize>, Result<u8, EscapeError>),
+{
+    unescape_raw_str_or_byte_str(literal_text, Mode::ByteStr, &mut |range, char| {
+        callback(range, char.map(byte_from_char))
+    })
+}
+
+#[derive(Debug, Clone, Copy)]
+pub enum Mode {
+    Char,
+    Str,
+    Byte,
+    ByteStr,
+}
+
+impl Mode {
+    pub fn in_single_quotes(self) -> bool {
+        match self {
+            Mode::Char | Mode::Byte => true,
+            Mode::Str | Mode::ByteStr => false,
+        }
+    }
+
+    pub fn in_double_quotes(self) -> bool {
+        !self.in_single_quotes()
+    }
+
+    pub fn is_bytes(self) -> bool {
+        match self {
+            Mode::Byte | Mode::ByteStr => true,
+            Mode::Char | Mode::Str => false,
+        }
+    }
+}
+
+
+fn scan_escape(first_char: char, chars: &mut Chars<'_>, mode: Mode) -> Result<char, EscapeError> {
+    if first_char != '\\' {
+        return match first_char {
+            '\t' | '\n' => Err(EscapeError::EscapeOnlyChar),
+            '\r' => Err(if chars.clone().next() == Some('\n') {
+                EscapeError::EscapeOnlyChar
+            } else {
+                EscapeError::BareCarriageReturn
+            }),
+            '\'' if mode.in_single_quotes() => Err(EscapeError::EscapeOnlyChar),
+            '"' if mode.in_double_quotes() => Err(EscapeError::EscapeOnlyChar),
+            _ => {
+                if mode.is_bytes() && !first_char.is_ascii() {
+                    return Err(EscapeError::NonAsciiCharInByte);
+                }
+                Ok(first_char)
+            }
+        };
+    }
+
+    let second_char = chars.next().ok_or(EscapeError::LoneSlash)?;
+
+    let res = match second_char {
+        '"' => '"',
+        'n' => '\n',
+        'r' => '\r',
+        't' => '\t',
+        '\\' => '\\',
+        '\'' => '\'',
+        '0' => '\0',
+
+        'x' => {
+            let hi = chars.next().ok_or(EscapeError::TooShortHexEscape)?;
+            let hi = hi.to_digit(16).ok_or(EscapeError::InvalidCharInHexEscape)?;
+
+            let lo = chars.next().ok_or(EscapeError::TooShortHexEscape)?;
+            let lo = lo.to_digit(16).ok_or(EscapeError::InvalidCharInHexEscape)?;
+
+            let value = hi * 16 + lo;
+
+            if !mode.is_bytes() && !is_ascii(value) {
+                return Err(EscapeError::OutOfRangeHexEscape);
+            }
+            let value = value as u8;
+
+            value as char
+        }
+
+        'u' => {
+            if chars.next() != Some('{') {
+                return Err(EscapeError::NoBraceInUnicodeEscape);
+            }
+
+            let mut n_digits = 1;
+            let mut value: u32 = match chars.next().ok_or(EscapeError::UnclosedUnicodeEscape)? {
+                '_' => return Err(EscapeError::LeadingUnderscoreUnicodeEscape),
+                '}' => return Err(EscapeError::EmptyUnicodeEscape),
+                c => c.to_digit(16).ok_or(EscapeError::InvalidCharInUnicodeEscape)?,
+            };
+
+            loop {
+                match chars.next() {
+                    None => return Err(EscapeError::UnclosedUnicodeEscape),
+                    Some('_') => continue,
+                    Some('}') => {
+                        if n_digits > 6 {
+                            return Err(EscapeError::OverlongUnicodeEscape);
+                        }
+                        if mode.is_bytes() {
+                            return Err(EscapeError::UnicodeEscapeInByte);
+                        }
+
+                        break std::char::from_u32(value).ok_or_else(|| {
+                            if value > 0x10FFFF {
+                                EscapeError::OutOfRangeUnicodeEscape
+                            } else {
+                                EscapeError::LoneSurrogateUnicodeEscape
+                            }
+                        })?;
+                    }
+                    Some(c) => {
+                        let digit = c.to_digit(16).ok_or(EscapeError::InvalidCharInUnicodeEscape)?;
+                        n_digits += 1;
+                        if n_digits > 6 {
+                            continue;
+                        }
+                        let digit = digit as u32;
+                        value = value * 16 + digit;
+                    }
+                };
+            }
+        }
+        _ => return Err(EscapeError::InvalidEscape),
+    };
+    Ok(res)
+}
+
+fn unescape_char_or_byte(chars: &mut Chars<'_>, mode: Mode) -> Result<char, EscapeError> {
+    let first_char = chars.next().ok_or(EscapeError::ZeroChars)?;
+    let res = scan_escape(first_char, chars, mode)?;
+    if chars.next().is_some() {
+        return Err(EscapeError::MoreThanOneChar);
+    }
+    Ok(res)
+}
+
+/// Takes a contents of a string literal (without quotes) and produces a
+/// sequence of escaped characters or errors.
+fn unescape_str_or_byte_str<F>(src: &str, mode: Mode, callback: &mut F)
+where
+    F: FnMut(Range<usize>, Result<char, EscapeError>),
+{
+    assert!(mode.in_double_quotes());
+    let initial_len = src.len();
+    let mut chars = src.chars();
+    while let Some(first_char) = chars.next() {
+        let start = initial_len - chars.as_str().len() - first_char.len_utf8();
+
+        let unescaped_char = match first_char {
+            '\\' => {
+                let (second_char, third_char) = {
+                    let mut chars = chars.clone();
+                    (chars.next(), chars.next())
+                };
+                match (second_char, third_char) {
+                    (Some('\n'), _) | (Some('\r'), Some('\n')) => {
+                        skip_ascii_whitespace(&mut chars);
+                        continue;
+                    }
+                    _ => scan_escape(first_char, &mut chars, mode),
+                }
+            }
+            '\r' => {
+                let second_char = chars.clone().next();
+                if second_char == Some('\n') {
+                    chars.next();
+                    Ok('\n')
+                } else {
+                    scan_escape(first_char, &mut chars, mode)
+                }
+            }
+            '\n' => Ok('\n'),
+            '\t' => Ok('\t'),
+            _ => scan_escape(first_char, &mut chars, mode),
+        };
+        let end = initial_len - chars.as_str().len();
+        callback(start..end, unescaped_char);
+    }
+
+    fn skip_ascii_whitespace(chars: &mut Chars<'_>) {
+        let str = chars.as_str();
+        let first_non_space = str
+            .bytes()
+            .position(|b| b != b' ' && b != b'\t' && b != b'\n' && b != b'\r')
+            .unwrap_or(str.len());
+        *chars = str[first_non_space..].chars()
+    }
+}
+
+/// Takes a contents of a string literal (without quotes) and produces a
+/// sequence of characters or errors.
+/// NOTE: Raw strings do not perform any explicit character escaping, here we
+/// only translate CRLF to LF and produce errors on bare CR.
+fn unescape_raw_str_or_byte_str<F>(literal_text: &str, mode: Mode, callback: &mut F)
+where
+    F: FnMut(Range<usize>, Result<char, EscapeError>),
+{
+    assert!(mode.in_double_quotes());
+    let initial_len = literal_text.len();
+
+    let mut chars = literal_text.chars();
+    while let Some(curr) = chars.next() {
+        let start = initial_len - chars.as_str().len() - curr.len_utf8();
+
+        let result = match (curr, chars.clone().next()) {
+            ('\r', Some('\n')) => {
+                chars.next();
+                Ok('\n')
+            },
+            ('\r', _) => Err(EscapeError::BareCarriageReturnInRawString),
+            (c, _) if mode.is_bytes() && !c.is_ascii() =>
+                Err(EscapeError::NonAsciiCharInByteString),
+            (c, _) => Ok(c),
+        };
+        let end = initial_len - chars.as_str().len();
+
+        callback(start..end, result);
+    }
+}
+
+fn byte_from_char(c: char) -> u8 {
+    let res = c as u32;
+    assert!(res <= u8::max_value() as u32, "guaranteed because of Mode::Byte(Str)");
+    res as u8
+}
+
+fn is_ascii(x: u32) -> bool {
+    x <= 0x7F
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn test_unescape_char_bad() {
+        fn check(literal_text: &str, expected_error: EscapeError) {
+            let actual_result = unescape_char(literal_text).map_err(|(_offset, err)| err);
+            assert_eq!(actual_result, Err(expected_error));
+        }
+
+        check("", EscapeError::ZeroChars);
+        check(r"\", EscapeError::LoneSlash);
+
+        check("\n", EscapeError::EscapeOnlyChar);
+        check("\r\n", EscapeError::EscapeOnlyChar);
+        check("\t", EscapeError::EscapeOnlyChar);
+        check("'", EscapeError::EscapeOnlyChar);
+        check("\r", EscapeError::BareCarriageReturn);
+
+        check("spam", EscapeError::MoreThanOneChar);
+        check(r"\x0ff", EscapeError::MoreThanOneChar);
+        check(r#"\"a"#, EscapeError::MoreThanOneChar);
+        check(r"\na", EscapeError::MoreThanOneChar);
+        check(r"\ra", EscapeError::MoreThanOneChar);
+        check(r"\ta", EscapeError::MoreThanOneChar);
+        check(r"\\a", EscapeError::MoreThanOneChar);
+        check(r"\'a", EscapeError::MoreThanOneChar);
+        check(r"\0a", EscapeError::MoreThanOneChar);
+        check(r"\u{0}x", EscapeError::MoreThanOneChar);
+        check(r"\u{1F63b}}", EscapeError::MoreThanOneChar);
+
+        check(r"\v", EscapeError::InvalidEscape);
+        check(r"\💩", EscapeError::InvalidEscape);
+        check(r"\●", EscapeError::InvalidEscape);
+
+        check(r"\x", EscapeError::TooShortHexEscape);
+        check(r"\x0", EscapeError::TooShortHexEscape);
+        check(r"\xf", EscapeError::TooShortHexEscape);
+        check(r"\xa", EscapeError::TooShortHexEscape);
+        check(r"\xx", EscapeError::InvalidCharInHexEscape);
+        check(r"\xы", EscapeError::InvalidCharInHexEscape);
+        check(r"\x🦀", EscapeError::InvalidCharInHexEscape);
+        check(r"\xtt", EscapeError::InvalidCharInHexEscape);
+        check(r"\xff", EscapeError::OutOfRangeHexEscape);
+        check(r"\xFF", EscapeError::OutOfRangeHexEscape);
+        check(r"\x80", EscapeError::OutOfRangeHexEscape);
+
+        check(r"\u", EscapeError::NoBraceInUnicodeEscape);
+        check(r"\u[0123]", EscapeError::NoBraceInUnicodeEscape);
+        check(r"\u{0x}", EscapeError::InvalidCharInUnicodeEscape);
+        check(r"\u{", EscapeError::UnclosedUnicodeEscape);
+        check(r"\u{0000", EscapeError::UnclosedUnicodeEscape);
+        check(r"\u{}", EscapeError::EmptyUnicodeEscape);
+        check(r"\u{_0000}", EscapeError::LeadingUnderscoreUnicodeEscape);
+        check(r"\u{0000000}", EscapeError::OverlongUnicodeEscape);
+        check(r"\u{FFFFFF}", EscapeError::OutOfRangeUnicodeEscape);
+        check(r"\u{ffffff}", EscapeError::OutOfRangeUnicodeEscape);
+        check(r"\u{ffffff}", EscapeError::OutOfRangeUnicodeEscape);
+
+        check(r"\u{DC00}", EscapeError::LoneSurrogateUnicodeEscape);
+        check(r"\u{DDDD}", EscapeError::LoneSurrogateUnicodeEscape);
+        check(r"\u{DFFF}", EscapeError::LoneSurrogateUnicodeEscape);
+
+        check(r"\u{D800}", EscapeError::LoneSurrogateUnicodeEscape);
+        check(r"\u{DAAA}", EscapeError::LoneSurrogateUnicodeEscape);
+        check(r"\u{DBFF}", EscapeError::LoneSurrogateUnicodeEscape);
+    }
+
+    #[test]
+    fn test_unescape_char_good() {
+        fn check(literal_text: &str, expected_char: char) {
+            let actual_result = unescape_char(literal_text);
+            assert_eq!(actual_result, Ok(expected_char));
+        }
+
+        check("a", 'a');
+        check("ы", 'ы');
+        check("🦀", '🦀');
+
+        check(r#"\""#, '"');
+        check(r"\n", '\n');
+        check(r"\r", '\r');
+        check(r"\t", '\t');
+        check(r"\\", '\\');
+        check(r"\'", '\'');
+        check(r"\0", '\0');
+
+        check(r"\x00", '\0');
+        check(r"\x5a", 'Z');
+        check(r"\x5A", 'Z');
+        check(r"\x7f", 127 as char);
+
+        check(r"\u{0}", '\0');
+        check(r"\u{000000}", '\0');
+        check(r"\u{41}", 'A');
+        check(r"\u{0041}", 'A');
+        check(r"\u{00_41}", 'A');
+        check(r"\u{4__1__}", 'A');
+        check(r"\u{1F63b}", '😻');
+    }
+
+    #[test]
+    fn test_unescape_str_good() {
+        fn check(literal_text: &str, expected: &str) {
+            let mut buf = Ok(String::with_capacity(literal_text.len()));
+            unescape_str(literal_text, &mut |range, c| {
+                if let Ok(b) = &mut buf {
+                    match c {
+                        Ok(c) => b.push(c),
+                        Err(e) => buf = Err((range, e)),
+                    }
+                }
+            });
+            let buf = buf.as_ref().map(|it| it.as_ref());
+            assert_eq!(buf, Ok(expected))
+        }
+
+        check("foo", "foo");
+        check("", "");
+        check(" \t\n\r\n", " \t\n\n");
+
+        check("hello \\\n     world", "hello world");
+        check("hello \\\r\n     world", "hello world");
+        check("thread's", "thread's")
+    }
+
+    #[test]
+    fn test_unescape_byte_bad() {
+        fn check(literal_text: &str, expected_error: EscapeError) {
+            let actual_result = unescape_byte(literal_text).map_err(|(_offset, err)| err);
+            assert_eq!(actual_result, Err(expected_error));
+        }
+
+        check("", EscapeError::ZeroChars);
+        check(r"\", EscapeError::LoneSlash);
+
+        check("\n", EscapeError::EscapeOnlyChar);
+        check("\r\n", EscapeError::EscapeOnlyChar);
+        check("\t", EscapeError::EscapeOnlyChar);
+        check("'", EscapeError::EscapeOnlyChar);
+        check("\r", EscapeError::BareCarriageReturn);
+
+        check("spam", EscapeError::MoreThanOneChar);
+        check(r"\x0ff", EscapeError::MoreThanOneChar);
+        check(r#"\"a"#, EscapeError::MoreThanOneChar);
+        check(r"\na", EscapeError::MoreThanOneChar);
+        check(r"\ra", EscapeError::MoreThanOneChar);
+        check(r"\ta", EscapeError::MoreThanOneChar);
+        check(r"\\a", EscapeError::MoreThanOneChar);
+        check(r"\'a", EscapeError::MoreThanOneChar);
+        check(r"\0a", EscapeError::MoreThanOneChar);
+
+        check(r"\v", EscapeError::InvalidEscape);
+        check(r"\💩", EscapeError::InvalidEscape);
+        check(r"\●", EscapeError::InvalidEscape);
+
+        check(r"\x", EscapeError::TooShortHexEscape);
+        check(r"\x0", EscapeError::TooShortHexEscape);
+        check(r"\xa", EscapeError::TooShortHexEscape);
+        check(r"\xf", EscapeError::TooShortHexEscape);
+        check(r"\xx", EscapeError::InvalidCharInHexEscape);
+        check(r"\xы", EscapeError::InvalidCharInHexEscape);
+        check(r"\x🦀", EscapeError::InvalidCharInHexEscape);
+        check(r"\xtt", EscapeError::InvalidCharInHexEscape);
+
+        check(r"\u", EscapeError::NoBraceInUnicodeEscape);
+        check(r"\u[0123]", EscapeError::NoBraceInUnicodeEscape);
+        check(r"\u{0x}", EscapeError::InvalidCharInUnicodeEscape);
+        check(r"\u{", EscapeError::UnclosedUnicodeEscape);
+        check(r"\u{0000", EscapeError::UnclosedUnicodeEscape);
+        check(r"\u{}", EscapeError::EmptyUnicodeEscape);
+        check(r"\u{_0000}", EscapeError::LeadingUnderscoreUnicodeEscape);
+        check(r"\u{0000000}", EscapeError::OverlongUnicodeEscape);
+
+        check("ы", EscapeError::NonAsciiCharInByte);
+        check("🦀", EscapeError::NonAsciiCharInByte);
+
+        check(r"\u{0}", EscapeError::UnicodeEscapeInByte);
+        check(r"\u{000000}", EscapeError::UnicodeEscapeInByte);
+        check(r"\u{41}", EscapeError::UnicodeEscapeInByte);
+        check(r"\u{0041}", EscapeError::UnicodeEscapeInByte);
+        check(r"\u{00_41}", EscapeError::UnicodeEscapeInByte);
+        check(r"\u{4__1__}", EscapeError::UnicodeEscapeInByte);
+        check(r"\u{1F63b}", EscapeError::UnicodeEscapeInByte);
+        check(r"\u{0}x", EscapeError::UnicodeEscapeInByte);
+        check(r"\u{1F63b}}", EscapeError::UnicodeEscapeInByte);
+        check(r"\u{FFFFFF}", EscapeError::UnicodeEscapeInByte);
+        check(r"\u{ffffff}", EscapeError::UnicodeEscapeInByte);
+        check(r"\u{ffffff}", EscapeError::UnicodeEscapeInByte);
+        check(r"\u{DC00}", EscapeError::UnicodeEscapeInByte);
+        check(r"\u{DDDD}", EscapeError::UnicodeEscapeInByte);
+        check(r"\u{DFFF}", EscapeError::UnicodeEscapeInByte);
+        check(r"\u{D800}", EscapeError::UnicodeEscapeInByte);
+        check(r"\u{DAAA}", EscapeError::UnicodeEscapeInByte);
+        check(r"\u{DBFF}", EscapeError::UnicodeEscapeInByte);
+    }
+
+    #[test]
+    fn test_unescape_byte_good() {
+        fn check(literal_text: &str, expected_byte: u8) {
+            let actual_result = unescape_byte(literal_text);
+            assert_eq!(actual_result, Ok(expected_byte));
+        }
+
+        check("a", b'a');
+
+        check(r#"\""#, b'"');
+        check(r"\n", b'\n');
+        check(r"\r", b'\r');
+        check(r"\t", b'\t');
+        check(r"\\", b'\\');
+        check(r"\'", b'\'');
+        check(r"\0", b'\0');
+
+        check(r"\x00", b'\0');
+        check(r"\x5a", b'Z');
+        check(r"\x5A", b'Z');
+        check(r"\x7f", 127);
+        check(r"\x80", 128);
+        check(r"\xff", 255);
+        check(r"\xFF", 255);
+    }
+
+    #[test]
+    fn test_unescape_byte_str_good() {
+        fn check(literal_text: &str, expected: &[u8]) {
+            let mut buf = Ok(Vec::with_capacity(literal_text.len()));
+            unescape_byte_str(literal_text, &mut |range, c| {
+                if let Ok(b) = &mut buf {
+                    match c {
+                        Ok(c) => b.push(c),
+                        Err(e) => buf = Err((range, e)),
+                    }
+                }
+            });
+            let buf = buf.as_ref().map(|it| it.as_ref());
+            assert_eq!(buf, Ok(expected))
+        }
+
+        check("foo", b"foo");
+        check("", b"");
+        check(" \t\n\r\n", b" \t\n\n");
+
+        check("hello \\\n     world", b"hello world");
+        check("hello \\\r\n     world", b"hello world");
+        check("thread's", b"thread's")
+    }
+
+    #[test]
+    fn test_unescape_raw_str() {
+        fn check(literal: &str, expected: &[(Range<usize>, Result<char, EscapeError>)]) {
+            let mut unescaped = Vec::with_capacity(literal.len());
+            unescape_raw_str(literal, &mut |range, res| unescaped.push((range, res)));
+            assert_eq!(unescaped, expected);
+        }
+
+        check("\r\n", &[(0..2, Ok('\n'))]);
+        check("\r", &[(0..1, Err(EscapeError::BareCarriageReturnInRawString))]);
+        check("\rx", &[(0..1, Err(EscapeError::BareCarriageReturnInRawString)), (1..2, Ok('x'))]);
+    }
+
+    #[test]
+    fn test_unescape_raw_byte_str() {
+        fn check(literal: &str, expected: &[(Range<usize>, Result<u8, EscapeError>)]) {
+            let mut unescaped = Vec::with_capacity(literal.len());
+            unescape_raw_byte_str(literal, &mut |range, res| unescaped.push((range, res)));
+            assert_eq!(unescaped, expected);
+        }
+
+        check("\r\n", &[(0..2, Ok(byte_from_char('\n')))]);
+        check("\r", &[(0..1, Err(EscapeError::BareCarriageReturnInRawString))]);
+        check("🦀", &[(0..4, Err(EscapeError::NonAsciiCharInByteString))]);
+        check(
+            "🦀a",
+            &[(0..4, Err(EscapeError::NonAsciiCharInByteString)), (4..5, Ok(byte_from_char('a')))],
+        );
+    }
+}
index 95fc22dc5eb766c6636314341cf97e829745c07e..5d0e490ebea5a0549ae4e43bfa4b9d994d66bfee 100644 (file)
@@ -139,14 +139,14 @@ pub(super) fn report_use_of_moved_or_uninitialized(
             let is_partial_move = move_site_vec.iter().any(|move_site| {
                 let move_out = self.move_data.moves[(*move_site).moi];
                 let moved_place = &self.move_data.move_paths[move_out.path].place;
-                used_place != moved_place.as_place_ref()
-                    && used_place.is_prefix_of(moved_place.as_place_ref())
+                used_place != moved_place.as_ref()
+                    && used_place.is_prefix_of(moved_place.as_ref())
             });
             for move_site in &move_site_vec {
                 let move_out = self.move_data.moves[(*move_site).moi];
                 let moved_place = &self.move_data.move_paths[move_out.path].place;
 
-                let move_spans = self.move_spans(moved_place.as_place_ref(), move_out.source);
+                let move_spans = self.move_spans(moved_place.as_ref(), move_out.source);
                 let move_span = move_spans.args_or_use();
 
                 let move_msg = if move_spans.for_closure() {
@@ -223,7 +223,7 @@ pub(super) fn report_use_of_moved_or_uninitialized(
 
                 let ty = place.ty(self.body, self.infcx.tcx).ty;
                 let opt_name =
-                    self.describe_place_with_options(place.as_place_ref(), IncludingDowncast(true));
+                    self.describe_place_with_options(place.as_ref(), IncludingDowncast(true));
                 let note_msg = match opt_name {
                     Some(ref name) => format!("`{}`", name),
                     None => "value".to_owned(),
@@ -275,11 +275,11 @@ pub(super) fn report_move_out_while_borrowed(
             "report_move_out_while_borrowed: location={:?} place={:?} span={:?} borrow={:?}",
             location, place, span, borrow
         );
-        let value_msg = match self.describe_place(place.as_place_ref()) {
+        let value_msg = match self.describe_place(place.as_ref()) {
             Some(name) => format!("`{}`", name),
             None => "value".to_owned(),
         };
-        let borrow_msg = match self.describe_place(borrow.borrowed_place.as_place_ref()) {
+        let borrow_msg = match self.describe_place(borrow.borrowed_place.as_ref()) {
             Some(name) => format!("`{}`", name),
             None => "value".to_owned(),
         };
@@ -287,12 +287,12 @@ pub(super) fn report_move_out_while_borrowed(
         let borrow_spans = self.retrieve_borrow_spans(borrow);
         let borrow_span = borrow_spans.args_or_use();
 
-        let move_spans = self.move_spans(place.as_place_ref(), location);
+        let move_spans = self.move_spans(place.as_ref(), location);
         let span = move_spans.args_or_use();
 
         let mut err = self.cannot_move_when_borrowed(
             span,
-            &self.describe_place(place.as_place_ref()).unwrap_or_else(|| "_".to_owned()),
+            &self.describe_place(place.as_ref()).unwrap_or_else(|| "_".to_owned()),
         );
         err.span_label(borrow_span, format!("borrow of {} occurs here", borrow_msg));
         err.span_label(span, format!("move out of {} occurs here", value_msg));
@@ -326,21 +326,21 @@ pub(super) fn report_use_while_mutably_borrowed(
 
         // Conflicting borrows are reported separately, so only check for move
         // captures.
-        let use_spans = self.move_spans(place.as_place_ref(), location);
+        let use_spans = self.move_spans(place.as_ref(), location);
         let span = use_spans.var_or_use();
 
         let mut err = self.cannot_use_when_mutably_borrowed(
             span,
-            &self.describe_place(place.as_place_ref()).unwrap_or_else(|| "_".to_owned()),
+            &self.describe_place(place.as_ref()).unwrap_or_else(|| "_".to_owned()),
             borrow_span,
-            &self.describe_place(borrow.borrowed_place.as_place_ref())
+            &self.describe_place(borrow.borrowed_place.as_ref())
                 .unwrap_or_else(|| "_".to_owned()),
         );
 
         borrow_spans.var_span_label(&mut err, {
             let place = &borrow.borrowed_place;
             let desc_place =
-                self.describe_place(place.as_place_ref()).unwrap_or_else(|| "_".to_owned());
+                self.describe_place(place.as_ref()).unwrap_or_else(|| "_".to_owned());
 
             format!("borrow occurs due to use of `{}`{}", desc_place, borrow_spans.describe())
         });
@@ -517,7 +517,7 @@ pub(super) fn report_conflicting_borrow(
             );
         } else {
             let borrow_place = &issued_borrow.borrowed_place;
-            let borrow_place_desc = self.describe_place(borrow_place.as_place_ref())
+            let borrow_place_desc = self.describe_place(borrow_place.as_ref())
                                         .unwrap_or_else(|| "_".to_owned());
             issued_spans.var_span_label(
                 &mut err,
@@ -650,8 +650,8 @@ pub(super) fn describe_place_for_conflicting_borrow(
 
                                 return Some((
                                     describe_base_place,
-                                    describe_place(first_borrowed_place.as_place_ref()),
-                                    describe_place(second_borrowed_place.as_place_ref()),
+                                    describe_place(first_borrowed_place.as_ref()),
+                                    describe_place(second_borrowed_place.as_ref()),
                                     union_ty.to_string(),
                                 ));
                             }
@@ -666,7 +666,7 @@ pub(super) fn describe_place_for_conflicting_borrow(
                 // If we didn't find a field access into a union, or both places match, then
                 // only return the description of the first place.
                 (
-                    describe_place(first_borrowed_place.as_place_ref()),
+                    describe_place(first_borrowed_place.as_ref()),
                     "".to_string(),
                     "".to_string(),
                     "".to_string(),
@@ -697,7 +697,7 @@ pub(super) fn report_borrowed_value_does_not_live_long_enough(
         );
 
         let drop_span = place_span.1;
-        let root_place = self.prefixes(borrow.borrowed_place.as_place_ref(), PrefixSet::All)
+        let root_place = self.prefixes(borrow.borrowed_place.as_ref(), PrefixSet::All)
             .last()
             .unwrap();
 
@@ -730,13 +730,13 @@ pub(super) fn report_borrowed_value_does_not_live_long_enough(
             }, borrow_span));
 
         if let StorageDeadOrDrop::Destructor(dropped_ty) =
-            self.classify_drop_access_kind(borrow.borrowed_place.as_place_ref())
+            self.classify_drop_access_kind(borrow.borrowed_place.as_ref())
         {
             // If a borrow of path `B` conflicts with drop of `D` (and
             // we're not in the uninteresting case where `B` is a
             // prefix of `D`), then report this as a more interesting
             // destructor conflict.
-            if !borrow.borrowed_place.as_place_ref().is_prefix_of(place_span.0.as_place_ref()) {
+            if !borrow.borrowed_place.as_ref().is_prefix_of(place_span.0.as_ref()) {
                 self.report_borrow_conflicts_with_destructor(
                     location, borrow, place_span, kind, dropped_ty,
                 );
@@ -744,7 +744,7 @@ pub(super) fn report_borrowed_value_does_not_live_long_enough(
             }
         }
 
-        let place_desc = self.describe_place(borrow.borrowed_place.as_place_ref());
+        let place_desc = self.describe_place(borrow.borrowed_place.as_ref());
 
         let kind_place = kind.filter(|_| place_desc.is_some()).map(|k| (k, place_span.0));
         let explanation = self.explain_why_borrow_contains_point(location, &borrow, kind_place);
@@ -951,12 +951,12 @@ fn report_borrow_conflicts_with_destructor(
 
         let mut err = self.cannot_borrow_across_destructor(borrow_span);
 
-        let what_was_dropped = match self.describe_place(place.as_place_ref()) {
+        let what_was_dropped = match self.describe_place(place.as_ref()) {
             Some(name) => format!("`{}`", name.as_str()),
             None => String::from("temporary value"),
         };
 
-        let label = match self.describe_place(borrow.borrowed_place.as_place_ref()) {
+        let label = match self.describe_place(borrow.borrowed_place.as_ref()) {
             Some(borrowed) => format!(
                 "here, drop of {D} needs exclusive access to `{B}`, \
                  because the type `{T}` implements the `Drop` trait",
@@ -1127,7 +1127,7 @@ fn try_report_cannot_return_reference_to_local(
                 format!("`{}` is borrowed here", place_desc),
             )
         } else {
-            let root_place = self.prefixes(borrow.borrowed_place.as_place_ref(),
+            let root_place = self.prefixes(borrow.borrowed_place.as_ref(),
                                            PrefixSet::All)
                 .last()
                 .unwrap();
@@ -1390,7 +1390,7 @@ pub(super) fn report_illegal_mutation_of_borrowed(
             let mut err = self.cannot_mutate_in_match_guard(
                 span,
                 loan_span,
-                &self.describe_place(place.as_place_ref()).unwrap_or_else(|| "_".to_owned()),
+                &self.describe_place(place.as_ref()).unwrap_or_else(|| "_".to_owned()),
                 "assign",
             );
             loan_spans.var_span_label(
@@ -1406,7 +1406,7 @@ pub(super) fn report_illegal_mutation_of_borrowed(
         let mut err = self.cannot_assign_to_borrowed(
             span,
             loan_span,
-            &self.describe_place(place.as_place_ref()).unwrap_or_else(|| "_".to_owned()),
+            &self.describe_place(place.as_ref()).unwrap_or_else(|| "_".to_owned()),
         );
 
         loan_spans.var_span_label(
@@ -1466,8 +1466,8 @@ pub(super) fn report_illegal_reassignment(
                 is_user_variable: None,
                 ..
             })
-            | None => (self.describe_place(place.as_place_ref()), assigned_span),
-            Some(decl) => (self.describe_place(err_place.as_place_ref()), decl.source_info.span),
+            | None => (self.describe_place(place.as_ref()), assigned_span),
+            Some(decl) => (self.describe_place(err_place.as_ref()), decl.source_info.span),
         };
 
         let mut err = self.cannot_reassign_immutable(
index 156897aedb70acb18fda91793b98ec3f71362fba..a05c77aad6700903e86bedd213034f579be3162a 100644 (file)
@@ -855,7 +855,7 @@ pub(super) fn borrow_spans(&self, use_span: Span, location: Location) -> UseSpan
                     def_id, is_generator, places
                 );
                 if let Some((args_span, var_span)) = self.closure_span(
-                    *def_id, Place::from(target).as_place_ref(), places
+                    *def_id, Place::from(target).as_ref(), places
                 ) {
                     return ClosureUse {
                         is_generator,
@@ -895,7 +895,7 @@ fn closure_span(
             for (upvar, place) in self.infcx.tcx.upvars(def_id)?.values().zip(places) {
                 match place {
                     Operand::Copy(place) |
-                    Operand::Move(place) if target_place == place.as_place_ref() => {
+                    Operand::Move(place) if target_place == place.as_ref() => {
                         debug!("closure_span: found captured local {:?}", place);
                         return Some((*args_span, upvar.span));
                     },
index cfc7e77f4e5a87417c60a2b49756f866ca2bcc13..8d27a32a285d8499e544273623c5a50c1f68565a 100644 (file)
@@ -560,7 +560,7 @@ fn visit_statement_entry(
                 self.check_if_path_or_subpath_is_moved(
                     location,
                     InitializationRequiringAction::Use,
-                    (place.as_place_ref(), span),
+                    (place.as_ref(), span),
                     flow_state,
                 );
             }
@@ -591,7 +591,7 @@ fn visit_statement_entry(
                         self.check_if_path_or_subpath_is_moved(
                             location,
                             InitializationRequiringAction::Use,
-                            (output.as_place_ref(), o.span),
+                            (output.as_ref(), o.span),
                             flow_state,
                         );
                     } else {
@@ -733,8 +733,8 @@ fn visit_terminator_entry(
                 cleanup: _,
             } => {
                 self.consume_operand(loc, (cond, span), flow_state);
-                use rustc::mir::interpret::InterpError::BoundsCheck;
-                if let BoundsCheck { ref len, ref index } = *msg {
+                use rustc::mir::interpret::{InterpError::Panic, PanicMessage};
+                if let Panic(PanicMessage::BoundsCheck { ref len, ref index }) = *msg {
                     self.consume_operand(loc, (len, span), flow_state);
                     self.consume_operand(loc, (index, span), flow_state);
                 }
@@ -1154,7 +1154,7 @@ fn mutate_place(
                 self.check_if_path_or_subpath_is_moved(
                     location,
                     InitializationRequiringAction::Update,
-                    (place_span.0.as_place_ref(), place_span.1),
+                    (place_span.0.as_ref(), place_span.1),
                     flow_state,
                 );
             }
@@ -1232,7 +1232,7 @@ fn consume_rvalue(
                 self.check_if_path_or_subpath_is_moved(
                     location,
                     action,
-                    (place.as_place_ref(), span),
+                    (place.as_ref(), span),
                     flow_state,
                 );
             }
@@ -1260,7 +1260,7 @@ fn consume_rvalue(
                 self.check_if_path_or_subpath_is_moved(
                     location,
                     InitializationRequiringAction::Use,
-                    (place.as_place_ref(), span),
+                    (place.as_ref(), span),
                     flow_state,
                 );
             }
@@ -1309,7 +1309,7 @@ fn consume_rvalue(
     fn propagate_closure_used_mut_upvar(&mut self, operand: &Operand<'tcx>) {
         let propagate_closure_used_mut_place = |this: &mut Self, place: &Place<'tcx>| {
             if place.projection.is_some() {
-                if let Some(field) = this.is_upvar_field_projection(place.as_place_ref()) {
+                if let Some(field) = this.is_upvar_field_projection(place.as_ref()) {
                     this.used_mut_upvars.push(field);
                 }
             } else if let PlaceBase::Local(local) = place.base {
@@ -1401,7 +1401,7 @@ fn consume_operand(
                 self.check_if_path_or_subpath_is_moved(
                     location,
                     InitializationRequiringAction::Use,
-                    (place.as_place_ref(), span),
+                    (place.as_ref(), span),
                     flow_state,
                 );
             }
@@ -1419,7 +1419,7 @@ fn consume_operand(
                 self.check_if_path_or_subpath_is_moved(
                     location,
                     InitializationRequiringAction::Use,
-                    (place.as_place_ref(), span),
+                    (place.as_ref(), span),
                     flow_state,
                 );
             }
@@ -1437,7 +1437,7 @@ fn check_for_invalidation_at_exit(
     ) {
         debug!("check_for_invalidation_at_exit({:?})", borrow);
         let place = &borrow.borrowed_place;
-        let root_place = self.prefixes(place.as_place_ref(), PrefixSet::All).last().unwrap();
+        let root_place = self.prefixes(place.as_ref(), PrefixSet::All).last().unwrap();
 
         // FIXME(nll-rfc#40): do more precise destructor tracking here. For now
         // we just know that all locals are dropped at function exit (otherwise
index 38653dc0e5e9b79cf8596245ca84a1a2a35b3112..738a091b0dd7624c809df545a033708c627de49d 100644 (file)
@@ -131,7 +131,7 @@ fn append_to_grouped_errors(
                     }
                 }
 
-                let move_spans = self.move_spans(original_path.as_place_ref(), location);
+                let move_spans = self.move_spans(original_path.as_ref(), location);
                 grouped_errors.push(GroupedMoveError::OtherIllegalMove {
                     use_spans: move_spans,
                     original_path,
@@ -160,7 +160,7 @@ fn append_binding_error(
         let from_simple_let = match_place.is_none();
         let match_place = match_place.as_ref().unwrap_or(move_from);
 
-        match self.move_data.rev_lookup.find(match_place.as_place_ref()) {
+        match self.move_data.rev_lookup.find(match_place.as_ref()) {
             // Error with the match place
             LookupResult::Parent(_) => {
                 for ge in &mut *grouped_errors {
@@ -192,7 +192,7 @@ fn append_binding_error(
             }
             // Error with the pattern
             LookupResult::Exact(_) => {
-                let mpi = match self.move_data.rev_lookup.find(move_from.as_place_ref()) {
+                let mpi = match self.move_data.rev_lookup.find(move_from.as_ref()) {
                     LookupResult::Parent(Some(mpi)) => mpi,
                     // move_from should be a projection from match_place.
                     _ => unreachable!("Probably not unreachable..."),
@@ -242,7 +242,7 @@ fn report(&mut self, error: GroupedMoveError<'tcx>) {
                 };
             debug!("report: original_path={:?} span={:?}, kind={:?} \
                    original_path.is_upvar_field_projection={:?}", original_path, span, kind,
-                   self.is_upvar_field_projection(original_path.as_place_ref()));
+                   self.is_upvar_field_projection(original_path.as_ref()));
             (
                 match kind {
                     IllegalMoveOriginKind::Static => {
@@ -277,7 +277,7 @@ fn report_cannot_move_from_static(
         span: Span
     ) -> DiagnosticBuilder<'a> {
         let description = if place.projection.is_none() {
-            format!("static item `{}`", self.describe_place(place.as_place_ref()).unwrap())
+            format!("static item `{}`", self.describe_place(place.as_ref()).unwrap())
         } else {
             let mut base_static = &place.projection;
             while let Some(box Projection { base: Some(ref proj), .. }) = base_static {
@@ -290,7 +290,7 @@ fn report_cannot_move_from_static(
 
             format!(
                 "`{:?}` as `{:?}` is a static item",
-                self.describe_place(place.as_place_ref()).unwrap(),
+                self.describe_place(place.as_ref()).unwrap(),
                 self.describe_place(base_static).unwrap(),
             )
         };
@@ -308,7 +308,7 @@ fn report_cannot_move_from_borrowed_content(
         // borrow to provide feedback about why this
         // was a move rather than a copy.
         let ty = deref_target_place.ty(self.body, self.infcx.tcx).ty;
-        let upvar_field = self.prefixes(move_place.as_place_ref(), PrefixSet::All)
+        let upvar_field = self.prefixes(move_place.as_ref(), PrefixSet::All)
             .find_map(|p| self.is_upvar_field_projection(p));
 
         let deref_base = match deref_target_place.projection {
@@ -363,10 +363,10 @@ fn report_cannot_move_from_borrowed_content(
                 let upvar_name = upvar.name;
                 let upvar_span = self.infcx.tcx.hir().span(upvar_hir_id);
 
-                let place_name = self.describe_place(move_place.as_place_ref()).unwrap();
+                let place_name = self.describe_place(move_place.as_ref()).unwrap();
 
                 let place_description = if self
-                    .is_upvar_field_projection(move_place.as_place_ref())
+                    .is_upvar_field_projection(move_place.as_ref())
                     .is_some()
                 {
                     format!("`{}`, a {}", place_name, capture_description)
@@ -393,7 +393,7 @@ fn report_cannot_move_from_borrowed_content(
             _ => {
                 let source = self.borrowed_content_source(deref_base);
                 match (
-                    self.describe_place(move_place.as_place_ref()),
+                    self.describe_place(move_place.as_ref()),
                     source.describe_for_named_place(),
                 ) {
                     (Some(place_desc), Some(source_desc)) => {
@@ -455,7 +455,7 @@ fn add_move_hints(
 
                 if binds_to.is_empty() {
                     let place_ty = move_from.ty(self.body, self.infcx.tcx).ty;
-                    let place_desc = match self.describe_place(move_from.as_place_ref()) {
+                    let place_desc = match self.describe_place(move_from.as_ref()) {
                         Some(desc) => format!("`{}`", desc),
                         None => format!("value"),
                     };
@@ -483,7 +483,7 @@ fn add_move_hints(
             GroupedMoveError::OtherIllegalMove { ref original_path, use_spans, .. } => {
                 let span = use_spans.var_or_use();
                 let place_ty = original_path.ty(self.body, self.infcx.tcx).ty;
-                let place_desc = match self.describe_place(original_path.as_place_ref()) {
+                let place_desc = match self.describe_place(original_path.as_ref()) {
                     Some(desc) => format!("`{}`", desc),
                     None => format!("value"),
                 };
index c424c06c41add30a8986b77cab091cbc4ca59082..937c6383be341e50f3a5429440820650ce969147 100644 (file)
@@ -42,7 +42,7 @@ pub(super) fn report_mutability_error(
         let item_msg;
         let reason;
         let mut opt_source = None;
-        let access_place_desc = self.describe_place(access_place.as_place_ref());
+        let access_place_desc = self.describe_place(access_place.as_ref());
         debug!("report_mutability_error: access_place_desc={:?}", access_place_desc);
 
         match the_place_err {
@@ -77,7 +77,7 @@ pub(super) fn report_mutability_error(
                 ));
 
                 item_msg = format!("`{}`", access_place_desc.unwrap());
-                if self.is_upvar_field_projection(access_place.as_place_ref()).is_some() {
+                if self.is_upvar_field_projection(access_place.as_ref()).is_some() {
                     reason = ", as it is not declared as mutable".to_string();
                 } else {
                     let name = self.upvars[upvar_index.index()].name;
@@ -109,7 +109,7 @@ pub(super) fn report_mutability_error(
                     ));
 
                     reason =
-                        if self.is_upvar_field_projection(access_place.as_place_ref()).is_some() {
+                        if self.is_upvar_field_projection(access_place.as_ref()).is_some() {
                             ", as it is a captured variable in a `Fn` closure".to_string()
                         } else {
                             ", as `Fn` closures cannot mutate their captured variables".to_string()
@@ -244,7 +244,7 @@ pub(super) fn report_mutability_error(
                     format!(
                         "mutable borrow occurs due to use of `{}` in closure",
                         // always Some() if the message is printed.
-                        self.describe_place(access_place.as_place_ref()).unwrap_or_default(),
+                        self.describe_place(access_place.as_ref()).unwrap_or_default(),
                     )
                 );
                 borrow_span
index abb84c59d9b9e740b6febb840fd4a89bf6ccc893..aba3ef1cbbfc9a64ec41f9e2ee9f0bbdd2f77898 100644 (file)
@@ -252,7 +252,7 @@ pub(in crate::borrow_check) fn explain_why_borrow_contains_point(
             Some(Cause::LiveVar(local, location)) => {
                 let span = body.source_info(location).span;
                 let spans = self
-                    .move_spans(Place::from(local).as_place_ref(), location)
+                    .move_spans(Place::from(local).as_ref(), location)
                     .or_else(|| self.borrow_spans(span, location));
 
                 let borrow_location = location;
@@ -305,7 +305,7 @@ pub(in crate::borrow_check) fn explain_why_borrow_contains_point(
                         );
                     if let Some(region_name) = region_name {
                         let opt_place_desc =
-                            self.describe_place(borrow.borrowed_place.as_place_ref());
+                            self.describe_place(borrow.borrowed_place.as_ref());
                         BorrowExplanation::MustBeValidFor {
                             category,
                             from_closure,
index c7b4a403052591d4bdd808731f4fe6194d404f88..90df0c91c7235b43ee33d46701274214c14001f2 100644 (file)
@@ -207,8 +207,8 @@ fn visit_terminator_kind(
                 cleanup: _,
             } => {
                 self.consume_operand(location, cond);
-                use rustc::mir::interpret::InterpError::BoundsCheck;
-                if let BoundsCheck { ref len, ref index } = *msg {
+                use rustc::mir::interpret::{InterpError::Panic, PanicMessage::BoundsCheck};
+                if let Panic(BoundsCheck { ref len, ref index }) = *msg {
                     self.consume_operand(location, len);
                     self.consume_operand(location, index);
                 }
index b0e364fa2dd9a0e5e779a219e2d8398d46876366..6ce2f968ed72d0f9c469bcec382a4a0fabc2cb91 100644 (file)
@@ -28,7 +28,7 @@
 use rustc::infer::outlives::env::RegionBoundPairs;
 use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime, NLLRegionVariableOrigin};
 use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
-use rustc::mir::interpret::{InterpError::BoundsCheck, ConstValue};
+use rustc::mir::interpret::{InterpError::Panic, ConstValue, PanicMessage};
 use rustc::mir::tcx::PlaceTy;
 use rustc::mir::visit::{PlaceContext, Visitor, NonMutatingUseContext};
 use rustc::mir::*;
@@ -1606,7 +1606,7 @@ fn check_terminator(
                     span_mirbug!(self, term, "bad Assert ({:?}, not bool", cond_ty);
                 }
 
-                if let BoundsCheck { ref len, ref index } = *msg {
+                if let Panic(PanicMessage::BoundsCheck { ref len, ref index }) = *msg {
                     if len.ty(body, tcx) != tcx.types.usize {
                         span_mirbug!(self, len, "bounds-check length non-usize {:?}", len)
                     }
index 75065816df0506363766dbda7f46b4ce34eec211..da3f165482655a9ffea313041c0753bed4649bbc 100644 (file)
@@ -50,7 +50,7 @@ pub(super) fn each_borrow_involving_path<'tcx, F, I, S>(
             body,
             &borrowed.borrowed_place,
             borrowed.kind,
-            place.as_place_ref(),
+            place.as_ref(),
             access,
             places_conflict::PlaceConflictBias::Overlap,
         ) {
index 348214f97f25606c1c27a458016335fcec77d72c..b2a03147ecf803dfd5ad567bb0949556da714afe 100644 (file)
@@ -36,7 +36,7 @@
         body,
         borrow_place,
         BorrowKind::Mut { allow_two_phase_borrow: true },
-        access_place.as_place_ref(),
+        access_place.as_ref(),
         AccessDepth::Deep,
         bias,
     )
index 2d9e7ac75c7b80449b3abc744043423539e3ba59..42d08a728e0a749805f305a86f3425e1c10de1b1 100644 (file)
@@ -4,7 +4,7 @@
 use crate::build::ForGuard::{OutsideGuard, RefWithinGuard};
 use crate::build::{BlockAnd, BlockAndExtension, Builder};
 use crate::hair::*;
-use rustc::mir::interpret::InterpError::BoundsCheck;
+use rustc::mir::interpret::{InterpError::Panic, PanicMessage::BoundsCheck};
 use rustc::mir::*;
 use rustc::ty::{CanonicalUserTypeAnnotation, Variance};
 
@@ -105,10 +105,10 @@ fn expr_as_place(
                     ),
                 );
 
-                let msg = BoundsCheck {
+                let msg = Panic(BoundsCheck {
                     len: Operand::Move(len),
                     index: Operand::Copy(Place::from(idx)),
-                };
+                });
                 let success = this.assert(block, Operand::Move(lt), true, msg, expr_span);
                 success.and(slice.index(idx))
             }
index 851a6b0b07cf6632c1b0d95bcc904feebfc09e7b..8790ebc41693faa9d5ba93256150c401ae98655c 100644 (file)
@@ -7,7 +7,7 @@
 use crate::build::{BlockAnd, BlockAndExtension, Builder};
 use crate::hair::*;
 use rustc::middle::region;
-use rustc::mir::interpret::InterpError;
+use rustc::mir::interpret::{InterpError::Panic, PanicMessage};
 use rustc::mir::*;
 use rustc::ty::{self, CanonicalUserTypeAnnotation, Ty, UpvarSubsts};
 use syntax_pos::Span;
@@ -101,7 +101,7 @@ fn expr_as_rvalue(
                         block,
                         Operand::Move(is_min),
                         false,
-                        InterpError::OverflowNeg,
+                        Panic(PanicMessage::OverflowNeg),
                         expr_span,
                     );
                 }
@@ -401,7 +401,7 @@ pub fn build_binary_op(
             let val = result_value.clone().field(val_fld, ty);
             let of = result_value.field(of_fld, bool_ty);
 
-            let err = InterpError::Overflow(op);
+            let err = Panic(PanicMessage::Overflow(op));
 
             block = self.assert(block, Operand::Move(of), false, err, span);
 
@@ -412,9 +412,9 @@ pub fn build_binary_op(
                 // and 2. there are two possible failure cases, divide-by-zero and overflow.
 
                 let (zero_err, overflow_err) = if op == BinOp::Div {
-                    (InterpError::DivisionByZero, InterpError::Overflow(op))
+                    (Panic(PanicMessage::DivisionByZero), Panic(PanicMessage::Overflow(op)))
                 } else {
-                    (InterpError::RemainderByZero, InterpError::Overflow(op))
+                    (Panic(PanicMessage::RemainderByZero), Panic(PanicMessage::Overflow(op)))
                 };
 
                 // Check for / 0
index b58cef9cce1e7779886da6a9023d81f9f95a8324..d72b0addae91500e6900d52617bb4aeacd15b83c 100644 (file)
@@ -1304,7 +1304,7 @@ fn calculate_fake_borrows<'b>(
                 prefix_cursor = base;
             }
 
-            all_fake_borrows.push(place.as_place_ref());
+            all_fake_borrows.push(place.as_ref());
         }
 
         // Deduplicate and ensure a deterministic order.
index b6dd544d395618945126a8b1f75936fdb458fbfb..c071b3101fce3f2651cb04ae147216b86043b96d 100644 (file)
@@ -171,7 +171,7 @@ pub(crate) fn drop_flag_effects_for_function_entry<'tcx, F>(
     let move_data = &ctxt.move_data;
     for arg in body.args_iter() {
         let place = mir::Place::from(arg);
-        let lookup_result = move_data.rev_lookup.find(place.as_place_ref());
+        let lookup_result = move_data.rev_lookup.find(place.as_ref());
         on_lookup_result_bits(tcx, body, move_data,
                               lookup_result,
                               |mpi| callback(mpi, DropFlagState::Present));
index ade732bbb75970ad08126d0a2434fb2e853e38a9..69bbe087921404ba5d3f4f977986050f75ffd3f7 100644 (file)
@@ -309,7 +309,7 @@ fn propagate_call_return(
         // when a call returns successfully, that means we need to set
         // the bits for that dest_place to 1 (initialized).
         on_lookup_result_bits(self.tcx, self.body, self.move_data(),
-                              self.move_data().rev_lookup.find(dest_place.as_place_ref()),
+                              self.move_data().rev_lookup.find(dest_place.as_ref()),
                               |mpi| { in_out.insert(mpi); });
     }
 }
@@ -367,7 +367,7 @@ fn propagate_call_return(
         // when a call returns successfully, that means we need to set
         // the bits for that dest_place to 0 (initialized).
         on_lookup_result_bits(self.tcx, self.body, self.move_data(),
-                              self.move_data().rev_lookup.find(dest_place.as_place_ref()),
+                              self.move_data().rev_lookup.find(dest_place.as_ref()),
                               |mpi| { in_out.remove(mpi); });
     }
 }
@@ -423,7 +423,7 @@ fn propagate_call_return(
         // when a call returns successfully, that means we need to set
         // the bits for that dest_place to 1 (initialized).
         on_lookup_result_bits(self.tcx, self.body, self.move_data(),
-                              self.move_data().rev_lookup.find(dest_place.as_place_ref()),
+                              self.move_data().rev_lookup.find(dest_place.as_ref()),
                               |mpi| { in_out.insert(mpi); });
     }
 }
index 436ac30ffb42ed9b3c131f2f443102d3c8196ca9..366b96b53b42312bd46173597a32e3605f000349 100644 (file)
@@ -274,9 +274,9 @@ fn gather_statement(&mut self, stmt: &Statement<'tcx>) {
                     // move-path for the interior so it will be separate from
                     // the exterior.
                     self.create_move_path(&place.clone().deref());
-                    self.gather_init(place.as_place_ref(), InitKind::Shallow);
+                    self.gather_init(place.as_ref(), InitKind::Shallow);
                 } else {
-                    self.gather_init(place.as_place_ref(), InitKind::Deep);
+                    self.gather_init(place.as_ref(), InitKind::Deep);
                 }
                 self.gather_rvalue(rval);
             }
@@ -286,7 +286,7 @@ fn gather_statement(&mut self, stmt: &Statement<'tcx>) {
             StatementKind::InlineAsm(ref asm) => {
                 for (output, kind) in asm.outputs.iter().zip(&asm.asm.outputs) {
                     if !kind.is_indirect {
-                        self.gather_init(output.as_place_ref(), InitKind::Deep);
+                        self.gather_init(output.as_ref(), InitKind::Deep);
                     }
                 }
                 for (_, input) in asm.inputs.iter() {
@@ -376,7 +376,7 @@ fn gather_terminator(&mut self, term: &Terminator<'tcx>) {
             TerminatorKind::DropAndReplace { ref location, ref value, .. } => {
                 self.create_move_path(location);
                 self.gather_operand(value);
-                self.gather_init(location.as_place_ref(), InitKind::Deep);
+                self.gather_init(location.as_ref(), InitKind::Deep);
             }
             TerminatorKind::Call {
                 ref func,
@@ -391,7 +391,7 @@ fn gather_terminator(&mut self, term: &Terminator<'tcx>) {
                 }
                 if let Some((ref destination, _bb)) = *destination {
                     self.create_move_path(destination);
-                    self.gather_init(destination.as_place_ref(), InitKind::NonPanicPathOnly);
+                    self.gather_init(destination.as_ref(), InitKind::NonPanicPathOnly);
                 }
             }
         }
index cf36c10a614e5a3fa06512be1149a2017933fe26..6623661f938fe6cbc2470ddcd83e25c54c15d522 100644 (file)
@@ -7,7 +7,7 @@
 use rustc::ty::layout::{LayoutOf, Primitive, Size};
 use rustc::mir::BinOp;
 use rustc::mir::interpret::{
-    InterpResult, InterpError, Scalar,
+    InterpResult, InterpError, Scalar, PanicMessage,
 };
 
 use super::{
@@ -261,7 +261,7 @@ pub fn hook_fn(
             let file = Symbol::intern(self.read_str(file_place)?);
             let line = self.read_scalar(line.into())?.to_u32()?;
             let col = self.read_scalar(col.into())?.to_u32()?;
-            return Err(InterpError::Panic { msg, file, line, col }.into());
+            return Err(InterpError::Panic(PanicMessage::Panic { msg, file, line, col }).into());
         } else if Some(def_id) == self.tcx.lang_items().begin_panic_fn() {
             assert!(args.len() == 2);
             // &'static str, &(&'static str, u32, u32)
@@ -279,7 +279,7 @@ pub fn hook_fn(
             let file = Symbol::intern(self.read_str(file_place)?);
             let line = self.read_scalar(line.into())?.to_u32()?;
             let col = self.read_scalar(col.into())?.to_u32()?;
-            return Err(InterpError::Panic { msg, file, line, col }.into());
+            return Err(InterpError::Panic(PanicMessage::Panic { msg, file, line, col }).into());
         } else {
             return Ok(false);
         }
index 20180c9cba542423aeaa53acc00b77e23c245692..b4edee72a4d19bb901406d5fc9c94e70ac5bd7e4 100644 (file)
@@ -2,7 +2,7 @@
 use rustc::ty::{self, layout::TyLayout};
 use syntax::ast::FloatTy;
 use rustc_apfloat::Float;
-use rustc::mir::interpret::{InterpResult, Scalar};
+use rustc::mir::interpret::{InterpResult, PanicMessage, Scalar};
 
 use super::{InterpCx, PlaceTy, Immediate, Machine, ImmTy};
 
@@ -173,8 +173,8 @@ fn binary_int_op(
                 return Ok((Scalar::from_bool(op(&l, &r)), false));
             }
             let op: Option<fn(i128, i128) -> (i128, bool)> = match bin_op {
-                Div if r == 0 => return err!(DivisionByZero),
-                Rem if r == 0 => return err!(RemainderByZero),
+                Div if r == 0 => return err!(Panic(PanicMessage::DivisionByZero)),
+                Rem if r == 0 => return err!(Panic(PanicMessage::RemainderByZero)),
                 Div => Some(i128::overflowing_div),
                 Rem => Some(i128::overflowing_rem),
                 Add => Some(i128::overflowing_add),
@@ -231,8 +231,8 @@ fn binary_int_op(
                     Add => u128::overflowing_add,
                     Sub => u128::overflowing_sub,
                     Mul => u128::overflowing_mul,
-                    Div if r == 0 => return err!(DivisionByZero),
-                    Rem if r == 0 => return err!(RemainderByZero),
+                    Div if r == 0 => return err!(Panic(PanicMessage::DivisionByZero)),
+                    Rem if r == 0 => return err!(Panic(PanicMessage::RemainderByZero)),
                     Div => u128::overflowing_div,
                     Rem => u128::overflowing_rem,
                     _ => bug!(),
index 68382071b4a6720a391b12f7677df35adff812a6..8fe882934dfb58c9934b5a400a39173eb044ef7e 100644 (file)
@@ -13,7 +13,7 @@
 
 use super::{
     GlobalId, AllocId, Allocation, Scalar, InterpResult, Pointer, PointerArithmetic,
-    InterpCx, Machine, AllocMap, AllocationExtra,
+    InterpCx, Machine, AllocMap, AllocationExtra, PanicMessage,
     RawConst, Immediate, ImmTy, ScalarMaybeUndef, Operand, OpTy, MemoryKind, LocalValue
 };
 
@@ -356,7 +356,7 @@ pub fn mplace_field(
                     // This can be violated because this runs during promotion on code where the
                     // type system has not yet ensured that such things don't happen.
                     debug!("tried to access element {} of array/slice with length {}", field, len);
-                    return err!(BoundsCheck { len, index: field });
+                    return err!(Panic(PanicMessage::BoundsCheck { len, index: field }));
                 }
                 stride * field
             }
index 75690b4d361c6548f1fa06e02019dbeaa779bd3e..a85b77c7b8143e397250cca72a2057252d36b6f1 100644 (file)
@@ -7,7 +7,7 @@
 use rustc_target::spec::abi::Abi;
 
 use super::{
-    InterpResult, PointerArithmetic, InterpError, Scalar,
+    InterpResult, PointerArithmetic, InterpError, Scalar, PanicMessage,
     InterpCx, Machine, Immediate, OpTy, ImmTy, PlaceTy, MPlaceTy, StackPopCleanup, FnVal,
 };
 
@@ -137,19 +137,23 @@ pub(super) fn eval_terminator(
                     // Compute error message
                     use rustc::mir::interpret::InterpError::*;
                     return match *msg {
-                        BoundsCheck { ref len, ref index } => {
+                        Panic(PanicMessage::BoundsCheck { ref len, ref index }) => {
                             let len = self.read_immediate(self.eval_operand(len, None)?)
                                 .expect("can't eval len").to_scalar()?
                                 .to_bits(self.memory().pointer_size())? as u64;
                             let index = self.read_immediate(self.eval_operand(index, None)?)
                                 .expect("can't eval index").to_scalar()?
                                 .to_bits(self.memory().pointer_size())? as u64;
-                            err!(BoundsCheck { len, index })
+                            err!(Panic(PanicMessage::BoundsCheck { len, index }))
                         }
-                        Overflow(op) => Err(Overflow(op).into()),
-                        OverflowNeg => Err(OverflowNeg.into()),
-                        DivisionByZero => Err(DivisionByZero.into()),
-                        RemainderByZero => Err(RemainderByZero.into()),
+                        Panic(PanicMessage::Overflow(op)) =>
+                            Err(Panic(PanicMessage::Overflow(op)).into()),
+                        Panic(PanicMessage::OverflowNeg) =>
+                            Err(Panic(PanicMessage::OverflowNeg).into()),
+                        Panic(PanicMessage::DivisionByZero) =>
+                            Err(Panic(PanicMessage::DivisionByZero).into()),
+                        Panic(PanicMessage::RemainderByZero) =>
+                            Err(Panic(PanicMessage::RemainderByZero).into()),
                         GeneratorResumedAfterReturn |
                         GeneratorResumedAfterPanic => unimplemented!(),
                         _ => bug!(),
index 887f93c64787884ccae038a4e4cafe719f65c9d6..d573423906c2ab58047d55c5bde6bfba735e7282 100644 (file)
@@ -79,7 +79,7 @@ fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Bo
         let needs_retag = |place: &Place<'tcx>| {
             // FIXME: Instead of giving up for unstable places, we should introduce
             // a temporary and retag on that.
-            is_stable(place.as_place_ref())
+            is_stable(place.as_ref())
                 && may_have_reference(place.ty(&*local_decls, tcx).ty, tcx)
         };
 
index 72390228aa839d22c9689bcd58b9637ad5041820..37fcd744a3883eaee60fc400fc68c4f92b415914 100644 (file)
@@ -13,7 +13,7 @@
 use rustc::mir::visit::{
     Visitor, PlaceContext, MutatingUseContext, MutVisitor, NonMutatingUseContext,
 };
-use rustc::mir::interpret::{InterpError, Scalar, GlobalId, InterpResult};
+use rustc::mir::interpret::{InterpError::Panic, Scalar, GlobalId, InterpResult, PanicMessage};
 use rustc::ty::{self, Instance, ParamEnv, Ty, TyCtxt};
 use syntax_pos::{Span, DUMMY_SP};
 use rustc::ty::subst::InternalSubsts;
@@ -339,12 +339,7 @@ fn use_ecx<F, T>(
                     // FIXME: implement
                     => {},
 
-                    | Panic { .. }
-                    | BoundsCheck{..}
-                    | Overflow(_)
-                    | OverflowNeg
-                    | DivisionByZero
-                    | RemainderByZero
+                    | Panic(_)
                     => {
                         diagnostic.report_as_lint(
                             self.ecx.tcx,
@@ -522,7 +517,7 @@ fn const_prop(
                             // Need to do overflow check here: For actual CTFE, MIR
                             // generation emits code that does this before calling the op.
                             if prim.to_bits()? == (1 << (prim.layout.size.bits() - 1)) {
-                                return err!(OverflowNeg);
+                                return err!(Panic(PanicMessage::OverflowNeg));
                             }
                         }
                         UnOp::Not => {
@@ -600,7 +595,7 @@ fn const_prop(
                     )
                 } else {
                     if overflow {
-                        let err = InterpError::Overflow(op).into();
+                        let err = Panic(PanicMessage::Overflow(op)).into();
                         let _: Option<()> = self.use_ecx(source_info, |_| Err(err));
                         return None;
                     }
@@ -838,11 +833,11 @@ fn visit_terminator(
                             .expect("some part of a failing const eval must be local");
                         use rustc::mir::interpret::InterpError::*;
                         let msg = match msg {
-                            Overflow(_) |
-                            OverflowNeg |
-                            DivisionByZero |
-                            RemainderByZero => msg.description().to_owned(),
-                            BoundsCheck { ref len, ref index } => {
+                            Panic(PanicMessage::Overflow(_)) |
+                            Panic(PanicMessage::OverflowNeg) |
+                            Panic(PanicMessage::DivisionByZero) |
+                            Panic(PanicMessage::RemainderByZero) => msg.description().to_owned(),
+                            Panic(PanicMessage::BoundsCheck { ref len, ref index }) => {
                                 let len = self
                                     .eval_operand(len, source_info)
                                     .expect("len must be const");
index 0748321f605938ed3830697a9b7ba1b0727a0409..0a021d9b8fa066d3b3c8f7ac44686cfba0f595ff 100644 (file)
@@ -105,7 +105,7 @@ fn find_dead_unwinds<'tcx>(
             init_data.apply_location(tcx, body, env, loc);
         }
 
-        let path = match env.move_data.rev_lookup.find(location.as_place_ref()) {
+        let path = match env.move_data.rev_lookup.find(location.as_ref()) {
             LookupResult::Exact(e) => e,
             LookupResult::Parent(..) => {
                 debug!("find_dead_unwinds: has parent; skipping");
@@ -360,7 +360,7 @@ fn collect_drop_flags(&mut self)
                 statement_index: data.statements.len()
             });
 
-            let path = self.move_data().rev_lookup.find(location.as_place_ref());
+            let path = self.move_data().rev_lookup.find(location.as_ref());
             debug!("collect_drop_flags: {:?}, place {:?} ({:?})",
                    bb, location, path);
 
@@ -399,7 +399,7 @@ fn elaborate_drops(&mut self)
             match terminator.kind {
                 TerminatorKind::Drop { ref location, target, unwind } => {
                     let init_data = self.initialization_data_at(loc);
-                    match self.move_data().rev_lookup.find(location.as_place_ref()) {
+                    match self.move_data().rev_lookup.find(location.as_ref()) {
                         LookupResult::Exact(path) => {
                             elaborate_drop(
                                 &mut Elaborator {
@@ -488,7 +488,7 @@ fn elaborate_replace(
             is_cleanup: false,
         });
 
-        match self.move_data().rev_lookup.find(location.as_place_ref()) {
+        match self.move_data().rev_lookup.find(location.as_ref()) {
             LookupResult::Exact(path) => {
                 debug!("elaborate_drop_and_replace({:?}) - tracked {:?}", terminator, path);
                 let init_data = self.initialization_data_at(loc);
@@ -558,7 +558,7 @@ fn drop_flags_for_fn_rets(&mut self) {
                 assert!(!self.patch.is_patched(bb));
 
                 let loc = Location { block: tgt, statement_index: 0 };
-                let path = self.move_data().rev_lookup.find(place.as_place_ref());
+                let path = self.move_data().rev_lookup.find(place.as_ref());
                 on_lookup_result_bits(
                     self.tcx, self.body, self.move_data(), path,
                     |child| self.set_drop_flag(loc, child, DropFlagState::Present)
@@ -632,7 +632,7 @@ fn drop_flags_for_locs(&mut self) {
                 assert!(!self.patch.is_patched(bb));
 
                 let loc = Location { block: bb, statement_index: data.statements.len() };
-                let path = self.move_data().rev_lookup.find(place.as_place_ref());
+                let path = self.move_data().rev_lookup.find(place.as_ref());
                 on_lookup_result_bits(
                     self.tcx, self.body, self.move_data(), path,
                     |child| self.set_drop_flag(loc, child, DropFlagState::Present)
index 739e2172b03bc6f6892fc06f5724495d815aa0b3..ffeaf4e19c22a76008d1a6a3a92d8b8caf68565a 100644 (file)
@@ -243,7 +243,7 @@ fn in_place(cx: &ConstCx<'_, 'tcx>, place: PlaceRef<'_, 'tcx>) -> bool {
     fn in_operand(cx: &ConstCx<'_, 'tcx>, operand: &Operand<'tcx>) -> bool {
         match *operand {
             Operand::Copy(ref place) |
-            Operand::Move(ref place) => Self::in_place(cx, place.as_place_ref()),
+            Operand::Move(ref place) => Self::in_place(cx, place.as_ref()),
 
             Operand::Constant(ref constant) => {
                 if let ConstValue::Unevaluated(def_id, _) = constant.literal.val {
@@ -272,7 +272,7 @@ fn in_rvalue_structurally(cx: &ConstCx<'_, 'tcx>, rvalue: &Rvalue<'tcx>) -> bool
             Rvalue::NullaryOp(..) => false,
 
             Rvalue::Discriminant(ref place) |
-            Rvalue::Len(ref place) => Self::in_place(cx, place.as_place_ref()),
+            Rvalue::Len(ref place) => Self::in_place(cx, place.as_ref()),
 
             Rvalue::Use(ref operand) |
             Rvalue::Repeat(ref operand, _) |
@@ -298,7 +298,7 @@ fn in_rvalue_structurally(cx: &ConstCx<'_, 'tcx>, rvalue: &Rvalue<'tcx>) -> bool
                     }
                 }
 
-                Self::in_place(cx, place.as_place_ref())
+                Self::in_place(cx, place.as_ref())
             }
 
             Rvalue::Aggregate(_, ref operands) => {
index 1fd865c42fcdb696b9c92ec793e4f3b0166cc1dd..7fe8480c819e6f690aee0fbda0a9a983c2b598fe 100644 (file)
@@ -168,7 +168,7 @@ fn each_block<'tcx, O>(
         if place == peek_arg_place {
             if let mir::Rvalue::Ref(_, mir::BorrowKind::Shared, ref peeking_at_place) = **rvalue {
                 // Okay, our search is over.
-                match move_data.rev_lookup.find(peeking_at_place.as_place_ref()) {
+                match move_data.rev_lookup.find(peeking_at_place.as_ref()) {
                     LookupResult::Exact(peek_mpi) => {
                         let bit_state = on_entry.contains(peek_mpi);
                         debug!("rustc_peek({:?} = &{:?}) bit_state: {}",
@@ -192,7 +192,7 @@ fn each_block<'tcx, O>(
             }
         }
 
-        let lhs_mpi = move_data.rev_lookup.find(place.as_place_ref());
+        let lhs_mpi = move_data.rev_lookup.find(place.as_ref());
 
         debug!("rustc_peek: computing effect on place: {:?} ({:?}) in stmt: {:?}",
                place, lhs_mpi, stmt);
index 73151b194de42fab1636702be45f1ed10215a1ae..0b2d7aacc4ddf79160293087a3c40fff1bb6fd9a 100644 (file)
@@ -5,8 +5,7 @@ pub fn target() -> TargetResult {
     base.cpu = "x86-64".to_string();
     base.max_atomic_width = Some(64);
     base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-mx32".to_string());
-    // BUG: temporarily workaround #59674
-    base.stack_probes = false;
+    base.stack_probes = true;
     base.has_elf_tls = false;
     // BUG(GabrielMajeri): disabling the PLT on x86_64 Linux with x32 ABI
     // breaks code gen. See LLVM bug 36743
index d314228a232c963aa45e57d5502c40bd85e1241a..5799e58a727a867aa52744516a4076082edef155 100644 (file)
@@ -1650,7 +1650,10 @@ pub fn associated_path_to_ty(
                             Applicability::MaybeIncorrect,
                         );
                     } else {
-                        err.span_label(span, format!("variant not found in `{}`", qself_ty));
+                        err.span_label(
+                            assoc_ident.span,
+                            format!("variant not found in `{}`", qself_ty),
+                        );
                     }
 
                     if let Some(sp) = tcx.hir().span_if_local(adt_def.did) {
index bde6db78aef32763bc7d781efc7eb576756a4eba..21cd4b694ae4ca625047e323b6b12d9f597ba8b8 100644 (file)
@@ -759,40 +759,40 @@ fn adt_destructor(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::Destructor> {
 fn primary_body_of(
     tcx: TyCtxt<'_>,
     id: hir::HirId,
-) -> Option<(hir::BodyId, Option<&hir::FnHeader>, Option<&hir::FnDecl>)> {
+) -> Option<(hir::BodyId, Option<&hir::Ty>, Option<&hir::FnHeader>, Option<&hir::FnDecl>)> {
     match tcx.hir().get(id) {
         Node::Item(item) => {
             match item.node {
-                hir::ItemKind::Const(_, body) |
-                hir::ItemKind::Static(_, _, body) =>
-                    Some((body, None, None)),
+                hir::ItemKind::Const(ref ty, body) |
+                hir::ItemKind::Static(ref ty, _, body) =>
+                    Some((body, Some(ty), None, None)),
                 hir::ItemKind::Fn(ref decl, ref header, .., body) =>
-                    Some((body, Some(header), Some(decl))),
+                    Some((body, None, Some(header), Some(decl))),
                 _ =>
                     None,
             }
         }
         Node::TraitItem(item) => {
             match item.node {
-                hir::TraitItemKind::Const(_, Some(body)) =>
-                    Some((body, None, None)),
+                hir::TraitItemKind::Const(ref ty, Some(body)) =>
+                    Some((body, Some(ty), None, None)),
                 hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) =>
-                    Some((body, Some(&sig.header), Some(&sig.decl))),
+                    Some((body, None, Some(&sig.header), Some(&sig.decl))),
                 _ =>
                     None,
             }
         }
         Node::ImplItem(item) => {
             match item.node {
-                hir::ImplItemKind::Const(_, body) =>
-                    Some((body, None, None)),
+                hir::ImplItemKind::Const(ref ty, body) =>
+                    Some((body, Some(ty), None, None)),
                 hir::ImplItemKind::Method(ref sig, body) =>
-                    Some((body, Some(&sig.header), Some(&sig.decl))),
+                    Some((body, None, Some(&sig.header), Some(&sig.decl))),
                 _ =>
                     None,
             }
         }
-        Node::AnonConst(constant) => Some((constant.body, None, None)),
+        Node::AnonConst(constant) => Some((constant.body, None, None, None)),
         _ => None,
     }
 }
@@ -825,7 +825,7 @@ fn typeck_tables_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::TypeckTables<'_> {
     let span = tcx.hir().span(id);
 
     // Figure out what primary body this item has.
-    let (body_id, fn_header, fn_decl) = primary_body_of(tcx, id)
+    let (body_id, body_ty, fn_header, fn_decl) = primary_body_of(tcx, id)
         .unwrap_or_else(|| {
             span_bug!(span, "can't type-check body of {:?}", def_id);
         });
@@ -856,7 +856,10 @@ fn typeck_tables_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::TypeckTables<'_> {
             fcx
         } else {
             let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id);
-            let expected_type = tcx.type_of(def_id);
+            let expected_type = body_ty.and_then(|ty| match ty.node {
+                hir::TyKind::Infer => Some(AstConv::ast_ty_to_ty(&fcx, ty)),
+                _ => None
+            }).unwrap_or_else(|| tcx.type_of(def_id));
             let expected_type = fcx.normalize_associated_types_in(body.value.span, &expected_type);
             fcx.require_type_is_sized(expected_type, body.value.span, traits::ConstSized);
 
index a5457c45d378cd5d5120b4b1af5d2a4bfad894d8..053ef1f8f8297a2c640045eb7a601d1c2f6c9e68 100644 (file)
@@ -1135,6 +1135,26 @@ fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
     checked_type_of(tcx, def_id, true).unwrap()
 }
 
+fn infer_placeholder_type(
+    tcx: TyCtxt<'_>,
+    def_id: DefId,
+    body_id: hir::BodyId,
+    span: Span,
+) -> Ty<'_> {
+    let ty = tcx.typeck_tables_of(def_id).node_type(body_id.hir_id);
+    let mut diag = bad_placeholder_type(tcx, span);
+    if ty != tcx.types.err {
+        diag.span_suggestion(
+            span,
+            "replace `_` with the correct type",
+            ty.to_string(),
+            Applicability::MaybeIncorrect,
+        );
+    }
+    diag.emit();
+    ty
+}
+
 /// Same as [`type_of`] but returns [`Option`] instead of failing.
 ///
 /// If you want to fail anyway, you can set the `fail` parameter to true, but in this case,
@@ -1160,7 +1180,16 @@ pub fn checked_type_of(tcx: TyCtxt<'_>, def_id: DefId, fail: bool) -> Option<Ty<
                 let substs = InternalSubsts::identity_for_item(tcx, def_id);
                 tcx.mk_fn_def(def_id, substs)
             }
-            TraitItemKind::Const(ref ty, _) | TraitItemKind::Type(_, Some(ref ty)) => icx.to_ty(ty),
+            TraitItemKind::Const(ref ty, body_id)  => {
+                body_id.and_then(|body_id| {
+                    if let hir::TyKind::Infer = ty.node {
+                        Some(infer_placeholder_type(tcx, def_id, body_id, ty.span))
+                    } else {
+                        None
+                    }
+                }).unwrap_or_else(|| icx.to_ty(ty))
+            },
+            TraitItemKind::Type(_, Some(ref ty)) => icx.to_ty(ty),
             TraitItemKind::Type(_, None) => {
                 if !fail {
                     return None;
@@ -1174,7 +1203,13 @@ pub fn checked_type_of(tcx: TyCtxt<'_>, def_id: DefId, fail: bool) -> Option<Ty<
                 let substs = InternalSubsts::identity_for_item(tcx, def_id);
                 tcx.mk_fn_def(def_id, substs)
             }
-            ImplItemKind::Const(ref ty, _) => icx.to_ty(ty),
+            ImplItemKind::Const(ref ty, body_id) => {
+                if let hir::TyKind::Infer = ty.node {
+                    infer_placeholder_type(tcx, def_id, body_id, ty.span)
+                } else {
+                    icx.to_ty(ty)
+                }
+            },
             ImplItemKind::Existential(_) => {
                 if tcx
                     .impl_trait_ref(tcx.hir().get_parent_did(hir_id))
@@ -1199,10 +1234,16 @@ pub fn checked_type_of(tcx: TyCtxt<'_>, def_id: DefId, fail: bool) -> Option<Ty<
 
         Node::Item(item) => {
             match item.node {
-                ItemKind::Static(ref t, ..)
-                | ItemKind::Const(ref t, _)
-                | ItemKind::Ty(ref t, _)
-                | ItemKind::Impl(.., ref t, _) => icx.to_ty(t),
+                ItemKind::Static(ref ty, .., body_id)
+                | ItemKind::Const(ref ty, body_id) => {
+                    if let hir::TyKind::Infer = ty.node {
+                        infer_placeholder_type(tcx, def_id, body_id, ty.span)
+                    } else {
+                        icx.to_ty(ty)
+                    }
+                },
+                ItemKind::Ty(ref ty, _)
+                | ItemKind::Impl(.., ref ty, _) => icx.to_ty(ty),
                 ItemKind::Fn(..) => {
                     let substs = InternalSubsts::identity_for_item(tcx, def_id);
                     tcx.mk_fn_def(def_id, substs)
index 58777130b7f29339b530468d6da409c92e8bf073..3627ce6a5aa501865a4435448d17492c908d221e 100644 (file)
@@ -21,6 +21,7 @@
 #![feature(inner_deref)]
 #![feature(never_type)]
 #![feature(mem_take)]
+#![feature(unicode_internals)]
 
 #![recursion_limit="256"]
 
index 6a3f58ec89e19112c571051b63234026dcf272a9..43f0eaae7c97e36eaee669b295fdbbfd093b6fb7 100644 (file)
@@ -126,6 +126,9 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
 
     // no-tracking-issue-start
 
+    // Allows using compiler's own crates.
+    (active, rustc_private, "1.0.0", Some(27812), None),
+
     // Allows using the `rust-intrinsic`'s "ABI".
     (active, intrinsics, "1.0.0", None, None),
 
index 0e88a0ee289378ff3353d269a3d014c65f2ec897..f4fc87506f357247666cca64a661a88d750cc84d 100644 (file)
@@ -2,6 +2,7 @@
     self, Arg, BinOpKind, BindingMode, BlockCheckMode, Expr, ExprKind, Ident, Item, ItemKind,
     Mutability, Pat, PatKind, PathSegment, QSelf, Ty, TyKind, VariantData,
 };
+use crate::feature_gate::{feature_err, UnstableFeatures};
 use crate::parse::{SeqSep, PResult, Parser, ParseSess};
 use crate::parse::parser::{BlockMode, PathStyle, SemiColonMode, TokenType, TokenExpectType};
 use crate::parse::token::{self, TokenKind};
@@ -326,8 +327,8 @@ fn tokens_to_string(tokens: &[TokenType]) -> String {
             self.token.is_keyword(kw::Return) ||
             self.token.is_keyword(kw::While)
         );
-        let cm = self.sess.source_map();
-        match (cm.lookup_line(self.token.span.lo()), cm.lookup_line(sp.lo())) {
+        let sm = self.sess.source_map();
+        match (sm.lookup_line(self.token.span.lo()), sm.lookup_line(sp.lo())) {
             (Ok(ref a), Ok(ref b)) if a.line != b.line && is_semi_suggestable => {
                 // The spans are in different lines, expected `;` and found `let` or `return`.
                 // High likelihood that it is only a missing `;`.
@@ -365,9 +366,53 @@ fn tokens_to_string(tokens: &[TokenType]) -> String {
                 err.span_label(self.token.span, "unexpected token");
             }
         }
+        self.maybe_annotate_with_ascription(&mut err, false);
         Err(err)
     }
 
+    pub fn maybe_annotate_with_ascription(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        maybe_expected_semicolon: bool,
+    ) {
+        if let Some((sp, likely_path)) = self.last_type_ascription {
+            let sm = self.sess.source_map();
+            let next_pos = sm.lookup_char_pos(self.token.span.lo());
+            let op_pos = sm.lookup_char_pos(sp.hi());
+
+            if likely_path {
+                err.span_suggestion(
+                    sp,
+                    "maybe write a path separator here",
+                    "::".to_string(),
+                    match self.sess.unstable_features {
+                        UnstableFeatures::Disallow => Applicability::MachineApplicable,
+                        _ => Applicability::MaybeIncorrect,
+                    },
+                );
+            } else if op_pos.line != next_pos.line && maybe_expected_semicolon {
+                err.span_suggestion(
+                    sp,
+                    "try using a semicolon",
+                    ";".to_string(),
+                    Applicability::MaybeIncorrect,
+                );
+            } else if let UnstableFeatures::Disallow = self.sess.unstable_features {
+                err.span_label(sp, "tried to parse a type due to this");
+            } else {
+                err.span_label(sp, "tried to parse a type due to this type ascription");
+            }
+            if let UnstableFeatures::Disallow = self.sess.unstable_features {
+                // Give extra information about type ascription only if it's a nightly compiler.
+            } else {
+                err.note("`#![feature(type_ascription)]` lets you annotate an expression with a \
+                          type: `<expr>: <type>`");
+                err.note("for more information, see \
+                          https://github.com/rust-lang/rust/issues/23416");
+            }
+        }
+    }
+
     /// Eats and discards tokens until one of `kets` is encountered. Respects token trees,
     /// passes through any errors encountered. Used for error recovery.
     crate fn eat_to_tokens(&mut self, kets: &[&TokenKind]) {
@@ -556,7 +601,7 @@ fn tokens_to_string(tokens: &[TokenType]) -> String {
         .collect::<Vec<_>>();
 
         if !discriminant_spans.is_empty() && has_fields {
-            let mut err = crate::feature_gate::feature_err(
+            let mut err = feature_err(
                 sess,
                 sym::arbitrary_enum_discriminant,
                 discriminant_spans.clone(),
@@ -769,8 +814,8 @@ pub fn unexpected_try_recover(
                 return Ok(recovered);
             }
         }
-        let cm = self.sess.source_map();
-        match (cm.lookup_line(prev_sp.lo()), cm.lookup_line(sp.lo())) {
+        let sm = self.sess.source_map();
+        match (sm.lookup_line(prev_sp.lo()), sm.lookup_line(sp.lo())) {
             (Ok(ref a), Ok(ref b)) if a.line == b.line => {
                 // When the spans are in the same line, it means that the only content
                 // between them is whitespace, point only at the found token.
@@ -887,47 +932,9 @@ pub fn unexpected_try_recover(
             self.look_ahead(2, |t| t.is_ident()) ||
             self.look_ahead(1, |t| t == &token::Colon) &&  // `foo:bar:baz`
             self.look_ahead(2, |t| t.is_ident()) ||
-            self.look_ahead(1, |t| t == &token::ModSep) &&  // `foo:bar::baz`
-            self.look_ahead(2, |t| t.is_ident())
-    }
-
-    crate fn bad_type_ascription(
-        &self,
-        err: &mut DiagnosticBuilder<'a>,
-        lhs_span: Span,
-        cur_op_span: Span,
-        next_sp: Span,
-        maybe_path: bool,
-    ) {
-        err.span_label(self.token.span, "expecting a type here because of type ascription");
-        let cm = self.sess.source_map();
-        let next_pos = cm.lookup_char_pos(next_sp.lo());
-        let op_pos = cm.lookup_char_pos(cur_op_span.hi());
-        if op_pos.line != next_pos.line {
-            err.span_suggestion(
-                cur_op_span,
-                "try using a semicolon",
-                ";".to_string(),
-                Applicability::MaybeIncorrect,
-            );
-        } else {
-            if maybe_path {
-                err.span_suggestion(
-                    cur_op_span,
-                    "maybe you meant to write a path separator here",
-                    "::".to_string(),
-                    Applicability::MaybeIncorrect,
-                );
-            } else {
-                err.note("`#![feature(type_ascription)]` lets you annotate an \
-                          expression with a type: `<expr>: <type>`")
-                    .span_note(
-                        lhs_span,
-                        "this expression expects an ascribed type after the colon",
-                    )
-                    .help("this might be indicative of a syntax error elsewhere");
-            }
-        }
+            self.look_ahead(1, |t| t == &token::ModSep) &&
+            (self.look_ahead(2, |t| t.is_ident()) ||   // `foo:bar::baz`
+             self.look_ahead(2, |t| t == &token::Lt))  // `foo:bar::<baz>`
     }
 
     crate fn recover_seq_parse_error(
index bfefd9adbfe8f050878c1c726ce55cbb607849b3..b97801a50d4721cbc6c9c88f5976388c9e9ed435 100644 (file)
@@ -1,12 +1,12 @@
 use crate::parse::ParseSess;
 use crate::parse::token::{self, Token, TokenKind};
 use crate::symbol::{sym, Symbol};
-use crate::parse::unescape;
 use crate::parse::unescape_error_reporting::{emit_unescape_error, push_escaped_char};
 
 use errors::{FatalError, Diagnostic, DiagnosticBuilder};
 use syntax_pos::{BytePos, Pos, Span, NO_EXPANSION};
 use rustc_lexer::Base;
+use rustc_lexer::unescape;
 
 use std::borrow::Cow;
 use std::char;
index 683d164156540a31cbc486fbe77e49792a25aabd..6409acba573ad33a43b9b0f49a2ec426807da896 100644 (file)
@@ -4,9 +4,6 @@
 use crate::parse::parser::Parser;
 use crate::parse::PResult;
 use crate::parse::token::{self, Token, TokenKind};
-use crate::parse::unescape::{unescape_char, unescape_byte};
-use crate::parse::unescape::{unescape_str, unescape_byte_str};
-use crate::parse::unescape::{unescape_raw_str, unescape_raw_byte_str};
 use crate::print::pprust;
 use crate::symbol::{kw, sym, Symbol};
 use crate::tokenstream::{TokenStream, TokenTree};
@@ -15,6 +12,9 @@
 use log::debug;
 use rustc_data_structures::sync::Lrc;
 use syntax_pos::Span;
+use rustc_lexer::unescape::{unescape_char, unescape_byte};
+use rustc_lexer::unescape::{unescape_str, unescape_byte_str};
+use rustc_lexer::unescape::{unescape_raw_str, unescape_raw_byte_str};
 
 use std::ascii;
 
index 4c4551b1757acefd44615353243d9ae937f961ea..225065c1cf11f84a7886bb1df712f74b3b4971df 100644 (file)
@@ -32,7 +32,6 @@
 crate mod classify;
 crate mod diagnostics;
 crate mod literal;
-crate mod unescape;
 crate mod unescape_error_reporting;
 
 /// Info about a parsing session.
index 1d4d02c7325826118bbefbf57101b84f77c19b9c..da38869463737d5d09873a5c3ebf23849baa2c7f 100644 (file)
@@ -239,6 +239,7 @@ pub struct Parser<'a> {
     /// error.
     crate unclosed_delims: Vec<UnmatchedBrace>,
     crate last_unexpected_token_span: Option<Span>,
+    crate last_type_ascription: Option<(Span, bool /* likely path typo */)>,
     /// If present, this `Parser` is not parsing Rust code but rather a macro call.
     crate subparser_name: Option<&'static str>,
 }
@@ -502,6 +503,7 @@ pub fn new(
             max_angle_bracket_count: 0,
             unclosed_delims: Vec::new(),
             last_unexpected_token_span: None,
+            last_type_ascription: None,
             subparser_name,
         };
 
@@ -1422,7 +1424,10 @@ fn parse_ty_common(&mut self, allow_plus: bool, allow_qpath_recovery: bool,
             }
         } else {
             let msg = format!("expected type, found {}", self.this_token_descr());
-            return Err(self.fatal(&msg));
+            let mut err = self.fatal(&msg);
+            err.span_label(self.token.span, "expected type");
+            self.maybe_annotate_with_ascription(&mut err, true);
+            return Err(err);
         };
 
         let span = lo.to(self.prev_span);
@@ -2823,10 +2828,11 @@ fn parse_assoc_expr(&mut self,
     }
 
     /// Parses an associative expression with operators of at least `min_prec` precedence.
-    fn parse_assoc_expr_with(&mut self,
-                                 min_prec: usize,
-                                 lhs: LhsExpr)
-                                 -> PResult<'a, P<Expr>> {
+    fn parse_assoc_expr_with(
+        &mut self,
+        min_prec: usize,
+        lhs: LhsExpr,
+    ) -> PResult<'a, P<Expr>> {
         let mut lhs = if let LhsExpr::AlreadyParsed(expr) = lhs {
             expr
         } else {
@@ -2840,9 +2846,11 @@ fn parse_assoc_expr_with(&mut self,
                 self.parse_prefix_expr(attrs)?
             }
         };
+        let last_type_ascription_set = self.last_type_ascription.is_some();
 
         match (self.expr_is_complete(&lhs), AssocOp::from_token(&self.token)) {
             (true, None) => {
+                self.last_type_ascription = None;
                 // Semi-statement forms are odd. See https://github.com/rust-lang/rust/issues/29071
                 return Ok(lhs);
             }
@@ -2857,12 +2865,14 @@ fn parse_assoc_expr_with(&mut self,
             // If the next token is a keyword, then the tokens above *are* unambiguously incorrect:
             // `if x { a } else { b } && if y { c } else { d }`
             if !self.look_ahead(1, |t| t.is_reserved_ident()) => {
+                self.last_type_ascription = None;
                 // These cases are ambiguous and can't be identified in the parser alone
                 let sp = self.sess.source_map().start_point(self.token.span);
                 self.sess.ambiguous_block_expr_parse.borrow_mut().insert(sp, lhs.span);
                 return Ok(lhs);
             }
             (true, Some(ref op)) if !op.can_continue_expr_unambiguously() => {
+                self.last_type_ascription = None;
                 return Ok(lhs);
             }
             (true, Some(_)) => {
@@ -2921,21 +2931,9 @@ fn parse_assoc_expr_with(&mut self,
                 continue
             } else if op == AssocOp::Colon {
                 let maybe_path = self.could_ascription_be_path(&lhs.node);
-                let next_sp = self.token.span;
+                self.last_type_ascription = Some((self.prev_span, maybe_path));
 
-                lhs = match self.parse_assoc_op_cast(lhs, lhs_span, ExprKind::Type) {
-                    Ok(lhs) => lhs,
-                    Err(mut err) => {
-                        self.bad_type_ascription(
-                            &mut err,
-                            lhs_span,
-                            cur_op_span,
-                            next_sp,
-                            maybe_path,
-                        );
-                        return Err(err);
-                    }
-                };
+                lhs = self.parse_assoc_op_cast(lhs, lhs_span, ExprKind::Type)?;
                 continue
             } else if op == AssocOp::DotDot || op == AssocOp::DotDotEq {
                 // If we didn’t have to handle `x..`/`x..=`, it would be pretty easy to
@@ -3020,6 +3018,9 @@ fn parse_assoc_expr_with(&mut self,
 
             if let Fixity::None = fixity { break }
         }
+        if last_type_ascription_set {
+            self.last_type_ascription = None;
+        }
         Ok(lhs)
     }
 
diff --git a/src/libsyntax/parse/unescape.rs b/src/libsyntax/parse/unescape.rs
deleted file mode 100644 (file)
index 87cc9c1..0000000
+++ /dev/null
@@ -1,602 +0,0 @@
-//! Utilities for validating string and char literals and turning them into
-//! values they represent.
-
-use std::str::Chars;
-use std::ops::Range;
-
-#[derive(Debug, PartialEq, Eq)]
-pub(crate) enum EscapeError {
-    ZeroChars,
-    MoreThanOneChar,
-
-    LoneSlash,
-    InvalidEscape,
-    BareCarriageReturn,
-    BareCarriageReturnInRawString,
-    EscapeOnlyChar,
-
-    TooShortHexEscape,
-    InvalidCharInHexEscape,
-    OutOfRangeHexEscape,
-
-    NoBraceInUnicodeEscape,
-    InvalidCharInUnicodeEscape,
-    EmptyUnicodeEscape,
-    UnclosedUnicodeEscape,
-    LeadingUnderscoreUnicodeEscape,
-    OverlongUnicodeEscape,
-    LoneSurrogateUnicodeEscape,
-    OutOfRangeUnicodeEscape,
-
-    UnicodeEscapeInByte,
-    NonAsciiCharInByte,
-    NonAsciiCharInByteString,
-}
-
-/// Takes a contents of a char literal (without quotes), and returns an
-/// unescaped char or an error
-pub(crate) fn unescape_char(literal_text: &str) -> Result<char, (usize, EscapeError)> {
-    let mut chars = literal_text.chars();
-    unescape_char_or_byte(&mut chars, Mode::Char)
-        .map_err(|err| (literal_text.len() - chars.as_str().len(), err))
-}
-
-/// Takes a contents of a string literal (without quotes) and produces a
-/// sequence of escaped characters or errors.
-pub(crate) fn unescape_str<F>(literal_text: &str, callback: &mut F)
-where
-    F: FnMut(Range<usize>, Result<char, EscapeError>),
-{
-    unescape_str_or_byte_str(literal_text, Mode::Str, callback)
-}
-
-pub(crate) fn unescape_byte(literal_text: &str) -> Result<u8, (usize, EscapeError)> {
-    let mut chars = literal_text.chars();
-    unescape_char_or_byte(&mut chars, Mode::Byte)
-        .map(byte_from_char)
-        .map_err(|err| (literal_text.len() - chars.as_str().len(), err))
-}
-
-/// Takes a contents of a string literal (without quotes) and produces a
-/// sequence of escaped characters or errors.
-pub(crate) fn unescape_byte_str<F>(literal_text: &str, callback: &mut F)
-where
-    F: FnMut(Range<usize>, Result<u8, EscapeError>),
-{
-    unescape_str_or_byte_str(literal_text, Mode::ByteStr, &mut |range, char| {
-        callback(range, char.map(byte_from_char))
-    })
-}
-
-/// Takes a contents of a string literal (without quotes) and produces a
-/// sequence of characters or errors.
-/// NOTE: Raw strings do not perform any explicit character escaping, here we
-/// only translate CRLF to LF and produce errors on bare CR.
-pub(crate) fn unescape_raw_str<F>(literal_text: &str, callback: &mut F)
-where
-    F: FnMut(Range<usize>, Result<char, EscapeError>),
-{
-    unescape_raw_str_or_byte_str(literal_text, Mode::Str, callback)
-}
-
-/// Takes a contents of a string literal (without quotes) and produces a
-/// sequence of characters or errors.
-/// NOTE: Raw strings do not perform any explicit character escaping, here we
-/// only translate CRLF to LF and produce errors on bare CR.
-pub(crate) fn unescape_raw_byte_str<F>(literal_text: &str, callback: &mut F)
-where
-    F: FnMut(Range<usize>, Result<u8, EscapeError>),
-{
-    unescape_raw_str_or_byte_str(literal_text, Mode::ByteStr, &mut |range, char| {
-        callback(range, char.map(byte_from_char))
-    })
-}
-
-#[derive(Debug, Clone, Copy)]
-pub(crate) enum Mode {
-    Char,
-    Str,
-    Byte,
-    ByteStr,
-}
-
-impl Mode {
-    fn in_single_quotes(self) -> bool {
-        match self {
-            Mode::Char | Mode::Byte => true,
-            Mode::Str | Mode::ByteStr => false,
-        }
-    }
-
-    pub(crate) fn in_double_quotes(self) -> bool {
-        !self.in_single_quotes()
-    }
-
-    pub(crate) fn is_bytes(self) -> bool {
-        match self {
-            Mode::Byte | Mode::ByteStr => true,
-            Mode::Char | Mode::Str => false,
-        }
-    }
-}
-
-
-fn scan_escape(first_char: char, chars: &mut Chars<'_>, mode: Mode) -> Result<char, EscapeError> {
-    if first_char != '\\' {
-        return match first_char {
-            '\t' | '\n' => Err(EscapeError::EscapeOnlyChar),
-            '\r' => Err(if chars.clone().next() == Some('\n') {
-                EscapeError::EscapeOnlyChar
-            } else {
-                EscapeError::BareCarriageReturn
-            }),
-            '\'' if mode.in_single_quotes() => Err(EscapeError::EscapeOnlyChar),
-            '"' if mode.in_double_quotes() => Err(EscapeError::EscapeOnlyChar),
-            _ => {
-                if mode.is_bytes() && !first_char.is_ascii() {
-                    return Err(EscapeError::NonAsciiCharInByte);
-                }
-                Ok(first_char)
-            }
-        };
-    }
-
-    let second_char = chars.next().ok_or(EscapeError::LoneSlash)?;
-
-    let res = match second_char {
-        '"' => '"',
-        'n' => '\n',
-        'r' => '\r',
-        't' => '\t',
-        '\\' => '\\',
-        '\'' => '\'',
-        '0' => '\0',
-
-        'x' => {
-            let hi = chars.next().ok_or(EscapeError::TooShortHexEscape)?;
-            let hi = hi.to_digit(16).ok_or(EscapeError::InvalidCharInHexEscape)?;
-
-            let lo = chars.next().ok_or(EscapeError::TooShortHexEscape)?;
-            let lo = lo.to_digit(16).ok_or(EscapeError::InvalidCharInHexEscape)?;
-
-            let value = hi * 16 + lo;
-
-            if !mode.is_bytes() && !is_ascii(value) {
-                return Err(EscapeError::OutOfRangeHexEscape);
-            }
-            let value = value as u8;
-
-            value as char
-        }
-
-        'u' => {
-            if chars.next() != Some('{') {
-                return Err(EscapeError::NoBraceInUnicodeEscape);
-            }
-
-            let mut n_digits = 1;
-            let mut value: u32 = match chars.next().ok_or(EscapeError::UnclosedUnicodeEscape)? {
-                '_' => return Err(EscapeError::LeadingUnderscoreUnicodeEscape),
-                '}' => return Err(EscapeError::EmptyUnicodeEscape),
-                c => c.to_digit(16).ok_or(EscapeError::InvalidCharInUnicodeEscape)?,
-            };
-
-            loop {
-                match chars.next() {
-                    None => return Err(EscapeError::UnclosedUnicodeEscape),
-                    Some('_') => continue,
-                    Some('}') => {
-                        if n_digits > 6 {
-                            return Err(EscapeError::OverlongUnicodeEscape);
-                        }
-                        if mode.is_bytes() {
-                            return Err(EscapeError::UnicodeEscapeInByte);
-                        }
-
-                        break std::char::from_u32(value).ok_or_else(|| {
-                            if value > 0x10FFFF {
-                                EscapeError::OutOfRangeUnicodeEscape
-                            } else {
-                                EscapeError::LoneSurrogateUnicodeEscape
-                            }
-                        })?;
-                    }
-                    Some(c) => {
-                        let digit = c.to_digit(16).ok_or(EscapeError::InvalidCharInUnicodeEscape)?;
-                        n_digits += 1;
-                        if n_digits > 6 {
-                            continue;
-                        }
-                        let digit = digit as u32;
-                        value = value * 16 + digit;
-                    }
-                };
-            }
-        }
-        _ => return Err(EscapeError::InvalidEscape),
-    };
-    Ok(res)
-}
-
-fn unescape_char_or_byte(chars: &mut Chars<'_>, mode: Mode) -> Result<char, EscapeError> {
-    let first_char = chars.next().ok_or(EscapeError::ZeroChars)?;
-    let res = scan_escape(first_char, chars, mode)?;
-    if chars.next().is_some() {
-        return Err(EscapeError::MoreThanOneChar);
-    }
-    Ok(res)
-}
-
-/// Takes a contents of a string literal (without quotes) and produces a
-/// sequence of escaped characters or errors.
-fn unescape_str_or_byte_str<F>(src: &str, mode: Mode, callback: &mut F)
-where
-    F: FnMut(Range<usize>, Result<char, EscapeError>),
-{
-    assert!(mode.in_double_quotes());
-    let initial_len = src.len();
-    let mut chars = src.chars();
-    while let Some(first_char) = chars.next() {
-        let start = initial_len - chars.as_str().len() - first_char.len_utf8();
-
-        let unescaped_char = match first_char {
-            '\\' => {
-                let (second_char, third_char) = {
-                    let mut chars = chars.clone();
-                    (chars.next(), chars.next())
-                };
-                match (second_char, third_char) {
-                    (Some('\n'), _) | (Some('\r'), Some('\n')) => {
-                        skip_ascii_whitespace(&mut chars);
-                        continue;
-                    }
-                    _ => scan_escape(first_char, &mut chars, mode),
-                }
-            }
-            '\r' => {
-                let second_char = chars.clone().next();
-                if second_char == Some('\n') {
-                    chars.next();
-                    Ok('\n')
-                } else {
-                    scan_escape(first_char, &mut chars, mode)
-                }
-            }
-            '\n' => Ok('\n'),
-            '\t' => Ok('\t'),
-            _ => scan_escape(first_char, &mut chars, mode),
-        };
-        let end = initial_len - chars.as_str().len();
-        callback(start..end, unescaped_char);
-    }
-
-    fn skip_ascii_whitespace(chars: &mut Chars<'_>) {
-        let str = chars.as_str();
-        let first_non_space = str
-            .bytes()
-            .position(|b| b != b' ' && b != b'\t' && b != b'\n' && b != b'\r')
-            .unwrap_or(str.len());
-        *chars = str[first_non_space..].chars()
-    }
-}
-
-/// Takes a contents of a string literal (without quotes) and produces a
-/// sequence of characters or errors.
-/// NOTE: Raw strings do not perform any explicit character escaping, here we
-/// only translate CRLF to LF and produce errors on bare CR.
-fn unescape_raw_str_or_byte_str<F>(literal_text: &str, mode: Mode, callback: &mut F)
-where
-    F: FnMut(Range<usize>, Result<char, EscapeError>),
-{
-    assert!(mode.in_double_quotes());
-    let initial_len = literal_text.len();
-
-    let mut chars = literal_text.chars();
-    while let Some(curr) = chars.next() {
-        let start = initial_len - chars.as_str().len() - curr.len_utf8();
-
-        let result = match (curr, chars.clone().next()) {
-            ('\r', Some('\n')) => {
-                chars.next();
-                Ok('\n')
-            },
-            ('\r', _) => Err(EscapeError::BareCarriageReturnInRawString),
-            (c, _) if mode.is_bytes() && !c.is_ascii() =>
-                Err(EscapeError::NonAsciiCharInByteString),
-            (c, _) => Ok(c),
-        };
-        let end = initial_len - chars.as_str().len();
-
-        callback(start..end, result);
-    }
-}
-
-fn byte_from_char(c: char) -> u8 {
-    let res = c as u32;
-    assert!(res <= u8::max_value() as u32, "guaranteed because of Mode::Byte(Str)");
-    res as u8
-}
-
-fn is_ascii(x: u32) -> bool {
-    x <= 0x7F
-}
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-
-    #[test]
-    fn test_unescape_char_bad() {
-        fn check(literal_text: &str, expected_error: EscapeError) {
-            let actual_result = unescape_char(literal_text).map_err(|(_offset, err)| err);
-            assert_eq!(actual_result, Err(expected_error));
-        }
-
-        check("", EscapeError::ZeroChars);
-        check(r"\", EscapeError::LoneSlash);
-
-        check("\n", EscapeError::EscapeOnlyChar);
-        check("\r\n", EscapeError::EscapeOnlyChar);
-        check("\t", EscapeError::EscapeOnlyChar);
-        check("'", EscapeError::EscapeOnlyChar);
-        check("\r", EscapeError::BareCarriageReturn);
-
-        check("spam", EscapeError::MoreThanOneChar);
-        check(r"\x0ff", EscapeError::MoreThanOneChar);
-        check(r#"\"a"#, EscapeError::MoreThanOneChar);
-        check(r"\na", EscapeError::MoreThanOneChar);
-        check(r"\ra", EscapeError::MoreThanOneChar);
-        check(r"\ta", EscapeError::MoreThanOneChar);
-        check(r"\\a", EscapeError::MoreThanOneChar);
-        check(r"\'a", EscapeError::MoreThanOneChar);
-        check(r"\0a", EscapeError::MoreThanOneChar);
-        check(r"\u{0}x", EscapeError::MoreThanOneChar);
-        check(r"\u{1F63b}}", EscapeError::MoreThanOneChar);
-
-        check(r"\v", EscapeError::InvalidEscape);
-        check(r"\💩", EscapeError::InvalidEscape);
-        check(r"\●", EscapeError::InvalidEscape);
-
-        check(r"\x", EscapeError::TooShortHexEscape);
-        check(r"\x0", EscapeError::TooShortHexEscape);
-        check(r"\xf", EscapeError::TooShortHexEscape);
-        check(r"\xa", EscapeError::TooShortHexEscape);
-        check(r"\xx", EscapeError::InvalidCharInHexEscape);
-        check(r"\xы", EscapeError::InvalidCharInHexEscape);
-        check(r"\x🦀", EscapeError::InvalidCharInHexEscape);
-        check(r"\xtt", EscapeError::InvalidCharInHexEscape);
-        check(r"\xff", EscapeError::OutOfRangeHexEscape);
-        check(r"\xFF", EscapeError::OutOfRangeHexEscape);
-        check(r"\x80", EscapeError::OutOfRangeHexEscape);
-
-        check(r"\u", EscapeError::NoBraceInUnicodeEscape);
-        check(r"\u[0123]", EscapeError::NoBraceInUnicodeEscape);
-        check(r"\u{0x}", EscapeError::InvalidCharInUnicodeEscape);
-        check(r"\u{", EscapeError::UnclosedUnicodeEscape);
-        check(r"\u{0000", EscapeError::UnclosedUnicodeEscape);
-        check(r"\u{}", EscapeError::EmptyUnicodeEscape);
-        check(r"\u{_0000}", EscapeError::LeadingUnderscoreUnicodeEscape);
-        check(r"\u{0000000}", EscapeError::OverlongUnicodeEscape);
-        check(r"\u{FFFFFF}", EscapeError::OutOfRangeUnicodeEscape);
-        check(r"\u{ffffff}", EscapeError::OutOfRangeUnicodeEscape);
-        check(r"\u{ffffff}", EscapeError::OutOfRangeUnicodeEscape);
-
-        check(r"\u{DC00}", EscapeError::LoneSurrogateUnicodeEscape);
-        check(r"\u{DDDD}", EscapeError::LoneSurrogateUnicodeEscape);
-        check(r"\u{DFFF}", EscapeError::LoneSurrogateUnicodeEscape);
-
-        check(r"\u{D800}", EscapeError::LoneSurrogateUnicodeEscape);
-        check(r"\u{DAAA}", EscapeError::LoneSurrogateUnicodeEscape);
-        check(r"\u{DBFF}", EscapeError::LoneSurrogateUnicodeEscape);
-    }
-
-    #[test]
-    fn test_unescape_char_good() {
-        fn check(literal_text: &str, expected_char: char) {
-            let actual_result = unescape_char(literal_text);
-            assert_eq!(actual_result, Ok(expected_char));
-        }
-
-        check("a", 'a');
-        check("ы", 'ы');
-        check("🦀", '🦀');
-
-        check(r#"\""#, '"');
-        check(r"\n", '\n');
-        check(r"\r", '\r');
-        check(r"\t", '\t');
-        check(r"\\", '\\');
-        check(r"\'", '\'');
-        check(r"\0", '\0');
-
-        check(r"\x00", '\0');
-        check(r"\x5a", 'Z');
-        check(r"\x5A", 'Z');
-        check(r"\x7f", 127 as char);
-
-        check(r"\u{0}", '\0');
-        check(r"\u{000000}", '\0');
-        check(r"\u{41}", 'A');
-        check(r"\u{0041}", 'A');
-        check(r"\u{00_41}", 'A');
-        check(r"\u{4__1__}", 'A');
-        check(r"\u{1F63b}", '😻');
-    }
-
-    #[test]
-    fn test_unescape_str_good() {
-        fn check(literal_text: &str, expected: &str) {
-            let mut buf = Ok(String::with_capacity(literal_text.len()));
-            unescape_str(literal_text, &mut |range, c| {
-                if let Ok(b) = &mut buf {
-                    match c {
-                        Ok(c) => b.push(c),
-                        Err(e) => buf = Err((range, e)),
-                    }
-                }
-            });
-            let buf = buf.as_ref().map(|it| it.as_ref());
-            assert_eq!(buf, Ok(expected))
-        }
-
-        check("foo", "foo");
-        check("", "");
-        check(" \t\n\r\n", " \t\n\n");
-
-        check("hello \\\n     world", "hello world");
-        check("hello \\\r\n     world", "hello world");
-        check("thread's", "thread's")
-    }
-
-    #[test]
-    fn test_unescape_byte_bad() {
-        fn check(literal_text: &str, expected_error: EscapeError) {
-            let actual_result = unescape_byte(literal_text).map_err(|(_offset, err)| err);
-            assert_eq!(actual_result, Err(expected_error));
-        }
-
-        check("", EscapeError::ZeroChars);
-        check(r"\", EscapeError::LoneSlash);
-
-        check("\n", EscapeError::EscapeOnlyChar);
-        check("\r\n", EscapeError::EscapeOnlyChar);
-        check("\t", EscapeError::EscapeOnlyChar);
-        check("'", EscapeError::EscapeOnlyChar);
-        check("\r", EscapeError::BareCarriageReturn);
-
-        check("spam", EscapeError::MoreThanOneChar);
-        check(r"\x0ff", EscapeError::MoreThanOneChar);
-        check(r#"\"a"#, EscapeError::MoreThanOneChar);
-        check(r"\na", EscapeError::MoreThanOneChar);
-        check(r"\ra", EscapeError::MoreThanOneChar);
-        check(r"\ta", EscapeError::MoreThanOneChar);
-        check(r"\\a", EscapeError::MoreThanOneChar);
-        check(r"\'a", EscapeError::MoreThanOneChar);
-        check(r"\0a", EscapeError::MoreThanOneChar);
-
-        check(r"\v", EscapeError::InvalidEscape);
-        check(r"\💩", EscapeError::InvalidEscape);
-        check(r"\●", EscapeError::InvalidEscape);
-
-        check(r"\x", EscapeError::TooShortHexEscape);
-        check(r"\x0", EscapeError::TooShortHexEscape);
-        check(r"\xa", EscapeError::TooShortHexEscape);
-        check(r"\xf", EscapeError::TooShortHexEscape);
-        check(r"\xx", EscapeError::InvalidCharInHexEscape);
-        check(r"\xы", EscapeError::InvalidCharInHexEscape);
-        check(r"\x🦀", EscapeError::InvalidCharInHexEscape);
-        check(r"\xtt", EscapeError::InvalidCharInHexEscape);
-
-        check(r"\u", EscapeError::NoBraceInUnicodeEscape);
-        check(r"\u[0123]", EscapeError::NoBraceInUnicodeEscape);
-        check(r"\u{0x}", EscapeError::InvalidCharInUnicodeEscape);
-        check(r"\u{", EscapeError::UnclosedUnicodeEscape);
-        check(r"\u{0000", EscapeError::UnclosedUnicodeEscape);
-        check(r"\u{}", EscapeError::EmptyUnicodeEscape);
-        check(r"\u{_0000}", EscapeError::LeadingUnderscoreUnicodeEscape);
-        check(r"\u{0000000}", EscapeError::OverlongUnicodeEscape);
-
-        check("ы", EscapeError::NonAsciiCharInByte);
-        check("🦀", EscapeError::NonAsciiCharInByte);
-
-        check(r"\u{0}", EscapeError::UnicodeEscapeInByte);
-        check(r"\u{000000}", EscapeError::UnicodeEscapeInByte);
-        check(r"\u{41}", EscapeError::UnicodeEscapeInByte);
-        check(r"\u{0041}", EscapeError::UnicodeEscapeInByte);
-        check(r"\u{00_41}", EscapeError::UnicodeEscapeInByte);
-        check(r"\u{4__1__}", EscapeError::UnicodeEscapeInByte);
-        check(r"\u{1F63b}", EscapeError::UnicodeEscapeInByte);
-        check(r"\u{0}x", EscapeError::UnicodeEscapeInByte);
-        check(r"\u{1F63b}}", EscapeError::UnicodeEscapeInByte);
-        check(r"\u{FFFFFF}", EscapeError::UnicodeEscapeInByte);
-        check(r"\u{ffffff}", EscapeError::UnicodeEscapeInByte);
-        check(r"\u{ffffff}", EscapeError::UnicodeEscapeInByte);
-        check(r"\u{DC00}", EscapeError::UnicodeEscapeInByte);
-        check(r"\u{DDDD}", EscapeError::UnicodeEscapeInByte);
-        check(r"\u{DFFF}", EscapeError::UnicodeEscapeInByte);
-        check(r"\u{D800}", EscapeError::UnicodeEscapeInByte);
-        check(r"\u{DAAA}", EscapeError::UnicodeEscapeInByte);
-        check(r"\u{DBFF}", EscapeError::UnicodeEscapeInByte);
-    }
-
-    #[test]
-    fn test_unescape_byte_good() {
-        fn check(literal_text: &str, expected_byte: u8) {
-            let actual_result = unescape_byte(literal_text);
-            assert_eq!(actual_result, Ok(expected_byte));
-        }
-
-        check("a", b'a');
-
-        check(r#"\""#, b'"');
-        check(r"\n", b'\n');
-        check(r"\r", b'\r');
-        check(r"\t", b'\t');
-        check(r"\\", b'\\');
-        check(r"\'", b'\'');
-        check(r"\0", b'\0');
-
-        check(r"\x00", b'\0');
-        check(r"\x5a", b'Z');
-        check(r"\x5A", b'Z');
-        check(r"\x7f", 127);
-        check(r"\x80", 128);
-        check(r"\xff", 255);
-        check(r"\xFF", 255);
-    }
-
-    #[test]
-    fn test_unescape_byte_str_good() {
-        fn check(literal_text: &str, expected: &[u8]) {
-            let mut buf = Ok(Vec::with_capacity(literal_text.len()));
-            unescape_byte_str(literal_text, &mut |range, c| {
-                if let Ok(b) = &mut buf {
-                    match c {
-                        Ok(c) => b.push(c),
-                        Err(e) => buf = Err((range, e)),
-                    }
-                }
-            });
-            let buf = buf.as_ref().map(|it| it.as_ref());
-            assert_eq!(buf, Ok(expected))
-        }
-
-        check("foo", b"foo");
-        check("", b"");
-        check(" \t\n\r\n", b" \t\n\n");
-
-        check("hello \\\n     world", b"hello world");
-        check("hello \\\r\n     world", b"hello world");
-        check("thread's", b"thread's")
-    }
-
-    #[test]
-    fn test_unescape_raw_str() {
-        fn check(literal: &str, expected: &[(Range<usize>, Result<char, EscapeError>)]) {
-            let mut unescaped = Vec::with_capacity(literal.len());
-            unescape_raw_str(literal, &mut |range, res| unescaped.push((range, res)));
-            assert_eq!(unescaped, expected);
-        }
-
-        check("\r\n", &[(0..2, Ok('\n'))]);
-        check("\r", &[(0..1, Err(EscapeError::BareCarriageReturnInRawString))]);
-        check("\rx", &[(0..1, Err(EscapeError::BareCarriageReturnInRawString)), (1..2, Ok('x'))]);
-    }
-
-    #[test]
-    fn test_unescape_raw_byte_str() {
-        fn check(literal: &str, expected: &[(Range<usize>, Result<u8, EscapeError>)]) {
-            let mut unescaped = Vec::with_capacity(literal.len());
-            unescape_raw_byte_str(literal, &mut |range, res| unescaped.push((range, res)));
-            assert_eq!(unescaped, expected);
-        }
-
-        check("\r\n", &[(0..2, Ok(byte_from_char('\n')))]);
-        check("\r", &[(0..1, Err(EscapeError::BareCarriageReturnInRawString))]);
-        check("🦀", &[(0..4, Err(EscapeError::NonAsciiCharInByteString))]);
-        check(
-            "🦀a",
-            &[(0..4, Err(EscapeError::NonAsciiCharInByteString)), (4..5, Ok(byte_from_char('a')))],
-        );
-    }
-}
index 71b41161ad8c6fd00553ad0f21e526a818e04c42..bc3ee8620e06835f96c150c122347b4553c97016 100644 (file)
@@ -3,12 +3,11 @@
 use std::ops::Range;
 use std::iter::once;
 
+use rustc_lexer::unescape::{EscapeError, Mode};
 use syntax_pos::{Span, BytePos};
 
 use crate::errors::{Handler, Applicability};
 
-use super::unescape::{EscapeError, Mode};
-
 pub(crate) fn emit_unescape_error(
     handler: &Handler,
     // interior part of the literal, without quotes
index 2d296147a1ff28ccfc663414be070942c10d333a..e53660b656865ddb87f29650eb1c364da43b4dd3 100644 (file)
@@ -141,7 +141,10 @@ fn parse_args<'a>(
 
     while p.token != token::Eof {
         if !p.eat(&token::Comma) {
-            return Err(ecx.struct_span_err(p.token.span, "expected token: `,`"));
+            let mut err = ecx.struct_span_err(p.token.span, "expected token: `,`");
+            err.span_label(p.token.span, "expected `,`");
+            p.maybe_annotate_with_ascription(&mut err, false);
+            return Err(err);
         }
         if p.token == token::Eof {
             break;
index da0f8ca6da0908121f7a213caa8f10e5a04795f8..7de90278ed732a55ca4a79d02b17b29d2a690100 100644 (file)
@@ -12,6 +12,7 @@
 #![feature(decl_macro)]
 #![feature(nll)]
 #![feature(rustc_diagnostic_macros)]
+#![feature(unicode_internals)]
 
 #![recursion_limit="256"]
 
index 9b70a40458287c08127f2ce5433b1b7b666c4db4..14d65bef8f6dd41aede5b5550bc9ff90edf25fea 100644 (file)
@@ -25,9 +25,9 @@ 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 is in this configuration
-# file below. When uncommented this will instruct the bootstrap.py script to
-# download from dev-static.rust-lang.org.
+# 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.
 #
 # This key is typically commented out at all times. If you're looking at a
 # stable release tarball it should *definitely* be commented out. If you're
index 10fb03c39302b470f85d4927e0d96c2ec31901ef..0f81fc41823ba13654876ff35bff907c1fe5a042 100644 (file)
@@ -4,6 +4,6 @@
 static A: System = System;
 #[global_allocator]
 static B: System = System;
-//~^ ERROR: cannot define more than one #[global_allocator]
+//~^ ERROR: cannot define more than one `#[global_allocator]`
 
 fn main() {}
index da247f6c316c311ee4552ef5955d53f1b289dc3f..6b0c2b2a25d38516d5d66c5c6223da5149937b5e 100644 (file)
@@ -1,4 +1,4 @@
-error: cannot define more than one #[global_allocator]
+error: cannot define more than one `#[global_allocator]`
   --> $DIR/two-allocators.rs:6:1
    |
 LL | static B: System = System;
index c424eb08a7a98abe8af0bc4f8b9e3cec2b8218ca..5b01314d8ad4ff3f85375a0577b58c9184b21c12 100644 (file)
@@ -10,13 +10,13 @@ error: expected token: `,`
   --> $DIR/bad-format-args.rs:3:16
    |
 LL |     format!("" 1);
-   |                ^
+   |                ^ expected `,`
 
 error: expected token: `,`
   --> $DIR/bad-format-args.rs:4:19
    |
 LL |     format!("", 1 1);
-   |                   ^
+   |                   ^ expected `,`
 
 error: aborting due to 3 previous errors
 
index 1a16aab6a41d1218e9c010c8b8fc314498d17c41..beb8941320bc2d83bb20dc4420345200a0b01480 100644 (file)
@@ -11,7 +11,10 @@ error[E0121]: the type placeholder `_` is not allowed within types on item signa
   --> $DIR/E0121.rs:3:13
    |
 LL | static BAR: _ = "test";
-   |             ^ not allowed in type signatures
+   |             ^
+   |             |
+   |             not allowed in type signatures
+   |             help: replace `_` with the correct type: `&'static str`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/existential-type/issue-58887.rs b/src/test/ui/existential-type/issue-58887.rs
new file mode 100644 (file)
index 0000000..f038648
--- /dev/null
@@ -0,0 +1,23 @@
+#![feature(existential_type)]
+
+trait UnwrapItemsExt {
+    type Iter;
+    fn unwrap_items(self) -> Self::Iter;
+}
+
+impl<I, T, E> UnwrapItemsExt for I
+where
+    I: Iterator<Item = Result<T, E>>,
+    E: std::fmt::Debug,
+{
+    existential type Iter: Iterator<Item = T>;
+    //~^ ERROR: could not find defining uses
+
+    fn unwrap_items(self) -> Self::Iter {
+    //~^ ERROR: type parameter `T` is part of concrete type
+    //~| ERROR: type parameter `E` is part of concrete type
+        self.map(|x| x.unwrap())
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/existential-type/issue-58887.stderr b/src/test/ui/existential-type/issue-58887.stderr
new file mode 100644 (file)
index 0000000..800f4b7
--- /dev/null
@@ -0,0 +1,30 @@
+error: type parameter `T` is part of concrete type but not used in parameter list for existential type
+  --> $DIR/issue-58887.rs:16:41
+   |
+LL |       fn unwrap_items(self) -> Self::Iter {
+   |  _________________________________________^
+LL | |
+LL | |
+LL | |         self.map(|x| x.unwrap())
+LL | |     }
+   | |_____^
+
+error: type parameter `E` is part of concrete type but not used in parameter list for existential type
+  --> $DIR/issue-58887.rs:16:41
+   |
+LL |       fn unwrap_items(self) -> Self::Iter {
+   |  _________________________________________^
+LL | |
+LL | |
+LL | |         self.map(|x| x.unwrap())
+LL | |     }
+   | |_____^
+
+error: could not find defining uses
+  --> $DIR/issue-58887.rs:13:5
+   |
+LL |     existential type Iter: Iterator<Item = T>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/feature-gate/rustc-private.rs b/src/test/ui/feature-gate/rustc-private.rs
new file mode 100644 (file)
index 0000000..7b8944b
--- /dev/null
@@ -0,0 +1,5 @@
+// gate-test-rustc_private
+
+extern crate libc; //~ ERROR  use of unstable library feature 'rustc_private'
+
+fn main() {}
diff --git a/src/test/ui/feature-gate/rustc-private.stderr b/src/test/ui/feature-gate/rustc-private.stderr
new file mode 100644 (file)
index 0000000..be32071
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead?
+  --> $DIR/rustc-private.rs:3:1
+   |
+LL | extern crate libc;
+   | ^^^^^^^^^^^^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/27812
+   = help: add `#![feature(rustc_private)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/hrtb/issue-62203-hrtb-ice.rs b/src/test/ui/hrtb/issue-62203-hrtb-ice.rs
new file mode 100644 (file)
index 0000000..454d7e5
--- /dev/null
@@ -0,0 +1,50 @@
+trait T0<'a, A> {
+    type O;
+}
+
+struct L<T> {
+    f: T,
+}
+
+// explicitly named variants of what one would normally denote by the
+// unit type `()`. Why do this? So that we can differentiate them in
+// the diagnostic output.
+struct Unit1;
+struct Unit2;
+struct Unit3;
+struct Unit4;
+
+impl<'a, A, T> T0<'a, A> for L<T>
+where
+    T: FnMut(A) -> Unit3,
+{
+    type O = T::Output;
+}
+
+trait T1: for<'r> Ty<'r> {
+    fn m<'a, B: Ty<'a>, F>(&self, f: F) -> Unit1
+    where
+        F: for<'r> T0<'r, (<Self as Ty<'r>>::V,), O = <B as Ty<'r>>::V>,
+    {
+        unimplemented!();
+    }
+}
+
+trait Ty<'a> {
+    type V;
+}
+
+fn main() {
+    let v = Unit2.m(
+        //~^ ERROR type mismatch
+        //~| ERROR type mismatch
+        L {
+            f : |x| { drop(x); Unit4 }
+        });
+}
+
+impl<'a> Ty<'a> for Unit2 {
+    type V = &'a u8;
+}
+
+impl T1 for Unit2 {}
diff --git a/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr b/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr
new file mode 100644 (file)
index 0000000..c2d0e0c
--- /dev/null
@@ -0,0 +1,22 @@
+error[E0271]: type mismatch resolving `for<'r> <L<[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:39]> as T0<'r, (<Unit2 as Ty<'r>>::V,)>>::O == <_ as Ty<'r>>::V`
+  --> $DIR/issue-62203-hrtb-ice.rs:38:19
+   |
+LL |     let v = Unit2.m(
+   |                   ^ expected struct `Unit4`, found associated type
+   |
+   = note: expected type `Unit4`
+              found type `<_ as Ty<'_>>::V`
+
+error[E0271]: type mismatch resolving `<[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:39] as std::ops::FnOnce<((&u8,),)>>::Output == Unit3`
+  --> $DIR/issue-62203-hrtb-ice.rs:38:19
+   |
+LL |     let v = Unit2.m(
+   |                   ^ expected struct `Unit4`, found struct `Unit3`
+   |
+   = note: expected type `Unit4`
+              found type `Unit3`
+   = note: required because of the requirements on the impl of `for<'r> T0<'r, (<Unit2 as Ty<'r>>::V,)>` for `L<[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:39]>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0271`.
index 4f0dc0a48876507581ba75d6a65186fb6d590477..0fe167963c3f4b3f84d680d081f078115c928a6f 100644 (file)
@@ -87,15 +87,12 @@ error: expected type, found `4`
   --> $DIR/issue-22644.rs:34:28
    |
 LL |     println!("{}", a: &mut 4);
-   |                            ^ expecting a type here because of type ascription
+   |                     -      ^ expected type
+   |                     |
+   |                     tried to parse a type due to this type ascription
    |
    = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `<expr>: <type>`
-note: this expression expects an ascribed type after the colon
-  --> $DIR/issue-22644.rs:34:20
-   |
-LL |     println!("{}", a: &mut 4);
-   |                    ^
-   = help: this might be indicative of a syntax error elsewhere
+   = note: for more information, see https://github.com/rust-lang/rust/issues/23416
 
 error: aborting due to 9 previous errors
 
index 0218a7abeaa4c8a4e6a39a433ac1fdc6f56aa646..acb093b51428b3ab5b4b57418266c8c8ac08f634 100644 (file)
@@ -2,15 +2,12 @@ error: expected type, found `42`
   --> $DIR/issue-34255-1.rs:8:24
    |
 LL |     Test::Drill(field: 42);
-   |                        ^^ expecting a type here because of type ascription
+   |                      - ^^ expected type
+   |                      |
+   |                      tried to parse a type due to this type ascription
    |
    = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `<expr>: <type>`
-note: this expression expects an ascribed type after the colon
-  --> $DIR/issue-34255-1.rs:8:17
-   |
-LL |     Test::Drill(field: 42);
-   |                 ^^^^^
-   = help: this might be indicative of a syntax error elsewhere
+   = note: for more information, see https://github.com/rust-lang/rust/issues/23416
 
 error: aborting due to previous error
 
index e24ffcdb0d990a3c6521248aa555fa327e2c9d7d..75eb55fa50bb33e5531210a355861e0bf6684130 100644 (file)
@@ -2,7 +2,7 @@ error: expected type, found `0`
   --> $DIR/issue-39616.rs:1:12
    |
 LL | fn foo(a: [0; 1]) {}
-   |            ^
+   |            ^ expected type
 
 error: expected one of `)`, `,`, `->`, `where`, or `{`, found `]`
   --> $DIR/issue-39616.rs:1:16
index 14b3b8cc5c85d04b8a64c6b847031e9373bdb27c..108542c9b6f135b3dd91162bcd17d671a5416ff4 100644 (file)
@@ -15,7 +15,10 @@ LL |         bar(baz: $rest)
    |                - help: try using a semicolon: `;`
 ...
 LL |     foo!(true);
-   |          ^^^^ expecting a type here because of type ascription
+   |          ^^^^ expected type
+   |
+   = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `<expr>: <type>`
+   = note: for more information, see https://github.com/rust-lang/rust/issues/23416
 
 error: aborting due to 2 previous errors
 
index 84e4c87ebc4daa215f691aeb408debbc5188d2e8..bacba10b55fba490dafb837daf829e6f5f4a8de9 100644 (file)
@@ -12,15 +12,12 @@ error: expected type, found keyword `loop`
   --> $DIR/lifetime_starts_expressions.rs:6:26
    |
 LL |     loop { break 'label: loop { break 'label 42; }; }
-   |                          ^^^^ expecting a type here because of type ascription
+   |                        - ^^^^ expected type
+   |                        |
+   |                        tried to parse a type due to this type ascription
    |
    = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `<expr>: <type>`
-note: this expression expects an ascribed type after the colon
-  --> $DIR/lifetime_starts_expressions.rs:6:12
-   |
-LL |     loop { break 'label: loop { break 'label 42; }; }
-   |            ^^^^^^^^^^^^
-   = help: this might be indicative of a syntax error elsewhere
+   = note: for more information, see https://github.com/rust-lang/rust/issues/23416
 
 error: aborting due to 2 previous errors
 
index d5b6d86b20ff16c394ef599fb7d425c89fe3d17f..f96848f8239f7ec437b017814c51c014ecea4b60 100644 (file)
@@ -2,7 +2,7 @@ error: expected token: `,`
   --> $DIR/missing-comma.rs:19:19
    |
 LL |     println!("{}" a);
-   |                   ^
+   |                   ^ expected `,`
 
 error: no rules expected the token `b`
   --> $DIR/missing-comma.rs:21:12
index c2491df903b76f0e1964701a5d480cf41267c349..2aff328393538c0031c1df39ce7706c693cc8452 100644 (file)
@@ -2,7 +2,7 @@ error: expected type, found `{`
   --> $DIR/issue-33262.rs:4:22
    |
 LL |     for i in 0..a as { }
-   |                      ^
+   |                      ^ expected type
 
 error: aborting due to previous error
 
index 19c5c82f82cd22d65d84e3a975c36bd35645a375..f02f60e4bfb1df142f74a4886049a65d524b500e 100644 (file)
@@ -2,7 +2,7 @@ error: expected type, found `'static`
   --> $DIR/trait-object-macro-matcher.rs:9:8
    |
 LL |     m!('static);
-   |        ^^^^^^^
+   |        ^^^^^^^ expected type
 
 error: aborting due to previous error
 
index 9ed2e6f5eb6c4e26e384bd7abc8b0ef95d35d18e..2311887a6fb36d35e6177d7c6da3bb10776084b9 100644 (file)
@@ -2,7 +2,7 @@ error: expected type, found `{`
   --> $DIR/recover-enum2.rs:6:18
    |
 LL |             abc: {},
-   |                  ^
+   |                  ^ expected type
 
 error: expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `{`
   --> $DIR/recover-enum2.rs:25:22
index d525bd3f4c6e5fee5e26c4b8466c158d3f282cfa..b46d3ca9c233ca2371fe33c3d989f57ca13a72a0 100644 (file)
@@ -2,15 +2,12 @@ error: expected type, found `3`
   --> $DIR/recover-from-bad-variant.rs:7:26
    |
 LL |     let x = Enum::Foo(a: 3, b: 4);
-   |                          ^ expecting a type here because of type ascription
+   |                        - ^ expected type
+   |                        |
+   |                        tried to parse a type due to this type ascription
    |
    = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `<expr>: <type>`
-note: this expression expects an ascribed type after the colon
-  --> $DIR/recover-from-bad-variant.rs:7:23
-   |
-LL |     let x = Enum::Foo(a: 3, b: 4);
-   |                       ^
-   = help: this might be indicative of a syntax error elsewhere
+   = note: for more information, see https://github.com/rust-lang/rust/issues/23416
 
 error[E0532]: expected tuple struct/variant, found struct variant `Enum::Foo`
   --> $DIR/recover-from-bad-variant.rs:10:9
index a759716b5a96384caa283ef53ddefe59832c1bd1..02b518e251678a718703c171590878175cac2b7c 100644 (file)
@@ -2,7 +2,7 @@ error: expected type, found keyword `mut`
   --> $DIR/removed-syntax-mut-vec-ty.rs:1:11
    |
 LL | type v = [mut isize];
-   |           ^^^
+   |           ^^^ expected type
 
 error: aborting due to previous error
 
index 730d5e2712b96e39bab7c48f8c51299814362f68..0a1655840b5509752ac70a4c634598976c98b55e 100644 (file)
@@ -2,7 +2,7 @@ error: expected type, found `{`
   --> $DIR/removed-syntax-record.rs:1:10
    |
 LL | type t = { f: () };
-   |          ^
+   |          ^ expected type
 
 error: aborting due to previous error
 
index a31b7aea8fee6f9d0117aece4e62e45dfa6e2462..7ffc26e9edead1542253912856dff347ae444faa 100644 (file)
@@ -29,7 +29,7 @@ error: expected type, found `'a`
   --> $DIR/trait-object-lifetime-parens.rs:9:17
    |
 LL |     let _: Box<('a) + Trait>;
-   |         -       ^^
+   |         -       ^^ expected type
    |         |
    |         while parsing the type for `_`
 
index ef0ba70c34066e1b9dce4aaa8599f68a332afc6d..b4338e2055431f74c9a3370704e9b067c9b9196b 100644 (file)
@@ -23,9 +23,7 @@ LL | enum Shape {
    | ---------- variant `Rombus` not found here
 ...
 LL |     println!("My shape is {:?}", Shape::Rombus{ size: 5});
-   |                                  -------^^^^^^
-   |                                  |
-   |                                  variant not found in `Shape`
+   |                                         ^^^^^^ variant not found in `Shape`
 
 error[E0599]: no variant or associated item named `Squareee` found for type `Shape` in the current scope
   --> $DIR/suggest-variants.rs:15:12
index 15ec087b1cc01d790083c55d356776c1fe2e037f..4a8d2f57d89d388a55552ab5c12a82a99009ad9f 100644 (file)
@@ -2,9 +2,12 @@ error: expected type, found `"foo"`
   --> $DIR/type-ascription-instead-of-method.rs:2:13
    |
 LL |     Box:new("foo".to_string())
-   |        -    ^^^^^ expecting a type here because of type ascription
+   |        -    ^^^^^ expected type
    |        |
-   |        help: maybe you meant to write a path separator here: `::`
+   |        help: maybe write a path separator here: `::`
+   |
+   = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `<expr>: <type>`
+   = note: for more information, see https://github.com/rust-lang/rust/issues/23416
 
 error: aborting due to previous error
 
index 5719a667a841509b4f16a3425f5d45930b019649..7e9a31c06c8b249169fa5b6a343fbbad68d115a0 100644 (file)
@@ -2,9 +2,12 @@ error: expected type, found `""`
   --> $DIR/type-ascription-instead-of-variant.rs:2:25
    |
 LL |     let _ = Option:Some("");
-   |                   -     ^^ expecting a type here because of type ascription
+   |                   -     ^^ expected type
    |                   |
-   |                   help: maybe you meant to write a path separator here: `::`
+   |                   help: maybe write a path separator here: `::`
+   |
+   = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `<expr>: <type>`
+   = note: for more information, see https://github.com/rust-lang/rust/issues/23416
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/type/ascription/issue-34255-1.rs b/src/test/ui/type/ascription/issue-34255-1.rs
new file mode 100644 (file)
index 0000000..c11a248
--- /dev/null
@@ -0,0 +1,15 @@
+struct Reactor {
+    input_cells: Vec<usize>,
+}
+
+impl Reactor {
+    pub fn new() -> Self {
+        input_cells: Vec::new()
+        //~^ ERROR cannot find value `input_cells` in this scope
+        //~| ERROR parenthesized type parameters may only be used with a `Fn` trait
+        //~| ERROR wrong number of type arguments: expected 1, found 0
+        //~| WARNING this was previously accepted by the compiler but is being phased out
+    }
+}
+
+// This case isn't currently being handled gracefully, including for completeness.
diff --git a/src/test/ui/type/ascription/issue-34255-1.stderr b/src/test/ui/type/ascription/issue-34255-1.stderr
new file mode 100644 (file)
index 0000000..531455b
--- /dev/null
@@ -0,0 +1,30 @@
+error[E0425]: cannot find value `input_cells` in this scope
+  --> $DIR/issue-34255-1.rs:7:9
+   |
+LL |         input_cells: Vec::new()
+   |         ^^^^^^^^^^^ a field by this name exists in `Self`
+
+error: parenthesized type parameters may only be used with a `Fn` trait
+  --> $DIR/issue-34255-1.rs:7:30
+   |
+LL |         input_cells: Vec::new()
+   |                              ^^
+   |
+   = note: `#[deny(parenthesized_params_in_types_and_modules)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #42238 <https://github.com/rust-lang/rust/issues/42238>
+
+error[E0601]: `main` function not found in crate `issue_34255_1`
+   |
+   = note: consider adding a `main` function to `$DIR/issue-34255-1.rs`
+
+error[E0107]: wrong number of type arguments: expected 1, found 0
+  --> $DIR/issue-34255-1.rs:7:22
+   |
+LL |         input_cells: Vec::new()
+   |                      ^^^^^^^^^^ expected 1 type argument
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0107, E0425, E0601.
+For more information about an error, try `rustc --explain E0107`.
diff --git a/src/test/ui/type/ascription/issue-47666.rs b/src/test/ui/type/ascription/issue-47666.rs
new file mode 100644 (file)
index 0000000..ceb1dd8
--- /dev/null
@@ -0,0 +1,5 @@
+fn main() {
+    let _ = Option:Some(vec![0, 1]); //~ ERROR expected type, found
+}
+
+// This case isn't currently being handled gracefully due to the macro invocation.
diff --git a/src/test/ui/type/ascription/issue-47666.stderr b/src/test/ui/type/ascription/issue-47666.stderr
new file mode 100644 (file)
index 0000000..7aa899f
--- /dev/null
@@ -0,0 +1,13 @@
+error: expected type, found reserved keyword `box`
+  --> $DIR/issue-47666.rs:2:25
+   |
+LL |     let _ = Option:Some(vec![0, 1]);
+   |                         ^^^^^^^^^^
+   |                         |
+   |                         expected type
+   |                         in this macro invocation
+   |
+   = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/type/ascription/issue-54516.rs b/src/test/ui/type/ascription/issue-54516.rs
new file mode 100644 (file)
index 0000000..6d65760
--- /dev/null
@@ -0,0 +1,6 @@
+use std::collections::BTreeMap;
+
+fn main() {
+    println!("{}", std::mem:size_of::<BTreeMap<u32, u32>>());
+    //~^ ERROR expected token: `,`
+}
diff --git a/src/test/ui/type/ascription/issue-54516.stderr b/src/test/ui/type/ascription/issue-54516.stderr
new file mode 100644 (file)
index 0000000..a846f3b
--- /dev/null
@@ -0,0 +1,13 @@
+error: expected token: `,`
+  --> $DIR/issue-54516.rs:4:58
+   |
+LL |     println!("{}", std::mem:size_of::<BTreeMap<u32, u32>>());
+   |                            -                             ^ expected `,`
+   |                            |
+   |                            help: maybe write a path separator here: `::`
+   |
+   = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `<expr>: <type>`
+   = note: for more information, see https://github.com/rust-lang/rust/issues/23416
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/type/ascription/issue-60933.rs b/src/test/ui/type/ascription/issue-60933.rs
new file mode 100644 (file)
index 0000000..8fb06c8
--- /dev/null
@@ -0,0 +1,4 @@
+fn main() {
+    let u: usize = std::mem:size_of::<u32>();
+    //~^ ERROR expected one of
+}
diff --git a/src/test/ui/type/ascription/issue-60933.stderr b/src/test/ui/type/ascription/issue-60933.stderr
new file mode 100644 (file)
index 0000000..c2fc7bb
--- /dev/null
@@ -0,0 +1,13 @@
+error: expected one of `!`, `::`, or `;`, found `(`
+  --> $DIR/issue-60933.rs:2:43
+   |
+LL |     let u: usize = std::mem:size_of::<u32>();
+   |                            -              ^ expected one of `!`, `::`, or `;` here
+   |                            |
+   |                            help: maybe write a path separator here: `::`
+   |
+   = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `<expr>: <type>`
+   = note: for more information, see https://github.com/rust-lang/rust/issues/23416
+
+error: aborting due to previous error
+
index a22d25697d8bd5ffa6848cd4b16de4202165f400..3fe676de59dab2f1c6b60bcead98564a61e6bd35 100644 (file)
@@ -2,7 +2,7 @@ error: expected type, found `10`
   --> $DIR/type-ascription-instead-of-initializer.rs:2:31
    |
 LL |     let x: Vec::with_capacity(10, 20);
-   |         --                    ^^
+   |         --                    ^^ expected type
    |         ||
    |         |help: use `=` if you meant to assign
    |         while parsing the type for `x`
index 1f8989db81412856a61c3e4a9c45ee12ccfb085f..8fbcb3969a79aa616970023f4064a78ea13c294c 100644 (file)
@@ -4,21 +4,21 @@ error: expected type, found `0`
 LL |     println!("test"):
    |                     - help: try using a semicolon: `;`
 LL |     0;
-   |     ^ expecting a type here because of type ascription
+   |     ^ expected type
+   |
+   = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `<expr>: <type>`
+   = note: for more information, see https://github.com/rust-lang/rust/issues/23416
 
 error: expected type, found `0`
   --> $DIR/type-ascription-instead-of-statement-end.rs:9:23
    |
 LL |     println!("test"): 0;
-   |                       ^ expecting a type here because of type ascription
+   |                     - ^ expected type
+   |                     |
+   |                     tried to parse a type due to this type ascription
    |
    = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `<expr>: <type>`
-note: this expression expects an ascribed type after the colon
-  --> $DIR/type-ascription-instead-of-statement-end.rs:9:5
-   |
-LL |     println!("test"): 0;
-   |     ^^^^^^^^^^^^^^^^
-   = help: this might be indicative of a syntax error elsewhere
+   = note: for more information, see https://github.com/rust-lang/rust/issues/23416
 
 error: aborting due to 2 previous errors
 
index ddaa5de4d3e27f09783169ef4e29533d18913bd0..2b4d9966c3d0b50259e1f64cd57839b3085d7b2b 100644 (file)
@@ -23,13 +23,19 @@ error[E0121]: the type placeholder `_` is not allowed within types on item signa
   --> $DIR/typeck_type_placeholder_item.rs:11:15
    |
 LL | static TEST3: _ = "test";
-   |               ^ not allowed in type signatures
+   |               ^
+   |               |
+   |               not allowed in type signatures
+   |               help: replace `_` with the correct type: `&'static str`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item.rs:14:15
    |
 LL | static TEST4: _ = 145;
-   |               ^ not allowed in type signatures
+   |               ^
+   |               |
+   |               not allowed in type signatures
+   |               help: replace `_` with the correct type: `i32`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item.rs:17:16
@@ -122,13 +128,19 @@ error[E0121]: the type placeholder `_` is not allowed within types on item signa
   --> $DIR/typeck_type_placeholder_item.rs:64:22
    |
 LL |     static FN_TEST3: _ = "test";
-   |                      ^ not allowed in type signatures
+   |                      ^
+   |                      |
+   |                      not allowed in type signatures
+   |                      help: replace `_` with the correct type: `&'static str`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item.rs:67:22
    |
 LL |     static FN_TEST4: _ = 145;
-   |                      ^ not allowed in type signatures
+   |                      ^
+   |                      |
+   |                      not allowed in type signatures
+   |                      help: replace `_` with the correct type: `i32`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item.rs:70:23
index 5f4cb4c1316d54357082839f6f3e310b52774014..905fc35350ed02e4e38cce373dc99fcf578707c3 100644 (file)
@@ -4,6 +4,24 @@
 fn test1() -> _ { Some(42) }
 //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
 
+const TEST2: _ = 42u32;
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+
+const TEST3: _ = Some(42);
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+
+trait Test4 {
+    const TEST4: _ = 42;
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+}
+
+struct Test5;
+
+impl Test5 {
+    const TEST5: _ = 13;
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+}
+
 pub fn main() {
     let _: Option<usize> = test1();
     let _: f64 = test1();
index 7fb5549825cc5da42dc62f9840add630d66dfb7c..c5b9566290c114b9fb2de41a0b89b06921a4305e 100644 (file)
@@ -7,6 +7,42 @@ LL | fn test1() -> _ { Some(42) }
    |               not allowed in type signatures
    |               help: replace `_` with the correct return type: `std::option::Option<i32>`
 
-error: aborting due to previous error
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item_help.rs:7:14
+   |
+LL | const TEST2: _ = 42u32;
+   |              ^
+   |              |
+   |              not allowed in type signatures
+   |              help: replace `_` with the correct type: `u32`
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item_help.rs:10:14
+   |
+LL | const TEST3: _ = Some(42);
+   |              ^
+   |              |
+   |              not allowed in type signatures
+   |              help: replace `_` with the correct type: `std::option::Option<i32>`
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item_help.rs:14:18
+   |
+LL |     const TEST4: _ = 42;
+   |                  ^
+   |                  |
+   |                  not allowed in type signatures
+   |                  help: replace `_` with the correct type: `i32`
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item_help.rs:21:18
+   |
+LL |     const TEST5: _ = 13;
+   |                  ^
+   |                  |
+   |                  not allowed in type signatures
+   |                  help: replace `_` with the correct type: `i32`
+
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0121`.
index b5ddc94bf02c641e5acbb08ae742014f40347f10..b269bb07078446c9c153e0f2acaf83bf8f19b935 160000 (submodule)
@@ -1 +1 @@
-Subproject commit b5ddc94bf02c641e5acbb08ae742014f40347f10
+Subproject commit b269bb07078446c9c153e0f2acaf83bf8f19b935