]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #54802 - davidtwco:issue-53040, r=pnkfelix
authorbors <bors@rust-lang.org>
Wed, 10 Oct 2018 14:51:01 +0000 (14:51 +0000)
committerbors <bors@rust-lang.org>
Wed, 10 Oct 2018 14:51:01 +0000 (14:51 +0000)
[nll] better error message when returning refs to upvars

Fixes #53040.

r? @nikomatsakis

151 files changed:
src/bootstrap/lib.rs
src/bootstrap/sanity.rs
src/bootstrap/test.rs
src/liballoc/str.rs
src/liballoc/string.rs
src/librustc/ich/impls_ty.rs
src/librustc/mir/interpret/error.rs
src/librustc/mir/interpret/mod.rs
src/librustc/mir/interpret/value.rs
src/librustc/mir/visit.rs
src/librustc/ty/structural_impls.rs
src/librustc_codegen_llvm/mir/constant.rs
src/librustc_lint/builtin.rs
src/librustc_mir/borrow_check/mutability_errors.rs
src/librustc_mir/borrow_check/nll/renumber.rs
src/librustc_mir/build/matches/mod.rs
src/librustc_mir/const_eval.rs
src/librustc_mir/hair/cx/expr.rs
src/librustc_mir/hair/cx/mod.rs
src/librustc_mir/hair/mod.rs
src/librustc_mir/hair/pattern/mod.rs
src/librustc_mir/hair/util.rs [new file with mode: 0644]
src/librustc_mir/interpret/cast.rs
src/librustc_mir/interpret/eval_context.rs
src/librustc_mir/interpret/intrinsics.rs
src/librustc_mir/interpret/machine.rs
src/librustc_mir/interpret/memory.rs
src/librustc_mir/interpret/mod.rs
src/librustc_mir/interpret/operand.rs
src/librustc_mir/interpret/operator.rs
src/librustc_mir/interpret/place.rs
src/librustc_mir/interpret/snapshot.rs
src/librustc_mir/interpret/terminator.rs
src/librustc_mir/interpret/traits.rs
src/librustc_mir/interpret/validity.rs
src/librustc_mir/monomorphize/collector.rs
src/librustc_mir/transform/const_prop.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/demand.rs
src/librustc_typeck/check/mod.rs
src/test/debuginfo/associated-types.rs
src/test/debuginfo/basic-types.rs
src/test/debuginfo/borrowed-basic.rs
src/test/debuginfo/borrowed-c-style-enum.rs
src/test/debuginfo/borrowed-enum.rs
src/test/debuginfo/borrowed-struct.rs
src/test/debuginfo/borrowed-tuple.rs
src/test/debuginfo/borrowed-unique-basic.rs
src/test/debuginfo/box.rs
src/test/debuginfo/boxed-struct.rs
src/test/debuginfo/by-value-self-argument-in-trait-impl.rs
src/test/debuginfo/c-style-enum-in-composite.rs
src/test/debuginfo/c-style-enum.rs
src/test/debuginfo/closure-in-generic-function.rs
src/test/debuginfo/cross-crate-spans.rs
src/test/debuginfo/destructured-fn-argument.rs
src/test/debuginfo/destructured-for-loop-variable.rs
src/test/debuginfo/destructured-local.rs
src/test/debuginfo/evec-in-struct.rs
src/test/debuginfo/extern-c-fn.rs
src/test/debuginfo/function-arguments.rs
src/test/debuginfo/generic-function.rs
src/test/debuginfo/generic-functions-nested.rs
src/test/debuginfo/generic-method-on-generic-struct.rs
src/test/debuginfo/generic-struct.rs
src/test/debuginfo/generic-tuple-style-enum.rs
src/test/debuginfo/include_string.rs
src/test/debuginfo/issue-22656.rs
src/test/debuginfo/lexical-scope-in-for-loop.rs
src/test/debuginfo/lexical-scope-in-if.rs
src/test/debuginfo/lexical-scope-in-match.rs
src/test/debuginfo/lexical-scope-in-stack-closure.rs
src/test/debuginfo/lexical-scope-in-unconditional-loop.rs
src/test/debuginfo/lexical-scope-in-unique-closure.rs
src/test/debuginfo/lexical-scope-in-while.rs
src/test/debuginfo/lexical-scope-with-macro.rs
src/test/debuginfo/lexical-scopes-in-block-expression.rs
src/test/debuginfo/method-on-generic-struct.rs
src/test/debuginfo/method-on-struct.rs
src/test/debuginfo/method-on-trait.rs
src/test/debuginfo/method-on-tuple-struct.rs
src/test/debuginfo/multi-cgu.rs
src/test/debuginfo/multiple-functions-equal-var-names.rs
src/test/debuginfo/multiple-functions.rs
src/test/debuginfo/name-shadowing-and-scope-nesting.rs
src/test/debuginfo/packed-struct-with-destructor.rs
src/test/debuginfo/packed-struct.rs
src/test/debuginfo/self-in-default-method.rs
src/test/debuginfo/self-in-generic-default-method.rs
src/test/debuginfo/shadowed-argument.rs
src/test/debuginfo/shadowed-variable.rs
src/test/debuginfo/simple-lexical-scope.rs
src/test/debuginfo/simple-struct.rs
src/test/debuginfo/simple-tuple.rs
src/test/debuginfo/static-method-on-struct-and-enum.rs
src/test/debuginfo/struct-in-struct.rs
src/test/debuginfo/struct-namespace.rs
src/test/debuginfo/struct-style-enum.rs
src/test/debuginfo/struct-with-destructor.rs
src/test/debuginfo/tuple-in-tuple.rs
src/test/debuginfo/tuple-struct.rs
src/test/debuginfo/tuple-style-enum.rs
src/test/debuginfo/union-smoke.rs
src/test/debuginfo/unique-enum.rs
src/test/debuginfo/var-captured-in-nested-closure.rs
src/test/debuginfo/var-captured-in-sendable-closure.rs
src/test/debuginfo/var-captured-in-stack-closure.rs
src/test/debuginfo/vec-slices.rs
src/test/debuginfo/vec.rs
src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr
src/test/ui/consts/const-eval/transmute-const.rs
src/test/ui/consts/const-eval/ub-enum.stderr
src/test/ui/consts/const-eval/ub-nonnull.rs [new file with mode: 0644]
src/test/ui/consts/const-eval/ub-nonnull.stderr [new file with mode: 0644]
src/test/ui/consts/const-eval/ub-ref.rs [new file with mode: 0644]
src/test/ui/consts/const-eval/ub-ref.stderr [new file with mode: 0644]
src/test/ui/consts/const-eval/ub-uninhabit.rs
src/test/ui/consts/const-eval/ub-uninhabit.stderr
src/test/ui/consts/const-eval/ub-usize-in-ref.rs [deleted file]
src/test/ui/consts/const-eval/union-ice.stderr
src/test/ui/consts/const-eval/union-ub-fat-ptr.rs [new file with mode: 0644]
src/test/ui/consts/const-eval/union-ub-fat-ptr.stderr [new file with mode: 0644]
src/test/ui/consts/const-eval/union-ub.rs
src/test/ui/consts/const-eval/valid-const.rs [new file with mode: 0644]
src/test/ui/did_you_mean/issue-38147-2.nll.stderr
src/test/ui/did_you_mean/issue-38147-3.nll.stderr
src/test/ui/issues/issue-14227.rs
src/test/ui/issues/issue-14227.stderr
src/test/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.rs [new file with mode: 0644]
src/test/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.stderr [new file with mode: 0644]
src/test/ui/nll/user-annotations/pattern_substs_on_brace_struct.rs [new file with mode: 0644]
src/test/ui/nll/user-annotations/pattern_substs_on_brace_struct.stderr [new file with mode: 0644]
src/test/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.rs [new file with mode: 0644]
src/test/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.stderr [new file with mode: 0644]
src/test/ui/nll/user-annotations/pattern_substs_on_tuple_struct.rs [new file with mode: 0644]
src/test/ui/nll/user-annotations/pattern_substs_on_tuple_struct.stderr [new file with mode: 0644]
src/test/ui/range/issue-54505-no-literals.fixed [new file with mode: 0644]
src/test/ui/range/issue-54505-no-literals.rs [new file with mode: 0644]
src/test/ui/range/issue-54505-no-literals.stderr [new file with mode: 0644]
src/test/ui/range/issue-54505-no-std.rs [new file with mode: 0644]
src/test/ui/range/issue-54505-no-std.stderr [new file with mode: 0644]
src/test/ui/range/issue-54505.fixed [new file with mode: 0644]
src/test/ui/range/issue-54505.rs [new file with mode: 0644]
src/test/ui/range/issue-54505.stderr [new file with mode: 0644]
src/test/ui/union-ub-fat-ptr.rs [deleted file]
src/test/ui/union-ub-fat-ptr.stderr [deleted file]
src/tools/compiletest/src/common.rs
src/tools/compiletest/src/header.rs
src/tools/compiletest/src/main.rs
src/tools/compiletest/src/runtest.rs
src/tools/miri

index 75c18cd2dd41c81ac8041ce97a29524a4a5b36f5..247727762d16e7efcf1fbfa06e3ff14835b2a565 100644 (file)
@@ -278,10 +278,6 @@ pub struct Build {
     initial_rustc: PathBuf,
     initial_cargo: PathBuf,
 
-    // Probed tools at runtime
-    lldb_version: Option<String>,
-    lldb_python_dir: Option<String>,
-
     // Runtime state filled in later on
     // C/C++ compilers and archiver for all targets
     cc: HashMap<Interned<String>, cc::Tool>,
@@ -416,8 +412,6 @@ pub fn new(config: Config) -> Build {
             ar: HashMap::new(),
             ranlib: HashMap::new(),
             crates: HashMap::new(),
-            lldb_version: None,
-            lldb_python_dir: None,
             is_sudo,
             ci_env: CiEnv::current(),
             delayed_failures: RefCell::new(Vec::new()),
index c2610de23bebadf6678a5c5bf7187b3311398dd2..724cb5841f48f1e975861dede918b5d7bc71779e 100644 (file)
@@ -236,19 +236,6 @@ pub fn check(build: &mut Build) {
         }
     }
 
-    let run = |cmd: &mut Command| {
-        cmd.output().map(|output| {
-            String::from_utf8_lossy(&output.stdout)
-                   .lines().next().unwrap_or_else(|| {
-                       panic!("{:?} failed {:?}", cmd, output)
-                   }).to_string()
-        })
-    };
-    build.lldb_version = run(Command::new("lldb").arg("--version")).ok();
-    if build.lldb_version.is_some() {
-        build.lldb_python_dir = run(Command::new("lldb").arg("-P")).ok();
-    }
-
     if let Some(ref s) = build.config.ccache {
         cmd_finder.must_have(s);
     }
index 0c4816dc90458e291d28a9abd4cd82ef2a861ee8..633c15b54b9ef22298a6e7b47f862b57531ec399 100644 (file)
@@ -1082,11 +1082,34 @@ fn run(self, builder: &Builder) {
         if let Some(ref gdb) = builder.config.gdb {
             cmd.arg("--gdb").arg(gdb);
         }
-        if let Some(ref vers) = builder.lldb_version {
+
+        let run = |cmd: &mut Command| {
+            cmd.output().map(|output| {
+                String::from_utf8_lossy(&output.stdout)
+                    .lines().next().unwrap_or_else(|| {
+                        panic!("{:?} failed {:?}", cmd, output)
+                    }).to_string()
+            })
+        };
+        let lldb_exe = if builder.config.lldb_enabled && !target.contains("emscripten") {
+            // Test against the lldb that was just built.
+            builder.llvm_out(target)
+                .join("bin")
+                .join("lldb")
+        } else {
+            PathBuf::from("lldb")
+        };
+        let lldb_version = Command::new(&lldb_exe)
+            .arg("--version")
+            .output()
+            .map(|output| { String::from_utf8_lossy(&output.stdout).to_string() })
+            .ok();
+        if let Some(ref vers) = lldb_version {
             cmd.arg("--lldb-version").arg(vers);
-        }
-        if let Some(ref dir) = builder.lldb_python_dir {
-            cmd.arg("--lldb-python-dir").arg(dir);
+            let lldb_python_dir = run(Command::new(&lldb_exe).arg("-P")).ok();
+            if let Some(ref dir) = lldb_python_dir {
+                cmd.arg("--lldb-python-dir").arg(dir);
+            }
         }
 
         // Get paths from cmd args
index 2af89562d69fe1d0a6f37c07350c212117c8b131..9916fa639e1d484acbcea4ec7bafcb2a62327f3a 100644 (file)
@@ -203,6 +203,7 @@ fn borrow(&self) -> &str {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl ToOwned for str {
     type Owned = String;
+    #[inline]
     fn to_owned(&self) -> String {
         unsafe { String::from_utf8_unchecked(self.as_bytes().to_owned()) }
     }
index 837e17cf640173b127fce5cd2758c1ad361e9aa7..ab3f8fc27072071c754c842094d57b295e441dbc 100644 (file)
@@ -2196,6 +2196,7 @@ fn as_ref(&self) -> &[u8] {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> From<&'a str> for String {
+    #[inline]
     fn from(s: &'a str) -> String {
         s.to_owned()
     }
index 3ff0034fbbee7d850988e443c87c9922861c36e0..e8c89cb3e0e7eb17bdbb6b207855fb86699f2a18 100644 (file)
@@ -391,10 +391,39 @@ fn hash_stable<W: StableHasherResult>(&self,
     }
 }
 
-impl_stable_hash_for!(struct mir::interpret::Pointer {
-    alloc_id,
-    offset
-});
+impl<'a, Tag> HashStable<StableHashingContext<'a>>
+for ::mir::interpret::Pointer<Tag>
+where Tag: HashStable<StableHashingContext<'a>>
+{
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a>,
+                                          hasher: &mut StableHasher<W>) {
+        let ::mir::interpret::Pointer { alloc_id, offset, tag } = self;
+        alloc_id.hash_stable(hcx, hasher);
+        offset.hash_stable(hcx, hasher);
+        tag.hash_stable(hcx, hasher);
+    }
+}
+
+impl<'a, Tag> HashStable<StableHashingContext<'a>>
+for ::mir::interpret::Scalar<Tag>
+where Tag: HashStable<StableHashingContext<'a>>
+{
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a>,
+                                          hasher: &mut StableHasher<W>) {
+        use mir::interpret::Scalar::*;
+
+        mem::discriminant(self).hash_stable(hcx, hasher);
+        match self {
+            Bits { bits, size } => {
+                bits.hash_stable(hcx, hasher);
+                size.hash_stable(hcx, hasher);
+            },
+            Ptr(ptr) => ptr.hash_stable(hcx, hasher),
+        }
+    }
+}
 
 impl<'a> HashStable<StableHashingContext<'a>> for mir::interpret::AllocId {
     fn hash_stable<W: StableHasherResult>(
@@ -449,25 +478,6 @@ fn hash_stable<W: StableHasherResult>(
     Mutable
 });
 
-
-impl<'a> HashStable<StableHashingContext<'a>>
-for ::mir::interpret::Scalar {
-    fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a>,
-                                          hasher: &mut StableHasher<W>) {
-        use mir::interpret::Scalar::*;
-
-        mem::discriminant(self).hash_stable(hcx, hasher);
-        match *self {
-            Bits { bits, size } => {
-                bits.hash_stable(hcx, hasher);
-                size.hash_stable(hcx, hasher);
-            },
-            Ptr(ptr) => ptr.hash_stable(hcx, hasher),
-        }
-    }
-}
-
 impl_stable_hash_for!(struct ty::Const<'tcx> {
     ty,
     val
@@ -560,6 +570,10 @@ fn hash_stable<W: StableHasherResult>(&self,
                 a.hash_stable(hcx, hasher);
                 b.hash_stable(hcx, hasher)
             },
+            FunctionRetMismatch(a, b) => {
+                a.hash_stable(hcx, hasher);
+                b.hash_stable(hcx, hasher)
+            },
             NoMirFor(ref s) => s.hash_stable(hcx, hasher),
             UnterminatedCString(ptr) => ptr.hash_stable(hcx, hasher),
             PointerOutOfBounds {
index 566673857b975b14df86284a76cf19ecd5e12f18..fe466e247c91749b8f5a2f6dc1b5be7ead80b362 100644 (file)
@@ -186,6 +186,7 @@ pub enum EvalErrorKind<'tcx, O> {
 
     FunctionAbiMismatch(Abi, Abi),
     FunctionArgMismatch(Ty<'tcx>, Ty<'tcx>),
+    FunctionRetMismatch(Ty<'tcx>, Ty<'tcx>),
     FunctionArgCountMismatch,
     NoMirFor(String),
     UnterminatedCString(Pointer),
@@ -294,7 +295,8 @@ pub fn description(&self) -> &str {
         use self::EvalErrorKind::*;
         match *self {
             MachineError(ref inner) => inner,
-            FunctionAbiMismatch(..) | FunctionArgMismatch(..) | FunctionArgCountMismatch =>
+            FunctionAbiMismatch(..) | FunctionArgMismatch(..) | FunctionRetMismatch(..)
+            | FunctionArgCountMismatch =>
                 "tried to call a function through a function pointer of incompatible type",
             InvalidMemoryAccess =>
                 "tried to access memory through an invalid pointer",
@@ -470,6 +472,10 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                 write!(f, "tried to call a function with argument of type {:?} \
                            passing data of type {:?}",
                     callee_ty, caller_ty),
+            FunctionRetMismatch(caller_ty, callee_ty) =>
+                write!(f, "tried to call a function with return type {:?} \
+                           passing return place of type {:?}",
+                    callee_ty, caller_ty),
             FunctionArgCountMismatch =>
                 write!(f, "tried to call a function with incorrect number of arguments"),
             BoundsCheck { ref len, ref index } =>
index e9d0b041339556162c663a4e6c7bfce5b73c88a5..5eee0fba5fb463bfb5a53fec00f34f418c629406 100644 (file)
@@ -138,54 +138,82 @@ impl<T: layout::HasDataLayout> PointerArithmetic for T {}
 /// each context.
 ///
 /// Defaults to the index based and loosely coupled AllocId.
+///
+/// Pointer is also generic over the `Tag` associated with each pointer,
+/// which is used to do provenance tracking during execution.
 #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, RustcEncodable, RustcDecodable, Hash)]
-pub struct Pointer<Id=AllocId> {
+pub struct Pointer<Tag=(),Id=AllocId> {
     pub alloc_id: Id,
     pub offset: Size,
+    pub tag: Tag,
 }
 
 /// Produces a `Pointer` which points to the beginning of the Allocation
 impl From<AllocId> for Pointer {
+    #[inline(always)]
     fn from(alloc_id: AllocId) -> Self {
         Pointer::new(alloc_id, Size::ZERO)
     }
 }
 
-impl<'tcx> Pointer {
+impl<'tcx> Pointer<()> {
+    #[inline(always)]
     pub fn new(alloc_id: AllocId, offset: Size) -> Self {
-        Pointer { alloc_id, offset }
+        Pointer { alloc_id, offset, tag: () }
+    }
+
+    #[inline(always)]
+    pub fn with_default_tag<Tag>(self) -> Pointer<Tag>
+        where Tag: Default
+    {
+        Pointer::new_with_tag(self.alloc_id, self.offset, Default::default())
+    }
+}
+
+impl<'tcx, Tag> Pointer<Tag> {
+    #[inline(always)]
+    pub fn new_with_tag(alloc_id: AllocId, offset: Size, tag: Tag) -> Self {
+        Pointer { alloc_id, offset, tag }
     }
 
     pub fn wrapping_signed_offset<C: HasDataLayout>(self, i: i64, cx: C) -> Self {
-        Pointer::new(
+        Pointer::new_with_tag(
             self.alloc_id,
             Size::from_bytes(cx.data_layout().wrapping_signed_offset(self.offset.bytes(), i)),
+            self.tag,
         )
     }
 
     pub fn overflowing_signed_offset<C: HasDataLayout>(self, i: i128, cx: C) -> (Self, bool) {
         let (res, over) = cx.data_layout().overflowing_signed_offset(self.offset.bytes(), i);
-        (Pointer::new(self.alloc_id, Size::from_bytes(res)), over)
+        (Pointer::new_with_tag(self.alloc_id, Size::from_bytes(res), self.tag), over)
     }
 
     pub fn signed_offset<C: HasDataLayout>(self, i: i64, cx: C) -> EvalResult<'tcx, Self> {
-        Ok(Pointer::new(
+        Ok(Pointer::new_with_tag(
             self.alloc_id,
             Size::from_bytes(cx.data_layout().signed_offset(self.offset.bytes(), i)?),
+            self.tag,
         ))
     }
 
     pub fn overflowing_offset<C: HasDataLayout>(self, i: Size, cx: C) -> (Self, bool) {
         let (res, over) = cx.data_layout().overflowing_offset(self.offset.bytes(), i.bytes());
-        (Pointer::new(self.alloc_id, Size::from_bytes(res)), over)
+        (Pointer::new_with_tag(self.alloc_id, Size::from_bytes(res), self.tag), over)
     }
 
     pub fn offset<C: HasDataLayout>(self, i: Size, cx: C) -> EvalResult<'tcx, Self> {
-        Ok(Pointer::new(
+        Ok(Pointer::new_with_tag(
             self.alloc_id,
             Size::from_bytes(cx.data_layout().offset(self.offset.bytes(), i.bytes())?),
+            self.tag
         ))
     }
+
+    #[inline]
+    pub fn erase_tag(self) -> Pointer {
+        Pointer { alloc_id: self.alloc_id, offset: self.offset, tag: () }
+    }
 }
 
 
@@ -496,15 +524,15 @@ pub fn set_id_same_memory(&mut self, id: AllocId, mem: M) {
 }
 
 #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
-pub struct Allocation {
+pub struct Allocation<Tag=()> {
     /// The actual bytes of the allocation.
     /// Note that the bytes of a pointer represent the offset of the pointer
     pub bytes: Vec<u8>,
-    /// Maps from byte addresses to allocations.
+    /// Maps from byte addresses to extra data for each pointer.
     /// Only the first byte of a pointer is inserted into the map; i.e.,
     /// every entry in this map applies to `pointer_size` consecutive bytes starting
     /// at the given offset.
-    pub relocations: Relocations,
+    pub relocations: Relocations<Tag>,
     /// Denotes undefined memory. Reading from undefined memory is forbidden in miri
     pub undef_mask: UndefMask,
     /// The alignment of the allocation to detect unaligned reads.
@@ -515,7 +543,7 @@ pub struct Allocation {
     pub mutability: Mutability,
 }
 
-impl Allocation {
+impl<Tag> Allocation<Tag> {
     /// Creates a read-only allocation initialized by the given bytes
     pub fn from_bytes(slice: &[u8], align: Align) -> Self {
         let mut undef_mask = UndefMask::new(Size::ZERO);
@@ -548,29 +576,29 @@ pub fn undef(size: Size, align: Align) -> Self {
 impl<'tcx> ::serialize::UseSpecializedDecodable for &'tcx Allocation {}
 
 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
-pub struct Relocations<Id=AllocId>(SortedMap<Size, Id>);
+pub struct Relocations<Tag=(), Id=AllocId>(SortedMap<Size, (Tag, Id)>);
 
-impl<Id> Relocations<Id> {
+impl<Tag, Id> Relocations<Tag, Id> {
     pub fn new() -> Self {
         Relocations(SortedMap::new())
     }
 
     // The caller must guarantee that the given relocations are already sorted
     // by address and contain no duplicates.
-    pub fn from_presorted(r: Vec<(Size, Id)>) -> Self {
+    pub fn from_presorted(r: Vec<(Size, (Tag, Id))>) -> Self {
         Relocations(SortedMap::from_presorted_elements(r))
     }
 }
 
-impl Deref for Relocations {
-    type Target = SortedMap<Size, AllocId>;
+impl<Tag> Deref for Relocations<Tag> {
+    type Target = SortedMap<Size, (Tag, AllocId)>;
 
     fn deref(&self) -> &Self::Target {
         &self.0
     }
 }
 
-impl DerefMut for Relocations {
+impl<Tag> DerefMut for Relocations<Tag> {
     fn deref_mut(&mut self) -> &mut Self::Target {
         &mut self.0
     }
index c81d55e69b61a124b380142c3c7cb7b99ef5f847..9e54b146fd02a61edcf79d88ccd9de0ca1d9804d 100644 (file)
@@ -79,7 +79,47 @@ pub fn new_dyn_trait(val: Scalar, vtable: Pointer) -> Self {
     }
 }
 
-impl<'tcx> Scalar {
+/// A `Scalar` represents an immediate, primitive value existing outside of a
+/// `memory::Allocation`. It is in many ways like a small chunk of a `Allocation`, up to 8 bytes in
+/// size. Like a range of bytes in an `Allocation`, a `Scalar` can either represent the raw bytes
+/// of a simple value or a pointer into another `Allocation`
+#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, RustcEncodable, RustcDecodable, Hash)]
+pub enum Scalar<Tag=(), Id=AllocId> {
+    /// The raw bytes of a simple value.
+    Bits {
+        /// The first `size` bytes are the value.
+        /// Do not try to read less or more bytes that that. The remaining bytes must be 0.
+        size: u8,
+        bits: u128,
+    },
+
+    /// A pointer into an `Allocation`. An `Allocation` in the `memory` module has a list of
+    /// relocations, but a `Scalar` is only large enough to contain one, so we just represent the
+    /// relocation and its associated offset together as a `Pointer` here.
+    Ptr(Pointer<Tag, Id>),
+}
+
+impl<'tcx> Scalar<()> {
+    #[inline]
+    pub fn with_default_tag<Tag>(self) -> Scalar<Tag>
+        where Tag: Default
+    {
+        match self {
+            Scalar::Ptr(ptr) => Scalar::Ptr(ptr.with_default_tag()),
+            Scalar::Bits { bits, size } => Scalar::Bits { bits, size },
+        }
+    }
+}
+
+impl<'tcx, Tag> Scalar<Tag> {
+    #[inline]
+    pub fn erase_tag(self) -> Scalar {
+        match self {
+            Scalar::Ptr(ptr) => Scalar::Ptr(ptr.erase_tag()),
+            Scalar::Bits { bits, size } => Scalar::Bits { bits, size },
+        }
+    }
+
     #[inline]
     pub fn ptr_null(cx: impl HasDataLayout) -> Self {
         Scalar::Bits {
@@ -208,7 +248,7 @@ pub fn to_bits(self, target_size: Size) -> EvalResult<'tcx, u128> {
     }
 
     #[inline]
-    pub fn to_ptr(self) -> EvalResult<'tcx, Pointer> {
+    pub fn to_ptr(self) -> EvalResult<'tcx, Pointer<Tag>> {
         match self {
             Scalar::Bits { bits: 0, .. } => err!(InvalidNullPointerUsage),
             Scalar::Bits { .. } => err!(ReadBytesAsPointer),
@@ -317,29 +357,9 @@ pub fn to_f64(self) -> EvalResult<'static, f64> {
     }
 }
 
-impl From<Pointer> for Scalar {
+impl<Tag> From<Pointer<Tag>> for Scalar<Tag> {
     #[inline(always)]
-    fn from(ptr: Pointer) -> Self {
+    fn from(ptr: Pointer<Tag>) -> Self {
         Scalar::Ptr(ptr)
     }
 }
-
-/// A `Scalar` represents an immediate, primitive value existing outside of a
-/// `memory::Allocation`. It is in many ways like a small chunk of a `Allocation`, up to 8 bytes in
-/// size. Like a range of bytes in an `Allocation`, a `Scalar` can either represent the raw bytes
-/// of a simple value or a pointer into another `Allocation`
-#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, RustcEncodable, RustcDecodable, Hash)]
-pub enum Scalar<Id=AllocId> {
-    /// The raw bytes of a simple value.
-    Bits {
-        /// The first `size` bytes are the value.
-        /// Do not try to read less or more bytes that that. The remaining bytes must be 0.
-        size: u8,
-        bits: u128,
-    },
-
-    /// A pointer into an `Allocation`. An `Allocation` in the `memory` module has a list of
-    /// relocations, but a `Scalar` is only large enough to contain one, so we just represent the
-    /// relocation and its associated offset together as a `Pointer` here.
-    Ptr(Pointer<Id>),
-}
index 7d8227053b373c3aa23ccdb6edf3150da8f66142..d2b0a6a37a74ac5a6bd8bd31ab275c1c0bd80c9c 100644 (file)
@@ -214,7 +214,7 @@ fn visit_ty(&mut self,
                 self.super_ty(ty);
             }
 
-            fn visit_canonical_ty(&mut self, ty: & $($mutability)* CanonicalTy<'tcx>) {
+            fn visit_user_ty(&mut self, ty: & $($mutability)* CanonicalTy<'tcx>) {
                 self.super_canonical_ty(ty);
             }
 
@@ -640,7 +640,7 @@ fn super_ascribe_user_ty(&mut self,
                                      c_ty: & $($mutability)* CanonicalTy<'tcx>,
                                      location: Location) {
                 self.visit_place(place, PlaceContext::Validate, location);
-                self.visit_canonical_ty(c_ty);
+                self.visit_user_ty(c_ty);
             }
 
             fn super_place(&mut self,
@@ -736,7 +736,7 @@ fn super_local_decl(&mut self,
                     source_info: *source_info,
                 });
                 if let Some(user_ty) = user_ty {
-                    self.visit_canonical_ty(user_ty);
+                    self.visit_user_ty(user_ty);
                 }
                 self.visit_source_info(source_info);
                 self.visit_source_scope(visibility_scope);
index 83a9491cf4673c57cc6629775a8d9c0c3a6d9b0c..3f62883c6a57b549cead28b2fcc35ec7532e7177 100644 (file)
@@ -492,6 +492,10 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lif
                 tcx.lift(&a)?,
                 tcx.lift(&b)?,
             ),
+            FunctionRetMismatch(a, b) => FunctionRetMismatch(
+                tcx.lift(&a)?,
+                tcx.lift(&b)?,
+            ),
             FunctionArgCountMismatch => FunctionArgCountMismatch,
             NoMirFor(ref s) => NoMirFor(s.clone()),
             UnterminatedCString(ptr) => UnterminatedCString(ptr),
index ce18f31da6907f440a25a5772bf0fcdf8e000b50..9f0f744389089c56981a35d1a08a55be3dc4ec32 100644 (file)
@@ -92,7 +92,7 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll
     let pointer_size = layout.pointer_size.bytes() as usize;
 
     let mut next_offset = 0;
-    for &(offset, alloc_id) in alloc.relocations.iter() {
+    for &(offset, ((), alloc_id)) in alloc.relocations.iter() {
         let offset = offset.bytes();
         assert_eq!(offset as usize as u64, offset);
         let offset = offset as usize;
@@ -105,7 +105,7 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll
         ).expect("const_alloc_to_llvm: could not read relocation pointer") as u64;
         llvals.push(scalar_to_llvm(
             cx,
-            Pointer { alloc_id, offset: Size::from_bytes(ptr_offset) }.into(),
+            Pointer::new(alloc_id, Size::from_bytes(ptr_offset)).into(),
             &layout::Scalar {
                 value: layout::Primitive::Pointer,
                 valid_range: 0..=!0
index f04e5496ce443fb503c821c7c09b0fae140b422f..d18edf22dc10c29c3a1902a088134497c6a5063d 100644 (file)
@@ -1558,15 +1558,13 @@ fn validate_const<'a, 'tcx>(
     let ecx = ::rustc_mir::const_eval::mk_eval_cx(tcx, gid.instance, param_env).unwrap();
     let result = (|| {
         let op = ecx.const_to_op(constant)?;
-        let mut todo = vec![(op, Vec::new())];
-        let mut seen = FxHashSet();
-        seen.insert(op);
-        while let Some((op, mut path)) = todo.pop() {
+        let mut ref_tracking = ::rustc_mir::interpret::RefTracking::new(op);
+        while let Some((op, mut path)) = ref_tracking.todo.pop() {
             ecx.validate_operand(
                 op,
                 &mut path,
-                &mut seen,
-                &mut todo,
+                Some(&mut ref_tracking),
+                /* const_mode */ true,
             )?;
         }
         Ok(())
index ba625fb08c82c6865d9103cc000c06f9f40c2e45..5ab1605d7f07ab404fc79d2ae791a68fe8a5412e 100644 (file)
@@ -218,6 +218,38 @@ pub(super) fn report_mutability_error(
         debug!("report_mutability_error: act={:?}, acted_on={:?}", act, acted_on);
 
         match the_place_err {
+            // Suggest making an existing shared borrow in a struct definition a mutable borrow.
+            //
+            // This is applicable when we have a deref of a field access to a deref of a local -
+            // something like `*((*_1).0`. The local that we get will be a reference to the
+            // struct we've got a field access of (it must be a reference since there's a deref
+            // after the field access).
+            Place::Projection(box Projection {
+                base: Place::Projection(box Projection {
+                    base: Place::Projection(box Projection {
+                        base,
+                        elem: ProjectionElem::Deref,
+                    }),
+                    elem: ProjectionElem::Field(field, _),
+                }),
+                elem: ProjectionElem::Deref,
+            }) => {
+                err.span_label(span, format!("cannot {ACT}", ACT = act));
+
+                if let Some((span, message)) = annotate_struct_field(
+                    self.infcx.tcx,
+                    base.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx),
+                    field,
+                ) {
+                    err.span_suggestion_with_applicability(
+                        span,
+                        "consider changing this to be mutable",
+                        message,
+                        Applicability::MaybeIncorrect,
+                    );
+                }
+            },
+
             // Suggest removing a `&mut` from the use of a mutable reference.
             Place::Local(local)
                 if {
@@ -592,3 +624,54 @@ fn suggest_ampmut<'cx, 'gcx, 'tcx>(
 fn is_closure_or_generator(ty: ty::Ty) -> bool {
     ty.is_closure() || ty.is_generator()
 }
+
+/// Add a suggestion to a struct definition given a field access to a local.
+/// This function expects the local to be a reference to a struct in order to produce a suggestion.
+///
+/// ```text
+/// LL |     s: &'a String
+///    |        ---------- use `&'a mut String` here to make mutable
+/// ```
+fn annotate_struct_field(
+    tcx: TyCtxt<'cx, 'gcx, 'tcx>,
+    ty: ty::Ty<'tcx>,
+    field: &mir::Field,
+) -> Option<(Span, String)> {
+    // Expect our local to be a reference to a struct of some kind.
+    if let ty::TyKind::Ref(_, ty, _) = ty.sty {
+        if let ty::TyKind::Adt(def, _) = ty.sty {
+            let field = def.all_fields().nth(field.index())?;
+            // Use the HIR types to construct the diagnostic message.
+            let node_id = tcx.hir.as_local_node_id(field.did)?;
+            let node = tcx.hir.find(node_id)?;
+            // Now we're dealing with the actual struct that we're going to suggest a change to,
+            // we can expect a field that is an immutable reference to a type.
+            if let hir::Node::Field(field) = node {
+                if let hir::TyKind::Rptr(lifetime, hir::MutTy {
+                    mutbl: hir::Mutability::MutImmutable,
+                    ref ty
+                }) = field.ty.node {
+                    // Get the snippets in two parts - the named lifetime (if there is one) and
+                    // type being referenced, that way we can reconstruct the snippet without loss
+                    // of detail.
+                    let type_snippet = tcx.sess.source_map().span_to_snippet(ty.span).ok()?;
+                    let lifetime_snippet = if !lifetime.is_elided() {
+                        format!("{} ", tcx.sess.source_map().span_to_snippet(lifetime.span).ok()?)
+                    } else {
+                        String::new()
+                    };
+
+                    return Some((
+                        field.ty.span,
+                        format!(
+                            "&{}mut {}",
+                            lifetime_snippet, &*type_snippet,
+                        ),
+                    ));
+                }
+            }
+        }
+    }
+
+    None
+}
index d77863d598f663792fd9a7f0edd0b6779c5bb7f6..15a60badc93e2b50ec4ae8e84585c31ec5a46459 100644 (file)
@@ -10,7 +10,7 @@
 
 use rustc::ty::subst::Substs;
 use rustc::ty::{self, CanonicalTy, ClosureSubsts, GeneratorSubsts, Ty, TypeFoldable};
-use rustc::mir::{BasicBlock, Location, Mir, Place, Statement, StatementKind};
+use rustc::mir::{BasicBlock, Location, Mir, Statement, StatementKind};
 use rustc::mir::visit::{MutVisitor, TyContext};
 use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
 
@@ -65,6 +65,14 @@ fn visit_ty(&mut self, ty: &mut Ty<'tcx>, ty_context: TyContext) {
         debug!("visit_ty: ty={:?}", ty);
     }
 
+    fn visit_user_ty(&mut self, _ty: &mut CanonicalTy<'tcx>) {
+        // `user_ty` annotations represent the types that the user
+        // wrote in the progarm. We don't want to erase the regions
+        // from these types: rather, we want to add them as
+        // constraints at type-check time.
+        debug!("visit_user_ty: skipping renumber");
+    }
+
     fn visit_substs(&mut self, substs: &mut &'tcx Substs<'tcx>, location: Location) {
         debug!("visit_substs(substs={:?}, location={:?})", substs, location);
 
@@ -112,19 +120,6 @@ fn visit_closure_substs(&mut self, substs: &mut ClosureSubsts<'tcx>, location: L
         debug!("visit_closure_substs: substs={:?}", substs);
     }
 
-    fn visit_ascribe_user_ty(
-        &mut self,
-        _place: &mut Place<'tcx>,
-        _variance: &mut ty::Variance,
-        _c_ty: &mut CanonicalTy<'tcx>,
-        _location: Location,
-    ) {
-        // User-assert-ty statements represent types that the user added explicitly.
-        // We don't want to erase the regions from these types: rather, we want to
-        // add them as constraints at type-check time.
-        debug!("visit_user_assert_ty: skipping renumber");
-    }
-
     fn visit_statement(
         &mut self,
         block: BasicBlock,
index 656c78a46ed78c84d75ce5366cdc21c004fec938..c2a7172d54cca22cf2a105366bf4d27a510d2c67 100644 (file)
@@ -1307,6 +1307,14 @@ fn ascribe_types<'pat>(
     ) {
         for ascription in ascriptions {
             let source_info = self.source_info(ascription.span);
+
+            debug!(
+                "adding user ascription at span {:?} of place {:?} and {:?}",
+                source_info.span,
+                ascription.source,
+                ascription.user_ty,
+            );
+
             self.cfg.push(
                 block,
                 Statement {
index 3b1eba51aaf45fbb34ebd4e67ccf7d223245cc9f..fd18d9feeea91e12b123b30dd2ad23fef05843f2 100644 (file)
@@ -12,6 +12,9 @@
 
 use std::fmt;
 use std::error::Error;
+use std::borrow::{Borrow, Cow};
+use std::hash::Hash;
+use std::collections::hash_map::Entry;
 
 use rustc::hir::{self, def_id::DefId};
 use rustc::mir::interpret::ConstEvalErr;
 use rustc::ty::layout::{self, LayoutOf, TyLayout};
 use rustc::ty::subst::Subst;
 use rustc_data_structures::indexed_vec::IndexVec;
+use rustc_data_structures::fx::FxHashMap;
 
 use syntax::ast::Mutability;
 use syntax::source_map::{Span, DUMMY_SP};
 
 use rustc::mir::interpret::{
     EvalResult, EvalError, EvalErrorKind, GlobalId,
-    Scalar, Allocation, ConstValue,
+    Scalar, Allocation, AllocId, ConstValue,
 };
 use interpret::{self,
     Place, PlaceTy, MemPlace, OpTy, Operand, Value,
@@ -118,9 +122,9 @@ pub fn op_to_const<'tcx>(
         }
     };
     let val = match normalized_op {
-        Err(MemPlace { ptr, align, extra }) => {
+        Err(MemPlace { ptr, align, meta }) => {
             // extract alloc-offset pair
-            assert!(extra.is_none());
+            assert!(meta.is_none());
             let ptr = ptr.to_ptr()?;
             let alloc = ecx.memory.get(ptr.alloc_id)?;
             assert!(alloc.align.abi() >= align.abi());
@@ -264,6 +268,67 @@ fn new() -> Self {
     }
 }
 
+impl<K: Hash + Eq, V> interpret::AllocMap<K, V> for FxHashMap<K, V> {
+    #[inline(always)]
+    fn contains_key<Q: ?Sized + Hash + Eq>(&mut self, k: &Q) -> bool
+        where K: Borrow<Q>
+    {
+        FxHashMap::contains_key(self, k)
+    }
+
+    #[inline(always)]
+    fn insert(&mut self, k: K, v: V) -> Option<V>
+    {
+        FxHashMap::insert(self, k, v)
+    }
+
+    #[inline(always)]
+    fn remove<Q: ?Sized + Hash + Eq>(&mut self, k: &Q) -> Option<V>
+        where K: Borrow<Q>
+    {
+        FxHashMap::remove(self, k)
+    }
+
+    #[inline(always)]
+    fn filter_map_collect<T>(&self, mut f: impl FnMut(&K, &V) -> Option<T>) -> Vec<T> {
+        self.iter()
+            .filter_map(move |(k, v)| f(k, &*v))
+            .collect()
+    }
+
+    #[inline(always)]
+    fn get_or<E>(
+        &self,
+        k: K,
+        vacant: impl FnOnce() -> Result<V, E>
+    ) -> Result<&V, E>
+    {
+        match self.get(&k) {
+            Some(v) => Ok(v),
+            None => {
+                vacant()?;
+                bug!("The CTFE machine shouldn't ever need to extend the alloc_map when reading")
+            }
+        }
+    }
+
+    #[inline(always)]
+    fn get_mut_or<E>(
+        &mut self,
+        k: K,
+        vacant: impl FnOnce() -> Result<V, E>
+    ) -> Result<&mut V, E>
+    {
+        match self.entry(k) {
+            Entry::Occupied(e) => Ok(e.into_mut()),
+            Entry::Vacant(e) => {
+                let v = vacant()?;
+                Ok(e.insert(v))
+            }
+        }
+    }
+}
+
 type CompileTimeEvalContext<'a, 'mir, 'tcx> =
     EvalContext<'a, 'mir, 'tcx, CompileTimeInterpreter<'a, 'mir, 'tcx>>;
 
@@ -272,8 +337,12 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx>
 {
     type MemoryData = ();
     type MemoryKinds = !;
+    type PointerTag = ();
+
+    type MemoryMap = FxHashMap<AllocId, (MemoryKind<!>, Allocation<()>)>;
 
-    const MUT_STATIC_KIND: Option<!> = None; // no mutating of statics allowed
+    const STATIC_KIND: Option<!> = None; // no copying of statics allowed
+    const ENFORCE_VALIDITY: bool = false; // for now, we don't
 
     fn find_fn(
         ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
@@ -338,10 +407,18 @@ fn ptr_op(
     fn find_foreign_static(
         _tcx: TyCtxtAt<'a, 'tcx, 'tcx>,
         _def_id: DefId,
-    ) -> EvalResult<'tcx, &'tcx Allocation> {
+    ) -> EvalResult<'tcx, Cow<'tcx, Allocation<Self::PointerTag>>> {
         err!(ReadForeignStatic)
     }
 
+    #[inline(always)]
+    fn static_with_default_tag(
+        alloc: &'_ Allocation
+    ) -> Cow<'_, Allocation<Self::PointerTag>> {
+        // We do not use a tag so we can just cheaply forward the reference
+        Cow::Borrowed(alloc)
+    }
+
     fn box_alloc(
         _ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
         _dest: PlaceTy<'tcx>,
index 8d50fbbdc6b35dd3d23ebd1591d61193986a0344..c969a3ef3485ff1fabe2c221add74a8473b596ca 100644 (file)
@@ -13,6 +13,7 @@
 use hair::cx::Cx;
 use hair::cx::block;
 use hair::cx::to_ref::ToRef;
+use hair::util::UserAnnotatedTyHelpers;
 use rustc::hir::def::{Def, CtorKind};
 use rustc::mir::interpret::GlobalId;
 use rustc::ty::{self, AdtKind, Ty};
@@ -475,7 +476,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                                 adt_def: adt,
                                 variant_index: 0,
                                 substs,
-                                user_ty: user_annotated_ty_for_adt(cx, expr.hir_id, adt),
+                                user_ty: cx.user_substs_applied_to_adt(expr.hir_id, adt),
                                 fields: field_refs(cx, fields),
                                 base: base.as_ref().map(|base| {
                                     FruInfo {
@@ -501,7 +502,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                                         adt_def: adt,
                                         variant_index: index,
                                         substs,
-                                        user_ty: user_annotated_ty_for_adt(cx, expr.hir_id, adt),
+                                        user_ty: cx.user_substs_applied_to_adt(expr.hir_id, adt),
                                         fields: field_refs(cx, fields),
                                         base: None,
                                     }
@@ -787,48 +788,17 @@ fn user_annotated_ty_for_def(
         // user.
         Def::StructCtor(_def_id, CtorKind::Const) |
         Def::VariantCtor(_def_id, CtorKind::Const) =>
-            match &cx.tables().node_id_to_type(hir_id).sty {
-                ty::Adt(adt_def, _) => user_annotated_ty_for_adt(cx, hir_id, adt_def),
-                sty => bug!("unexpected sty: {:?}", sty),
-            },
+            cx.user_substs_applied_to_ty_of_hir_id(hir_id),
 
         // `Self` is used in expression as a tuple struct constructor or an unit struct constructor
-        Def::SelfCtor(_) => {
-            let sty = &cx.tables().node_id_to_type(hir_id).sty;
-            match sty {
-                ty::FnDef(ref def_id, _) => {
-                    Some(cx.tables().user_substs(hir_id)?.unchecked_map(|user_substs| {
-                        // Here, we just pair a `DefId` with the
-                        // `user_substs`, so no new types etc are introduced.
-                        cx.tcx().mk_fn_def(*def_id, user_substs)
-                    }))
-                }
-                ty::Adt(ref adt_def, _) => {
-                    user_annotated_ty_for_adt(cx, hir_id, adt_def)
-                }
-                _ => {
-                    bug!("unexpected sty: {:?}", sty)
-                }
-            }
-        }
+        Def::SelfCtor(_) =>
+            cx.user_substs_applied_to_ty_of_hir_id(hir_id),
+
         _ =>
             bug!("user_annotated_ty_for_def: unexpected def {:?} at {:?}", def, hir_id)
     }
 }
 
-fn user_annotated_ty_for_adt(
-    cx: &mut Cx<'a, 'gcx, 'tcx>,
-    hir_id: hir::HirId,
-    adt_def: &'tcx AdtDef,
-) -> Option<CanonicalTy<'tcx>> {
-    let user_substs = cx.tables().user_substs(hir_id)?;
-    Some(user_substs.unchecked_map(|user_substs| {
-        // Here, we just pair an `AdtDef` with the
-        // `user_substs`, so no new types etc are introduced.
-        cx.tcx().mk_adt(adt_def, user_substs)
-    }))
-}
-
 fn method_callee<'a, 'gcx, 'tcx>(
     cx: &mut Cx<'a, 'gcx, 'tcx>,
     expr: &hir::Expr,
@@ -943,7 +913,7 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                         adt_def,
                         variant_index: adt_def.variant_index_with_id(def_id),
                         substs,
-                        user_ty: user_annotated_ty_for_adt(cx, expr.hir_id, adt_def),
+                        user_ty: cx.user_substs_applied_to_adt(expr.hir_id, adt_def),
                         fields: vec![],
                         base: None,
                     }
index 4d4a89fca8b83b77023d08daad411e14c32ff178..5f798135966d49c25068313a533e628e215dc51f 100644 (file)
@@ -15,6 +15,7 @@
 //!
 
 use hair::*;
+use hair::util::UserAnnotatedTyHelpers;
 
 use rustc_data_structures::indexed_vec::Idx;
 use rustc::hir::def_id::{DefId, LOCAL_CRATE};
@@ -272,6 +273,16 @@ pub fn type_moves_by_default(&self, ty: Ty<'tcx>, span: Span) -> bool {
     }
 }
 
+impl UserAnnotatedTyHelpers<'gcx, 'tcx> for Cx<'_, 'gcx, 'tcx> {
+    fn tcx(&self) -> TyCtxt<'_, 'gcx, 'tcx> {
+        self.tcx()
+    }
+
+    fn tables(&self) -> &ty::TypeckTables<'tcx> {
+        self.tables()
+    }
+}
+
 fn lint_level_for_hir_id(tcx: TyCtxt, mut id: ast::NodeId) -> ast::NodeId {
     // Right now we insert a `with_ignore` node in the dep graph here to
     // ignore the fact that `lint_levels` below depends on the entire crate.
index eb73a2021484b0f7a5ad60b20b38ff130b50dd05..e4f88e4fcc3ba2e6238314ee14aa63d813707ca8 100644 (file)
@@ -29,6 +29,8 @@
 pub mod pattern;
 pub use self::pattern::{BindingMode, Pattern, PatternKind, FieldPattern};
 
+mod util;
+
 #[derive(Copy, Clone, Debug)]
 pub enum LintLevel {
     Inherited,
index b22cc4a1a42b50d14c1d139f99a9044c334b13b9..04090e5087ffc47c21a579d03e231bc195909447 100644 (file)
@@ -18,6 +18,8 @@
 
 use const_eval::{const_field, const_variant_index};
 
+use hair::util::UserAnnotatedTyHelpers;
+
 use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability};
 use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, sign_extend};
 use rustc::ty::{self, CanonicalTy, TyCtxt, AdtDef, Ty, Region};
@@ -529,8 +531,9 @@ fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat) -> Pattern<'tcx> {
                                        field: Field::new(i),
                                        pattern: self.lower_pattern(field),
                                    })
-                                   .collect();
-                self.lower_variant_or_leaf(def, pat.span, ty, subpatterns)
+                    .collect();
+
+                self.lower_variant_or_leaf(def, pat.hir_id, pat.span, ty, subpatterns)
             }
 
             PatKind::Struct(ref qpath, ref fields, _) => {
@@ -546,7 +549,7 @@ fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat) -> Pattern<'tcx> {
                           })
                           .collect();
 
-                self.lower_variant_or_leaf(def, pat.span, ty, subpatterns)
+                self.lower_variant_or_leaf(def, pat.hir_id, pat.span, ty, subpatterns)
             }
         };
 
@@ -637,12 +640,12 @@ fn slice_or_array_pattern(
     fn lower_variant_or_leaf(
         &mut self,
         def: Def,
+        hir_id: hir::HirId,
         span: Span,
         ty: Ty<'tcx>,
-        subpatterns: Vec<FieldPattern<'tcx>>)
-        -> PatternKind<'tcx>
-    {
-        match def {
+        subpatterns: Vec<FieldPattern<'tcx>>,
+    ) -> PatternKind<'tcx> {
+        let mut kind = match def {
             Def::Variant(variant_id) | Def::VariantCtor(variant_id, ..) => {
                 let enum_id = self.tcx.parent_def_id(variant_id).unwrap();
                 let adt_def = self.tcx.adt_def(enum_id);
@@ -675,7 +678,24 @@ fn lower_variant_or_leaf(
                 self.errors.push(PatternError::NonConstPath(span));
                 PatternKind::Wild
             }
+        };
+
+        if let Some(user_ty) = self.user_substs_applied_to_ty_of_hir_id(hir_id) {
+            let subpattern = Pattern {
+                span,
+                ty,
+                kind: Box::new(kind),
+            };
+
+            debug!("pattern user_ty = {:?} for pattern at {:?}", user_ty, span);
+
+            kind = PatternKind::AscribeUserType {
+                subpattern,
+                user_ty,
+            };
         }
+
+        kind
     }
 
     /// Takes a HIR Path. If the path is a constant, evaluates it and feeds
@@ -729,7 +749,7 @@ fn lower_path(&mut self,
                     },
                 }
             }
-            _ => self.lower_variant_or_leaf(def, span, ty, vec![]),
+            _ => self.lower_variant_or_leaf(def, id, span, ty, vec![]),
         };
 
         Pattern {
@@ -894,6 +914,17 @@ fn const_to_pat(
     }
 }
 
+impl UserAnnotatedTyHelpers<'tcx, 'tcx> for PatternContext<'_, 'tcx> {
+    fn tcx(&self) -> TyCtxt<'_, 'tcx, 'tcx> {
+        self.tcx
+    }
+
+    fn tables(&self) -> &ty::TypeckTables<'tcx> {
+        self.tables
+    }
+}
+
+
 pub trait PatternFoldable<'tcx> : Sized {
     fn fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
         self.super_fold_with(folder)
diff --git a/src/librustc_mir/hair/util.rs b/src/librustc_mir/hair/util.rs
new file mode 100644 (file)
index 0000000..48a2e67
--- /dev/null
@@ -0,0 +1,56 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use rustc::hir;
+use rustc::ty::{self, AdtDef, CanonicalTy, TyCtxt};
+
+crate trait UserAnnotatedTyHelpers<'gcx: 'tcx, 'tcx> {
+    fn tcx(&self) -> TyCtxt<'_, 'gcx, 'tcx>;
+
+    fn tables(&self) -> &ty::TypeckTables<'tcx>;
+
+    fn user_substs_applied_to_adt(
+        &self,
+        hir_id: hir::HirId,
+        adt_def: &'tcx AdtDef,
+    ) -> Option<CanonicalTy<'tcx>> {
+        let user_substs = self.tables().user_substs(hir_id)?;
+        Some(user_substs.unchecked_map(|user_substs| {
+            // Here, we just pair an `AdtDef` with the
+            // `user_substs`, so no new types etc are introduced.
+            self.tcx().mk_adt(adt_def, user_substs)
+        }))
+    }
+
+    /// Looks up the type associated with this hir-id and applies the
+    /// user-given substitutions; the hir-id must map to a suitable
+    /// type.
+    fn user_substs_applied_to_ty_of_hir_id(&self, hir_id: hir::HirId) -> Option<CanonicalTy<'tcx>> {
+        let user_substs = self.tables().user_substs(hir_id)?;
+        match &self.tables().node_id_to_type(hir_id).sty {
+            ty::Adt(adt_def, _) => Some(user_substs.unchecked_map(|user_substs| {
+                // Ok to call `unchecked_map` because we just pair an
+                // `AdtDef` with the `user_substs`, so no new types
+                // etc are introduced.
+                self.tcx().mk_adt(adt_def, user_substs)
+            })),
+            ty::FnDef(def_id, _) => Some(user_substs.unchecked_map(|user_substs| {
+                // Here, we just pair a `DefId` with the
+                // `user_substs`, so no new types etc are introduced.
+                self.tcx().mk_fn_def(*def_id, user_substs)
+            })),
+            sty => bug!(
+                "sty: {:?} should not have user-substs {:?} recorded ",
+                sty,
+                user_substs
+            ),
+        }
+    }
+}
index c6b527f42294c1134535272da53f0774ca17338b..bfc7e6801fc463fe39fd778fef7e4bdeede63d63 100644 (file)
@@ -33,9 +33,9 @@ fn type_is_fat_ptr(&self, ty: Ty<'tcx>) -> bool {
 
     pub fn cast(
         &mut self,
-        src: OpTy<'tcx>,
+        src: OpTy<'tcx, M::PointerTag>,
         kind: CastKind,
-        dest: PlaceTy<'tcx>,
+        dest: PlaceTy<'tcx, M::PointerTag>,
     ) -> EvalResult<'tcx> {
         let src_layout = src.layout;
         let dst_layout = dest.layout;
@@ -143,10 +143,10 @@ pub fn cast(
 
     pub(super) fn cast_scalar(
         &self,
-        val: Scalar,
+        val: Scalar<M::PointerTag>,
         src_layout: TyLayout<'tcx>,
         dest_layout: TyLayout<'tcx>,
-    ) -> EvalResult<'tcx, Scalar> {
+    ) -> EvalResult<'tcx, Scalar<M::PointerTag>> {
         use rustc::ty::TyKind::*;
         trace!("Casting {:?}: {:?} to {:?}", val, src_layout.ty, dest_layout.ty);
 
@@ -182,7 +182,7 @@ fn cast_from_int(
         v: u128,
         src_layout: TyLayout<'tcx>,
         dest_layout: TyLayout<'tcx>,
-    ) -> EvalResult<'tcx, Scalar> {
+    ) -> EvalResult<'tcx, Scalar<M::PointerTag>> {
         let signed = src_layout.abi.is_signed();
         let v = if signed {
             self.sign_extend(v, src_layout)
@@ -239,7 +239,7 @@ fn cast_from_float(
         bits: u128,
         fty: FloatTy,
         dest_ty: Ty<'tcx>
-    ) -> EvalResult<'tcx, Scalar> {
+    ) -> EvalResult<'tcx, Scalar<M::PointerTag>> {
         use rustc::ty::TyKind::*;
         use rustc_apfloat::FloatConvert;
         match dest_ty.sty {
@@ -283,7 +283,11 @@ fn cast_from_float(
         }
     }
 
-    fn cast_from_ptr(&self, ptr: Pointer, ty: Ty<'tcx>) -> EvalResult<'tcx, Scalar> {
+    fn cast_from_ptr(
+        &self,
+        ptr: Pointer<M::PointerTag>,
+        ty: Ty<'tcx>
+    ) -> EvalResult<'tcx, Scalar<M::PointerTag>> {
         use rustc::ty::TyKind::*;
         match ty.sty {
             // Casting to a reference or fn pointer is not permitted by rustc,
@@ -298,8 +302,8 @@ fn cast_from_ptr(&self, ptr: Pointer, ty: Ty<'tcx>) -> EvalResult<'tcx, Scalar>
 
     fn unsize_into_ptr(
         &mut self,
-        src: OpTy<'tcx>,
-        dest: PlaceTy<'tcx>,
+        src: OpTy<'tcx, M::PointerTag>,
+        dest: PlaceTy<'tcx, M::PointerTag>,
         // The pointee types
         sty: Ty<'tcx>,
         dty: Ty<'tcx>,
@@ -339,8 +343,8 @@ fn unsize_into_ptr(
 
     fn unsize_into(
         &mut self,
-        src: OpTy<'tcx>,
-        dest: PlaceTy<'tcx>,
+        src: OpTy<'tcx, M::PointerTag>,
+        dest: PlaceTy<'tcx, M::PointerTag>,
     ) -> EvalResult<'tcx> {
         match (&src.layout.ty.sty, &dest.layout.ty.sty) {
             (&ty::Ref(_, s, _), &ty::Ref(_, d, _)) |
index ff059e7d1853b0c8592d3af9bd8edf2d9700b198..f6944b2a9ae8555b73b0cbf6573697663137f044 100644 (file)
@@ -49,12 +49,12 @@ pub struct EvalContext<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'a, 'mir, 'tcx>> {
     pub memory: Memory<'a, 'mir, 'tcx, M>,
 
     /// The virtual call stack.
-    pub(crate) stack: Vec<Frame<'mir, 'tcx>>,
+    pub(crate) stack: Vec<Frame<'mir, 'tcx, M::PointerTag>>,
 }
 
 /// A stack frame.
 #[derive(Clone)]
-pub struct Frame<'mir, 'tcx: 'mir> {
+pub struct Frame<'mir, 'tcx: 'mir, Tag=()> {
     ////////////////////////////////////////////////////////////////////////////////
     // Function and callsite information
     ////////////////////////////////////////////////////////////////////////////////
@@ -74,14 +74,14 @@ pub struct Frame<'mir, 'tcx: 'mir> {
     pub return_to_block: StackPopCleanup,
 
     /// The location where the result of the current stack frame should be written to.
-    pub return_place: Place,
+    pub return_place: Place<Tag>,
 
     /// The list of locals for this stack frame, stored in order as
     /// `[return_ptr, arguments..., variables..., temporaries...]`.
     /// The locals are stored as `Option<Value>`s.
     /// `None` represents a local that is currently dead, while a live local
     /// can either directly contain `Scalar` or refer to some part of an `Allocation`.
-    pub locals: IndexVec<mir::Local, LocalValue<AllocId>>,
+    pub locals: IndexVec<mir::Local, LocalValue<Tag>>,
 
     ////////////////////////////////////////////////////////////////////////////////
     // Current position within the function
@@ -108,24 +108,24 @@ pub enum StackPopCleanup {
 
 // State of a local variable
 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
-pub enum LocalValue<Id=AllocId> {
+pub enum LocalValue<Tag=(), Id=AllocId> {
     Dead,
     // Mostly for convenience, we re-use the `Operand` type here.
     // This is an optimization over just always having a pointer here;
     // we can thus avoid doing an allocation when the local just stores
     // immediate values *and* never has its address taken.
-    Live(Operand<Id>),
+    Live(Operand<Tag, Id>),
 }
 
-impl<'tcx> LocalValue {
-    pub fn access(&self) -> EvalResult<'tcx, &Operand> {
+impl<'tcx, Tag> LocalValue<Tag> {
+    pub fn access(&self) -> EvalResult<'tcx, &Operand<Tag>> {
         match self {
             LocalValue::Dead => err!(DeadLocal),
             LocalValue::Live(ref val) => Ok(val),
         }
     }
 
-    pub fn access_mut(&mut self) -> EvalResult<'tcx, &mut Operand> {
+    pub fn access_mut(&mut self) -> EvalResult<'tcx, &mut Operand<Tag>> {
         match self {
             LocalValue::Dead => err!(DeadLocal),
             LocalValue::Live(ref mut val) => Ok(val),
@@ -218,7 +218,7 @@ pub fn memory_mut(&mut self) -> &mut Memory<'a, 'mir, 'tcx, M> {
         &mut self.memory
     }
 
-    pub fn stack(&self) -> &[Frame<'mir, 'tcx>] {
+    pub fn stack(&self) -> &[Frame<'mir, 'tcx, M::PointerTag>] {
         &self.stack
     }
 
@@ -230,7 +230,11 @@ pub fn cur_frame(&self) -> usize {
 
     /// Mark a storage as live, killing the previous content and returning it.
     /// Remember to deallocate that!
-    pub fn storage_live(&mut self, local: mir::Local) -> EvalResult<'tcx, LocalValue> {
+    pub fn storage_live(
+        &mut self,
+        local: mir::Local
+    ) -> EvalResult<'tcx, LocalValue<M::PointerTag>> {
+        assert!(local != mir::RETURN_PLACE, "Cannot make return place live");
         trace!("{:?} is now live", local);
 
         let layout = self.layout_of_local(self.cur_frame(), local)?;
@@ -241,13 +245,14 @@ pub fn storage_live(&mut self, local: mir::Local) -> EvalResult<'tcx, LocalValue
 
     /// Returns the old value of the local.
     /// Remember to deallocate that!
-    pub fn storage_dead(&mut self, local: mir::Local) -> LocalValue {
+    pub fn storage_dead(&mut self, local: mir::Local) -> LocalValue<M::PointerTag> {
+        assert!(local != mir::RETURN_PLACE, "Cannot make return place dead");
         trace!("{:?} is now dead", local);
 
         mem::replace(&mut self.frame_mut().locals[local], LocalValue::Dead)
     }
 
-    pub fn str_to_value(&mut self, s: &str) -> EvalResult<'tcx, Value> {
+    pub fn str_to_value(&mut self, s: &str) -> EvalResult<'tcx, Value<M::PointerTag>> {
         let ptr = self.memory.allocate_static_bytes(s.as_bytes());
         Ok(Value::new_slice(Scalar::Ptr(ptr), s.len() as u64, self.tcx.tcx))
     }
@@ -325,10 +330,10 @@ pub fn layout_of_local(
     }
 
     /// Return the actual dynamic size and alignment of the place at the given type.
-    /// Only the "extra" (metadata) part of the place matters.
+    /// Only the `meta` part of the place matters.
     pub(super) fn size_and_align_of(
         &self,
-        metadata: Option<Scalar>,
+        metadata: Option<Scalar<M::PointerTag>>,
         layout: TyLayout<'tcx>,
     ) -> EvalResult<'tcx, (Size, Align)> {
         let metadata = match metadata {
@@ -409,9 +414,9 @@ pub(super) fn size_and_align_of(
     #[inline]
     pub fn size_and_align_of_mplace(
         &self,
-        mplace: MPlaceTy<'tcx>
+        mplace: MPlaceTy<'tcx, M::PointerTag>
     ) -> EvalResult<'tcx, (Size, Align)> {
-        self.size_and_align_of(mplace.extra, mplace.layout)
+        self.size_and_align_of(mplace.meta, mplace.layout)
     }
 
     pub fn push_stack_frame(
@@ -419,7 +424,7 @@ pub fn push_stack_frame(
         instance: ty::Instance<'tcx>,
         span: source_map::Span,
         mir: &'mir mir::Mir<'tcx>,
-        return_place: Place,
+        return_place: Place<M::PointerTag>,
         return_to_block: StackPopCleanup,
     ) -> EvalResult<'tcx> {
         ::log_settings::settings().indentation += 1;
@@ -446,6 +451,9 @@ pub fn push_stack_frame(
             let dummy =
                 LocalValue::Live(Operand::Immediate(Value::Scalar(ScalarMaybeUndef::Undef)));
             let mut locals = IndexVec::from_elem(dummy, &mir.local_decls);
+            // Return place is handled specially by the `eval_place` functions, and the
+            // entry in `locals` should never be used. Make it dead, to be sure.
+            locals[mir::RETURN_PLACE] = LocalValue::Dead;
             // Now mark those locals as dead that we do not want to initialize
             match self.tcx.describe_def(instance.def_id()) {
                 // statics and constants don't have `Storage*` statements, no need to look for them
@@ -514,7 +522,10 @@ pub(super) fn pop_stack_frame(&mut self) -> EvalResult<'tcx> {
         Ok(())
     }
 
-    pub(super) fn deallocate_local(&mut self, local: LocalValue) -> EvalResult<'tcx> {
+    pub(super) fn deallocate_local(
+        &mut self,
+        local: LocalValue<M::PointerTag>,
+    ) -> EvalResult<'tcx> {
         // FIXME: should we tell the user that there was a local which was never written to?
         if let LocalValue::Live(Operand::Indirect(MemPlace { ptr, .. })) = local {
             trace!("deallocating local");
@@ -536,12 +547,12 @@ pub fn const_eval(&self, gid: GlobalId<'tcx>) -> EvalResult<'tcx, &'tcx ty::Cons
     }
 
     #[inline(always)]
-    pub fn frame(&self) -> &Frame<'mir, 'tcx> {
+    pub fn frame(&self) -> &Frame<'mir, 'tcx, M::PointerTag> {
         self.stack.last().expect("no call frames exist")
     }
 
     #[inline(always)]
-    pub fn frame_mut(&mut self) -> &mut Frame<'mir, 'tcx> {
+    pub fn frame_mut(&mut self) -> &mut Frame<'mir, 'tcx, M::PointerTag> {
         self.stack.last_mut().expect("no call frames exist")
     }
 
@@ -557,7 +568,7 @@ pub fn substs(&self) -> &'tcx Substs<'tcx> {
         }
     }
 
-    pub fn dump_place(&self, place: Place) {
+    pub fn dump_place(&self, place: Place<M::PointerTag>) {
         // Debug output
         if !log_enabled!(::log::Level::Trace) {
             return;
index 5fee49ba2fcf2ddb5bca8745a35b1bfc72510055..a669b2aafc2b8868a0a743e8372208bd270c4cbb 100644 (file)
 };
 
 
-fn numeric_intrinsic<'tcx>(
+fn numeric_intrinsic<'tcx, Tag>(
     name: &str,
     bits: u128,
     kind: Primitive,
-) -> EvalResult<'tcx, Scalar> {
+) -> EvalResult<'tcx, Scalar<Tag>> {
     let size = match kind {
         Primitive::Int(integer, _) => integer.size(),
         _ => bug!("invalid `{}` argument: {:?}", name, bits),
@@ -51,8 +51,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
     pub fn emulate_intrinsic(
         &mut self,
         instance: ty::Instance<'tcx>,
-        args: &[OpTy<'tcx>],
-        dest: PlaceTy<'tcx>,
+        args: &[OpTy<'tcx, M::PointerTag>],
+        dest: PlaceTy<'tcx, M::PointerTag>,
     ) -> EvalResult<'tcx, bool> {
         let substs = instance.substs;
 
@@ -169,8 +169,8 @@ pub fn emulate_intrinsic(
     pub fn hook_fn(
         &mut self,
         instance: ty::Instance<'tcx>,
-        args: &[OpTy<'tcx>],
-        dest: Option<PlaceTy<'tcx>>,
+        args: &[OpTy<'tcx, M::PointerTag>],
+        dest: Option<PlaceTy<'tcx, M::PointerTag>>,
     ) -> EvalResult<'tcx, bool> {
         let def_id = instance.def_id();
         // Some fn calls are actually BinOp intrinsics
index 1eb0280409527cec262f2bcf527bfde73c5d829a..a444f0bafd23c1f3d7d7b24de03ead89bb79923f 100644 (file)
 //! This separation exists to ensure that no fancy miri features like
 //! interpreting common C functions leak into CTFE.
 
+use std::borrow::{Borrow, Cow};
+use std::hash::Hash;
+
 use rustc::hir::def_id::DefId;
-use rustc::mir::interpret::{Allocation, EvalResult, Scalar};
+use rustc::mir::interpret::{Allocation, AllocId, EvalResult, Scalar};
 use rustc::mir;
 use rustc::ty::{self, layout::TyLayout, query::TyCtxtAt};
 
-use super::{EvalContext, PlaceTy, OpTy};
+use super::{EvalContext, PlaceTy, OpTy, MemoryKind};
+
+/// The functionality needed by memory to manage its allocations
+pub trait AllocMap<K: Hash + Eq, V> {
+    /// Test if the map contains the given key.
+    /// Deliberately takes `&mut` because that is sufficient, and some implementations
+    /// can be more efficient then (using `RefCell::get_mut`).
+    fn contains_key<Q: ?Sized + Hash + Eq>(&mut self, k: &Q) -> bool
+        where K: Borrow<Q>;
+
+    /// Insert new entry into the map.
+    fn insert(&mut self, k: K, v: V) -> Option<V>;
+
+    /// Remove entry from the map.
+    fn remove<Q: ?Sized + Hash + Eq>(&mut self, k: &Q) -> Option<V>
+        where K: Borrow<Q>;
+
+    /// Return data based the keys and values in the map.
+    fn filter_map_collect<T>(&self, f: impl FnMut(&K, &V) -> Option<T>) -> Vec<T>;
+
+    /// Return a reference to entry `k`.  If no such entry exists, call
+    /// `vacant` and either forward its error, or add its result to the map
+    /// and return a reference to *that*.
+    fn get_or<E>(
+        &self,
+        k: K,
+        vacant: impl FnOnce() -> Result<V, E>
+    ) -> Result<&V, E>;
+
+    /// Return a mutable reference to entry `k`.  If no such entry exists, call
+    /// `vacant` and either forward its error, or add its result to the map
+    /// and return a reference to *that*.
+    fn get_mut_or<E>(
+        &mut self,
+        k: K,
+        vacant: impl FnOnce() -> Result<V, E>
+    ) -> Result<&mut V, E>;
+}
 
 /// Methods of this trait signifies a point where CTFE evaluation would fail
 /// and some use case dependent behaviour can instead be applied.
-/// FIXME: We should be able to get rid of the 'a here if we can get rid of the 'a in
-/// `snapshot::EvalSnapshot`.
 pub trait Machine<'a, 'mir, 'tcx>: Sized {
     /// Additional data that can be accessed via the Memory
     type MemoryData;
@@ -30,8 +68,25 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized {
     /// Additional memory kinds a machine wishes to distinguish from the builtin ones
     type MemoryKinds: ::std::fmt::Debug + Copy + Eq;
 
-    /// The memory kind to use for mutated statics -- or None if those are not supported.
-    const MUT_STATIC_KIND: Option<Self::MemoryKinds>;
+    /// Memory's allocation map
+    type MemoryMap:
+        AllocMap<AllocId, (MemoryKind<Self::MemoryKinds>, Allocation<Self::PointerTag>)> +
+        Default +
+        Clone;
+
+    /// Tag tracked alongside every pointer.  This is inert for now, in preparation for
+    /// a future implementation of "Stacked Borrows"
+    /// <https://www.ralfj.de/blog/2018/08/07/stacked-borrows.html>.
+    type PointerTag: ::std::fmt::Debug + Default + Copy + Eq + Hash + 'static;
+
+    /// The memory kind to use for copied statics -- or None if those are not supported.
+    /// Statics are copied under two circumstances: When they are mutated, and when
+    /// `static_with_default_tag` or `find_foreign_static` (see below) returns an owned allocation
+    /// that is added to the memory so that the work is not done twice.
+    const STATIC_KIND: Option<Self::MemoryKinds>;
+
+    /// Whether to enforce the validity invariant
+    const ENFORCE_VALIDITY: bool;
 
     /// Called before a basic block terminator is executed.
     /// You can use this to detect endlessly running programs.
@@ -50,8 +105,8 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized {
     fn find_fn(
         ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
         instance: ty::Instance<'tcx>,
-        args: &[OpTy<'tcx>],
-        dest: Option<PlaceTy<'tcx>>,
+        args: &[OpTy<'tcx, Self::PointerTag>],
+        dest: Option<PlaceTy<'tcx, Self::PointerTag>>,
         ret: Option<mir::BasicBlock>,
     ) -> EvalResult<'tcx, Option<&'mir mir::Mir<'tcx>>>;
 
@@ -60,18 +115,30 @@ fn find_fn(
     fn call_intrinsic(
         ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
         instance: ty::Instance<'tcx>,
-        args: &[OpTy<'tcx>],
-        dest: PlaceTy<'tcx>,
+        args: &[OpTy<'tcx, Self::PointerTag>],
+        dest: PlaceTy<'tcx, Self::PointerTag>,
     ) -> EvalResult<'tcx>;
 
     /// Called for read access to a foreign static item.
-    /// This can be called multiple times for the same static item and should return consistent
-    /// results.  Once the item is *written* the first time, as usual for statics a copy is
-    /// made and this function is not called again.
+    ///
+    /// This will only be called once per static and machine; the result is cached in
+    /// the machine memory. (This relies on `AllocMap::get_or` being able to add the
+    /// owned allocation to the map even when the map is shared.)
     fn find_foreign_static(
         tcx: TyCtxtAt<'a, 'tcx, 'tcx>,
         def_id: DefId,
-    ) -> EvalResult<'tcx, &'tcx Allocation>;
+    ) -> EvalResult<'tcx, Cow<'tcx, Allocation<Self::PointerTag>>>;
+
+    /// Called to turn an allocation obtained from the `tcx` into one that has
+    /// the appropriate tags on each pointer.
+    ///
+    /// This should avoid copying if no work has to be done! If this returns an owned
+    /// allocation (because a copy had to be done to add the tags), machine memory will
+    /// cache the result. (This relies on `AllocMap::get_or` being able to add the
+    /// owned allocation to the map even when the map is shared.)
+    fn static_with_default_tag(
+        alloc: &'_ Allocation
+    ) -> Cow<'_, Allocation<Self::PointerTag>>;
 
     /// Called for all binary operations on integer(-like) types when one operand is a pointer
     /// value, and for the `Offset` operation that is inherently about pointers.
@@ -80,18 +147,18 @@ fn find_foreign_static(
     fn ptr_op(
         ecx: &EvalContext<'a, 'mir, 'tcx, Self>,
         bin_op: mir::BinOp,
-        left: Scalar,
+        left: Scalar<Self::PointerTag>,
         left_layout: TyLayout<'tcx>,
-        right: Scalar,
+        right: Scalar<Self::PointerTag>,
         right_layout: TyLayout<'tcx>,
-    ) -> EvalResult<'tcx, (Scalar, bool)>;
+    ) -> EvalResult<'tcx, (Scalar<Self::PointerTag>, bool)>;
 
     /// Heap allocations via the `box` keyword
     ///
     /// Returns a pointer to the allocated memory
     fn box_alloc(
         ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
-        dest: PlaceTy<'tcx>,
+        dest: PlaceTy<'tcx, Self::PointerTag>,
     ) -> EvalResult<'tcx>;
 
     /// Execute a validation operation
index 222d1164667d360177ac0a612d4fb8eaeea85a33..7d3ae19e1a30c69cf519d60f633a86c17c779616 100644 (file)
 
 use std::collections::VecDeque;
 use std::ptr;
+use std::borrow::Cow;
 
-use rustc::ty::{self, Instance, query::TyCtxtAt};
+use rustc::ty::{self, Instance, ParamEnv, query::TyCtxtAt};
 use rustc::ty::layout::{self, Align, TargetDataLayout, Size, HasDataLayout};
-use rustc::mir::interpret::{Pointer, AllocId, Allocation, ConstValue, GlobalId,
-                            EvalResult, Scalar, EvalErrorKind, AllocType, PointerArithmetic,
-                            truncate};
+use rustc::mir::interpret::{
+    Pointer, AllocId, Allocation, ConstValue, GlobalId,
+    EvalResult, Scalar, EvalErrorKind, AllocType, PointerArithmetic,
+    truncate
+};
 pub use rustc::mir::interpret::{write_target_uint, read_target_uint};
 use rustc_data_structures::fx::{FxHashSet, FxHashMap};
 
 use syntax::ast::Mutability;
 
-use super::{Machine, ScalarMaybeUndef};
+use super::{Machine, AllocMap, ScalarMaybeUndef};
 
 #[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)]
 pub enum MemoryKind<T> {
     /// Error if deallocated except during a stack pop
     Stack,
+    /// Error if ever deallocated
+    Vtable,
     /// Additional memory kinds a machine wishes to distinguish from the builtin ones
     Machine(T),
 }
@@ -48,9 +53,13 @@ pub struct Memory<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'a, 'mir, 'tcx>> {
     /// Allocations local to this instance of the miri engine.  The kind
     /// helps ensure that the same mechanism is used for allocation and
     /// deallocation.  When an allocation is not found here, it is a
-    /// static and looked up in the `tcx` for read access.  Writing to
-    /// a static creates a copy here, in the machine.
-    alloc_map: FxHashMap<AllocId, (MemoryKind<M::MemoryKinds>, Allocation)>,
+    /// static and looked up in the `tcx` for read access.  Some machines may
+    /// have to mutate this map even on a read-only access to a static (because
+    /// they do pointer provenance tracking and the allocations in `tcx` have
+    /// the wrong type), so we let the machine override this type.
+    /// Either way, if the machine allows writing to a static, doing so will
+    /// create a copy of the static allocation here.
+    alloc_map: M::MemoryMap,
 
     /// To be able to compare pointers with NULL, and to check alignment for accesses
     /// to ZSTs (where pointers may dangle), we keep track of the size even for allocations
@@ -98,23 +107,23 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
     pub fn new(tcx: TyCtxtAt<'a, 'tcx, 'tcx>, data: M::MemoryData) -> Self {
         Memory {
             data,
-            alloc_map: FxHashMap::default(),
+            alloc_map: Default::default(),
             dead_alloc_map: FxHashMap::default(),
             tcx,
         }
     }
 
-    pub fn create_fn_alloc(&mut self, instance: Instance<'tcx>) -> Pointer {
-        self.tcx.alloc_map.lock().create_fn_alloc(instance).into()
+    pub fn create_fn_alloc(&mut self, instance: Instance<'tcx>) -> Pointer<M::PointerTag> {
+        Pointer::from(self.tcx.alloc_map.lock().create_fn_alloc(instance)).with_default_tag()
     }
 
-    pub fn allocate_static_bytes(&mut self, bytes: &[u8]) -> Pointer {
-        self.tcx.allocate_bytes(bytes).into()
+    pub fn allocate_static_bytes(&mut self, bytes: &[u8]) -> Pointer<M::PointerTag> {
+        Pointer::from(self.tcx.allocate_bytes(bytes)).with_default_tag()
     }
 
     pub fn allocate_with(
         &mut self,
-        alloc: Allocation,
+        alloc: Allocation<M::PointerTag>,
         kind: MemoryKind<M::MemoryKinds>,
     ) -> EvalResult<'tcx, AllocId> {
         let id = self.tcx.alloc_map.lock().reserve();
@@ -127,19 +136,20 @@ pub fn allocate(
         size: Size,
         align: Align,
         kind: MemoryKind<M::MemoryKinds>,
-    ) -> EvalResult<'tcx, Pointer> {
-        self.allocate_with(Allocation::undef(size, align), kind).map(Pointer::from)
+    ) -> EvalResult<'tcx, Pointer<M::PointerTag>> {
+        let ptr = Pointer::from(self.allocate_with(Allocation::undef(size, align), kind)?);
+        Ok(ptr.with_default_tag())
     }
 
     pub fn reallocate(
         &mut self,
-        ptr: Pointer,
+        ptr: Pointer<M::PointerTag>,
         old_size: Size,
         old_align: Align,
         new_size: Size,
         new_align: Align,
         kind: MemoryKind<M::MemoryKinds>,
-    ) -> EvalResult<'tcx, Pointer> {
+    ) -> EvalResult<'tcx, Pointer<M::PointerTag>> {
         if ptr.offset.bytes() != 0 {
             return err!(ReallocateNonBasePtr);
         }
@@ -160,7 +170,7 @@ pub fn reallocate(
     }
 
     /// Deallocate a local, or do nothing if that local has been made into a static
-    pub fn deallocate_local(&mut self, ptr: Pointer) -> EvalResult<'tcx> {
+    pub fn deallocate_local(&mut self, ptr: Pointer<M::PointerTag>) -> EvalResult<'tcx> {
         // The allocation might be already removed by static interning.
         // This can only really happen in the CTFE instance, not in miri.
         if self.alloc_map.contains_key(&ptr.alloc_id) {
@@ -172,7 +182,7 @@ pub fn deallocate_local(&mut self, ptr: Pointer) -> EvalResult<'tcx> {
 
     pub fn deallocate(
         &mut self,
-        ptr: Pointer,
+        ptr: Pointer<M::PointerTag>,
         size_and_align: Option<(Size, Align)>,
         kind: MemoryKind<M::MemoryKinds>,
     ) -> EvalResult<'tcx> {
@@ -231,16 +241,20 @@ pub fn deallocate(
 
     /// Check that the pointer is aligned AND non-NULL. This supports ZSTs in two ways:
     /// You can pass a scalar, and a `Pointer` does not have to actually still be allocated.
-    pub fn check_align(&self, ptr: Scalar, required_align: Align) -> EvalResult<'tcx> {
+    pub fn check_align(
+        &self,
+        ptr: Scalar<M::PointerTag>,
+        required_align: Align
+    ) -> EvalResult<'tcx> {
         // Check non-NULL/Undef, extract offset
         let (offset, alloc_align) = match ptr {
             Scalar::Ptr(ptr) => {
-                let (size, align) = self.get_size_and_align(ptr.alloc_id)?;
+                let (size, align) = self.get_size_and_align(ptr.alloc_id);
                 // check this is not NULL -- which we can ensure only if this is in-bounds
                 // of some (potentially dead) allocation.
                 if ptr.offset > size {
                     return err!(PointerOutOfBounds {
-                        ptr,
+                        ptr: ptr.erase_tag(),
                         access: true,
                         allocation_size: size,
                     });
@@ -284,31 +298,49 @@ pub fn check_align(&self, ptr: Scalar, required_align: Align) -> EvalResult<'tcx
     /// If you want to check bounds before doing a memory access, be sure to
     /// check the pointer one past the end of your access, then everything will
     /// work out exactly.
-    pub fn check_bounds(&self, ptr: Pointer, access: bool) -> EvalResult<'tcx> {
+    pub fn check_bounds_ptr(&self, ptr: Pointer<M::PointerTag>, access: bool) -> EvalResult<'tcx> {
         let alloc = self.get(ptr.alloc_id)?;
         let allocation_size = alloc.bytes.len() as u64;
         if ptr.offset.bytes() > allocation_size {
             return err!(PointerOutOfBounds {
-                ptr,
+                ptr: ptr.erase_tag(),
                 access,
                 allocation_size: Size::from_bytes(allocation_size),
             });
         }
         Ok(())
     }
+
+    /// Check if the memory range beginning at `ptr` and of size `Size` is "in-bounds".
+    #[inline(always)]
+    pub fn check_bounds(
+        &self,
+        ptr: Pointer<M::PointerTag>,
+        size: Size,
+        access: bool
+    ) -> EvalResult<'tcx> {
+        // if ptr.offset is in bounds, then so is ptr (because offset checks for overflow)
+        self.check_bounds_ptr(ptr.offset(size, &*self)?, access)
+    }
 }
 
 /// Allocation accessors
 impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
-    /// Helper function to obtain the global (tcx) allocation for a static
+    /// Helper function to obtain the global (tcx) allocation for a static.
+    /// This attempts to return a reference to an existing allocation if
+    /// one can be found in `tcx`. That, however, is only possible if `tcx` and
+    /// this machine use the same pointer tag, so it is indirected through
+    /// `M::static_with_default_tag`.
     fn get_static_alloc(
         tcx: TyCtxtAt<'a, 'tcx, 'tcx>,
         id: AllocId,
-    ) -> EvalResult<'tcx, &'tcx Allocation> {
+    ) -> EvalResult<'tcx, Cow<'tcx, Allocation<M::PointerTag>>> {
         let alloc = tcx.alloc_map.lock().get(id);
         let def_id = match alloc {
             Some(AllocType::Memory(mem)) => {
-                return Ok(mem)
+                // We got tcx memory. Let the machine figure out whether and how to
+                // turn that into memory with the right pointer tag.
+                return Ok(M::static_with_default_tag(mem))
             }
             Some(AllocType::Function(..)) => {
                 return err!(DerefFunctionPointer)
@@ -335,63 +367,101 @@ fn get_static_alloc(
             EvalErrorKind::ReferencedConstant(err).into()
         }).map(|const_val| {
             if let ConstValue::ByRef(_, allocation, _) = const_val.val {
-                allocation
+                // We got tcx memory. Let the machine figure out whether and how to
+                // turn that into memory with the right pointer tag.
+                M::static_with_default_tag(allocation)
             } else {
                 bug!("Matching on non-ByRef static")
             }
         })
     }
 
-    pub fn get(&self, id: AllocId) -> EvalResult<'tcx, &Allocation> {
-        match self.alloc_map.get(&id) {
-            // Normal alloc?
-            Some(alloc) => Ok(&alloc.1),
-            // Static. No need to make any copies, just provide read access to the global static
-            // memory in tcx.
-            None => Self::get_static_alloc(self.tcx, id),
-        }
-    }
-
-    pub fn get_size_and_align(&self, id: AllocId) -> EvalResult<'tcx, (Size, Align)> {
-        Ok(match self.get(id) {
-            Ok(alloc) => (Size::from_bytes(alloc.bytes.len() as u64), alloc.align),
-            Err(err) => match err.kind {
-                EvalErrorKind::DanglingPointerDeref =>
-                    // This should be in the dead allocation map
-                    *self.dead_alloc_map.get(&id).expect(
-                        "allocation missing in dead_alloc_map"
-                    ),
-                // E.g. a function ptr allocation
-                _ => return Err(err)
+    pub fn get(&self, id: AllocId) -> EvalResult<'tcx, &Allocation<M::PointerTag>> {
+        // The error type of the inner closure here is somewhat funny.  We have two
+        // ways of "erroring": An actual error, or because we got a reference from
+        // `get_static_alloc` that we can actually use directly without inserting anything anywhere.
+        // So the error type is `EvalResult<'tcx, &Allocation<M::PointerTag>>`.
+        let a = self.alloc_map.get_or(id, || {
+            let alloc = Self::get_static_alloc(self.tcx, id).map_err(Err)?;
+            match alloc {
+                Cow::Borrowed(alloc) => {
+                    // We got a ref, cheaply return that as an "error" so that the
+                    // map does not get mutated.
+                    Err(Ok(alloc))
+                }
+                Cow::Owned(alloc) => {
+                    // Need to put it into the map and return a ref to that
+                    let kind = M::STATIC_KIND.expect(
+                        "I got an owned allocation that I have to copy but the machine does \
+                            not expect that to happen"
+                    );
+                    Ok((MemoryKind::Machine(kind), alloc))
+                }
             }
-        })
+        });
+        // Now unpack that funny error type
+        match a {
+            Ok(a) => Ok(&a.1),
+            Err(a) => a
+        }
     }
 
     pub fn get_mut(
         &mut self,
         id: AllocId,
-    ) -> EvalResult<'tcx, &mut Allocation> {
-        // Static?
-        if !self.alloc_map.contains_key(&id) {
-            // Ask the machine for what to do
-            if let Some(kind) = M::MUT_STATIC_KIND {
-                // The machine supports mutating statics.  Make a copy, use that.
-                self.deep_copy_static(id, MemoryKind::Machine(kind))?;
-            } else {
-                return err!(ModifiedConstantMemory)
+    ) -> EvalResult<'tcx, &mut Allocation<M::PointerTag>> {
+        let tcx = self.tcx;
+        let a = self.alloc_map.get_mut_or(id, || {
+            // Need to make a copy, even if `get_static_alloc` is able
+            // to give us a cheap reference.
+            let alloc = Self::get_static_alloc(tcx, id)?;
+            if alloc.mutability == Mutability::Immutable {
+                return err!(ModifiedConstantMemory);
+            }
+            let kind = M::STATIC_KIND.expect(
+                "An allocation is being mutated but the machine does not expect that to happen"
+            );
+            Ok((MemoryKind::Machine(kind), alloc.into_owned()))
+        });
+        // Unpack the error type manually because type inference doesn't
+        // work otherwise (and we cannot help it because `impl Trait`)
+        match a {
+            Err(e) => Err(e),
+            Ok(a) => {
+                let a = &mut a.1;
+                if a.mutability == Mutability::Immutable {
+                    return err!(ModifiedConstantMemory);
+                }
+                Ok(a)
             }
         }
-        // If we come here, we know the allocation is in our map
-        let alloc = &mut self.alloc_map.get_mut(&id).unwrap().1;
-        // See if we are allowed to mutate this
-        if alloc.mutability == Mutability::Immutable {
-            err!(ModifiedConstantMemory)
-        } else {
-            Ok(alloc)
+    }
+
+    pub fn get_size_and_align(&self, id: AllocId) -> (Size, Align) {
+        if let Ok(alloc) = self.get(id) {
+            return (Size::from_bytes(alloc.bytes.len() as u64), alloc.align);
+        }
+        // Could also be a fn ptr or extern static
+        match self.tcx.alloc_map.lock().get(id) {
+            Some(AllocType::Function(..)) => (Size::ZERO, Align::from_bytes(1, 1).unwrap()),
+            Some(AllocType::Static(did)) => {
+                // The only way `get` couldn't have worked here is if this is an extern static
+                assert!(self.tcx.is_foreign_item(did));
+                // Use size and align of the type
+                let ty = self.tcx.type_of(did);
+                let layout = self.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap();
+                (layout.size, layout.align)
+            }
+            _ => {
+                // Must be a deallocated pointer
+                *self.dead_alloc_map.get(&id).expect(
+                    "allocation missing in dead_alloc_map"
+                )
+            }
         }
     }
 
-    pub fn get_fn(&self, ptr: Pointer) -> EvalResult<'tcx, Instance<'tcx>> {
+    pub fn get_fn(&self, ptr: Pointer<M::PointerTag>) -> EvalResult<'tcx, Instance<'tcx>> {
         if ptr.offset.bytes() != 0 {
             return err!(InvalidFunctionPointer);
         }
@@ -402,108 +472,132 @@ pub fn get_fn(&self, ptr: Pointer) -> EvalResult<'tcx, Instance<'tcx>> {
         }
     }
 
+    pub fn mark_immutable(&mut self, id: AllocId) -> EvalResult<'tcx> {
+        self.get_mut(id)?.mutability = Mutability::Immutable;
+        Ok(())
+    }
+
     /// For debugging, print an allocation and all allocations it points to, recursively.
     pub fn dump_alloc(&self, id: AllocId) {
-        if !log_enabled!(::log::Level::Trace) {
-            return;
-        }
         self.dump_allocs(vec![id]);
     }
 
+    fn dump_alloc_helper<Tag>(
+        &self,
+        allocs_seen: &mut FxHashSet<AllocId>,
+        allocs_to_print: &mut VecDeque<AllocId>,
+        mut msg: String,
+        alloc: &Allocation<Tag>,
+        extra: String,
+    ) {
+        use std::fmt::Write;
+
+        let prefix_len = msg.len();
+        let mut relocations = vec![];
+
+        for i in 0..(alloc.bytes.len() as u64) {
+            let i = Size::from_bytes(i);
+            if let Some(&(_, target_id)) = alloc.relocations.get(&i) {
+                if allocs_seen.insert(target_id) {
+                    allocs_to_print.push_back(target_id);
+                }
+                relocations.push((i, target_id));
+            }
+            if alloc.undef_mask.is_range_defined(i, i + Size::from_bytes(1)).is_ok() {
+                // this `as usize` is fine, since `i` came from a `usize`
+                write!(msg, "{:02x} ", alloc.bytes[i.bytes() as usize]).unwrap();
+            } else {
+                msg.push_str("__ ");
+            }
+        }
+
+        trace!(
+            "{}({} bytes, alignment {}){}",
+            msg,
+            alloc.bytes.len(),
+            alloc.align.abi(),
+            extra
+        );
+
+        if !relocations.is_empty() {
+            msg.clear();
+            write!(msg, "{:1$}", "", prefix_len).unwrap(); // Print spaces.
+            let mut pos = Size::ZERO;
+            let relocation_width = (self.pointer_size().bytes() - 1) * 3;
+            for (i, target_id) in relocations {
+                // this `as usize` is fine, since we can't print more chars than `usize::MAX`
+                write!(msg, "{:1$}", "", ((i - pos) * 3).bytes() as usize).unwrap();
+                let target = format!("({})", target_id);
+                // this `as usize` is fine, since we can't print more chars than `usize::MAX`
+                write!(msg, "â””{0:─^1$}┘ ", target, relocation_width as usize).unwrap();
+                pos = i + self.pointer_size();
+            }
+            trace!("{}", msg);
+        }
+    }
+
     /// For debugging, print a list of allocations and all allocations they point to, recursively.
     pub fn dump_allocs(&self, mut allocs: Vec<AllocId>) {
         if !log_enabled!(::log::Level::Trace) {
             return;
         }
-        use std::fmt::Write;
         allocs.sort();
         allocs.dedup();
         let mut allocs_to_print = VecDeque::from(allocs);
         let mut allocs_seen = FxHashSet::default();
 
         while let Some(id) = allocs_to_print.pop_front() {
-            let mut msg = format!("Alloc {:<5} ", format!("{}:", id));
-            let prefix_len = msg.len();
-            let mut relocations = vec![];
-
-            let (alloc, immutable) =
-                // normal alloc?
-                match self.alloc_map.get(&id) {
-                    Some((kind, alloc)) => (alloc, match kind {
+            let msg = format!("Alloc {:<5} ", format!("{}:", id));
+
+            // normal alloc?
+            match self.alloc_map.get_or(id, || Err(())) {
+                Ok((kind, alloc)) => {
+                    let extra = match kind {
                         MemoryKind::Stack => " (stack)".to_owned(),
+                        MemoryKind::Vtable => " (vtable)".to_owned(),
                         MemoryKind::Machine(m) => format!(" ({:?})", m),
-                    }),
-                    None => {
-                        // static alloc?
-                        match self.tcx.alloc_map.lock().get(id) {
-                            Some(AllocType::Memory(a)) => (a, " (immutable)".to_owned()),
-                            Some(AllocType::Function(func)) => {
-                                trace!("{} {}", msg, func);
-                                continue;
-                            }
-                            Some(AllocType::Static(did)) => {
-                                trace!("{} {:?}", msg, did);
-                                continue;
-                            }
-                            None => {
-                                trace!("{} (deallocated)", msg);
-                                continue;
-                            }
+                    };
+                    self.dump_alloc_helper(
+                        &mut allocs_seen, &mut allocs_to_print,
+                        msg, alloc, extra
+                    );
+                },
+                Err(()) => {
+                    // static alloc?
+                    match self.tcx.alloc_map.lock().get(id) {
+                        Some(AllocType::Memory(alloc)) => {
+                            self.dump_alloc_helper(
+                                &mut allocs_seen, &mut allocs_to_print,
+                                msg, alloc, " (immutable)".to_owned()
+                            );
+                        }
+                        Some(AllocType::Function(func)) => {
+                            trace!("{} {}", msg, func);
+                        }
+                        Some(AllocType::Static(did)) => {
+                            trace!("{} {:?}", msg, did);
+                        }
+                        None => {
+                            trace!("{} (deallocated)", msg);
                         }
-                    },
-                };
-
-            for i in 0..(alloc.bytes.len() as u64) {
-                let i = Size::from_bytes(i);
-                if let Some(&target_id) = alloc.relocations.get(&i) {
-                    if allocs_seen.insert(target_id) {
-                        allocs_to_print.push_back(target_id);
                     }
-                    relocations.push((i, target_id));
-                }
-                if alloc.undef_mask.is_range_defined(i, i + Size::from_bytes(1)).is_ok() {
-                    // this `as usize` is fine, since `i` came from a `usize`
-                    write!(msg, "{:02x} ", alloc.bytes[i.bytes() as usize]).unwrap();
-                } else {
-                    msg.push_str("__ ");
-                }
-            }
+                },
+            };
 
-            trace!(
-                "{}({} bytes, alignment {}){}",
-                msg,
-                alloc.bytes.len(),
-                alloc.align.abi(),
-                immutable
-            );
-
-            if !relocations.is_empty() {
-                msg.clear();
-                write!(msg, "{:1$}", "", prefix_len).unwrap(); // Print spaces.
-                let mut pos = Size::ZERO;
-                let relocation_width = (self.pointer_size().bytes() - 1) * 3;
-                for (i, target_id) in relocations {
-                    // this `as usize` is fine, since we can't print more chars than `usize::MAX`
-                    write!(msg, "{:1$}", "", ((i - pos) * 3).bytes() as usize).unwrap();
-                    let target = format!("({})", target_id);
-                    // this `as usize` is fine, since we can't print more chars than `usize::MAX`
-                    write!(msg, "â””{0:─^1$}┘ ", target, relocation_width as usize).unwrap();
-                    pos = i + self.pointer_size();
-                }
-                trace!("{}", msg);
-            }
         }
     }
 
     pub fn leak_report(&self) -> usize {
         trace!("### LEAK REPORT ###");
-        let mut_static_kind = M::MUT_STATIC_KIND.map(|k| MemoryKind::Machine(k));
-        let leaks: Vec<_> = self.alloc_map
-            .iter()
-            .filter_map(|(&id, &(kind, _))|
-                // exclude mutable statics
-                if Some(kind) == mut_static_kind { None } else { Some(id) } )
-            .collect();
+        let leaks: Vec<_> = self.alloc_map.filter_map_collect(|&id, &(kind, _)| {
+            // exclude statics and vtables
+            let exclude = match kind {
+                MemoryKind::Stack => false,
+                MemoryKind::Vtable => true,
+                MemoryKind::Machine(k) => Some(k) == M::STATIC_KIND,
+            };
+            if exclude { None } else { Some(id) }
+        });
         let n = leaks.len();
         self.dump_allocs(leaks);
         n
@@ -515,17 +609,20 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
     /// The last argument controls whether we error out when there are undefined
     /// or pointer bytes.  You should never call this, call `get_bytes` or
     /// `get_bytes_with_undef_and_ptr` instead,
+    ///
+    /// This function also guarantees that the resulting pointer will remain stable
+    /// even when new allocations are pushed to the `HashMap`. `copy_repeatedly` relies
+    /// on that.
     fn get_bytes_internal(
         &self,
-        ptr: Pointer,
+        ptr: Pointer<M::PointerTag>,
         size: Size,
         align: Align,
         check_defined_and_ptr: bool,
     ) -> EvalResult<'tcx, &[u8]> {
         assert_ne!(size.bytes(), 0, "0-sized accesses should never even get a `Pointer`");
         self.check_align(ptr.into(), align)?;
-        // if ptr.offset is in bounds, then so is ptr (because offset checks for overflow)
-        self.check_bounds(ptr.offset(size, &*self)?, true)?;
+        self.check_bounds(ptr, size, true)?;
 
         if check_defined_and_ptr {
             self.check_defined(ptr, size)?;
@@ -543,7 +640,12 @@ fn get_bytes_internal(
     }
 
     #[inline]
-    fn get_bytes(&self, ptr: Pointer, size: Size, align: Align) -> EvalResult<'tcx, &[u8]> {
+    fn get_bytes(
+        &self,
+        ptr: Pointer<M::PointerTag>,
+        size: Size,
+        align: Align
+    ) -> EvalResult<'tcx, &[u8]> {
         self.get_bytes_internal(ptr, size, align, true)
     }
 
@@ -552,7 +654,7 @@ fn get_bytes(&self, ptr: Pointer, size: Size, align: Align) -> EvalResult<'tcx,
     #[inline]
     fn get_bytes_with_undef_and_ptr(
         &self,
-        ptr: Pointer,
+        ptr: Pointer<M::PointerTag>,
         size: Size,
         align: Align
     ) -> EvalResult<'tcx, &[u8]> {
@@ -563,14 +665,13 @@ fn get_bytes_with_undef_and_ptr(
     /// so be sure to actually put data there!
     fn get_bytes_mut(
         &mut self,
-        ptr: Pointer,
+        ptr: Pointer<M::PointerTag>,
         size: Size,
         align: Align,
     ) -> EvalResult<'tcx, &mut [u8]> {
         assert_ne!(size.bytes(), 0, "0-sized accesses should never even get a `Pointer`");
         self.check_align(ptr.into(), align)?;
-        // if ptr.offset is in bounds, then so is ptr (because offset checks for overflow)
-        self.check_bounds(ptr.offset(size, &self)?, true)?;
+        self.check_bounds(ptr, size, true)?;
 
         self.mark_definedness(ptr, size, true)?;
         self.clear_relocations(ptr, size)?;
@@ -583,8 +684,12 @@ fn get_bytes_mut(
     }
 }
 
-/// Reading and writing
-impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
+/// Interning (for CTFE)
+impl<'a, 'mir, 'tcx, M> Memory<'a, 'mir, 'tcx, M>
+where
+    M: Machine<'a, 'mir, 'tcx, PointerTag=()>,
+    M::MemoryMap: AllocMap<AllocId, (MemoryKind<M::MemoryKinds>, Allocation<()>)>,
+{
     /// mark an allocation as static and initialized, either mutable or not
     pub fn intern_static(
         &mut self,
@@ -600,14 +705,14 @@ pub fn intern_static(
         let (kind, mut alloc) = self.alloc_map.remove(&alloc_id).unwrap();
         match kind {
             MemoryKind::Machine(_) => bug!("Static cannot refer to machine memory"),
-            MemoryKind::Stack => {},
+            MemoryKind::Stack | MemoryKind::Vtable => {},
         }
         // ensure llvm knows not to put this into immutable memory
         alloc.mutability = mutability;
         let alloc = self.tcx.intern_const_alloc(alloc);
         self.tcx.alloc_map.lock().set_id_memory(alloc_id, alloc);
         // recurse into inner allocations
-        for &alloc in alloc.relocations.values() {
+        for &(_, alloc) in alloc.relocations.values() {
             // FIXME: Reusing the mutability here is likely incorrect.  It is originally
             // determined via `is_freeze`, and data is considered frozen if there is no
             // `UnsafeCell` *immediately* in that data -- however, this search stops
@@ -621,28 +726,15 @@ pub fn intern_static(
         }
         Ok(())
     }
+}
 
-    /// The alloc_id must refer to a (mutable) static; a deep copy of that
-    /// static is made into this memory.
-    fn deep_copy_static(
-        &mut self,
-        id: AllocId,
-        kind: MemoryKind<M::MemoryKinds>,
-    ) -> EvalResult<'tcx> {
-        let alloc = Self::get_static_alloc(self.tcx, id)?;
-        if alloc.mutability == Mutability::Immutable {
-            return err!(ModifiedConstantMemory);
-        }
-        let old = self.alloc_map.insert(id, (kind, alloc.clone()));
-        assert!(old.is_none(), "deep_copy_static: must not overwrite existing memory");
-        Ok(())
-    }
-
+/// Reading and writing
+impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
     pub fn copy(
         &mut self,
-        src: Scalar,
+        src: Scalar<M::PointerTag>,
         src_align: Align,
-        dest: Scalar,
+        dest: Scalar<M::PointerTag>,
         dest_align: Align,
         size: Size,
         nonoverlapping: bool,
@@ -652,9 +744,9 @@ pub fn copy(
 
     pub fn copy_repeatedly(
         &mut self,
-        src: Scalar,
+        src: Scalar<M::PointerTag>,
         src_align: Align,
-        dest: Scalar,
+        dest: Scalar<M::PointerTag>,
         dest_align: Align,
         size: Size,
         length: u64,
@@ -681,9 +773,9 @@ pub fn copy_repeatedly(
                 new_relocations.extend(
                     relocations
                     .iter()
-                    .map(|&(offset, alloc_id)| {
+                    .map(|&(offset, reloc)| {
                     (offset + dest.offset - src.offset + (i * size * relocations.len() as u64),
-                    alloc_id)
+                     reloc)
                     })
                 );
             }
@@ -698,6 +790,8 @@ pub fn copy_repeatedly(
         // SAFE: The above indexing would have panicked if there weren't at least `size` bytes
         // behind `src` and `dest`. Also, we use the overlapping-safe `ptr::copy` if `src` and
         // `dest` could possibly overlap.
+        // The pointers above remain valid even if the `HashMap` table is moved around because they
+        // point into the `Vec` storing the bytes.
         unsafe {
             assert_eq!(size.bytes() as usize as u64, size.bytes());
             if src.alloc_id == dest.alloc_id {
@@ -733,7 +827,7 @@ pub fn copy_repeatedly(
         Ok(())
     }
 
-    pub fn read_c_str(&self, ptr: Pointer) -> EvalResult<'tcx, &[u8]> {
+    pub fn read_c_str(&self, ptr: Pointer<M::PointerTag>) -> EvalResult<'tcx, &[u8]> {
         let alloc = self.get(ptr.alloc_id)?;
         assert_eq!(ptr.offset.bytes() as usize as u64, ptr.offset.bytes());
         let offset = ptr.offset.bytes() as usize;
@@ -744,11 +838,11 @@ pub fn read_c_str(&self, ptr: Pointer) -> EvalResult<'tcx, &[u8]> {
                 self.check_defined(ptr, p1)?;
                 Ok(&alloc.bytes[offset..offset + size])
             }
-            None => err!(UnterminatedCString(ptr)),
+            None => err!(UnterminatedCString(ptr.erase_tag())),
         }
     }
 
-    pub fn read_bytes(&self, ptr: Scalar, size: Size) -> EvalResult<'tcx, &[u8]> {
+    pub fn read_bytes(&self, ptr: Scalar<M::PointerTag>, size: Size) -> EvalResult<'tcx, &[u8]> {
         // Empty accesses don't need to be valid pointers, but they should still be non-NULL
         let align = Align::from_bytes(1, 1).unwrap();
         if size.bytes() == 0 {
@@ -758,7 +852,7 @@ pub fn read_bytes(&self, ptr: Scalar, size: Size) -> EvalResult<'tcx, &[u8]> {
         self.get_bytes(ptr.to_ptr()?, size, align)
     }
 
-    pub fn write_bytes(&mut self, ptr: Scalar, src: &[u8]) -> EvalResult<'tcx> {
+    pub fn write_bytes(&mut self, ptr: Scalar<M::PointerTag>, src: &[u8]) -> EvalResult<'tcx> {
         // Empty accesses don't need to be valid pointers, but they should still be non-NULL
         let align = Align::from_bytes(1, 1).unwrap();
         if src.is_empty() {
@@ -770,7 +864,12 @@ pub fn write_bytes(&mut self, ptr: Scalar, src: &[u8]) -> EvalResult<'tcx> {
         Ok(())
     }
 
-    pub fn write_repeat(&mut self, ptr: Scalar, val: u8, count: Size) -> EvalResult<'tcx> {
+    pub fn write_repeat(
+        &mut self,
+        ptr: Scalar<M::PointerTag>,
+        val: u8,
+        count: Size
+    ) -> EvalResult<'tcx> {
         // Empty accesses don't need to be valid pointers, but they should still be non-NULL
         let align = Align::from_bytes(1, 1).unwrap();
         if count.bytes() == 0 {
@@ -787,10 +886,10 @@ pub fn write_repeat(&mut self, ptr: Scalar, val: u8, count: Size) -> EvalResult<
     /// Read a *non-ZST* scalar
     pub fn read_scalar(
         &self,
-        ptr: Pointer,
+        ptr: Pointer<M::PointerTag>,
         ptr_align: Align,
         size: Size
-    ) -> EvalResult<'tcx, ScalarMaybeUndef> {
+    ) -> EvalResult<'tcx, ScalarMaybeUndef<M::PointerTag>> {
         // get_bytes_unchecked tests alignment and relocation edges
         let bytes = self.get_bytes_with_undef_and_ptr(
             ptr, size, ptr_align.min(self.int_align(size))
@@ -811,8 +910,8 @@ pub fn read_scalar(
         } else {
             let alloc = self.get(ptr.alloc_id)?;
             match alloc.relocations.get(&ptr.offset) {
-                Some(&alloc_id) => {
-                    let ptr = Pointer::new(alloc_id, Size::from_bytes(bits as u64));
+                Some(&(tag, alloc_id)) => {
+                    let ptr = Pointer::new_with_tag(alloc_id, Size::from_bytes(bits as u64), tag);
                     return Ok(ScalarMaybeUndef::Scalar(ptr.into()))
                 }
                 None => {},
@@ -822,17 +921,20 @@ pub fn read_scalar(
         Ok(ScalarMaybeUndef::Scalar(Scalar::from_uint(bits, size)))
     }
 
-    pub fn read_ptr_sized(&self, ptr: Pointer, ptr_align: Align)
-        -> EvalResult<'tcx, ScalarMaybeUndef> {
+    pub fn read_ptr_sized(
+        &self,
+        ptr: Pointer<M::PointerTag>,
+        ptr_align: Align
+    ) -> EvalResult<'tcx, ScalarMaybeUndef<M::PointerTag>> {
         self.read_scalar(ptr, ptr_align, self.pointer_size())
     }
 
     /// Write a *non-ZST* scalar
     pub fn write_scalar(
         &mut self,
-        ptr: Pointer,
+        ptr: Pointer<M::PointerTag>,
         ptr_align: Align,
-        val: ScalarMaybeUndef,
+        val: ScalarMaybeUndef<M::PointerTag>,
         type_size: Size,
     ) -> EvalResult<'tcx> {
         let val = match val {
@@ -866,7 +968,7 @@ pub fn write_scalar(
             Scalar::Ptr(val) => {
                 self.get_mut(ptr.alloc_id)?.relocations.insert(
                     ptr.offset,
-                    val.alloc_id,
+                    (val.tag, val.alloc_id),
                 );
             }
             _ => {}
@@ -875,8 +977,12 @@ pub fn write_scalar(
         Ok(())
     }
 
-    pub fn write_ptr_sized(&mut self, ptr: Pointer, ptr_align: Align, val: ScalarMaybeUndef)
-        -> EvalResult<'tcx> {
+    pub fn write_ptr_sized(
+        &mut self,
+        ptr: Pointer<M::PointerTag>,
+        ptr_align: Align,
+        val: ScalarMaybeUndef<M::PointerTag>
+    ) -> EvalResult<'tcx> {
         let ptr_size = self.pointer_size();
         self.write_scalar(ptr.into(), ptr_align, val, ptr_size)
     }
@@ -901,9 +1007,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
     /// Return all relocations overlapping with the given ptr-offset pair.
     fn relocations(
         &self,
-        ptr: Pointer,
+        ptr: Pointer<M::PointerTag>,
         size: Size,
-    ) -> EvalResult<'tcx, &[(Size, AllocId)]> {
+    ) -> EvalResult<'tcx, &[(Size, (M::PointerTag, AllocId))]> {
         // We have to go back `pointer_size - 1` bytes, as that one would still overlap with
         // the beginning of this range.
         let start = ptr.offset.bytes().saturating_sub(self.pointer_size().bytes() - 1);
@@ -913,7 +1019,7 @@ fn relocations(
 
     /// Check that there ar eno relocations overlapping with the given range.
     #[inline(always)]
-    fn check_relocations(&self, ptr: Pointer, size: Size) -> EvalResult<'tcx> {
+    fn check_relocations(&self, ptr: Pointer<M::PointerTag>, size: Size) -> EvalResult<'tcx> {
         if self.relocations(ptr, size)?.len() != 0 {
             err!(ReadPointerAsBytes)
         } else {
@@ -927,7 +1033,7 @@ fn check_relocations(&self, ptr: Pointer, size: Size) -> EvalResult<'tcx> {
     /// uninitialized.  This is a somewhat odd "spooky action at a distance",
     /// but it allows strictly more code to run than if we would just error
     /// immediately in that case.
-    fn clear_relocations(&mut self, ptr: Pointer, size: Size) -> EvalResult<'tcx> {
+    fn clear_relocations(&mut self, ptr: Pointer<M::PointerTag>, size: Size) -> EvalResult<'tcx> {
         // Find the start and end of the given range and its outermost relocations.
         let (first, last) = {
             // Find all relocations overlapping the given range.
@@ -962,7 +1068,7 @@ fn clear_relocations(&mut self, ptr: Pointer, size: Size) -> EvalResult<'tcx> {
     /// Error if there are relocations overlapping with the egdes of the
     /// given memory range.
     #[inline]
-    fn check_relocation_edges(&self, ptr: Pointer, size: Size) -> EvalResult<'tcx> {
+    fn check_relocation_edges(&self, ptr: Pointer<M::PointerTag>, size: Size) -> EvalResult<'tcx> {
         self.check_relocations(ptr, Size::ZERO)?;
         self.check_relocations(ptr.offset(size, self)?, Size::ZERO)?;
         Ok(())
@@ -974,8 +1080,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
     // FIXME: Add a fast version for the common, nonoverlapping case
     fn copy_undef_mask(
         &mut self,
-        src: Pointer,
-        dest: Pointer,
+        src: Pointer<M::PointerTag>,
+        dest: Pointer<M::PointerTag>,
         size: Size,
         repeat: u64,
     ) -> EvalResult<'tcx> {
@@ -1002,7 +1108,7 @@ fn copy_undef_mask(
     /// Checks that a range of bytes is defined. If not, returns the `ReadUndefBytes`
     /// error which will report the first byte which is undefined.
     #[inline]
-    fn check_defined(&self, ptr: Pointer, size: Size) -> EvalResult<'tcx> {
+    fn check_defined(&self, ptr: Pointer<M::PointerTag>, size: Size) -> EvalResult<'tcx> {
         let alloc = self.get(ptr.alloc_id)?;
         alloc.undef_mask.is_range_defined(
             ptr.offset,
@@ -1012,7 +1118,7 @@ fn check_defined(&self, ptr: Pointer, size: Size) -> EvalResult<'tcx> {
 
     pub fn mark_definedness(
         &mut self,
-        ptr: Pointer,
+        ptr: Pointer<M::PointerTag>,
         size: Size,
         new_state: bool,
     ) -> EvalResult<'tcx> {
index b840af193b64a7d87c4fb3c4a40664d93e19a26f..39628598ef31cd1d1172d9fa35e16e0ce22bb964 100644 (file)
@@ -32,6 +32,8 @@
 
 pub use self::memory::{Memory, MemoryKind};
 
-pub use self::machine::Machine;
+pub use self::machine::{Machine, AllocMap};
 
 pub use self::operand::{ScalarMaybeUndef, Value, ValTy, Operand, OpTy};
+
+pub use self::validity::RefTracking;
index b53bcfa993d53d9ecb389c9347e442afe73eb363..039a92cee2ca2fcfba65f06617ece23d6de56141 100644 (file)
 use super::{EvalContext, Machine, MemPlace, MPlaceTy, MemoryKind};
 
 #[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, RustcEncodable, RustcDecodable, Hash)]
-pub enum ScalarMaybeUndef<Id=AllocId> {
-    Scalar(Scalar<Id>),
+pub enum ScalarMaybeUndef<Tag=(), Id=AllocId> {
+    Scalar(Scalar<Tag, Id>),
     Undef,
 }
 
-impl From<Scalar> for ScalarMaybeUndef {
+impl<Tag> From<Scalar<Tag>> for ScalarMaybeUndef<Tag> {
     #[inline(always)]
-    fn from(s: Scalar) -> Self {
+    fn from(s: Scalar<Tag>) -> Self {
         ScalarMaybeUndef::Scalar(s)
     }
 }
 
-impl<'tcx> ScalarMaybeUndef {
+impl<'tcx> ScalarMaybeUndef<()> {
     #[inline]
-    pub fn not_undef(self) -> EvalResult<'static, Scalar> {
+    pub fn with_default_tag<Tag>(self) -> ScalarMaybeUndef<Tag>
+        where Tag: Default
+    {
+        match self {
+            ScalarMaybeUndef::Scalar(s) => ScalarMaybeUndef::Scalar(s.with_default_tag()),
+            ScalarMaybeUndef::Undef => ScalarMaybeUndef::Undef,
+        }
+    }
+}
+
+impl<'tcx, Tag> ScalarMaybeUndef<Tag> {
+    #[inline]
+    pub fn erase_tag(self) -> ScalarMaybeUndef
+    {
+        match self {
+            ScalarMaybeUndef::Scalar(s) => ScalarMaybeUndef::Scalar(s.erase_tag()),
+            ScalarMaybeUndef::Undef => ScalarMaybeUndef::Undef,
+        }
+    }
+
+    #[inline]
+    pub fn not_undef(self) -> EvalResult<'static, Scalar<Tag>> {
         match self {
             ScalarMaybeUndef::Scalar(scalar) => Ok(scalar),
             ScalarMaybeUndef::Undef => err!(ReadUndefBytes(Size::from_bytes(0))),
@@ -47,7 +68,7 @@ pub fn not_undef(self) -> EvalResult<'static, Scalar> {
     }
 
     #[inline(always)]
-    pub fn to_ptr(self) -> EvalResult<'tcx, Pointer> {
+    pub fn to_ptr(self) -> EvalResult<'tcx, Pointer<Tag>> {
         self.not_undef()?.to_ptr()
     }
 
@@ -126,26 +147,49 @@ pub fn to_isize(self, cx: impl HasDataLayout) -> EvalResult<'tcx, i64> {
 /// In particular, thanks to `ScalarPair`, arithmetic operations and casts can be entirely
 /// defined on `Value`, and do not have to work with a `Place`.
 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
-pub enum Value<Id=AllocId> {
-    Scalar(ScalarMaybeUndef<Id>),
-    ScalarPair(ScalarMaybeUndef<Id>, ScalarMaybeUndef<Id>),
+pub enum Value<Tag=(), Id=AllocId> {
+    Scalar(ScalarMaybeUndef<Tag, Id>),
+    ScalarPair(ScalarMaybeUndef<Tag, Id>, ScalarMaybeUndef<Tag, Id>),
 }
 
-impl<'tcx> Value {
+impl Value {
+    #[inline]
+    pub fn with_default_tag<Tag>(self) -> Value<Tag>
+        where Tag: Default
+    {
+        match self {
+            Value::Scalar(x) => Value::Scalar(x.with_default_tag()),
+            Value::ScalarPair(x, y) =>
+                Value::ScalarPair(x.with_default_tag(), y.with_default_tag()),
+        }
+    }
+}
+
+impl<'tcx, Tag> Value<Tag> {
+    #[inline]
+    pub fn erase_tag(self) -> Value
+    {
+        match self {
+            Value::Scalar(x) => Value::Scalar(x.erase_tag()),
+            Value::ScalarPair(x, y) =>
+                Value::ScalarPair(x.erase_tag(), y.erase_tag()),
+        }
+    }
+
     pub fn new_slice(
-        val: Scalar,
+        val: Scalar<Tag>,
         len: u64,
         cx: impl HasDataLayout
     ) -> Self {
         Value::ScalarPair(val.into(), Scalar::from_uint(len, cx.data_layout().pointer_size).into())
     }
 
-    pub fn new_dyn_trait(val: Scalar, vtable: Pointer) -> Self {
+    pub fn new_dyn_trait(val: Scalar<Tag>, vtable: Pointer<Tag>) -> Self {
         Value::ScalarPair(val.into(), Scalar::Ptr(vtable).into())
     }
 
     #[inline]
-    pub fn to_scalar_or_undef(self) -> ScalarMaybeUndef {
+    pub fn to_scalar_or_undef(self) -> ScalarMaybeUndef<Tag> {
         match self {
             Value::Scalar(val) => val,
             Value::ScalarPair(..) => bug!("Got a fat pointer where a scalar was expected"),
@@ -153,12 +197,12 @@ pub fn to_scalar_or_undef(self) -> ScalarMaybeUndef {
     }
 
     #[inline]
-    pub fn to_scalar(self) -> EvalResult<'tcx, Scalar> {
+    pub fn to_scalar(self) -> EvalResult<'tcx, Scalar<Tag>> {
         self.to_scalar_or_undef().not_undef()
     }
 
     #[inline]
-    pub fn to_scalar_pair(self) -> EvalResult<'tcx, (Scalar, Scalar)> {
+    pub fn to_scalar_pair(self) -> EvalResult<'tcx, (Scalar<Tag>, Scalar<Tag>)> {
         match self {
             Value::Scalar(..) => bug!("Got a thin pointer where a scalar pair was expected"),
             Value::ScalarPair(a, b) => Ok((a.not_undef()?, b.not_undef()?))
@@ -168,7 +212,7 @@ pub fn to_scalar_pair(self) -> EvalResult<'tcx, (Scalar, Scalar)> {
     /// Convert the value into a pointer (or a pointer-sized integer).
     /// Throws away the second half of a ScalarPair!
     #[inline]
-    pub fn to_scalar_ptr(self) -> EvalResult<'tcx, Scalar> {
+    pub fn to_scalar_ptr(self) -> EvalResult<'tcx, Scalar<Tag>> {
         match self {
             Value::Scalar(ptr) |
             Value::ScalarPair(ptr, _) => ptr.not_undef(),
@@ -179,15 +223,15 @@ pub fn to_scalar_ptr(self) -> EvalResult<'tcx, Scalar> {
 // ScalarPair needs a type to interpret, so we often have a value and a type together
 // as input for binary and cast operations.
 #[derive(Copy, Clone, Debug)]
-pub struct ValTy<'tcx> {
-    value: Value,
+pub struct ValTy<'tcx, Tag=()> {
+    value: Value<Tag>,
     pub layout: TyLayout<'tcx>,
 }
 
-impl<'tcx> ::std::ops::Deref for ValTy<'tcx> {
-    type Target = Value;
+impl<'tcx, Tag> ::std::ops::Deref for ValTy<'tcx, Tag> {
+    type Target = Value<Tag>;
     #[inline(always)]
-    fn deref(&self) -> &Value {
+    fn deref(&self) -> &Value<Tag> {
         &self.value
     }
 }
@@ -196,14 +240,37 @@ fn deref(&self) -> &Value {
 /// or still in memory.  The latter is an optimization, to delay reading that chunk of
 /// memory and to avoid having to store arbitrary-sized data here.
 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
-pub enum Operand<Id=AllocId> {
-    Immediate(Value<Id>),
-    Indirect(MemPlace<Id>),
+pub enum Operand<Tag=(), Id=AllocId> {
+    Immediate(Value<Tag, Id>),
+    Indirect(MemPlace<Tag, Id>),
 }
 
 impl Operand {
     #[inline]
-    pub fn to_mem_place(self) -> MemPlace {
+    pub fn with_default_tag<Tag>(self) -> Operand<Tag>
+        where Tag: Default
+    {
+        match self {
+            Operand::Immediate(x) => Operand::Immediate(x.with_default_tag()),
+            Operand::Indirect(x) => Operand::Indirect(x.with_default_tag()),
+        }
+    }
+}
+
+impl<Tag> Operand<Tag> {
+    #[inline]
+    pub fn erase_tag(self) -> Operand
+    {
+        match self {
+            Operand::Immediate(x) => Operand::Immediate(x.erase_tag()),
+            Operand::Indirect(x) => Operand::Indirect(x.erase_tag()),
+        }
+    }
+
+    #[inline]
+    pub fn to_mem_place(self) -> MemPlace<Tag>
+        where Tag: ::std::fmt::Debug
+    {
         match self {
             Operand::Indirect(mplace) => mplace,
             _ => bug!("to_mem_place: expected Operand::Indirect, got {:?}", self),
@@ -212,7 +279,9 @@ pub fn to_mem_place(self) -> MemPlace {
     }
 
     #[inline]
-    pub fn to_immediate(self) -> Value {
+    pub fn to_immediate(self) -> Value<Tag>
+        where Tag: ::std::fmt::Debug
+    {
         match self {
             Operand::Immediate(val) => val,
             _ => bug!("to_immediate: expected Operand::Immediate, got {:?}", self),
@@ -222,22 +291,22 @@ pub fn to_immediate(self) -> Value {
 }
 
 #[derive(Copy, Clone, Debug)]
-pub struct OpTy<'tcx> {
-    crate op: Operand, // ideally we'd make this private, but const_prop needs this
+pub struct OpTy<'tcx, Tag=()> {
+    crate op: Operand<Tag>, // ideally we'd make this private, but const_prop needs this
     pub layout: TyLayout<'tcx>,
 }
 
-impl<'tcx> ::std::ops::Deref for OpTy<'tcx> {
-    type Target = Operand;
+impl<'tcx, Tag> ::std::ops::Deref for OpTy<'tcx, Tag> {
+    type Target = Operand<Tag>;
     #[inline(always)]
-    fn deref(&self) -> &Operand {
+    fn deref(&self) -> &Operand<Tag> {
         &self.op
     }
 }
 
-impl<'tcx> From<MPlaceTy<'tcx>> for OpTy<'tcx> {
+impl<'tcx, Tag: Copy> From<MPlaceTy<'tcx, Tag>> for OpTy<'tcx, Tag> {
     #[inline(always)]
-    fn from(mplace: MPlaceTy<'tcx>) -> Self {
+    fn from(mplace: MPlaceTy<'tcx, Tag>) -> Self {
         OpTy {
             op: Operand::Indirect(*mplace),
             layout: mplace.layout
@@ -245,9 +314,9 @@ fn from(mplace: MPlaceTy<'tcx>) -> Self {
     }
 }
 
-impl<'tcx> From<ValTy<'tcx>> for OpTy<'tcx> {
+impl<'tcx, Tag> From<ValTy<'tcx, Tag>> for OpTy<'tcx, Tag> {
     #[inline(always)]
-    fn from(val: ValTy<'tcx>) -> Self {
+    fn from(val: ValTy<'tcx, Tag>) -> Self {
         OpTy {
             op: Operand::Immediate(val.value),
             layout: val.layout
@@ -256,18 +325,36 @@ fn from(val: ValTy<'tcx>) -> Self {
 }
 
 // Validation needs to hash OpTy, but we cannot hash Layout -- so we just hash the type
-impl<'tcx> Hash for OpTy<'tcx> {
+impl<'tcx, Tag> Hash for OpTy<'tcx, Tag>
+    where Tag: Hash
+{
     fn hash<H: Hasher>(&self, state: &mut H) {
         self.op.hash(state);
         self.layout.ty.hash(state);
     }
 }
-impl<'tcx> PartialEq for OpTy<'tcx> {
+impl<'tcx, Tag> PartialEq for OpTy<'tcx, Tag>
+    where Tag: PartialEq
+{
     fn eq(&self, other: &Self) -> bool {
         self.op == other.op && self.layout.ty == other.layout.ty
     }
 }
-impl<'tcx> Eq for OpTy<'tcx> {}
+impl<'tcx, Tag> Eq for OpTy<'tcx, Tag>
+    where Tag: Eq
+{}
+
+impl<'tcx, Tag> OpTy<'tcx, Tag>
+{
+    #[inline]
+    pub fn erase_tag(self) -> OpTy<'tcx>
+    {
+        OpTy {
+            op: self.op.erase_tag(),
+            layout: self.layout,
+        }
+    }
+}
 
 // Use the existing layout if given (but sanity check in debug mode),
 // or compute the layout.
@@ -295,8 +382,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
     /// Return None if the layout does not permit loading this as a value.
     pub(super) fn try_read_value_from_mplace(
         &self,
-        mplace: MPlaceTy<'tcx>,
-    ) -> EvalResult<'tcx, Option<Value>> {
+        mplace: MPlaceTy<'tcx, M::PointerTag>,
+    ) -> EvalResult<'tcx, Option<Value<M::PointerTag>>> {
         if mplace.layout.is_unsized() {
             // Dont touch unsized
             return Ok(None);
@@ -339,8 +426,8 @@ pub(super) fn try_read_value_from_mplace(
     /// in a `Value`, not on which data is stored there currently.
     pub(crate) fn try_read_value(
         &self,
-        src: OpTy<'tcx>,
-    ) -> EvalResult<'tcx, Result<Value, MemPlace>> {
+        src: OpTy<'tcx, M::PointerTag>,
+    ) -> EvalResult<'tcx, Result<Value<M::PointerTag>, MemPlace<M::PointerTag>>> {
         Ok(match src.try_as_mplace() {
             Ok(mplace) => {
                 if let Some(val) = self.try_read_value_from_mplace(mplace)? {
@@ -355,7 +442,10 @@ pub(crate) fn try_read_value(
 
     /// Read a value from a place, asserting that that is possible with the given layout.
     #[inline(always)]
-    pub fn read_value(&self, op: OpTy<'tcx>) -> EvalResult<'tcx, ValTy<'tcx>> {
+    pub fn read_value(
+        &self,
+        op: OpTy<'tcx, M::PointerTag>
+    ) -> EvalResult<'tcx, ValTy<'tcx, M::PointerTag>> {
         if let Ok(value) = self.try_read_value(op)? {
             Ok(ValTy { value, layout: op.layout })
         } else {
@@ -364,7 +454,10 @@ pub fn read_value(&self, op: OpTy<'tcx>) -> EvalResult<'tcx, ValTy<'tcx>> {
     }
 
     /// Read a scalar from a place
-    pub fn read_scalar(&self, op: OpTy<'tcx>) -> EvalResult<'tcx, ScalarMaybeUndef> {
+    pub fn read_scalar(
+        &self,
+        op: OpTy<'tcx, M::PointerTag>
+    ) -> EvalResult<'tcx, ScalarMaybeUndef<M::PointerTag>> {
         match *self.read_value(op)? {
             Value::ScalarPair(..) => bug!("got ScalarPair for type: {:?}", op.layout.ty),
             Value::Scalar(val) => Ok(val),
@@ -374,7 +467,7 @@ pub fn read_scalar(&self, op: OpTy<'tcx>) -> EvalResult<'tcx, ScalarMaybeUndef>
     // Turn the MPlace into a string (must already be dereferenced!)
     pub fn read_str(
         &self,
-        mplace: MPlaceTy<'tcx>,
+        mplace: MPlaceTy<'tcx, M::PointerTag>,
     ) -> EvalResult<'tcx, &str> {
         let len = mplace.len(self)?;
         let bytes = self.memory.read_bytes(mplace.ptr, Size::from_bytes(len as u64))?;
@@ -383,7 +476,10 @@ pub fn read_str(
         Ok(str)
     }
 
-    pub fn uninit_operand(&mut self, layout: TyLayout<'tcx>) -> EvalResult<'tcx, Operand> {
+    pub fn uninit_operand(
+        &mut self,
+        layout: TyLayout<'tcx>
+    ) -> EvalResult<'tcx, Operand<M::PointerTag>> {
         // This decides which types we will use the Immediate optimization for, and hence should
         // match what `try_read_value` and `eval_place_to_op` support.
         if layout.is_zst() {
@@ -410,9 +506,9 @@ pub fn uninit_operand(&mut self, layout: TyLayout<'tcx>) -> EvalResult<'tcx, Ope
     /// Projection functions
     pub fn operand_field(
         &self,
-        op: OpTy<'tcx>,
+        op: OpTy<'tcx, M::PointerTag>,
         field: u64,
-    ) -> EvalResult<'tcx, OpTy<'tcx>> {
+    ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
         let base = match op.try_as_mplace() {
             Ok(mplace) => {
                 // The easy case
@@ -445,9 +541,9 @@ pub fn operand_field(
 
     pub fn operand_downcast(
         &self,
-        op: OpTy<'tcx>,
+        op: OpTy<'tcx, M::PointerTag>,
         variant: usize,
-    ) -> EvalResult<'tcx, OpTy<'tcx>> {
+    ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
         // Downcasts only change the layout
         Ok(match op.try_as_mplace() {
             Ok(mplace) => {
@@ -464,8 +560,8 @@ pub fn operand_downcast(
     // will always be a MemPlace.
     pub(super) fn deref_operand(
         &self,
-        src: OpTy<'tcx>,
-    ) -> EvalResult<'tcx, MPlaceTy<'tcx>> {
+        src: OpTy<'tcx, M::PointerTag>,
+    ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
         let val = self.read_value(src)?;
         trace!("deref to {} on {:?}", val.layout.ty, *val);
         Ok(self.ref_to_mplace(val)?)
@@ -473,9 +569,9 @@ pub(super) fn deref_operand(
 
     pub fn operand_projection(
         &self,
-        base: OpTy<'tcx>,
+        base: OpTy<'tcx, M::PointerTag>,
         proj_elem: &mir::PlaceElem<'tcx>,
-    ) -> EvalResult<'tcx, OpTy<'tcx>> {
+    ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
         use rustc::mir::ProjectionElem::*;
         Ok(match *proj_elem {
             Field(field, _) => self.operand_field(base, field.index() as u64)?,
@@ -503,7 +599,7 @@ fn eval_place_to_op(
         &self,
         mir_place: &mir::Place<'tcx>,
         layout: Option<TyLayout<'tcx>>,
-    ) -> EvalResult<'tcx, OpTy<'tcx>> {
+    ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
         use rustc::mir::Place::*;
         let op = match *mir_place {
             Local(mir::RETURN_PLACE) => return err!(ReadFromReturnPointer),
@@ -533,7 +629,7 @@ pub fn eval_operand(
         &self,
         mir_op: &mir::Operand<'tcx>,
         layout: Option<TyLayout<'tcx>>,
-    ) -> EvalResult<'tcx, OpTy<'tcx>> {
+    ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
         use rustc::mir::Operand::*;
         let op = match *mir_op {
             // FIXME: do some more logic on `move` to invalidate the old location
@@ -558,7 +654,7 @@ pub fn eval_operand(
     pub(super) fn eval_operands(
         &self,
         ops: &[mir::Operand<'tcx>],
-    ) -> EvalResult<'tcx, Vec<OpTy<'tcx>>> {
+    ) -> EvalResult<'tcx, Vec<OpTy<'tcx, M::PointerTag>>> {
         ops.into_iter()
             .map(|op| self.eval_operand(op, None))
             .collect()
@@ -568,7 +664,7 @@ pub(super) fn eval_operands(
     pub(super) fn const_value_to_op(
         &self,
         val: ConstValue<'tcx>,
-    ) -> EvalResult<'tcx, Operand> {
+    ) -> EvalResult<'tcx, Operand<M::PointerTag>> {
         trace!("const_value_to_op: {:?}", val);
         match val {
             ConstValue::Unevaluated(def_id, substs) => {
@@ -581,23 +677,28 @@ pub(super) fn const_value_to_op(
             ConstValue::ByRef(id, alloc, offset) => {
                 // We rely on mutability being set correctly in that allocation to prevent writes
                 // where none should happen -- and for `static mut`, we copy on demand anyway.
-                Ok(Operand::Indirect(MemPlace::from_ptr(Pointer::new(id, offset), alloc.align)))
+                Ok(Operand::Indirect(
+                    MemPlace::from_ptr(Pointer::new(id, offset), alloc.align)
+                ).with_default_tag())
             },
             ConstValue::ScalarPair(a, b) =>
-                Ok(Operand::Immediate(Value::ScalarPair(a.into(), b.into()))),
+                Ok(Operand::Immediate(Value::ScalarPair(a.into(), b.into())).with_default_tag()),
             ConstValue::Scalar(x) =>
-                Ok(Operand::Immediate(Value::Scalar(x.into()))),
+                Ok(Operand::Immediate(Value::Scalar(x.into())).with_default_tag()),
         }
     }
     pub fn const_to_op(
         &self,
         cnst: &ty::Const<'tcx>,
-    ) -> EvalResult<'tcx, OpTy<'tcx>> {
+    ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
         let op = self.const_value_to_op(cnst.val)?;
         Ok(OpTy { op, layout: self.layout_of(cnst.ty)? })
     }
 
-    pub(super) fn global_to_op(&self, gid: GlobalId<'tcx>) -> EvalResult<'tcx, Operand> {
+    pub(super) fn global_to_op(
+        &self,
+        gid: GlobalId<'tcx>
+    ) -> EvalResult<'tcx, Operand<M::PointerTag>> {
         let cv = self.const_eval(gid)?;
         self.const_value_to_op(cv.val)
     }
@@ -605,7 +706,7 @@ pub(super) fn global_to_op(&self, gid: GlobalId<'tcx>) -> EvalResult<'tcx, Opera
     /// Read discriminant, return the runtime value as well as the variant index.
     pub fn read_discriminant(
         &self,
-        rval: OpTy<'tcx>,
+        rval: OpTy<'tcx, M::PointerTag>,
     ) -> EvalResult<'tcx, (u128, usize)> {
         trace!("read_discriminant_value {:#?}", rval.layout);
         if rval.layout.abi.is_uninhabited() {
index dd6ee374c0facc9f4b4370f5577fb62f8c7b6636..5f4bafc39f3deec8aa57efb12157d67c36fd7a14 100644 (file)
@@ -24,9 +24,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
     pub fn binop_with_overflow(
         &mut self,
         op: mir::BinOp,
-        left: ValTy<'tcx>,
-        right: ValTy<'tcx>,
-        dest: PlaceTy<'tcx>,
+        left: ValTy<'tcx, M::PointerTag>,
+        right: ValTy<'tcx, M::PointerTag>,
+        dest: PlaceTy<'tcx, M::PointerTag>,
     ) -> EvalResult<'tcx> {
         let (val, overflowed) = self.binary_op_val(op, left, right)?;
         let val = Value::ScalarPair(val.into(), Scalar::from_bool(overflowed).into());
@@ -38,9 +38,9 @@ pub fn binop_with_overflow(
     pub fn binop_ignore_overflow(
         &mut self,
         op: mir::BinOp,
-        left: ValTy<'tcx>,
-        right: ValTy<'tcx>,
-        dest: PlaceTy<'tcx>,
+        left: ValTy<'tcx, M::PointerTag>,
+        right: ValTy<'tcx, M::PointerTag>,
+        dest: PlaceTy<'tcx, M::PointerTag>,
     ) -> EvalResult<'tcx> {
         let (val, _overflowed) = self.binary_op_val(op, left, right)?;
         self.write_scalar(val, dest)
@@ -53,7 +53,7 @@ fn binary_char_op(
         bin_op: mir::BinOp,
         l: char,
         r: char,
-    ) -> EvalResult<'tcx, (Scalar, bool)> {
+    ) -> EvalResult<'tcx, (Scalar<M::PointerTag>, bool)> {
         use rustc::mir::BinOp::*;
 
         let res = match bin_op {
@@ -73,7 +73,7 @@ fn binary_bool_op(
         bin_op: mir::BinOp,
         l: bool,
         r: bool,
-    ) -> EvalResult<'tcx, (Scalar, bool)> {
+    ) -> EvalResult<'tcx, (Scalar<M::PointerTag>, bool)> {
         use rustc::mir::BinOp::*;
 
         let res = match bin_op {
@@ -98,7 +98,7 @@ fn binary_float_op(
         // passing in raw bits
         l: u128,
         r: u128,
-    ) -> EvalResult<'tcx, (Scalar, bool)> {
+    ) -> EvalResult<'tcx, (Scalar<M::PointerTag>, bool)> {
         use rustc::mir::BinOp::*;
 
         macro_rules! float_math {
@@ -138,7 +138,7 @@ fn binary_int_op(
         left_layout: TyLayout<'tcx>,
         r: u128,
         right_layout: TyLayout<'tcx>,
-    ) -> EvalResult<'tcx, (Scalar, bool)> {
+    ) -> EvalResult<'tcx, (Scalar<M::PointerTag>, bool)> {
         use rustc::mir::BinOp::*;
 
         // Shift ops can have an RHS with a different numeric type.
@@ -288,9 +288,9 @@ fn binary_int_op(
     pub fn binary_op_val(
         &self,
         bin_op: mir::BinOp,
-        left: ValTy<'tcx>,
-        right: ValTy<'tcx>,
-    ) -> EvalResult<'tcx, (Scalar, bool)> {
+        left: ValTy<'tcx, M::PointerTag>,
+        right: ValTy<'tcx, M::PointerTag>,
+    ) -> EvalResult<'tcx, (Scalar<M::PointerTag>, bool)> {
         self.binary_op(
             bin_op,
             left.to_scalar()?, left.layout,
@@ -302,11 +302,11 @@ pub fn binary_op_val(
     pub fn binary_op(
         &self,
         bin_op: mir::BinOp,
-        left: Scalar,
+        left: Scalar<M::PointerTag>,
         left_layout: TyLayout<'tcx>,
-        right: Scalar,
+        right: Scalar<M::PointerTag>,
         right_layout: TyLayout<'tcx>,
-    ) -> EvalResult<'tcx, (Scalar, bool)> {
+    ) -> EvalResult<'tcx, (Scalar<M::PointerTag>, bool)> {
         trace!("Running binary op {:?}: {:?} ({:?}), {:?} ({:?})",
             bin_op, left, left_layout.ty, right, right_layout.ty);
 
@@ -352,9 +352,9 @@ pub fn binary_op(
     pub fn unary_op(
         &self,
         un_op: mir::UnOp,
-        val: Scalar,
+        val: Scalar<M::PointerTag>,
         layout: TyLayout<'tcx>,
-    ) -> EvalResult<'tcx, Scalar> {
+    ) -> EvalResult<'tcx, Scalar<M::PointerTag>> {
         use rustc::mir::UnOp::*;
         use rustc_apfloat::ieee::{Single, Double};
         use rustc_apfloat::Float;
index 8878e5ca83f41f05ca770d22f78b756fa03b0316..8b9c6a5a270537fdaec0cff1e9e4c4c711ccf876 100644 (file)
 //! All high-level functions to write to memory work on places as destinations.
 
 use std::convert::TryFrom;
+use std::hash::Hash;
 
 use rustc::mir;
 use rustc::ty::{self, Ty};
 use rustc::ty::layout::{self, Size, Align, LayoutOf, TyLayout, HasDataLayout};
 
 use rustc::mir::interpret::{
-    GlobalId, AllocId, Scalar, EvalResult, Pointer, PointerArithmetic
+    GlobalId, AllocId, Allocation, Scalar, EvalResult, Pointer, PointerArithmetic
+};
+use super::{
+    EvalContext, Machine, AllocMap,
+    Value, ValTy, ScalarMaybeUndef, Operand, OpTy, MemoryKind
 };
-use super::{EvalContext, Machine, Value, ValTy, ScalarMaybeUndef, Operand, OpTy, MemoryKind};
 
 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
-pub struct MemPlace<Id=AllocId> {
+pub struct MemPlace<Tag=(), Id=AllocId> {
     /// A place may have an integral pointer for ZSTs, and since it might
     /// be turned back into a reference before ever being dereferenced.
     /// However, it may never be undef.
-    pub ptr: Scalar<Id>,
+    pub ptr: Scalar<Tag, Id>,
     pub align: Align,
     /// Metadata for unsized places.  Interpretation is up to the type.
     /// Must not be present for sized types, but can be missing for unsized types
     /// (e.g. `extern type`).
-    pub extra: Option<Scalar<Id>>,
+    pub meta: Option<Scalar<Tag, Id>>,
 }
 
 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
-pub enum Place<Id=AllocId> {
+pub enum Place<Tag=(), Id=AllocId> {
     /// A place referring to a value allocated in the `Memory` system.
-    Ptr(MemPlace<Id>),
+    Ptr(MemPlace<Tag, Id>),
 
     /// To support alloc-free locals, we are able to write directly to a local.
     /// (Without that optimization, we'd just always be a `MemPlace`.)
@@ -50,37 +54,37 @@ pub enum Place<Id=AllocId> {
 }
 
 #[derive(Copy, Clone, Debug)]
-pub struct PlaceTy<'tcx> {
-    place: Place,
+pub struct PlaceTy<'tcx, Tag=()> {
+    place: Place<Tag>,
     pub layout: TyLayout<'tcx>,
 }
 
-impl<'tcx> ::std::ops::Deref for PlaceTy<'tcx> {
-    type Target = Place;
+impl<'tcx, Tag> ::std::ops::Deref for PlaceTy<'tcx, Tag> {
+    type Target = Place<Tag>;
     #[inline(always)]
-    fn deref(&self) -> &Place {
+    fn deref(&self) -> &Place<Tag> {
         &self.place
     }
 }
 
 /// A MemPlace with its layout. Constructing it is only possible in this module.
 #[derive(Copy, Clone, Debug)]
-pub struct MPlaceTy<'tcx> {
-    mplace: MemPlace,
+pub struct MPlaceTy<'tcx, Tag=()> {
+    mplace: MemPlace<Tag>,
     pub layout: TyLayout<'tcx>,
 }
 
-impl<'tcx> ::std::ops::Deref for MPlaceTy<'tcx> {
-    type Target = MemPlace;
+impl<'tcx, Tag> ::std::ops::Deref for MPlaceTy<'tcx, Tag> {
+    type Target = MemPlace<Tag>;
     #[inline(always)]
-    fn deref(&self) -> &MemPlace {
+    fn deref(&self) -> &MemPlace<Tag> {
         &self.mplace
     }
 }
 
-impl<'tcx> From<MPlaceTy<'tcx>> for PlaceTy<'tcx> {
+impl<'tcx, Tag> From<MPlaceTy<'tcx, Tag>> for PlaceTy<'tcx, Tag> {
     #[inline(always)]
-    fn from(mplace: MPlaceTy<'tcx>) -> Self {
+    fn from(mplace: MPlaceTy<'tcx, Tag>) -> Self {
         PlaceTy {
             place: Place::Ptr(mplace.mplace),
             layout: mplace.layout
@@ -89,29 +93,52 @@ fn from(mplace: MPlaceTy<'tcx>) -> Self {
 }
 
 impl MemPlace {
+    #[inline]
+    pub fn with_default_tag<Tag>(self) -> MemPlace<Tag>
+        where Tag: Default
+    {
+        MemPlace {
+            ptr: self.ptr.with_default_tag(),
+            align: self.align,
+            meta: self.meta.map(Scalar::with_default_tag),
+        }
+    }
+}
+
+impl<Tag> MemPlace<Tag> {
+    #[inline]
+    pub fn erase_tag(self) -> MemPlace
+    {
+        MemPlace {
+            ptr: self.ptr.erase_tag(),
+            align: self.align,
+            meta: self.meta.map(Scalar::erase_tag),
+        }
+    }
+
     #[inline(always)]
-    pub fn from_scalar_ptr(ptr: Scalar, align: Align) -> Self {
+    pub fn from_scalar_ptr(ptr: Scalar<Tag>, align: Align) -> Self {
         MemPlace {
             ptr,
             align,
-            extra: None,
+            meta: None,
         }
     }
 
     #[inline(always)]
-    pub fn from_ptr(ptr: Pointer, align: Align) -> Self {
+    pub fn from_ptr(ptr: Pointer<Tag>, align: Align) -> Self {
         Self::from_scalar_ptr(ptr.into(), align)
     }
 
     #[inline(always)]
-    pub fn to_scalar_ptr_align(self) -> (Scalar, Align) {
-        assert_eq!(self.extra, None);
+    pub fn to_scalar_ptr_align(self) -> (Scalar<Tag>, Align) {
+        assert!(self.meta.is_none());
         (self.ptr, self.align)
     }
 
-    /// Extract the ptr part of the mplace
+    /// metact the ptr part of the mplace
     #[inline(always)]
-    pub fn to_ptr(self) -> EvalResult<'tcx, Pointer> {
+    pub fn to_ptr(self) -> EvalResult<'tcx, Pointer<Tag>> {
         // At this point, we forget about the alignment information --
         // the place has been turned into a reference, and no matter where it came from,
         // it now must be aligned.
@@ -120,29 +147,41 @@ pub fn to_ptr(self) -> EvalResult<'tcx, Pointer> {
 
     /// Turn a mplace into a (thin or fat) pointer, as a reference, pointing to the same space.
     /// This is the inverse of `ref_to_mplace`.
-    pub fn to_ref(self) -> Value {
+    pub fn to_ref(self) -> Value<Tag> {
         // We ignore the alignment of the place here -- special handling for packed structs ends
         // at the `&` operator.
-        match self.extra {
+        match self.meta {
             None => Value::Scalar(self.ptr.into()),
-            Some(extra) => Value::ScalarPair(self.ptr.into(), extra.into()),
+            Some(meta) => Value::ScalarPair(self.ptr.into(), meta.into()),
         }
     }
 }
 
-impl<'tcx> MPlaceTy<'tcx> {
+impl<'tcx, Tag> MPlaceTy<'tcx, Tag> {
+    /// Produces a MemPlace that works for ZST but nothing else
     #[inline]
-    fn from_aligned_ptr(ptr: Pointer, layout: TyLayout<'tcx>) -> Self {
+    pub fn dangling(layout: TyLayout<'tcx>, cx: impl HasDataLayout) -> Self {
+        MPlaceTy {
+            mplace: MemPlace::from_scalar_ptr(
+                Scalar::from_uint(layout.align.abi(), cx.pointer_size()),
+                layout.align
+            ),
+            layout
+        }
+    }
+
+    #[inline]
+    fn from_aligned_ptr(ptr: Pointer<Tag>, layout: TyLayout<'tcx>) -> Self {
         MPlaceTy { mplace: MemPlace::from_ptr(ptr, layout.align), layout }
     }
 
     #[inline]
     pub(super) fn len(self, cx: impl HasDataLayout) -> EvalResult<'tcx, u64> {
         if self.layout.is_unsized() {
-            // We need to consult `extra` metadata
+            // We need to consult `meta` metadata
             match self.layout.ty.sty {
                 ty::Slice(..) | ty::Str =>
-                    return self.extra.unwrap().to_usize(cx),
+                    return self.mplace.meta.unwrap().to_usize(cx),
                 _ => bug!("len not supported on unsized type {:?}", self.layout.ty),
             }
         } else {
@@ -156,30 +195,30 @@ pub(super) fn len(self, cx: impl HasDataLayout) -> EvalResult<'tcx, u64> {
     }
 
     #[inline]
-    pub(super) fn vtable(self) -> EvalResult<'tcx, Pointer> {
+    pub(super) fn vtable(self) -> EvalResult<'tcx, Pointer<Tag>> {
         match self.layout.ty.sty {
-            ty::Dynamic(..) => self.extra.unwrap().to_ptr(),
+            ty::Dynamic(..) => self.mplace.meta.unwrap().to_ptr(),
             _ => bug!("vtable not supported on type {:?}", self.layout.ty),
         }
     }
 }
 
-impl<'tcx> OpTy<'tcx> {
+impl<'tcx, Tag: ::std::fmt::Debug> OpTy<'tcx, Tag> {
     #[inline(always)]
-    pub fn try_as_mplace(self) -> Result<MPlaceTy<'tcx>, Value> {
-        match *self {
+    pub fn try_as_mplace(self) -> Result<MPlaceTy<'tcx, Tag>, Value<Tag>> {
+        match self.op {
             Operand::Indirect(mplace) => Ok(MPlaceTy { mplace, layout: self.layout }),
             Operand::Immediate(value) => Err(value),
         }
     }
 
     #[inline(always)]
-    pub fn to_mem_place(self) -> MPlaceTy<'tcx> {
+    pub fn to_mem_place(self) -> MPlaceTy<'tcx, Tag> {
         self.try_as_mplace().unwrap()
     }
 }
 
-impl<'tcx> Place {
+impl<'tcx, Tag: ::std::fmt::Debug> Place<Tag> {
     /// Produces a Place that will error if attempted to be read from or written to
     #[inline]
     pub fn null(cx: impl HasDataLayout) -> Self {
@@ -187,17 +226,17 @@ pub fn null(cx: impl HasDataLayout) -> Self {
     }
 
     #[inline]
-    pub fn from_scalar_ptr(ptr: Scalar, align: Align) -> Self {
+    pub fn from_scalar_ptr(ptr: Scalar<Tag>, align: Align) -> Self {
         Place::Ptr(MemPlace::from_scalar_ptr(ptr, align))
     }
 
     #[inline]
-    pub fn from_ptr(ptr: Pointer, align: Align) -> Self {
+    pub fn from_ptr(ptr: Pointer<Tag>, align: Align) -> Self {
         Place::Ptr(MemPlace::from_ptr(ptr, align))
     }
 
     #[inline]
-    pub fn to_mem_place(self) -> MemPlace {
+    pub fn to_mem_place(self) -> MemPlace<Tag> {
         match self {
             Place::Ptr(mplace) => mplace,
             _ => bug!("to_mem_place: expected Place::Ptr, got {:?}", self),
@@ -206,17 +245,17 @@ pub fn to_mem_place(self) -> MemPlace {
     }
 
     #[inline]
-    pub fn to_scalar_ptr_align(self) -> (Scalar, Align) {
+    pub fn to_scalar_ptr_align(self) -> (Scalar<Tag>, Align) {
         self.to_mem_place().to_scalar_ptr_align()
     }
 
     #[inline]
-    pub fn to_ptr(self) -> EvalResult<'tcx, Pointer> {
+    pub fn to_ptr(self) -> EvalResult<'tcx, Pointer<Tag>> {
         self.to_mem_place().to_ptr()
     }
 }
 
-impl<'tcx> PlaceTy<'tcx> {
+impl<'tcx, Tag: ::std::fmt::Debug> PlaceTy<'tcx, Tag> {
     /// Produces a Place that will error if attempted to be read from or written to
     #[inline]
     pub fn null(cx: impl HasDataLayout, layout: TyLayout<'tcx>) -> Self {
@@ -224,25 +263,31 @@ pub fn null(cx: impl HasDataLayout, layout: TyLayout<'tcx>) -> Self {
     }
 
     #[inline]
-    pub fn to_mem_place(self) -> MPlaceTy<'tcx> {
+    pub fn to_mem_place(self) -> MPlaceTy<'tcx, Tag> {
         MPlaceTy { mplace: self.place.to_mem_place(), layout: self.layout }
     }
 }
 
-impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
+// separating the pointer tag for `impl Trait`, see https://github.com/rust-lang/rust/issues/54385
+impl<'a, 'mir, 'tcx, Tag, M> EvalContext<'a, 'mir, 'tcx, M>
+where
+    Tag: ::std::fmt::Debug+Default+Copy+Eq+Hash+'static,
+    M: Machine<'a, 'mir, 'tcx, PointerTag=Tag>,
+    M::MemoryMap: AllocMap<AllocId, (MemoryKind<M::MemoryKinds>, Allocation<Tag>)>,
+{
     /// Take a value, which represents a (thin or fat) reference, and make it a place.
     /// Alignment is just based on the type.  This is the inverse of `MemPlace::to_ref`.
     pub fn ref_to_mplace(
-        &self, val: ValTy<'tcx>
-    ) -> EvalResult<'tcx, MPlaceTy<'tcx>> {
+        &self, val: ValTy<'tcx, M::PointerTag>
+    ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
         let pointee_type = val.layout.ty.builtin_deref(true).unwrap().ty;
         let layout = self.layout_of(pointee_type)?;
         let align = layout.align;
         let mplace = match *val {
             Value::Scalar(ptr) =>
-                MemPlace { ptr: ptr.not_undef()?, align, extra: None },
-            Value::ScalarPair(ptr, extra) =>
-                MemPlace { ptr: ptr.not_undef()?, align, extra: Some(extra.not_undef()?) },
+                MemPlace { ptr: ptr.not_undef()?, align, meta: None },
+            Value::ScalarPair(ptr, meta) =>
+                MemPlace { ptr: ptr.not_undef()?, align, meta: Some(meta.not_undef()?) },
         };
         Ok(MPlaceTy { mplace, layout })
     }
@@ -253,9 +298,9 @@ pub fn ref_to_mplace(
     #[inline(always)]
     pub fn mplace_field(
         &self,
-        base: MPlaceTy<'tcx>,
+        base: MPlaceTy<'tcx, M::PointerTag>,
         field: u64,
-    ) -> EvalResult<'tcx, MPlaceTy<'tcx>> {
+    ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
         // Not using the layout method because we want to compute on u64
         let offset = match base.layout.fields {
             layout::FieldPlacement::Arbitrary { ref offsets, .. } =>
@@ -278,13 +323,13 @@ pub fn mplace_field(
         let field_layout = base.layout.field(self, usize::try_from(field).unwrap_or(0))?;
 
         // Offset may need adjustment for unsized fields
-        let (extra, offset) = if field_layout.is_unsized() {
+        let (meta, offset) = if field_layout.is_unsized() {
             // re-use parent metadata to determine dynamic field layout
-            let (_, align) = self.size_and_align_of(base.extra, field_layout)?;
-            (base.extra, offset.abi_align(align))
+            let (_, align) = self.size_and_align_of(base.meta, field_layout)?;
+            (base.meta, offset.abi_align(align))
 
         } else {
-            // base.extra could be present; we might be accessing a sized field of an unsized
+            // base.meta could be present; we might be accessing a sized field of an unsized
             // struct.
             (None, offset)
         };
@@ -295,15 +340,17 @@ pub fn mplace_field(
             // codegen -- mostly to see if we can get away with that
             .restrict_for_offset(offset); // must be last thing that happens
 
-        Ok(MPlaceTy { mplace: MemPlace { ptr, align, extra }, layout: field_layout })
+        Ok(MPlaceTy { mplace: MemPlace { ptr, align, meta }, layout: field_layout })
     }
 
     // Iterates over all fields of an array. Much more efficient than doing the
     // same by repeatedly calling `mplace_array`.
     pub fn mplace_array_fields(
         &self,
-        base: MPlaceTy<'tcx>,
-    ) -> EvalResult<'tcx, impl Iterator<Item=EvalResult<'tcx, MPlaceTy<'tcx>>> + 'a> {
+        base: MPlaceTy<'tcx, Tag>,
+    ) ->
+        EvalResult<'tcx, impl Iterator<Item=EvalResult<'tcx, MPlaceTy<'tcx, Tag>>> + 'a>
+    {
         let len = base.len(self)?; // also asserts that we have a type where this makes sense
         let stride = match base.layout.fields {
             layout::FieldPlacement::Array { stride, .. } => stride,
@@ -314,7 +361,7 @@ pub fn mplace_array_fields(
         Ok((0..len).map(move |i| {
             let ptr = base.ptr.ptr_offset(i * stride, dl)?;
             Ok(MPlaceTy {
-                mplace: MemPlace { ptr, align: base.align, extra: None },
+                mplace: MemPlace { ptr, align: base.align, meta: None },
                 layout
             })
         }))
@@ -322,10 +369,10 @@ pub fn mplace_array_fields(
 
     pub fn mplace_subslice(
         &self,
-        base: MPlaceTy<'tcx>,
+        base: MPlaceTy<'tcx, M::PointerTag>,
         from: u64,
         to: u64,
-    ) -> EvalResult<'tcx, MPlaceTy<'tcx>> {
+    ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
         let len = base.len(self)?; // also asserts that we have a type where this makes sense
         assert!(from <= len - to);
 
@@ -338,9 +385,9 @@ pub fn mplace_subslice(
         };
         let ptr = base.ptr.ptr_offset(from_offset, self)?;
 
-        // Compute extra and new layout
+        // Compute meta and new layout
         let inner_len = len - to - from;
-        let (extra, ty) = match base.layout.ty.sty {
+        let (meta, ty) = match base.layout.ty.sty {
             // It is not nice to match on the type, but that seems to be the only way to
             // implement this.
             ty::Array(inner, _) =>
@@ -355,27 +402,27 @@ pub fn mplace_subslice(
         let layout = self.layout_of(ty)?;
 
         Ok(MPlaceTy {
-            mplace: MemPlace { ptr, align: base.align, extra },
+            mplace: MemPlace { ptr, align: base.align, meta },
             layout
         })
     }
 
     pub fn mplace_downcast(
         &self,
-        base: MPlaceTy<'tcx>,
+        base: MPlaceTy<'tcx, M::PointerTag>,
         variant: usize,
-    ) -> EvalResult<'tcx, MPlaceTy<'tcx>> {
+    ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
         // Downcasts only change the layout
-        assert_eq!(base.extra, None);
+        assert!(base.meta.is_none());
         Ok(MPlaceTy { layout: base.layout.for_variant(self, variant), ..base })
     }
 
     /// Project into an mplace
     pub fn mplace_projection(
         &self,
-        base: MPlaceTy<'tcx>,
+        base: MPlaceTy<'tcx, M::PointerTag>,
         proj_elem: &mir::PlaceElem<'tcx>,
-    ) -> EvalResult<'tcx, MPlaceTy<'tcx>> {
+    ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
         use rustc::mir::ProjectionElem::*;
         Ok(match *proj_elem {
             Field(field, _) => self.mplace_field(base, field.index() as u64)?,
@@ -416,9 +463,9 @@ pub fn mplace_projection(
     /// Just a convenience function, but used quite a bit.
     pub fn place_field(
         &mut self,
-        base: PlaceTy<'tcx>,
+        base: PlaceTy<'tcx, M::PointerTag>,
         field: u64,
-    ) -> EvalResult<'tcx, PlaceTy<'tcx>> {
+    ) -> EvalResult<'tcx, PlaceTy<'tcx, M::PointerTag>> {
         // FIXME: We could try to be smarter and avoid allocation for fields that span the
         // entire place.
         let mplace = self.force_allocation(base)?;
@@ -427,9 +474,9 @@ pub fn place_field(
 
     pub fn place_downcast(
         &mut self,
-        base: PlaceTy<'tcx>,
+        base: PlaceTy<'tcx, M::PointerTag>,
         variant: usize,
-    ) -> EvalResult<'tcx, PlaceTy<'tcx>> {
+    ) -> EvalResult<'tcx, PlaceTy<'tcx, M::PointerTag>> {
         // Downcast just changes the layout
         Ok(match base.place {
             Place::Ptr(mplace) =>
@@ -444,9 +491,9 @@ pub fn place_downcast(
     /// Project into a place
     pub fn place_projection(
         &mut self,
-        base: PlaceTy<'tcx>,
+        base: PlaceTy<'tcx, M::PointerTag>,
         proj_elem: &mir::ProjectionElem<'tcx, mir::Local, Ty<'tcx>>,
-    ) -> EvalResult<'tcx, PlaceTy<'tcx>> {
+    ) -> EvalResult<'tcx, PlaceTy<'tcx, M::PointerTag>> {
         use rustc::mir::ProjectionElem::*;
         Ok(match *proj_elem {
             Field(field, _) =>  self.place_field(base, field.index() as u64)?,
@@ -466,7 +513,7 @@ pub fn place_projection(
     pub(super) fn eval_place_to_mplace(
         &self,
         mir_place: &mir::Place<'tcx>
-    ) -> EvalResult<'tcx, MPlaceTy<'tcx>> {
+    ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
         use rustc::mir::Place::*;
         Ok(match *mir_place {
             Promoted(ref promoted) => {
@@ -503,7 +550,7 @@ pub(super) fn eval_place_to_mplace(
                 // and miri: They use the same query to eventually obtain a `ty::Const`
                 // and use that for further computation.
                 let alloc = self.tcx.alloc_map.lock().intern_static(cid.instance.def_id());
-                MPlaceTy::from_aligned_ptr(alloc.into(), layout)
+                MPlaceTy::from_aligned_ptr(Pointer::from(alloc).with_default_tag(), layout)
             }
 
             _ => bug!("eval_place_to_mplace called on {:?}", mir_place),
@@ -512,7 +559,10 @@ pub(super) fn eval_place_to_mplace(
 
     /// Compute a place.  You should only use this if you intend to write into this
     /// place; for reading, a more efficient alternative is `eval_place_for_read`.
-    pub fn eval_place(&mut self, mir_place: &mir::Place<'tcx>) -> EvalResult<'tcx, PlaceTy<'tcx>> {
+    pub fn eval_place(
+        &mut self,
+        mir_place: &mir::Place<'tcx>
+    ) -> EvalResult<'tcx, PlaceTy<'tcx, M::PointerTag>> {
         use rustc::mir::Place::*;
         let place = match *mir_place {
             Local(mir::RETURN_PLACE) => PlaceTy {
@@ -542,8 +592,8 @@ pub fn eval_place(&mut self, mir_place: &mir::Place<'tcx>) -> EvalResult<'tcx, P
     /// Write a scalar to a place
     pub fn write_scalar(
         &mut self,
-        val: impl Into<ScalarMaybeUndef>,
-        dest: PlaceTy<'tcx>,
+        val: impl Into<ScalarMaybeUndef<M::PointerTag>>,
+        dest: PlaceTy<'tcx, M::PointerTag>,
     ) -> EvalResult<'tcx> {
         self.write_value(Value::Scalar(val.into()), dest)
     }
@@ -551,10 +601,17 @@ pub fn write_scalar(
     /// Write a value to a place
     pub fn write_value(
         &mut self,
-        src_val: Value,
-        dest: PlaceTy<'tcx>,
+        src_val: Value<M::PointerTag>,
+        dest: PlaceTy<'tcx, M::PointerTag>,
     ) -> EvalResult<'tcx> {
         trace!("write_value: {:?} <- {:?}", *dest, src_val);
+        // Check that the value actually is okay for that type
+        if M::ENFORCE_VALIDITY {
+            // Something changed somewhere, better make sure it matches the type!
+            let op = OpTy { op: Operand::Immediate(src_val), layout: dest.layout };
+            self.validate_operand(op, &mut vec![], None, /*const_mode*/false)?;
+        }
+
         // See if we can avoid an allocation. This is the counterpart to `try_read_value`,
         // but not factored as a separate function.
         let mplace = match dest.place {
@@ -576,11 +633,12 @@ pub fn write_value(
         self.write_value_to_mplace(src_val, dest)
     }
 
-    /// Write a value to memory
+    /// Write a value to memory. This does NOT do validation, so you better had already
+    /// done that before calling this!
     fn write_value_to_mplace(
         &mut self,
-        value: Value,
-        dest: MPlaceTy<'tcx>,
+        value: Value<M::PointerTag>,
+        dest: MPlaceTy<'tcx, M::PointerTag>,
     ) -> EvalResult<'tcx> {
         let (ptr, ptr_align) = dest.to_scalar_ptr_align();
         // Note that it is really important that the type here is the right one, and matches the
@@ -621,8 +679,8 @@ fn write_value_to_mplace(
     /// Copy the data from an operand to a place
     pub fn copy_op(
         &mut self,
-        src: OpTy<'tcx>,
-        dest: PlaceTy<'tcx>,
+        src: OpTy<'tcx, M::PointerTag>,
+        dest: PlaceTy<'tcx, M::PointerTag>,
     ) -> EvalResult<'tcx> {
         assert!(!src.layout.is_unsized() && !dest.layout.is_unsized(),
             "Cannot copy unsized data");
@@ -640,20 +698,26 @@ pub fn copy_op(
         };
         // Slow path, this does not fit into an immediate. Just memcpy.
         trace!("copy_op: {:?} <- {:?}", *dest, *src);
-        let (dest_ptr, dest_align) = self.force_allocation(dest)?.to_scalar_ptr_align();
+        let dest = self.force_allocation(dest)?;
+        let (dest_ptr, dest_align) = dest.to_scalar_ptr_align();
         self.memory.copy(
             src_ptr, src_align,
             dest_ptr, dest_align,
             src.layout.size, false
-        )
+        )?;
+        if M::ENFORCE_VALIDITY {
+            // Something changed somewhere, better make sure it matches the type!
+            self.validate_operand(dest.into(), &mut vec![], None, /*const_mode*/false)?;
+        }
+        Ok(())
     }
 
     /// Make sure that a place is in memory, and return where it is.
     /// This is essentially `force_to_memplace`.
     pub fn force_allocation(
         &mut self,
-        place: PlaceTy<'tcx>,
-    ) -> EvalResult<'tcx, MPlaceTy<'tcx>> {
+        place: PlaceTy<'tcx, M::PointerTag>,
+    ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
         let mplace = match place.place {
             Place::Local { frame, local } => {
                 match *self.stack[frame].locals[local].access()? {
@@ -668,6 +732,8 @@ pub fn force_allocation(
                         // that has different alignment than the outer field.
                         let local_layout = self.layout_of_local(frame, local)?;
                         let ptr = self.allocate(local_layout, MemoryKind::Stack)?;
+                        // We don't have to validate as we can assume the local
+                        // was already valid for its type.
                         self.write_value_to_mplace(value, ptr)?;
                         let mplace = ptr.mplace;
                         // Update the local
@@ -687,7 +753,7 @@ pub fn allocate(
         &mut self,
         layout: TyLayout<'tcx>,
         kind: MemoryKind<M::MemoryKinds>,
-    ) -> EvalResult<'tcx, MPlaceTy<'tcx>> {
+    ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
         assert!(!layout.is_unsized(), "cannot alloc memory for unsized type");
         let ptr = self.memory.allocate(layout.size, layout.align, kind)?;
         Ok(MPlaceTy::from_aligned_ptr(ptr, layout))
@@ -696,7 +762,7 @@ pub fn allocate(
     pub fn write_discriminant_index(
         &mut self,
         variant_index: usize,
-        dest: PlaceTy<'tcx>,
+        dest: PlaceTy<'tcx, M::PointerTag>,
     ) -> EvalResult<'tcx> {
         match dest.layout.variants {
             layout::Variants::Single { index } => {
@@ -744,7 +810,10 @@ pub fn write_discriminant_index(
 
     /// Every place can be read from, so we can turm them into an operand
     #[inline(always)]
-    pub fn place_to_op(&self, place: PlaceTy<'tcx>) -> EvalResult<'tcx, OpTy<'tcx>> {
+    pub fn place_to_op(
+        &self,
+        place: PlaceTy<'tcx, M::PointerTag>
+    ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
         let op = match place.place {
             Place::Ptr(mplace) => {
                 Operand::Indirect(mplace)
@@ -757,8 +826,8 @@ pub fn place_to_op(&self, place: PlaceTy<'tcx>) -> EvalResult<'tcx, OpTy<'tcx>>
 
     /// Turn a place with a `dyn Trait` type into a place with the actual dynamic type.
     /// Also return some more information so drop doesn't have to run the same code twice.
-    pub(super) fn unpack_dyn_trait(&self, mplace: MPlaceTy<'tcx>)
-    -> EvalResult<'tcx, (ty::Instance<'tcx>, MPlaceTy<'tcx>)> {
+    pub(super) fn unpack_dyn_trait(&self, mplace: MPlaceTy<'tcx, M::PointerTag>)
+    -> EvalResult<'tcx, (ty::Instance<'tcx>, MPlaceTy<'tcx, M::PointerTag>)> {
         let vtable = mplace.vtable()?; // also sanity checks the type
         let (instance, ty) = self.read_drop_type_from_vtable(vtable)?;
         let layout = self.layout_of(ty)?;
@@ -771,7 +840,7 @@ pub(super) fn unpack_dyn_trait(&self, mplace: MPlaceTy<'tcx>)
         }
 
         let mplace = MPlaceTy {
-            mplace: MemPlace { extra: None, ..*mplace },
+            mplace: MemPlace { meta: None, ..*mplace },
             layout
         };
         Ok((instance, mplace))
index 9b507eca3633b1cf16f771dd4ae16f0c05ce86e5..06aee8605c6e10cc05fadee13a6503f3e0f3959e 100644 (file)
@@ -99,6 +99,8 @@ macro_rules! __impl_snapshot_field {
     ($field:ident, $ctx:expr, $delegate:expr) => ($delegate);
 }
 
+// This assumes the type has two type parameters, first for the tag (set to `()`),
+// then for the id
 macro_rules! impl_snapshot_for {
     // FIXME(mark-i-m): Some of these should be `?` rather than `*`.
     (enum $enum_name:ident {
@@ -108,7 +110,7 @@ macro_rules! impl_snapshot_for {
         impl<'a, Ctx> self::Snapshot<'a, Ctx> for $enum_name
             where Ctx: self::SnapshotContext<'a>,
         {
-            type Item = $enum_name<AllocIdSnapshot<'a>>;
+            type Item = $enum_name<(), AllocIdSnapshot<'a>>;
 
             #[inline]
             fn snapshot(&self, __ctx: &'a Ctx) -> Self::Item {
@@ -129,7 +131,7 @@ fn snapshot(&self, __ctx: &'a Ctx) -> Self::Item {
         impl<'a, Ctx> self::Snapshot<'a, Ctx> for $struct_name
             where Ctx: self::SnapshotContext<'a>,
         {
-            type Item = $struct_name<AllocIdSnapshot<'a>>;
+            type Item = $struct_name<(), AllocIdSnapshot<'a>>;
 
             #[inline]
             fn snapshot(&self, __ctx: &'a Ctx) -> Self::Item {
@@ -175,12 +177,13 @@ fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
 impl_snapshot_for!(struct Pointer {
     alloc_id,
     offset -> *offset, // just copy offset verbatim
+    tag -> *tag, // just copy tag
 });
 
 impl<'a, Ctx> Snapshot<'a, Ctx> for Scalar
     where Ctx: SnapshotContext<'a>,
 {
-    type Item = Scalar<AllocIdSnapshot<'a>>;
+    type Item = Scalar<(), AllocIdSnapshot<'a>>;
 
     fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
         match self {
@@ -206,11 +209,11 @@ fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
 impl_stable_hash_for!(struct ::interpret::MemPlace {
     ptr,
     align,
-    extra,
+    meta,
 });
 impl_snapshot_for!(struct MemPlace {
     ptr,
-    extra,
+    meta,
     align -> *align, // just copy alignment verbatim
 });
 
@@ -234,7 +237,7 @@ fn hash_stable<W: StableHasherResult>(
 impl<'a, Ctx> Snapshot<'a, Ctx> for Place
     where Ctx: SnapshotContext<'a>,
 {
-    type Item = Place<AllocIdSnapshot<'a>>;
+    type Item = Place<(), AllocIdSnapshot<'a>>;
 
     fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
         match self {
@@ -278,11 +281,11 @@ fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
 impl<'a, Ctx> Snapshot<'a, Ctx> for Relocations
     where Ctx: SnapshotContext<'a>,
 {
-    type Item = Relocations<AllocIdSnapshot<'a>>;
+    type Item = Relocations<(), AllocIdSnapshot<'a>>;
 
     fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
         Relocations::from_presorted(self.iter()
-            .map(|(size, id)| (*size, id.snapshot(ctx)))
+            .map(|(size, ((), id))| (*size, ((), id.snapshot(ctx))))
             .collect())
     }
 }
@@ -290,7 +293,7 @@ fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
 #[derive(Eq, PartialEq)]
 struct AllocationSnapshot<'a> {
     bytes: &'a [u8],
-    relocations: Relocations<AllocIdSnapshot<'a>>,
+    relocations: Relocations<(), AllocIdSnapshot<'a>>,
     undef_mask: &'a UndefMask,
     align: &'a Align,
     mutability: &'a Mutability,
@@ -334,8 +337,8 @@ struct FrameSnapshot<'a, 'tcx: 'a> {
     instance: &'a ty::Instance<'tcx>,
     span: &'a Span,
     return_to_block: &'a StackPopCleanup,
-    return_place: Place<AllocIdSnapshot<'a>>,
-    locals: IndexVec<mir::Local, LocalValue<AllocIdSnapshot<'a>>>,
+    return_place: Place<(), AllocIdSnapshot<'a>>,
+    locals: IndexVec<mir::Local, LocalValue<(), AllocIdSnapshot<'a>>>,
     block: &'a mir::BasicBlock,
     stmt: usize,
 }
index c7ed69e0cb66d882a01ba78fc599b96d9bc675ba..e599608b2dac99d875218f4f98c7e9ce6240d57d 100644 (file)
@@ -205,8 +205,8 @@ fn check_argument_compat(
     fn pass_argument(
         &mut self,
         skip_zst: bool,
-        caller_arg: &mut impl Iterator<Item=OpTy<'tcx>>,
-        callee_arg: PlaceTy<'tcx>,
+        caller_arg: &mut impl Iterator<Item=OpTy<'tcx, M::PointerTag>>,
+        callee_arg: PlaceTy<'tcx, M::PointerTag>,
     ) -> EvalResult<'tcx> {
         if skip_zst && callee_arg.layout.is_zst() {
             // Nothing to do.
@@ -231,8 +231,8 @@ fn eval_fn_call(
         instance: ty::Instance<'tcx>,
         span: Span,
         caller_abi: Abi,
-        args: &[OpTy<'tcx>],
-        dest: Option<PlaceTy<'tcx>>,
+        args: &[OpTy<'tcx, M::PointerTag>],
+        dest: Option<PlaceTy<'tcx, M::PointerTag>>,
         ret: Option<mir::BasicBlock>,
     ) -> EvalResult<'tcx> {
         trace!("eval_fn_call: {:#?}", instance);
@@ -287,7 +287,7 @@ fn eval_fn_call(
 
                 let return_place = match dest {
                     Some(place) => *place,
-                    None => Place::null(&self),
+                    None => Place::null(&self), // any access will error. good!
                 };
                 self.push_stack_frame(
                     instance,
@@ -330,7 +330,7 @@ fn eval_fn_call(
                     // last incoming argument.  These two iterators do not have the same type,
                     // so to keep the code paths uniform we accept an allocation
                     // (for RustCall ABI only).
-                    let caller_args : Cow<[OpTy<'tcx>]> =
+                    let caller_args : Cow<[OpTy<'tcx, M::PointerTag>]> =
                         if caller_abi == Abi::RustCall && !args.is_empty() {
                             // Untuple
                             let (&untuple_arg, args) = args.split_last().unwrap();
@@ -339,7 +339,7 @@ fn eval_fn_call(
                                 .chain((0..untuple_arg.layout.fields.count()).into_iter()
                                     .map(|i| self.operand_field(untuple_arg, i as u64))
                                 )
-                                .collect::<EvalResult<Vec<OpTy<'tcx>>>>()?)
+                                .collect::<EvalResult<Vec<OpTy<'tcx, M::PointerTag>>>>()?)
                         } else {
                             // Plain arg passing
                             Cow::from(args)
@@ -373,6 +373,20 @@ fn eval_fn_call(
                         trace!("Caller has too many args over");
                         return err!(FunctionArgCountMismatch);
                     }
+                    // Don't forget to check the return type!
+                    if let Some(caller_ret) = dest {
+                        let callee_ret = self.eval_place(&mir::Place::Local(mir::RETURN_PLACE))?;
+                        if !Self::check_argument_compat(caller_ret.layout, callee_ret.layout) {
+                            return err!(FunctionRetMismatch(
+                                caller_ret.layout.ty, callee_ret.layout.ty
+                            ));
+                        }
+                    } else {
+                        // FIXME: The caller thinks this function cannot return. How do
+                        // we verify that the callee agrees?
+                        // On the plus side, the the callee ever writes to its return place,
+                        // that will be detected as UB (because we set that to NULL above).
+                    }
                     Ok(())
                 })();
                 match res {
@@ -412,7 +426,7 @@ fn eval_fn_call(
 
     fn drop_in_place(
         &mut self,
-        place: PlaceTy<'tcx>,
+        place: PlaceTy<'tcx, M::PointerTag>,
         instance: ty::Instance<'tcx>,
         span: Span,
         target: mir::BasicBlock,
index 5ea588b957a4ffed98f4a25d3424e301b2d1f2a4..227c85772d228aa22f5179c0726fb0f22e5164c0 100644 (file)
@@ -12,8 +12,6 @@
 use rustc::ty::layout::{Size, Align, LayoutOf};
 use rustc::mir::interpret::{Scalar, Pointer, EvalResult, PointerArithmetic};
 
-use syntax::ast::Mutability;
-
 use super::{EvalContext, Machine, MemoryKind};
 
 impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
@@ -27,9 +25,11 @@ pub fn get_vtable(
         &mut self,
         ty: Ty<'tcx>,
         trait_ref: ty::PolyTraitRef<'tcx>,
-    ) -> EvalResult<'tcx, Pointer> {
+    ) -> EvalResult<'tcx, Pointer<M::PointerTag>> {
         debug!("get_vtable(trait_ref={:?})", trait_ref);
 
+        // FIXME: Cache this!
+
         let layout = self.layout_of(trait_ref.self_ty())?;
         assert!(!layout.is_unsized(), "can't create a vtable for an unsized type");
         let size = layout.size.bytes();
@@ -41,7 +41,7 @@ pub fn get_vtable(
         let vtable = self.memory.allocate(
             ptr_size * (3 + methods.len() as u64),
             ptr_align,
-            MemoryKind::Stack,
+            MemoryKind::Vtable,
         )?;
 
         let drop = ::monomorphize::resolve_drop_in_place(*self.tcx, ty);
@@ -63,10 +63,7 @@ pub fn get_vtable(
             }
         }
 
-        self.memory.intern_static(
-            vtable.alloc_id,
-            Mutability::Immutable,
-        )?;
+        self.memory.mark_immutable(vtable.alloc_id)?;
 
         Ok(vtable)
     }
@@ -74,7 +71,7 @@ pub fn get_vtable(
     /// Return the drop fn instance as well as the actual dynamic type
     pub fn read_drop_type_from_vtable(
         &self,
-        vtable: Pointer,
+        vtable: Pointer<M::PointerTag>,
     ) -> EvalResult<'tcx, (ty::Instance<'tcx>, ty::Ty<'tcx>)> {
         // we don't care about the pointee type, we just want a pointer
         let pointer_align = self.tcx.data_layout.pointer_align;
@@ -90,7 +87,7 @@ pub fn read_drop_type_from_vtable(
 
     pub fn read_size_and_align_from_vtable(
         &self,
-        vtable: Pointer,
+        vtable: Pointer<M::PointerTag>,
     ) -> EvalResult<'tcx, (Size, Align)> {
         let pointer_size = self.pointer_size();
         let pointer_align = self.tcx.data_layout.pointer_align;
index c5238d24cf7eddcbb8db0934fa74490205210541..9dc035a3e20b81d115f4680e87ac6a59ae15bb09 100644 (file)
@@ -9,20 +9,21 @@
 // except according to those terms.
 
 use std::fmt::Write;
+use std::hash::Hash;
 
 use syntax_pos::symbol::Symbol;
-use rustc::ty::layout::{self, Size, Primitive};
-use rustc::ty::{self, Ty};
+use rustc::ty::layout::{self, Size, Align, TyLayout};
+use rustc::ty;
 use rustc_data_structures::fx::FxHashSet;
 use rustc::mir::interpret::{
-    Scalar, AllocType, EvalResult, EvalErrorKind, PointerArithmetic
+    Scalar, AllocType, EvalResult, EvalErrorKind
 };
 
 use super::{
-    OpTy, Machine, EvalContext, ScalarMaybeUndef
+    ValTy, OpTy, MPlaceTy, Machine, EvalContext, ScalarMaybeUndef
 };
 
-macro_rules! validation_failure{
+macro_rules! validation_failure {
     ($what:expr, $where:expr, $details:expr) => {{
         let where_ = path_format($where);
         let where_ = if where_.is_empty() {
@@ -49,6 +50,22 @@ macro_rules! validation_failure{
     }};
 }
 
+macro_rules! try_validation {
+    ($e:expr, $what:expr, $where:expr, $details:expr) => {{
+        match $e {
+            Ok(x) => x,
+            Err(_) => return validation_failure!($what, $where, $details),
+        }
+    }};
+
+    ($e:expr, $what:expr, $where:expr) => {{
+        match $e {
+            Ok(x) => x,
+            Err(_) => return validation_failure!($what, $where),
+        }
+    }}
+}
+
 /// We want to show a nice path to the invalid field for diagnotsics,
 /// but avoid string operations in the happy case where no error happens.
 /// So we track a `Vec<PathElem>` where `PathElem` contains all the data we
@@ -63,6 +80,23 @@ pub enum PathElem {
     Tag,
 }
 
+/// State for tracking recursive validation of references
+pub struct RefTracking<'tcx, Tag> {
+    pub seen: FxHashSet<(OpTy<'tcx, Tag>)>,
+    pub todo: Vec<(OpTy<'tcx, Tag>, Vec<PathElem>)>,
+}
+
+impl<'tcx, Tag: Copy+Eq+Hash> RefTracking<'tcx, Tag> {
+    pub fn new(op: OpTy<'tcx, Tag>) -> Self {
+        let mut ref_tracking = RefTracking {
+            seen: FxHashSet(),
+            todo: vec![(op, Vec::new())],
+        };
+        ref_tracking.seen.insert(op);
+        ref_tracking
+    }
+}
+
 // Adding a Deref and making a copy of the path to be put into the queue
 // always go together.  This one does it with only new allocation.
 fn path_clone_and_deref(path: &Vec<PathElem>) -> Vec<PathElem> {
@@ -95,133 +129,251 @@ fn path_format(path: &Vec<PathElem>) -> String {
     out
 }
 
+fn scalar_format<Tag>(value: ScalarMaybeUndef<Tag>) -> String {
+    match value {
+        ScalarMaybeUndef::Undef =>
+            "uninitialized bytes".to_owned(),
+        ScalarMaybeUndef::Scalar(Scalar::Ptr(_)) =>
+            "a pointer".to_owned(),
+        ScalarMaybeUndef::Scalar(Scalar::Bits { bits, .. }) =>
+            bits.to_string(),
+    }
+}
+
 impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
-    fn validate_scalar(
+    /// Make sure that `value` is valid for `ty`, *assuming* `ty` is a primitive type.
+    fn validate_primitive_type(
         &self,
-        value: ScalarMaybeUndef,
-        size: Size,
-        scalar: &layout::Scalar,
+        value: ValTy<'tcx, M::PointerTag>,
         path: &Vec<PathElem>,
-        ty: Ty,
+        ref_tracking: Option<&mut RefTracking<'tcx, M::PointerTag>>,
+        const_mode: bool,
     ) -> EvalResult<'tcx> {
-        trace!("validate scalar: {:#?}, {:#?}, {:#?}, {}", value, size, scalar, ty);
-        let (lo, hi) = scalar.valid_range.clone().into_inner();
-
-        let value = match value {
-            ScalarMaybeUndef::Scalar(scalar) => scalar,
-            ScalarMaybeUndef::Undef => return validation_failure!("undefined bytes", path),
-        };
-
-        let bits = match value {
-            Scalar::Bits { bits, size: value_size } => {
-                assert_eq!(value_size as u64, size.bytes());
-                bits
+        // Go over all the primitive types
+        let ty = value.layout.ty;
+        match ty.sty {
+            ty::Bool => {
+                let value = value.to_scalar_or_undef();
+                try_validation!(value.to_bool(),
+                    scalar_format(value), path, "a boolean");
             },
-            Scalar::Ptr(_) => {
-                match ty.sty {
-                    ty::Bool |
-                    ty::Char |
-                    ty::Float(_) |
-                    ty::Int(_) |
-                    ty::Uint(_) => {
-                        return validation_failure!(
-                                "a pointer",
-                                path,
-                                format!("the type {}", ty.sty)
-                            );
+            ty::Char => {
+                let value = value.to_scalar_or_undef();
+                try_validation!(value.to_char(),
+                    scalar_format(value), path, "a valid unicode codepoint");
+            },
+            ty::Float(_) | ty::Int(_) | ty::Uint(_) => {
+                let size = value.layout.size;
+                let value = value.to_scalar_or_undef();
+                if const_mode {
+                    // Integers/floats in CTFE: Must be scalar bits, pointers are dangerous
+                    try_validation!(value.to_bits(size),
+                        scalar_format(value), path, "initialized plain bits");
+                } else {
+                    // At run-time, for now, we accept *anything* for these types, including
+                    // undef. We should fix that, but let's start low.
+                }
+            }
+            _ if ty.is_box() || ty.is_region_ptr() || ty.is_unsafe_ptr() => {
+                // Handle fat pointers. We also check fat raw pointers,
+                // their metadata must be valid!
+                // This also checks that the ptr itself is initialized, which
+                // seems reasonable even for raw pointers.
+                let place = try_validation!(self.ref_to_mplace(value),
+                    "undefined data in pointer", path);
+                // Check metadata early, for better diagnostics
+                if place.layout.is_unsized() {
+                    let tail = self.tcx.struct_tail(place.layout.ty);
+                    match tail.sty {
+                        ty::Dynamic(..) => {
+                            let vtable = try_validation!(place.meta.unwrap().to_ptr(),
+                                "non-pointer vtable in fat pointer", path);
+                            try_validation!(self.read_drop_type_from_vtable(vtable),
+                                "invalid drop fn in vtable", path);
+                            try_validation!(self.read_size_and_align_from_vtable(vtable),
+                                "invalid size or align in vtable", path);
+                            // FIXME: More checks for the vtable.
+                        }
+                        ty::Slice(..) | ty::Str => {
+                            try_validation!(place.meta.unwrap().to_usize(self),
+                                "non-integer slice length in fat pointer", path);
+                        }
+                        ty::Foreign(..) => {
+                            // Unsized, but not fat.
+                        }
+                        _ =>
+                            bug!("Unexpected unsized type tail: {:?}", tail),
                     }
-                    ty::RawPtr(_) |
-                    ty::Ref(_, _, _) |
-                    ty::FnPtr(_) => {}
-                    _ => { unreachable!(); }
                 }
+                // for safe ptrs, also check the ptr values itself
+                if !ty.is_unsafe_ptr() {
+                    // Make sure this is non-NULL and aligned
+                    let (size, align) = self.size_and_align_of(place.meta, place.layout)?;
+                    match self.memory.check_align(place.ptr, align) {
+                        Ok(_) => {},
+                        Err(err) => match err.kind {
+                            EvalErrorKind::InvalidNullPointerUsage =>
+                                return validation_failure!("NULL reference", path),
+                            EvalErrorKind::AlignmentCheckFailed { .. } =>
+                                return validation_failure!("unaligned reference", path),
+                            _ =>
+                                return validation_failure!(
+                                    "dangling (deallocated) reference", path
+                                ),
+                        }
+                    }
+                    // non-ZST also have to be dereferencable
+                    if size != Size::ZERO {
+                        let ptr = try_validation!(place.ptr.to_ptr(),
+                            "integer pointer in non-ZST reference", path);
+                        if const_mode {
+                            // Skip validation entirely for some external statics
+                            let alloc_kind = self.tcx.alloc_map.lock().get(ptr.alloc_id);
+                            if let Some(AllocType::Static(did)) = alloc_kind {
+                                // `extern static` cannot be validated as they have no body.
+                                // FIXME: Statics from other crates are also skipped.
+                                // They might be checked at a different type, but for now we
+                                // want to avoid recursing too deeply.  This is not sound!
+                                if !did.is_local() || self.tcx.is_foreign_item(did) {
+                                    return Ok(());
+                                }
+                            }
+                        }
+                        try_validation!(self.memory.check_bounds(ptr, size, false),
+                            "dangling (not entirely in bounds) reference", path);
+                    }
+                    if let Some(ref_tracking) = ref_tracking {
+                        // Check if we have encountered this pointer+layout combination
+                        // before.  Proceed recursively even for integer pointers, no
+                        // reason to skip them! They are (recursively) valid for some ZST,
+                        // but not for others (e.g. `!` is a ZST).
+                        let op = place.into();
+                        if ref_tracking.seen.insert(op) {
+                            trace!("Recursing below ptr {:#?}", *op);
+                            ref_tracking.todo.push((op, path_clone_and_deref(path)));
+                        }
+                    }
+                }
+            }
+            ty::FnPtr(_sig) => {
+                let value = value.to_scalar_or_undef();
+                let ptr = try_validation!(value.to_ptr(),
+                    scalar_format(value), path, "a pointer");
+                let _fn = try_validation!(self.memory.get_fn(ptr),
+                    scalar_format(value), path, "a function pointer");
+                // FIXME: Check if the signature matches
+            }
+            // This should be all the primitive types
+            ty::Never => bug!("Uninhabited type should have been catched earlier"),
+            _ => bug!("Unexpected primitive type {}", value.layout.ty)
+        }
+        Ok(())
+    }
 
-                let ptr_size = self.pointer_size();
-                let ptr_max = u128::max_value() >> (128 - ptr_size.bits());
-                return if lo > hi {
-                    if lo - hi == 1 {
-                        // no gap, all values are ok
-                        Ok(())
-                    } else if hi < ptr_max || lo > 1 {
-                        let max = u128::max_value() >> (128 - size.bits());
-                        validation_failure!(
-                            "pointer",
-                            path,
-                            format!("something in the range {:?} or {:?}", 0..=lo, hi..=max)
-                        )
-                    } else {
-                        Ok(())
+    /// Make sure that `value` matches the
+    fn validate_scalar_layout(
+        &self,
+        value: ScalarMaybeUndef<M::PointerTag>,
+        size: Size,
+        path: &Vec<PathElem>,
+        layout: &layout::Scalar,
+    ) -> EvalResult<'tcx> {
+        let (lo, hi) = layout.valid_range.clone().into_inner();
+        let max_hi = u128::max_value() >> (128 - size.bits()); // as big as the size fits
+        assert!(hi <= max_hi);
+        if lo == 0 && hi == max_hi {
+            // Nothing to check
+            return Ok(());
+        }
+        // At least one value is excluded. Get the bits.
+        let value = try_validation!(value.not_undef(),
+            scalar_format(value), path, format!("something in the range {:?}", layout.valid_range));
+        let bits = match value {
+            Scalar::Ptr(ptr) => {
+                if lo == 1 && hi == max_hi {
+                    // only NULL is not allowed.
+                    // We can call `check_align` to check non-NULL-ness, but have to also look
+                    // for function pointers.
+                    let non_null =
+                        self.memory.check_align(
+                            Scalar::Ptr(ptr), Align::from_bytes(1, 1).unwrap()
+                        ).is_ok() ||
+                        self.memory.get_fn(ptr).is_ok();
+                    if !non_null {
+                        // could be NULL
+                        return validation_failure!("a potentially NULL pointer", path);
                     }
-                } else if hi < ptr_max || lo > 1 {
-                    validation_failure!(
-                        "pointer",
-                        path,
-                        format!("something in the range {:?}", scalar.valid_range)
-                    )
+                    return Ok(());
                 } else {
-                    Ok(())
-                };
-            },
-        };
-
-        // char gets a special treatment, because its number space is not contiguous so `TyLayout`
-        // has no special checks for chars
-        match ty.sty {
-            ty::Char => {
-                debug_assert_eq!(size.bytes(), 4);
-                if ::std::char::from_u32(bits as u32).is_none() {
+                    // Conservatively, we reject, because the pointer *could* have this
+                    // value.
                     return validation_failure!(
-                        "character",
+                        "a pointer",
                         path,
-                        "a valid unicode codepoint"
+                        format!(
+                            "something that cannot possibly be outside the (wrapping) range {:?}",
+                            layout.valid_range
+                        )
                     );
                 }
             }
-            _ => {},
-        }
-
+            Scalar::Bits { bits, size: value_size } => {
+                assert_eq!(value_size as u64, size.bytes());
+                bits
+            }
+        };
+        // Now compare. This is slightly subtle because this is a special "wrap-around" range.
         use std::ops::RangeInclusive;
         let in_range = |bound: RangeInclusive<u128>| bound.contains(&bits);
         if lo > hi {
-            if in_range(0..=hi) || in_range(lo..=u128::max_value()) {
+            // wrapping around
+            if in_range(0..=hi) || in_range(lo..=max_hi) {
                 Ok(())
             } else {
                 validation_failure!(
                     bits,
                     path,
-                    format!("something in the range {:?} or {:?}", ..=hi, lo..)
+                    format!("something in the range {:?} or {:?}", 0..=hi, lo..=max_hi)
                 )
             }
         } else {
-            if in_range(scalar.valid_range.clone()) {
+            if in_range(layout.valid_range.clone()) {
                 Ok(())
             } else {
                 validation_failure!(
                     bits,
                     path,
-                    format!("something in the range {:?}", scalar.valid_range)
+                    if hi == max_hi {
+                        format!("something greater or equal to {}", lo)
+                    } else {
+                        format!("something in the range {:?}", layout.valid_range)
+                    }
                 )
             }
         }
     }
 
-    /// This function checks the data at `op`.
+    /// This function checks the data at `op`.  `op` is assumed to cover valid memory if it
+    /// is an indirect operand.
     /// It will error if the bits at the destination do not match the ones described by the layout.
     /// The `path` may be pushed to, but the part that is present when the function
     /// starts must not be changed!
+    ///
+    /// `ref_tracking` can be None to avoid recursive checking below references.
+    /// This also toggles between "run-time" (no recursion) and "compile-time" (with recursion)
+    /// validation (e.g., pointer values are fine in integers at runtime).
     pub fn validate_operand(
         &self,
-        dest: OpTy<'tcx>,
+        dest: OpTy<'tcx, M::PointerTag>,
         path: &mut Vec<PathElem>,
-        seen: &mut FxHashSet<(OpTy<'tcx>)>,
-        todo: &mut Vec<(OpTy<'tcx>, Vec<PathElem>)>,
+        mut ref_tracking: Option<&mut RefTracking<'tcx, M::PointerTag>>,
+        const_mode: bool,
     ) -> EvalResult<'tcx> {
-        trace!("validate_operand: {:?}, {:#?}", *dest, dest.layout);
+        trace!("validate_operand: {:?}, {:?}", *dest, dest.layout.ty);
 
-        // Find the right variant.  We have to handle this as a prelude, not via
-        // proper recursion with the new inner layout, to be able to later nicely
-        // print the field names of the enum field that is being accessed.
-        let (variant, dest) = match dest.layout.variants {
+        // If this is a multi-variant layout, we have find the right one and proceed with that.
+        // (No good reasoning to make this recursion, but it is equivalent to that.)
+        let dest = match dest.layout.variants {
             layout::Variants::NicheFilling { .. } |
             layout::Variants::Tagged { .. } => {
                 let variant = match self.read_discriminant(dest) {
@@ -237,124 +389,104 @@ pub fn validate_operand(
                             ),
                     }
                 };
-                let inner_dest = self.operand_downcast(dest, variant)?;
                 // Put the variant projection onto the path, as a field
                 path.push(PathElem::Field(dest.layout.ty
                                           .ty_adt_def()
                                           .unwrap()
                                           .variants[variant].name));
+                // Proceed with this variant
+                let dest = self.operand_downcast(dest, variant)?;
                 trace!("variant layout: {:#?}", dest.layout);
-                (variant, inner_dest)
+                dest
             },
-            layout::Variants::Single { index } => {
-                // Pre-processing for trait objects: Treat them at their real type.
-                // (We do not do this for slices and strings: For slices it is not needed,
-                // `mplace_array_fields` does the right thing, and for strings there is no
-                // real type that would show the actual length.)
-                let dest = match dest.layout.ty.sty {
-                    ty::Dynamic(..) => {
-                        let dest = dest.to_mem_place(); // immediate trait objects are not a thing
-                        match self.unpack_dyn_trait(dest) {
-                            Ok(res) => res.1.into(),
-                            Err(_) =>
-                                return validation_failure!(
-                                    "invalid vtable in fat pointer", path
-                                ),
-                        }
-                    }
-                    _ => dest
-                };
-                (index, dest)
-            }
+            layout::Variants::Single { .. } => dest,
         };
 
-        // Remember the length, in case we need to truncate
-        let path_len = path.len();
+        // First thing, find the real type:
+        // If it is a trait object, switch to the actual type that was used to create it.
+        let dest = match dest.layout.ty.sty {
+            ty::Dynamic(..) => {
+                let dest = dest.to_mem_place(); // immediate trait objects are not a thing
+                self.unpack_dyn_trait(dest)?.1.into()
+            },
+            _ => dest
+        };
 
-        // Validate all fields
-        match dest.layout.fields {
-            // primitives are unions with zero fields
-            // We still check `layout.fields`, not `layout.abi`, because `layout.abi`
-            // is `Scalar` for newtypes around scalars, but we want to descend through the
-            // fields to get a proper `path`.
-            layout::FieldPlacement::Union(0) => {
-                match dest.layout.abi {
-                    // nothing to do, whatever the pointer points to, it is never going to be read
-                    layout::Abi::Uninhabited =>
-                        return validation_failure!("a value of an uninhabited type", path),
-                    // check that the scalar is a valid pointer or that its bit range matches the
-                    // expectation.
-                    layout::Abi::Scalar(ref scalar_layout) => {
-                        let size = scalar_layout.value.size(self);
-                        let value = match self.read_value(dest) {
-                            Ok(val) => val,
-                            Err(err) => match err.kind {
-                                EvalErrorKind::PointerOutOfBounds { .. } |
-                                EvalErrorKind::ReadUndefBytes(_) =>
-                                    return validation_failure!(
-                                        "uninitialized or out-of-bounds memory", path
-                                    ),
-                                _ =>
-                                    return validation_failure!(
-                                        "unrepresentable data", path
-                                    ),
-                            }
-                        };
-                        let scalar = value.to_scalar_or_undef();
-                        self.validate_scalar(scalar, size, scalar_layout, &path, dest.layout.ty)?;
-                        if scalar_layout.value == Primitive::Pointer {
-                            // ignore integer pointers, we can't reason about the final hardware
-                            if let Scalar::Ptr(ptr) = scalar.not_undef()? {
-                                let alloc_kind = self.tcx.alloc_map.lock().get(ptr.alloc_id);
-                                if let Some(AllocType::Static(did)) = alloc_kind {
-                                    // statics from other crates are already checked.
-                                    // extern statics cannot be validated as they have no body.
-                                    if !did.is_local() || self.tcx.is_foreign_item(did) {
-                                        return Ok(());
-                                    }
-                                }
-                                if value.layout.ty.builtin_deref(false).is_some() {
-                                    let ptr_op = self.ref_to_mplace(value)?.into();
-                                    // we have not encountered this pointer+layout combination
-                                    // before.
-                                    if seen.insert(ptr_op) {
-                                        trace!("Recursing below ptr {:#?}", *value);
-                                        todo.push((ptr_op, path_clone_and_deref(path)));
-                                    }
-                                }
-                            }
-                        }
-                    },
-                    _ => bug!("bad abi for FieldPlacement::Union(0): {:#?}", dest.layout.abi),
-                }
+        // If this is a scalar, validate the scalar layout.
+        // Things can be aggregates and have scalar layout at the same time, and that
+        // is very relevant for `NonNull` and similar structs: We need to validate them
+        // at their scalar layout *before* descending into their fields.
+        // FIXME: We could avoid some redundant checks here. For newtypes wrapping
+        // scalars, we do the same check on every "level" (e.g. first we check
+        // MyNewtype and then the scalar in there).
+        match dest.layout.abi {
+            layout::Abi::Uninhabited =>
+                return validation_failure!("a value of an uninhabited type", path),
+            layout::Abi::Scalar(ref layout) => {
+                let value = try_validation!(self.read_scalar(dest),
+                            "uninitialized or unrepresentable data", path);
+                self.validate_scalar_layout(value, dest.layout.size, &path, layout)?;
             }
-            layout::FieldPlacement::Union(_) => {
+            // FIXME: Should we do something for ScalarPair? Vector?
+            _ => {}
+        }
+
+        // Check primitive types.  We do this after checking the scalar layout,
+        // just to have that done as well.  Primitives can have varying layout,
+        // so we check them separately and before aggregate handling.
+        // It is CRITICAL that we get this check right, or we might be
+        // validating the wrong thing!
+        let primitive = match dest.layout.fields {
+            // Primitives appear as Union with 0 fields -- except for fat pointers.
+            layout::FieldPlacement::Union(0) => true,
+            _ => dest.layout.ty.builtin_deref(true).is_some(),
+        };
+        if primitive {
+            let value = try_validation!(self.read_value(dest),
+                "uninitialized or unrepresentable data", path);
+            return self.validate_primitive_type(
+                value,
+                &path,
+                ref_tracking,
+                const_mode,
+            );
+        }
+
+        // Validate all fields of compound data structures
+        let path_len = path.len(); // Remember the length, in case we need to truncate
+        match dest.layout.fields {
+            layout::FieldPlacement::Union(..) => {
                 // We can't check unions, their bits are allowed to be anything.
                 // The fields don't need to correspond to any bit pattern of the union's fields.
                 // See https://github.com/rust-lang/rust/issues/32836#issuecomment-406875389
             },
-            layout::FieldPlacement::Array { stride, .. } if !dest.layout.is_zst() => {
-                let dest = dest.to_mem_place(); // non-ZST array/slice/str cannot be immediate
+            layout::FieldPlacement::Arbitrary { ref offsets, .. } => {
+                // Go look at all the fields
+                for i in 0..offsets.len() {
+                    let field = self.operand_field(dest, i as u64)?;
+                    path.push(self.aggregate_field_path_elem(dest.layout, i));
+                    self.validate_operand(
+                        field,
+                        path,
+                        ref_tracking.as_mut().map(|r| &mut **r),
+                        const_mode,
+                    )?;
+                    path.truncate(path_len);
+                }
+            }
+            layout::FieldPlacement::Array { stride, .. } => {
+                let dest = if dest.layout.is_zst() {
+                    // it's a ZST, the memory content cannot matter
+                    MPlaceTy::dangling(dest.layout, self)
+                } else {
+                    // non-ZST array/slice/str cannot be immediate
+                    dest.to_mem_place()
+                };
                 match dest.layout.ty.sty {
                     // Special handling for strings to verify UTF-8
                     ty::Str => {
-                        match self.read_str(dest) {
-                            Ok(_) => {},
-                            Err(err) => match err.kind {
-                                EvalErrorKind::PointerOutOfBounds { .. } |
-                                EvalErrorKind::ReadUndefBytes(_) =>
-                                    // The error here looks slightly different than it does
-                                    // for slices, because we do not report the index into the
-                                    // str at which we are OOB.
-                                    return validation_failure!(
-                                        "uninitialized or out-of-bounds memory", path
-                                    ),
-                                _ =>
-                                    return validation_failure!(
-                                        "non-UTF-8 data in str", path
-                                    ),
-                            }
-                        }
+                        try_validation!(self.read_str(dest),
+                            "uninitialized or non-UTF-8 data in str", path);
                     }
                     // Special handling for arrays/slices of builtin integer types
                     ty::Array(tys, ..) | ty::Slice(tys) if {
@@ -390,18 +522,9 @@ pub fn validate_operand(
                                             "undefined bytes", path
                                         )
                                     },
-                                    EvalErrorKind::PointerOutOfBounds { allocation_size, .. } => {
-                                        // If the array access is out-of-bounds, the first
-                                        // undefined access is the after the end of the array.
-                                        let i = (allocation_size.bytes() * ty_size) as usize;
-                                        path.push(PathElem::ArrayElem(i));
-                                    },
-                                    _ => (),
+                                    // Other errors shouldn't be possible
+                                    _ => return Err(err),
                                 }
-
-                                return validation_failure!(
-                                    "uninitialized or out-of-bounds memory", path
-                                )
                             }
                         }
                     },
@@ -411,83 +534,32 @@ pub fn validate_operand(
                         for (i, field) in self.mplace_array_fields(dest)?.enumerate() {
                             let field = field?;
                             path.push(PathElem::ArrayElem(i));
-                            self.validate_operand(field.into(), path, seen, todo)?;
+                            self.validate_operand(
+                                field.into(),
+                                path,
+                                ref_tracking.as_mut().map(|r| &mut **r),
+                                const_mode,
+                            )?;
                             path.truncate(path_len);
                         }
                     }
                 }
             },
-            layout::FieldPlacement::Array { .. } => {
-                // An empty array.  Nothing to do.
-            }
-            layout::FieldPlacement::Arbitrary { ref offsets, .. } => {
-                // Fat pointers are treated like pointers, not aggregates.
-                if dest.layout.ty.builtin_deref(true).is_some() {
-                    // This is a fat pointer.
-                    let ptr = match self.read_value(dest.into())
-                        .and_then(|val| self.ref_to_mplace(val))
-                    {
-                        Ok(ptr) => ptr,
-                        Err(_) =>
-                            return validation_failure!(
-                                "undefined location or metadata in fat pointer", path
-                            ),
-                    };
-                    // check metadata early, for better diagnostics
-                    match self.tcx.struct_tail(ptr.layout.ty).sty {
-                        ty::Dynamic(..) => {
-                            match ptr.extra.unwrap().to_ptr() {
-                                Ok(_) => {},
-                                Err(_) =>
-                                    return validation_failure!(
-                                        "non-pointer vtable in fat pointer", path
-                                    ),
-                            }
-                            // FIXME: More checks for the vtable.
-                        }
-                        ty::Slice(..) | ty::Str => {
-                            match ptr.extra.unwrap().to_usize(self) {
-                                Ok(_) => {},
-                                Err(_) =>
-                                    return validation_failure!(
-                                        "non-integer slice length in fat pointer", path
-                                    ),
-                            }
-                        }
-                        _ =>
-                            bug!("Unexpected unsized type tail: {:?}",
-                                self.tcx.struct_tail(ptr.layout.ty)
-                            ),
-                    }
-                    // for safe ptrs, recursively check it
-                    if !dest.layout.ty.is_unsafe_ptr() {
-                        let ptr = ptr.into();
-                        if seen.insert(ptr) {
-                            trace!("Recursing below fat ptr {:?}", ptr);
-                            todo.push((ptr, path_clone_and_deref(path)));
-                        }
-                    }
-                } else {
-                    // Not a pointer, perform regular aggregate handling below
-                    for i in 0..offsets.len() {
-                        let field = self.operand_field(dest, i as u64)?;
-                        path.push(self.aggregate_field_path_elem(dest.layout.ty, variant, i));
-                        self.validate_operand(field, path, seen, todo)?;
-                        path.truncate(path_len);
-                    }
-                }
-            }
         }
         Ok(())
     }
 
-    fn aggregate_field_path_elem(&self, ty: Ty<'tcx>, variant: usize, field: usize) -> PathElem {
-        match ty.sty {
+    fn aggregate_field_path_elem(&self, layout: TyLayout<'tcx>, field: usize) -> PathElem {
+        match layout.ty.sty {
             // generators and closures.
             ty::Closure(def_id, _) | ty::Generator(def_id, _, _) => {
-                let node_id = self.tcx.hir.as_local_node_id(def_id).unwrap();
-                let freevar = self.tcx.with_freevars(node_id, |fv| fv[field]);
-                PathElem::ClosureVar(self.tcx.hir.name(freevar.var_id()))
+                if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) {
+                    let freevar = self.tcx.with_freevars(node_id, |fv| fv[field]);
+                    PathElem::ClosureVar(self.tcx.hir.name(freevar.var_id()))
+                } else {
+                    // The closure is not local, so we cannot get the name
+                    PathElem::ClosureVar(Symbol::intern(&field.to_string()))
+                }
             }
 
             // tuples
@@ -495,7 +567,10 @@ fn aggregate_field_path_elem(&self, ty: Ty<'tcx>, variant: usize, field: usize)
 
             // enums
             ty::Adt(def, ..) if def.is_enum() => {
-                let variant = &def.variants[variant];
+                let variant = match layout.variants {
+                    layout::Variants::Single { index } => &def.variants[index],
+                    _ => bug!("aggregate_field_path_elem: got enum but not in a specific variant"),
+                };
                 PathElem::Field(variant.fields[field].ident.name)
             }
 
@@ -503,7 +578,7 @@ fn aggregate_field_path_elem(&self, ty: Ty<'tcx>, variant: usize, field: usize)
             ty::Adt(def, _) => PathElem::Field(def.non_enum_variant().fields[field].ident.name),
 
             // nothing else has an aggregate layout
-            _ => bug!("aggregate_field_path_elem: got non-aggregate type {:?}", ty),
+            _ => bug!("aggregate_field_path_elem: got non-aggregate type {:?}", layout.ty),
         }
     }
 }
index b2fa83493849cf37f2dad731c8e11cadd67a59ba..29f167629441b964f2a2090649eb64a15eadc561 100644 (file)
@@ -1163,7 +1163,7 @@ fn collect_miri<'a, 'tcx>(
         }
         Some(AllocType::Memory(alloc)) => {
             trace!("collecting {:?} with {:#?}", alloc_id, alloc);
-            for &inner in alloc.relocations.values() {
+            for &((), inner) in alloc.relocations.values() {
                 collect_miri(tcx, inner, output);
             }
         },
@@ -1272,7 +1272,7 @@ fn collect_const<'a, 'tcx>(
         ConstValue::Scalar(Scalar::Ptr(ptr)) =>
             collect_miri(tcx, ptr.alloc_id, output),
         ConstValue::ByRef(_id, alloc, _offset) => {
-            for &id in alloc.relocations.values() {
+            for &((), id) in alloc.relocations.values() {
                 collect_miri(tcx, id, output);
             }
         }
index 70d50d589d1a041b1e24d827e70fffa07c3187b9..626baf207eebc0aa4871168e4a0a98fb0a6dbccc 100644 (file)
@@ -154,6 +154,7 @@ fn use_ecx<F, T>(
                     // FIXME: figure out the rules and start linting
                     | FunctionAbiMismatch(..)
                     | FunctionArgMismatch(..)
+                    | FunctionRetMismatch(..)
                     | FunctionArgCountMismatch
                     // fine at runtime, might be a register address or sth
                     | ReadBytesAsPointer
index 28d2ae413de6d2375694cdf125c28ac7f9c8a2f5..e4ad02595d107df0f8f0499283db6f0dfa3ca042 100644 (file)
@@ -402,21 +402,44 @@ fn check_generic_arg_count(
     }
 
     /// Creates the relevant generic argument substitutions
-    /// corresponding to a set of generic parameters.
-    pub fn create_substs_for_generic_args<'a, 'b, A, P, I>(
+    /// corresponding to a set of generic parameters. This is a
+    /// rather complex little function. Let me try to explain the
+    /// role of each of its parameters:
+    ///
+    /// To start, we are given the `def_id` of the thing we are
+    /// creating the substitutions for, and a partial set of
+    /// substitutions `parent_substs`. In general, the substitutions
+    /// for an item begin with substitutions for all the "parents" of
+    /// that item -- so e.g. for a method it might include the
+    /// parameters from the impl.
+    ///
+    /// Therefore, the method begins by walking down these parents,
+    /// starting with the outermost parent and proceed inwards until
+    /// it reaches `def_id`. For each parent P, it will check `parent_substs`
+    /// first to see if the parent's substitutions are listed in there. If so,
+    /// we can append those and move on. Otherwise, it invokes the
+    /// three callback functions:
+    ///
+    /// - `args_for_def_id`: given the def-id P, supplies back the
+    ///   generic arguments that were given to that parent from within
+    ///   the path; so e.g. if you have `<T as Foo>::Bar`, the def-id
+    ///   might refer to the trait `Foo`, and the arguments might be
+    ///   `[T]`. The boolean value indicates whether to infer values
+    ///   for arguments whose values were not explicitly provided.
+    /// - `provided_kind`: given the generic parameter and the value from `args_for_def_id`,
+    ///   instantiate a `Kind`
+    /// - `inferred_kind`: if no parameter was provided, and inference is enabled, then
+    ///   creates a suitable inference variable.
+    pub fn create_substs_for_generic_args<'a, 'b>(
         tcx: TyCtxt<'a, 'gcx, 'tcx>,
         def_id: DefId,
         parent_substs: &[Kind<'tcx>],
         has_self: bool,
         self_ty: Option<Ty<'tcx>>,
-        args_for_def_id: A,
-        provided_kind: P,
-        inferred_kind: I,
-    ) -> &'tcx Substs<'tcx> where
-        A: Fn(DefId) -> (Option<&'b GenericArgs>, bool),
-        P: Fn(&GenericParamDef, &GenericArg) -> Kind<'tcx>,
-        I: Fn(Option<&[Kind<'tcx>]>, &GenericParamDef, bool) -> Kind<'tcx>
-    {
+        args_for_def_id: impl Fn(DefId) -> (Option<&'b GenericArgs>, bool),
+        provided_kind: impl Fn(&GenericParamDef, &GenericArg) -> Kind<'tcx>,
+        inferred_kind: impl Fn(Option<&[Kind<'tcx>]>, &GenericParamDef, bool) -> Kind<'tcx>,
+    ) -> &'tcx Substs<'tcx> {
         // Collect the segments of the path: we need to substitute arguments
         // for parameters throughout the entire path (wherever there are
         // generic parameters).
index 71c78e7f87c07613f09eb5537faa668ffb2074d2..85b6bcbd144fc7a8debf1e8d8444b1efdcb94f81 100644 (file)
@@ -309,11 +309,20 @@ pub fn check_ref(&self,
                 };
                 if self.can_coerce(ref_ty, expected) {
                     if let Ok(src) = cm.span_to_snippet(sp) {
-                        let sugg_expr = match expr.node { // parenthesize if needed (Issue #46756)
+                        let needs_parens = match expr.node {
+                            // parenthesize if needed (Issue #46756)
                             hir::ExprKind::Cast(_, _) |
-                            hir::ExprKind::Binary(_, _, _) => format!("({})", src),
-                            _ => src,
+                            hir::ExprKind::Binary(_, _, _) => true,
+                            // parenthesize borrows of range literals (Issue #54505)
+                            _ if self.is_range_literal(expr) => true,
+                            _ => false,
                         };
+                        let sugg_expr = if needs_parens {
+                            format!("({})", src)
+                        } else {
+                            src
+                        };
+
                         if let Some(sugg) = self.can_use_as_ref(expr) {
                             return Some(sugg);
                         }
@@ -374,6 +383,66 @@ pub fn check_ref(&self,
         None
     }
 
+    /// This function checks if the specified expression is a built-in range literal.
+    /// (See: `LoweringContext::lower_expr()` in `src/librustc/hir/lowering.rs`).
+    fn is_range_literal(&self, expr: &hir::Expr) -> bool {
+        use hir::{Path, QPath, ExprKind, TyKind};
+
+        // We support `::std::ops::Range` and `::core::ops::Range` prefixes
+        let is_range_path = |path: &Path| {
+            let mut segs = path.segments.iter()
+                .map(|seg| seg.ident.as_str());
+
+            if let (Some(root), Some(std_core), Some(ops), Some(range), None) =
+                (segs.next(), segs.next(), segs.next(), segs.next(), segs.next())
+            {
+                // "{{root}}" is the equivalent of `::` prefix in Path
+                root == "{{root}}" && (std_core == "std" || std_core == "core")
+                    && ops == "ops" && range.starts_with("Range")
+            } else {
+                false
+            }
+        };
+
+        let span_is_range_literal = |span: &Span| {
+            // Check whether a span corresponding to a range expression
+            // is a range literal, rather than an explicit struct or `new()` call.
+            let source_map = self.tcx.sess.source_map();
+            let end_point = source_map.end_point(*span);
+
+            if let Ok(end_string) = source_map.span_to_snippet(end_point) {
+                !(end_string.ends_with("}") || end_string.ends_with(")"))
+            } else {
+                false
+            }
+        };
+
+        match expr.node {
+            // All built-in range literals but `..=` and `..` desugar to Structs
+            ExprKind::Struct(QPath::Resolved(None, ref path), _, _) |
+            // `..` desugars to its struct path
+            ExprKind::Path(QPath::Resolved(None, ref path)) => {
+                return is_range_path(&path) && span_is_range_literal(&expr.span);
+            }
+
+            // `..=` desugars into `::std::ops::RangeInclusive::new(...)`
+            ExprKind::Call(ref func, _) => {
+                if let ExprKind::Path(QPath::TypeRelative(ref ty, ref segment)) = func.node {
+                    if let TyKind::Path(QPath::Resolved(None, ref path)) = ty.node {
+                        let call_to_new = segment.ident.as_str() == "new";
+
+                        return is_range_path(&path) && span_is_range_literal(&expr.span)
+                            && call_to_new;
+                    }
+                }
+            }
+
+            _ => {}
+        }
+
+        false
+    }
+
     pub fn check_for_cast(&self,
                       err: &mut DiagnosticBuilder<'tcx>,
                       expr: &hir::Expr,
index 529f1e6161be987dd9a429d0c9d173f8066b9a5b..be8b16dd2f577ca2deb5e1ccda5259434b3fc835 100644 (file)
@@ -2164,6 +2164,13 @@ pub fn write_substs(&self, node_id: hir::HirId, substs: &'tcx Substs<'tcx>) {
     /// occurred**, so that annotations like `Vec<_>` are preserved
     /// properly.
     pub fn write_user_substs_from_substs(&self, hir_id: hir::HirId, substs: &'tcx Substs<'tcx>) {
+        debug!(
+            "write_user_substs_from_substs({:?}, {:?}) in fcx {}",
+            hir_id,
+            substs,
+            self.tag(),
+        );
+
         if !substs.is_noop() {
             let user_substs = self.infcx.canonicalize_response(&substs);
             debug!("instantiate_value_path: user_substs = {:?}", user_substs);
@@ -3752,6 +3759,13 @@ fn check_expr_kind(
         expected: Expectation<'tcx>,
         needs: Needs
     ) -> Ty<'tcx> {
+        debug!(
+            "check_expr_kind(expr={:?}, expected={:?}, needs={:?})",
+            expr,
+            expected,
+            needs,
+        );
+
         let tcx = self.tcx;
         let id = expr.id;
         match expr.node {
@@ -4981,10 +4995,13 @@ pub fn instantiate_value_path(&self,
                                   span: Span,
                                   node_id: ast::NodeId)
                                   -> (Ty<'tcx>, Def) {
-        debug!("instantiate_value_path(path={:?}, def={:?}, node_id={})",
-               segments,
-               def,
-               node_id);
+        debug!(
+            "instantiate_value_path(segments={:?}, self_ty={:?}, def={:?}, node_id={})",
+            segments,
+            self_ty,
+            def,
+            node_id,
+        );
 
         let path_segs = self.def_ids_for_path_segments(segments, def);
 
@@ -5194,6 +5211,11 @@ pub fn instantiate_value_path(&self,
         let hir_id = self.tcx.hir.node_to_hir_id(node_id);
         self.write_substs(hir_id, substs);
 
+        debug!(
+            "instantiate_value_path: id={:?} substs={:?}",
+            node_id,
+            substs,
+        );
         self.write_user_substs_from_substs(hir_id, substs);
 
         (ty_substituted, new_def)
index ccd94022711cd7362408154793d7b80f6cff185b..229f9466b512257ea140ca9ec9d8b3226e30c3b7 100644 (file)
 // lldb-command:run
 
 // lldb-command:print arg
-// lldb-check:[...]$0 = Struct<i32> { b: -1, b1: 0 }
+// lldbg-check:[...]$0 = Struct<i32> { b: -1, b1: 0 }
+// lldbr-check:(associated_types::Struct<i32>) arg = Struct<i32> { b: -1, b1: 0 }
 // lldb-command:continue
 
 // lldb-command:print inferred
-// lldb-check:[...]$1 = 1
+// lldbg-check:[...]$1 = 1
+// lldbr-check:(i64) inferred = 1
 // lldb-command:print explicitly
-// lldb-check:[...]$2 = 1
+// lldbg-check:[...]$2 = 1
+// lldbr-check:(i64) explicitly = 1
 // lldb-command:continue
 
 // lldb-command:print arg
-// lldb-check:[...]$3 = 2
+// lldbg-check:[...]$3 = 2
+// lldbr-check:(i64) arg = 2
 // lldb-command:continue
 
 // lldb-command:print arg
-// lldb-check:[...]$4 = (4, 5)
+// lldbg-check:[...]$4 = (4, 5)
+// lldbr-check:((i32, i64)) arg = { = 4 = 5 }
 // lldb-command:continue
 
 // lldb-command:print a
-// lldb-check:[...]$5 = 6
+// lldbg-check:[...]$5 = 6
+// lldbr-check:(i32) a = 6
 // lldb-command:print b
-// lldb-check:[...]$6 = 7
+// lldbg-check:[...]$6 = 7
+// lldbr-check:(i64) b = 7
 // lldb-command:continue
 
 // lldb-command:print a
-// lldb-check:[...]$7 = 8
+// lldbg-check:[...]$7 = 8
+// lldbr-check:(i64) a = 8
 // lldb-command:print b
-// lldb-check:[...]$8 = 9
+// lldbg-check:[...]$8 = 9
+// lldbr-check:(i32) b = 9
 // lldb-command:continue
 
 #![allow(unused_variables)]
index 01ce5bd31626e33ed0d3a5b047318144b30d7155..75737cd6f135e835cdc9337a8a77c1a2fd2eeaae 100644 (file)
 
 // lldb-command:run
 // lldb-command:print b
-// lldb-check:[...]$0 = false
+// lldbg-check:[...]$0 = false
+// lldbr-check:(bool) b = false
 // lldb-command:print i
-// lldb-check:[...]$1 = -1
+// lldbg-check:[...]$1 = -1
+// lldbr-check:(isize) i = -1
 
-// NOTE: LLDB does not support 32bit chars
-// d ebugger:print (usize)(c)
-// c heck:$3 = 97
+// NOTE: only rust-enabled lldb supports 32bit chars
+// lldbr-command:print c
+// lldbr-check:(char) c = 'a'
 
 // lldb-command:print i8
-// lldb-check:[...]$2 = 'D'
+// lldbg-check:[...]$2 = 'D'
+// lldbr-check:(i8) i8 = 68
 // lldb-command:print i16
-// lldb-check:[...]$3 = -16
+// lldbg-check:[...]$3 = -16
+// lldbr-check:(i16) i16 = -16
 // lldb-command:print i32
-// lldb-check:[...]$4 = -32
+// lldbg-check:[...]$4 = -32
+// lldbr-check:(i32) i32 = -32
 // lldb-command:print i64
-// lldb-check:[...]$5 = -64
+// lldbg-check:[...]$5 = -64
+// lldbr-check:(i64) i64 = -64
 // lldb-command:print u
-// lldb-check:[...]$6 = 1
+// lldbg-check:[...]$6 = 1
+// lldbr-check:(usize) u = 1
 // lldb-command:print u8
-// lldb-check:[...]$7 = 'd'
+// lldbg-check:[...]$7 = 'd'
+// lldbr-check:(u8) u8 = 100
 // lldb-command:print u16
-// lldb-check:[...]$8 = 16
+// lldbg-check:[...]$8 = 16
+// lldbr-check:(u16) u16 = 16
 // lldb-command:print u32
-// lldb-check:[...]$9 = 32
+// lldbg-check:[...]$9 = 32
+// lldbr-check:(u32) u32 = 32
 // lldb-command:print u64
-// lldb-check:[...]$10 = 64
+// lldbg-check:[...]$10 = 64
+// lldbr-check:(u64) u64 = 64
 // lldb-command:print f32
-// lldb-check:[...]$11 = 2.5
+// lldbg-check:[...]$11 = 2.5
+// lldbr-check:(f32) f32 = 2.5
 // lldb-command:print f64
-// lldb-check:[...]$12 = 3.5
+// lldbg-check:[...]$12 = 3.5
+// lldbr-check:(f64) f64 = 3.5
 
 #![allow(unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
index f6c0ff09efe93f7fa3ac509327d9ca71bb979424..6f618c3881f968e056b8a7e2c4193ac66833c1a8 100644 (file)
 
 // lldb-command:run
 // lldb-command:print *bool_ref
-// lldb-check:[...]$0 = true
+// lldbg-check:[...]$0 = true
+// lldbr-check:(bool) *bool_ref = true
 
 // lldb-command:print *int_ref
-// lldb-check:[...]$1 = -1
+// lldbg-check:[...]$1 = -1
+// lldbr-check:(isize) *int_ref = -1
 
-// NOTE: lldb doesn't support 32bit chars at the moment
-// d ebugger:print *char_ref
-// c heck:[...]$x = 97
+// NOTE: only rust-enabled lldb supports 32bit chars
+// lldbr-command:print *char_ref
+// lldbr-check:(char) *char_ref = 'a'
 
 // lldb-command:print *i8_ref
-// lldb-check:[...]$2 = 'D'
+// lldbg-check:[...]$2 = 'D'
+// lldbr-check:(i8) *i8_ref = 68
 
 // lldb-command:print *i16_ref
-// lldb-check:[...]$3 = -16
+// lldbg-check:[...]$3 = -16
+// lldbr-check:(i16) *i16_ref = -16
 
 // lldb-command:print *i32_ref
-// lldb-check:[...]$4 = -32
+// lldbg-check:[...]$4 = -32
+// lldbr-check:(i32) *i32_ref = -32
 
 // lldb-command:print *i64_ref
-// lldb-check:[...]$5 = -64
+// lldbg-check:[...]$5 = -64
+// lldbr-check:(i64) *i64_ref = -64
 
 // lldb-command:print *uint_ref
-// lldb-check:[...]$6 = 1
+// lldbg-check:[...]$6 = 1
+// lldbr-check:(usize) *uint_ref = 1
 
 // lldb-command:print *u8_ref
-// lldb-check:[...]$7 = 'd'
+// lldbg-check:[...]$7 = 'd'
+// lldbr-check:(u8) *u8_ref = 100
 
 // lldb-command:print *u16_ref
-// lldb-check:[...]$8 = 16
+// lldbg-check:[...]$8 = 16
+// lldbr-check:(u16) *u16_ref = 16
 
 // lldb-command:print *u32_ref
-// lldb-check:[...]$9 = 32
+// lldbg-check:[...]$9 = 32
+// lldbr-check:(u32) *u32_ref = 32
 
 // lldb-command:print *u64_ref
-// lldb-check:[...]$10 = 64
+// lldbg-check:[...]$10 = 64
+// lldbr-check:(u64) *u64_ref = 64
 
 // lldb-command:print *f32_ref
-// lldb-check:[...]$11 = 2.5
+// lldbg-check:[...]$11 = 2.5
+// lldbr-check:(f32) *f32_ref = 2.5
 
 // lldb-command:print *f64_ref
-// lldb-check:[...]$12 = 3.5
+// lldbg-check:[...]$12 = 3.5
+// lldbr-check:(f64) *f64_ref = 3.5
 
 #![allow(unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
index d6f379634be5bceddfa9b652316bb0871b6afea8..73b92b82ba0a6032c888e9301be75cbbad271185 100644 (file)
 // lldb-command:run
 
 // lldb-command:print *the_a_ref
-// lldb-check:[...]$0 = TheA
+// lldbg-check:[...]$0 = TheA
+// lldbr-check:(borrowed_c_style_enum::ABC) *the_a_ref = borrowed_c_style_enum::ABC::TheA
 
 // lldb-command:print *the_b_ref
-// lldb-check:[...]$1 = TheB
+// lldbg-check:[...]$1 = TheB
+// lldbr-check:(borrowed_c_style_enum::ABC) *the_b_ref = borrowed_c_style_enum::ABC::TheB
 
 // lldb-command:print *the_c_ref
-// lldb-check:[...]$2 = TheC
+// lldbg-check:[...]$2 = TheC
+// lldbr-check:(borrowed_c_style_enum::ABC) *the_c_ref = borrowed_c_style_enum::ABC::TheC
 
 #![allow(unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
index 9e63beff3cb2eeb0f7c3973a87224fe562f3cc9c..9143e83343fb89cddc0ee653302d92e8e4c585c1 100644 (file)
 // lldb-command:run
 
 // lldb-command:print *the_a_ref
-// lldb-check:[...]$0 = TheA { x: 0, y: 8970181431921507452 }
+// lldbg-check:[...]$0 = TheA { x: 0, y: 8970181431921507452 }
+// lldbr-check:(borrowed_enum::ABC::TheA) *the_a_ref = TheA { borrowed_enum::ABC::TheA: 0, borrowed_enum::ABC::TheB: 8970181431921507452 }
 // lldb-command:print *the_b_ref
-// lldb-check:[...]$1 = TheB(0, 286331153, 286331153)
+// lldbg-check:[...]$1 = TheB(0, 286331153, 286331153)
+// lldbr-check:(borrowed_enum::ABC::TheB) *the_b_ref = { = 0 = 286331153 = 286331153 }
 // lldb-command:print *univariant_ref
-// lldb-check:[...]$2 = TheOnlyCase(4820353753753434)
+// lldbg-check:[...]$2 = TheOnlyCase(4820353753753434)
+// lldbr-check:(borrowed_enum::Univariant) *univariant_ref = { borrowed_enum::TheOnlyCase = { = 4820353753753434 } }
 
 #![allow(unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
index 01428e515e27f25b15dfc333980167356c33015a..3efb4dd470e65800ce62a5b860ecb7dc1f96eace 100644 (file)
 // lldb-command:run
 
 // lldb-command:print *stack_val_ref
-// lldb-check:[...]$0 = SomeStruct { x: 10, y: 23.5 }
+// lldbg-check:[...]$0 = SomeStruct { x: 10, y: 23.5 }
+// lldbr-check:(borrowed_struct::SomeStruct) *stack_val_ref = SomeStruct { x: 10, y: 23.5 }
 
 // lldb-command:print *stack_val_interior_ref_1
-// lldb-check:[...]$1 = 10
+// lldbg-check:[...]$1 = 10
+// lldbr-check:(isize) *stack_val_interior_ref_1 = 10
 
 // lldb-command:print *stack_val_interior_ref_2
-// lldb-check:[...]$2 = 23.5
+// lldbg-check:[...]$2 = 23.5
+// lldbr-check:(f64) *stack_val_interior_ref_2 = 23.5
 
 // lldb-command:print *ref_to_unnamed
-// lldb-check:[...]$3 = SomeStruct { x: 11, y: 24.5 }
+// lldbg-check:[...]$3 = SomeStruct { x: 11, y: 24.5 }
+// lldbr-check:(borrowed_struct::SomeStruct) *ref_to_unnamed = SomeStruct { x: 11, y: 24.5 }
 
 // lldb-command:print *unique_val_ref
-// lldb-check:[...]$4 = SomeStruct { x: 13, y: 26.5 }
+// lldbg-check:[...]$4 = SomeStruct { x: 13, y: 26.5 }
+// lldbr-check:(borrowed_struct::SomeStruct) *unique_val_ref = SomeStruct { x: 13, y: 26.5 }
 
 // lldb-command:print *unique_val_interior_ref_1
-// lldb-check:[...]$5 = 13
+// lldbg-check:[...]$5 = 13
+// lldbr-check:(isize) *unique_val_interior_ref_1 = 13
 
 // lldb-command:print *unique_val_interior_ref_2
-// lldb-check:[...]$6 = 26.5
+// lldbg-check:[...]$6 = 26.5
+// lldbr-check:(f64) *unique_val_interior_ref_2 = 26.5
 
 #![allow(unused_variables)]
 #![feature(box_syntax)]
index 17db88ee37f53fcecbeaad6a81a415e8274e2caf..ec7c000350f53023ce9fa366227feab7b4a54c48 100644 (file)
 // lldb-command:run
 
 // lldb-command:print *stack_val_ref
-// lldb-check:[...]$0 = (-14, -19)
+// lldbg-check:[...]$0 = (-14, -19)
+// lldbr-check:((i16, f32)) *stack_val_ref = { = -14 = -19 }
 
 // lldb-command:print *ref_to_unnamed
-// lldb-check:[...]$1 = (-15, -20)
+// lldbg-check:[...]$1 = (-15, -20)
+// lldbr-check:((i16, f32)) *ref_to_unnamed = { = -15 = -20 }
 
 // lldb-command:print *unique_val_ref
-// lldb-check:[...]$2 = (-17, -22)
+// lldbg-check:[...]$2 = (-17, -22)
+// lldbr-check:((i16, f32)) *unique_val_ref = { = -17 = -22 }
 
 
 #![allow(unused_variables)]
index 9e95498b0c30e7cbbd6903efb3a121e9e1bb9e27..78effa5f3dffe3af4575bfb9d6bac054e0f6d7f6 100644 (file)
 // lldb-command:run
 
 // lldb-command:print *bool_ref
-// lldb-check:[...]$0 = true
+// lldbg-check:[...]$0 = true
+// lldbr-check:(bool) *bool_ref = true
 
 // lldb-command:print *int_ref
-// lldb-check:[...]$1 = -1
+// lldbg-check:[...]$1 = -1
+// lldbr-check:(isize) *int_ref = -1
 
-// d ebugger:print *char_ref
-// c heck:[...]$3 = 97
+// NOTE: only rust-enabled lldb supports 32bit chars
+// lldbr-command:print *char_ref
+// lldbr-check:(char) *char_ref = 97
 
 // lldb-command:print *i8_ref
-// lldb-check:[...]$2 = 68
+// lldbg-check:[...]$2 = 68
+// lldbr-check:(i8) *i8_ref = 68
 
 // lldb-command:print *i16_ref
-// lldb-check:[...]$3 = -16
+// lldbg-check:[...]$3 = -16
+// lldbr-check:(i16) *i16_ref = -16
 
 // lldb-command:print *i32_ref
-// lldb-check:[...]$4 = -32
+// lldbg-check:[...]$4 = -32
+// lldbr-check:(i32) *i32_ref = -32
 
 // lldb-command:print *i64_ref
-// lldb-check:[...]$5 = -64
+// lldbg-check:[...]$5 = -64
+// lldbr-check:(i64) *i64_ref = -64
 
 // lldb-command:print *uint_ref
-// lldb-check:[...]$6 = 1
+// lldbg-check:[...]$6 = 1
+// lldbr-check:(usize) *uint_ref = 1
 
 // lldb-command:print *u8_ref
-// lldb-check:[...]$7 = 100
+// lldbg-check:[...]$7 = 100
+// lldbr-check:(u8) *u8_ref = 100
 
 // lldb-command:print *u16_ref
-// lldb-check:[...]$8 = 16
+// lldbg-check:[...]$8 = 16
+// lldbr-check:(u16) *u16_ref = 16
 
 // lldb-command:print *u32_ref
-// lldb-check:[...]$9 = 32
+// lldbg-check:[...]$9 = 32
+// lldbr-check:(u32) *u32_ref = 32
 
 // lldb-command:print *u64_ref
-// lldb-check:[...]$10 = 64
+// lldbg-check:[...]$10 = 64
+// lldbr-check:(u64) *u64_ref = 64
 
 // lldb-command:print *f32_ref
-// lldb-check:[...]$11 = 2.5
+// lldbg-check:[...]$11 = 2.5
+// lldbr-check:(f32) *f32_ref = 2.5
 
 // lldb-command:print *f64_ref
-// lldb-check:[...]$12 = 3.5
+// lldbg-check:[...]$12 = 3.5
+// lldbr-check:(f64) *f64_ref = 3.5
 
 #![allow(unused_variables)]
 #![feature(box_syntax)]
index 98c09fe09de8f3f2937ef30b644e15bbae403352..7e25a9bf76a86e947511c16f88386d000a923e13 100644 (file)
 
 // lldb-command:run
 // lldb-command:print *a
-// lldb-check:[...]$0 = 1
+// lldbg-check:[...]$0 = 1
+// lldbr-check:(i32) *a = 1
 // lldb-command:print *b
-// lldb-check:[...]$1 = (2, 3.5)
+// lldbg-check:[...]$1 = (2, 3.5)
+// lldbr-check:((i32, f64)) *b = { = 2 = 3.5 }
 
 #![allow(unused_variables)]
 #![feature(box_syntax)]
index ac091b4a533db49b8b3fabe694e74eba386ad5d0..130ea3822cb3ae9e91eee7886d7fd80e2ab610ea 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-tidy-linelength
+
 // min-lldb-version: 310
 
 // compile-flags:-g
 // lldb-command:run
 
 // lldb-command:print *unique
-// lldb-check:[...]$0 = StructWithSomePadding { x: 99, y: 999, z: 9999, w: 99999 }
+// lldbg-check:[...]$0 = StructWithSomePadding { x: 99, y: 999, z: 9999, w: 99999 }
+// lldbr-check:(boxed_struct::StructWithSomePadding) *unique = StructWithSomePadding { x: 99, y: 999, z: 9999, w: 99999 }
 
 // lldb-command:print *unique_dtor
-// lldb-check:[...]$1 = StructWithDestructor { x: 77, y: 777, z: 7777, w: 77777 }
+// lldbg-check:[...]$1 = StructWithDestructor { x: 77, y: 777, z: 7777, w: 77777 }
+// lldbr-check:(boxed_struct::StructWithDestructor) *unique_dtor = StructWithDestructor { x: 77, y: 777, z: 7777, w: 77777 }
 
 #![allow(unused_variables)]
 #![feature(box_syntax)]
index c14f8c7b354fcaaf75dbfef7792ee6c78c238480..c0fb2dbdda2746776004599a6b7f288f253d3e50 100644 (file)
 // lldb-command:run
 
 // lldb-command:print self
-// lldb-check:[...]$0 = 1111
+// lldbg-check:[...]$0 = 1111
+// lldbr-check:(isize) self = 1111
 // lldb-command:continue
 
 // lldb-command:print self
-// lldb-check:[...]$1 = Struct { x: 2222, y: 3333 }
+// lldbg-check:[...]$1 = Struct { x: 2222, y: 3333 }
+// lldbr-check:(by_value_self_argument_in_trait_impl::Struct) self = Struct { x: 2222, y: 3333 }
 // lldb-command:continue
 
 // lldb-command:print self
-// lldb-check:[...]$2 = (4444.5, 5555, 6666, 7777.5)
+// lldbg-check:[...]$2 = (4444.5, 5555, 6666, 7777.5)
+// lldbr-check:((f64, isize, isize, f64)) self = { = 4444.5 = 5555 = 6666 = 7777.5 }
 // lldb-command:continue
 
 #![feature(omit_gdb_pretty_printer_section)]
index 004e15d1cc6c15a0745afa92bc96d3d910f6a8dd..0a19a040a5f438bed847e4d88a6a48b15ca7844d 100644 (file)
 // lldb-command:run
 
 // lldb-command:print tuple_interior_padding
-// lldb-check:[...]$0 = (0, OneHundred)
+// lldbg-check:[...]$0 = (0, OneHundred)
+// lldbr-check:((i16, c_style_enum_in_composite::AnEnum)) tuple_interior_padding = { = 0 = c_style_enum_in_composite::AnEnum::OneHundred }
 
 // lldb-command:print tuple_padding_at_end
-// lldb-check:[...]$1 = ((1, OneThousand), 2)
+// lldbg-check:[...]$1 = ((1, OneThousand), 2)
+// lldbr-check:(((u64, c_style_enum_in_composite::AnEnum), u64)) tuple_padding_at_end = { = { = 1 = c_style_enum_in_composite::AnEnum::OneThousand } = 2 }
 // lldb-command:print tuple_different_enums
-// lldb-check:[...]$2 = (OneThousand, MountainView, OneMillion, Vienna)
+// lldbg-check:[...]$2 = (OneThousand, MountainView, OneMillion, Vienna)
+// lldbr-check:((c_style_enum_in_composite::AnEnum, c_style_enum_in_composite::AnotherEnum, c_style_enum_in_composite::AnEnum, c_style_enum_in_composite::AnotherEnum)) tuple_different_enums = { = c_style_enum_in_composite::AnEnum::OneThousand = c_style_enum_in_composite::AnotherEnum::MountainView = c_style_enum_in_composite::AnEnum::OneMillion = c_style_enum_in_composite::AnotherEnum::Vienna }
 
 // lldb-command:print padded_struct
-// lldb-check:[...]$3 = PaddedStruct { a: 3, b: OneMillion, c: 4, d: Toronto, e: 5 }
+// lldbg-check:[...]$3 = PaddedStruct { a: 3, b: OneMillion, c: 4, d: Toronto, e: 5 }
+// lldbr-check:(c_style_enum_in_composite::PaddedStruct) padded_struct = PaddedStruct { a: 3, b: c_style_enum_in_composite::AnEnum::OneMillion, c: 4, d: c_style_enum_in_composite::AnotherEnum::Toronto, e: 5 }
 
 // lldb-command:print packed_struct
-// lldb-check:[...]$4 = PackedStruct { a: 6, b: OneHundred, c: 7, d: Vienna, e: 8 }
+// lldbg-check:[...]$4 = PackedStruct { a: 6, b: OneHundred, c: 7, d: Vienna, e: 8 }
+// lldbr-check:(c_style_enum_in_composite::PackedStruct) packed_struct = PackedStruct { a: 6, b: c_style_enum_in_composite::AnEnum::OneHundred, c: 7, d: c_style_enum_in_composite::AnotherEnum::Vienna, e: 8 }
 
 // lldb-command:print non_padded_struct
-// lldb-check:[...]$5 = NonPaddedStruct { a: OneMillion, b: MountainView, c: OneThousand, d: Toronto }
+// lldbg-check:[...]$5 = NonPaddedStruct { a: OneMillion, b: MountainView, c: OneThousand, d: Toronto }
+// lldbr-check:(c_style_enum_in_composite::NonPaddedStruct) non_padded_struct = NonPaddedStruct { a: c_style_enum_in_composite::AnEnum::OneMillion, b: c_style_enum_in_composite::AnotherEnum::MountainView, c: c_style_enum_in_composite::AnEnum::OneThousand, d: c_style_enum_in_composite::AnotherEnum::Toronto }
 
 // lldb-command:print struct_with_drop
-// lldb-check:[...]$6 = (StructWithDrop { a: OneHundred, b: Vienna }, 9)
+// lldbg-check:[...]$6 = (StructWithDrop { a: OneHundred, b: Vienna }, 9)
+// lldbr-check:((c_style_enum_in_composite::StructWithDrop, i64)) struct_with_drop = { = StructWithDrop { a: c_style_enum_in_composite::AnEnum::OneHundred, b: c_style_enum_in_composite::AnotherEnum::Vienna } = 9 }
 
 #![allow(unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
index 2dbac8e3d9eac0cff654f54edffbc4ec311f5af8..a756d4fdf6ce799fb192cdf73ac10459af284e64 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-tidy-linelength
+
 // ignore-aarch64
 // ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
 // min-lldb-version: 310
 // lldb-command:run
 
 // lldb-command:print auto_one
-// lldb-check:[...]$0 = One
+// lldbg-check:[...]$0 = One
+// lldbr-check:(c_style_enum::AutoDiscriminant) auto_one = c_style_enum::AutoDiscriminant::One
 
 // lldb-command:print auto_two
-// lldb-check:[...]$1 = Two
+// lldbg-check:[...]$1 = Two
+// lldbr-check:(c_style_enum::AutoDiscriminant) auto_two = c_style_enum::AutoDiscriminant::Two
 
 // lldb-command:print auto_three
-// lldb-check:[...]$2 = Three
+// lldbg-check:[...]$2 = Three
+// lldbr-check:(c_style_enum::AutoDiscriminant) auto_three = c_style_enum::AutoDiscriminant::Three
 
 // lldb-command:print manual_one_hundred
-// lldb-check:[...]$3 = OneHundred
+// lldbg-check:[...]$3 = OneHundred
+// lldbr-check:(c_style_enum::ManualDiscriminant) manual_one_hundred = c_style_enum::ManualDiscriminant::OneHundred
 
 // lldb-command:print manual_one_thousand
-// lldb-check:[...]$4 = OneThousand
+// lldbg-check:[...]$4 = OneThousand
+// lldbr-check:(c_style_enum::ManualDiscriminant) manual_one_thousand = c_style_enum::ManualDiscriminant::OneThousand
 
 // lldb-command:print manual_one_million
-// lldb-check:[...]$5 = OneMillion
+// lldbg-check:[...]$5 = OneMillion
+// lldbr-check:(c_style_enum::ManualDiscriminant) manual_one_million = c_style_enum::ManualDiscriminant::OneMillion
 
 // lldb-command:print single_variant
-// lldb-check:[...]$6 = TheOnlyVariant
+// lldbg-check:[...]$6 = TheOnlyVariant
+// lldbr-check:(c_style_enum::SingleVariant) single_variant = c_style_enum::SingleVariant::TheOnlyVariant
 
 #![allow(unused_variables)]
 #![allow(dead_code)]
index 5335e0bfa4a6984297f7449e3da158962850b19a..bb61b394a9c7be2831228671e66f38d8e0ca8488 100644 (file)
 // lldb-command:run
 
 // lldb-command:print x
-// lldb-check:[...]$0 = 0.5
+// lldbg-check:[...]$0 = 0.5
+// lldbr-check:(f64) x = 0.5
 // lldb-command:print y
-// lldb-check:[...]$1 = 10
+// lldbg-check:[...]$1 = 10
+// lldbr-check:(i32) y = 10
 // lldb-command:continue
 
 // lldb-command:print *x
-// lldb-check:[...]$2 = 29
+// lldbg-check:[...]$2 = 29
+// lldbr-check:(i32) *x = 29
 // lldb-command:print *y
-// lldb-check:[...]$3 = 110
+// lldbg-check:[...]$3 = 110
+// lldbr-check:(i32) *y = 110
 // lldb-command:continue
 
 #![feature(box_syntax)]
index 28728df92805103c5c708df6c38f2f5fab1ff166..9002e19ce21baa77b38b903e732393794e475362 100644 (file)
 // lldb-command:run
 
 // lldb-command:print result
-// lldb-check:[...]$0 = (17, 17)
+// lldbg-check:[...]$0 = (17, 17)
+// lldbr-check:((u32, u32)) result = { = 17 = 17 }
 // lldb-command:print a_variable
-// lldb-check:[...]$1 = 123456789
+// lldbg-check:[...]$1 = 123456789
+// lldbr-check:(u32) a_variable = 123456789
 // lldb-command:print another_variable
-// lldb-check:[...]$2 = 123456789.5
+// lldbg-check:[...]$2 = 123456789.5
+// lldbr-check:(f64) another_variable = 123456789.5
 // lldb-command:continue
 
 // lldb-command:print result
-// lldb-check:[...]$3 = (1212, 1212)
+// lldbg-check:[...]$3 = (1212, 1212)
+// lldbr-check:((i16, i16)) result = { = 1212 = 1212 }
 // lldb-command:print a_variable
-// lldb-check:[...]$4 = 123456789
+// lldbg-check:[...]$4 = 123456789
+// lldbr-check:(u32) a_variable = 123456789
 // lldb-command:print another_variable
-// lldb-check:[...]$5 = 123456789.5
+// lldbg-check:[...]$5 = 123456789.5
+// lldbr-check:(f64) another_variable = 123456789.5
 // lldb-command:continue
 
 
index efa9ee59b22b2233588d078348b2c34f07b852e5..b152fa27906f1d146fee8142c683d9817ddb5f2b 100644 (file)
 // lldb-command:run
 
 // lldb-command:print a
-// lldb-check:[...]$0 = 1
+// lldbg-check:[...]$0 = 1
+// lldbr-check:(isize) a = 1
 // lldb-command:print b
-// lldb-check:[...]$1 = false
+// lldbg-check:[...]$1 = false
+// lldbr-check:(bool) b = false
 // lldb-command:continue
 
 // lldb-command:print a
-// lldb-check:[...]$2 = 2
+// lldbg-check:[...]$2 = 2
+// lldbr-check:(isize) a = 2
 // lldb-command:print b
-// lldb-check:[...]$3 = 3
+// lldbg-check:[...]$3 = 3
+// lldbr-check:(u16) b = 3
 // lldb-command:print c
-// lldb-check:[...]$4 = 4
+// lldbg-check:[...]$4 = 4
+// lldbr-check:(u16) c = 4
 // lldb-command:continue
 
 // lldb-command:print a
-// lldb-check:[...]$5 = 5
+// lldbg-check:[...]$5 = 5
+// lldbr-check:(isize) a = 5
 // lldb-command:print b
-// lldb-check:[...]$6 = (6, 7)
+// lldbg-check:[...]$6 = (6, 7)
+// lldbr-check:((u32, u32)) b = { = 6 = 7 }
 // lldb-command:continue
 
 // lldb-command:print h
-// lldb-check:[...]$7 = 8
+// lldbg-check:[...]$7 = 8
+// lldbr-check:(i16) h = 8
 // lldb-command:print i
-// lldb-check:[...]$8 = Struct { a: 9, b: 10 }
+// lldbg-check:[...]$8 = Struct { a: 9, b: 10 }
+// lldbr-check:(destructured_fn_argument::Struct) i = Struct { a: 9, b: 10 }
 // lldb-command:print j
-// lldb-check:[...]$9 = 11
+// lldbg-check:[...]$9 = 11
+// lldbr-check:(i16) j = 11
 // lldb-command:continue
 
 // lldb-command:print k
-// lldb-check:[...]$10 = 12
+// lldbg-check:[...]$10 = 12
+// lldbr-check:(i64) k = 12
 // lldb-command:print l
-// lldb-check:[...]$11 = 13
+// lldbg-check:[...]$11 = 13
+// lldbr-check:(i32) l = 13
 // lldb-command:continue
 
 // lldb-command:print m
-// lldb-check:[...]$12 = 14
+// lldbg-check:[...]$12 = 14
+// lldbr-check:(isize) m = 14
 // lldb-command:print n
-// lldb-check:[...]$13 = 16
+// lldbg-check:[...]$13 = 16
+// lldbr-check:(i32) n = 16
 // lldb-command:continue
 
 // lldb-command:print o
-// lldb-check:[...]$14 = 18
+// lldbg-check:[...]$14 = 18
+// lldbr-check:(i32) o = 18
 // lldb-command:continue
 
 // lldb-command:print p
-// lldb-check:[...]$15 = 19
+// lldbg-check:[...]$15 = 19
+// lldbr-check:(i64) p = 19
 // lldb-command:print q
-// lldb-check:[...]$16 = 20
+// lldbg-check:[...]$16 = 20
+// lldbr-check:(i32) q = 20
 // lldb-command:print r
-// lldb-check:[...]$17 = Struct { a: 21, b: 22 }
+// lldbg-check:[...]$17 = Struct { a: 21, b: 22 }
+// lldbr-check:(destructured_fn_argument::Struct) r = Struct { a: 21, b: 22 }
 // lldb-command:continue
 
 // lldb-command:print s
-// lldb-check:[...]$18 = 24
+// lldbg-check:[...]$18 = 24
+// lldbr-check:(i32) s = 24
 // lldb-command:print t
-// lldb-check:[...]$19 = 23
+// lldbg-check:[...]$19 = 23
+// lldbr-check:(i64) t = 23
 // lldb-command:continue
 
 // lldb-command:print u
-// lldb-check:[...]$20 = 25
+// lldbg-check:[...]$20 = 25
+// lldbr-check:(i16) u = 25
 // lldb-command:print v
-// lldb-check:[...]$21 = 26
+// lldbg-check:[...]$21 = 26
+// lldbr-check:(i32) v = 26
 // lldb-command:print w
-// lldb-check:[...]$22 = 27
+// lldbg-check:[...]$22 = 27
+// lldbr-check:(i64) w = 27
 // lldb-command:print x
-// lldb-check:[...]$23 = 28
+// lldbg-check:[...]$23 = 28
+// lldbr-check:(i32) x = 28
 // lldb-command:print y
-// lldb-check:[...]$24 = 29
+// lldbg-check:[...]$24 = 29
+// lldbr-check:(i64) y = 29
 // lldb-command:print z
-// lldb-check:[...]$25 = 30
+// lldbg-check:[...]$25 = 30
+// lldbr-check:(i32) z = 30
 // lldb-command:print ae
-// lldb-check:[...]$26 = 31
+// lldbg-check:[...]$26 = 31
+// lldbr-check:(i64) ae = 31
 // lldb-command:print oe
-// lldb-check:[...]$27 = 32
+// lldbg-check:[...]$27 = 32
+// lldbr-check:(i32) oe = 32
 // lldb-command:print ue
-// lldb-check:[...]$28 = 33
+// lldbg-check:[...]$28 = 33
+// lldbr-check:(u16) ue = 33
 // lldb-command:continue
 
 // lldb-command:print aa
-// lldb-check:[...]$29 = (34, 35)
+// lldbg-check:[...]$29 = (34, 35)
+// lldbr-check:((isize, isize)) aa = { = 34 = 35 }
 // lldb-command:continue
 
 // lldb-command:print bb
-// lldb-check:[...]$30 = (36, 37)
+// lldbg-check:[...]$30 = (36, 37)
+// lldbr-check:((isize, isize)) bb = { = 36 = 37 }
 // lldb-command:continue
 
 // lldb-command:print cc
-// lldb-check:[...]$31 = 38
+// lldbg-check:[...]$31 = 38
+// lldbr-check:(isize) cc = 38
 // lldb-command:continue
 
 // lldb-command:print dd
-// lldb-check:[...]$32 = (40, 41, 42)
+// lldbg-check:[...]$32 = (40, 41, 42)
+// lldbr-check:((isize, isize, isize)) dd = { = 40 = 41 = 42 }
 // lldb-command:continue
 
 // lldb-command:print *ee
-// lldb-check:[...]$33 = (43, 44, 45)
+// lldbg-check:[...]$33 = (43, 44, 45)
+// lldbr-check:((isize, isize, isize)) *ee = { = 43 = 44 = 45 }
 // lldb-command:continue
 
 // lldb-command:print *ff
-// lldb-check:[...]$34 = 46
+// lldbg-check:[...]$34 = 46
+// lldbr-check:(isize) *ff = 46
 // lldb-command:print gg
-// lldb-check:[...]$35 = (47, 48)
+// lldbg-check:[...]$35 = (47, 48)
+// lldbr-check:((isize, isize)) gg = { = 47 = 48 }
 // lldb-command:continue
 
 // lldb-command:print *hh
-// lldb-check:[...]$36 = 50
+// lldbg-check:[...]$36 = 50
+// lldbr-check:(i32) *hh = 50
 // lldb-command:continue
 
 // lldb-command:print ii
-// lldb-check:[...]$37 = 51
+// lldbg-check:[...]$37 = 51
+// lldbr-check:(i32) ii = 51
 // lldb-command:continue
 
 // lldb-command:print *jj
-// lldb-check:[...]$38 = 52
+// lldbg-check:[...]$38 = 52
+// lldbr-check:(i32) *jj = 52
 // lldb-command:continue
 
 // lldb-command:print kk
-// lldb-check:[...]$39 = 53
+// lldbg-check:[...]$39 = 53
+// lldbr-check:(f64) kk = 53
 // lldb-command:print ll
-// lldb-check:[...]$40 = 54
+// lldbg-check:[...]$40 = 54
+// lldbr-check:(isize) ll = 54
 // lldb-command:continue
 
 // lldb-command:print mm
-// lldb-check:[...]$41 = 55
+// lldbg-check:[...]$41 = 55
+// lldbr-check:(f64) mm = 55
 // lldb-command:print *nn
-// lldb-check:[...]$42 = 56
+// lldbg-check:[...]$42 = 56
+// lldbr-check:(isize) *nn = 56
 // lldb-command:continue
 
 // lldb-command:print oo
-// lldb-check:[...]$43 = 57
+// lldbg-check:[...]$43 = 57
+// lldbr-check:(isize) oo = 57
 // lldb-command:print pp
-// lldb-check:[...]$44 = 58
+// lldbg-check:[...]$44 = 58
+// lldbr-check:(isize) pp = 58
 // lldb-command:print qq
-// lldb-check:[...]$45 = 59
+// lldbg-check:[...]$45 = 59
+// lldbr-check:(isize) qq = 59
 // lldb-command:continue
 
 // lldb-command:print rr
-// lldb-check:[...]$46 = 60
+// lldbg-check:[...]$46 = 60
+// lldbr-check:(isize) rr = 60
 // lldb-command:print ss
-// lldb-check:[...]$47 = 61
+// lldbg-check:[...]$47 = 61
+// lldbr-check:(isize) ss = 61
 // lldb-command:print tt
-// lldb-check:[...]$48 = 62
+// lldbg-check:[...]$48 = 62
+// lldbr-check:(isize) tt = 62
 // lldb-command:continue
 
 #![allow(unused_variables)]
index e973c22fd4a8502b785310a15e6792422ed48f74..48231a906c902a7032a7187f33dc6c2dac277621 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-tidy-linelength
+
 // min-lldb-version: 310
 
 // compile-flags:-g
 
 // DESTRUCTURED STRUCT
 // lldb-command:print x
-// lldb-check:[...]$0 = 400
+// lldbg-check:[...]$0 = 400
+// lldbr-check:(i16) x = 400
 // lldb-command:print y
-// lldb-check:[...]$1 = 401.5
+// lldbg-check:[...]$1 = 401.5
+// lldbr-check:(f32) y = 401.5
 // lldb-command:print z
-// lldb-check:[...]$2 = true
+// lldbg-check:[...]$2 = true
+// lldbr-check:(bool) z = true
 // lldb-command:continue
 
 // DESTRUCTURED TUPLE
 // lldb-command:print _i8
-// lldb-check:[...]$3 = 0x6f
+// lldbg-check:[...]$3 = 0x6f
+// lldbr-check:(i8) _i8 = 111
 // lldb-command:print _u8
-// lldb-check:[...]$4 = 0x70
+// lldbg-check:[...]$4 = 0x70
+// lldbr-check:(u8) _u8 = 112
 // lldb-command:print _i16
-// lldb-check:[...]$5 = -113
+// lldbg-check:[...]$5 = -113
+// lldbr-check:(i16) _i16 = -113
 // lldb-command:print _u16
-// lldb-check:[...]$6 = 114
+// lldbg-check:[...]$6 = 114
+// lldbr-check:(u16) _u16 = 114
 // lldb-command:print _i32
-// lldb-check:[...]$7 = -115
+// lldbg-check:[...]$7 = -115
+// lldbr-check:(i32) _i32 = -115
 // lldb-command:print _u32
-// lldb-check:[...]$8 = 116
+// lldbg-check:[...]$8 = 116
+// lldbr-check:(u32) _u32 = 116
 // lldb-command:print _i64
-// lldb-check:[...]$9 = -117
+// lldbg-check:[...]$9 = -117
+// lldbr-check:(i64) _i64 = -117
 // lldb-command:print _u64
-// lldb-check:[...]$10 = 118
+// lldbg-check:[...]$10 = 118
+// lldbr-check:(u64) _u64 = 118
 // lldb-command:print _f32
-// lldb-check:[...]$11 = 119.5
+// lldbg-check:[...]$11 = 119.5
+// lldbr-check:(f32) _f32 = 119.5
 // lldb-command:print _f64
-// lldb-check:[...]$12 = 120.5
+// lldbg-check:[...]$12 = 120.5
+// lldbr-check:(f64) _f64 = 120.5
 // lldb-command:continue
 
 // MORE COMPLEX CASE
 // lldb-command:print v1
-// lldb-check:[...]$13 = 80000
+// lldbg-check:[...]$13 = 80000
+// lldbr-check:(i32) v1 = 80000
 // lldb-command:print x1
-// lldb-check:[...]$14 = 8000
+// lldbg-check:[...]$14 = 8000
+// lldbr-check:(i16) x1 = 8000
 // lldb-command:print *y1
-// lldb-check:[...]$15 = 80001.5
+// lldbg-check:[...]$15 = 80001.5
+// lldbr-check:(f32) *y1 = 80001.5
 // lldb-command:print z1
-// lldb-check:[...]$16 = false
+// lldbg-check:[...]$16 = false
+// lldbr-check:(bool) z1 = false
 // lldb-command:print *x2
-// lldb-check:[...]$17 = -30000
+// lldbg-check:[...]$17 = -30000
+// lldbr-check:(i16) *x2 = -30000
 // lldb-command:print y2
-// lldb-check:[...]$18 = -300001.5
+// lldbg-check:[...]$18 = -300001.5
+// lldbr-check:(f32) y2 = -300001.5
 // lldb-command:print *z2
-// lldb-check:[...]$19 = true
+// lldbg-check:[...]$19 = true
+// lldbr-check:(bool) *z2 = true
 // lldb-command:print v2
-// lldb-check:[...]$20 = 854237.5
+// lldbg-check:[...]$20 = 854237.5
+// lldbr-check:(f64) v2 = 854237.5
 // lldb-command:continue
 
 // SIMPLE IDENTIFIER
 // lldb-command:print i
-// lldb-check:[...]$21 = 1234
+// lldbg-check:[...]$21 = 1234
+// lldbr-check:(i32) i = 1234
 // lldb-command:continue
 
 // lldb-command:print simple_struct_ident
-// lldb-check:[...]$22 = Struct { x: 3537, y: 35437.5, z: true }
+// lldbg-check:[...]$22 = Struct { x: 3537, y: 35437.5, z: true }
+// lldbr-check:(destructured_for_loop_variable::Struct) simple_struct_ident = Struct { x: 3537, y: 35437.5, z: true }
 // lldb-command:continue
 
 // lldb-command:print simple_tuple_ident
-// lldb-check:[...]$23 = (34903493, 232323)
+// lldbg-check:[...]$23 = (34903493, 232323)
+// lldbr-check:((u32, i64)) simple_tuple_ident = { = 34903493 = 232323 }
 // lldb-command:continue
 
 #![allow(unused_variables)]
index 1f18b77ab8f6fbf6b797096506b4d89b4d9991f5..5a2edf81d29316012d8a31e0ba3e82c3cfc86099 100644 (file)
 // lldb-command:run
 
 // lldb-command:print a
-// lldb-check:[...]$0 = 1
+// lldbg-check:[...]$0 = 1
+// lldbr-check:(isize) a = 1
 // lldb-command:print b
-// lldb-check:[...]$1 = false
+// lldbg-check:[...]$1 = false
+// lldbr-check:(bool) b = false
 
 // lldb-command:print c
-// lldb-check:[...]$2 = 2
+// lldbg-check:[...]$2 = 2
+// lldbr-check:(isize) c = 2
 // lldb-command:print d
-// lldb-check:[...]$3 = 3
+// lldbg-check:[...]$3 = 3
+// lldbr-check:(u16) d = 3
 // lldb-command:print e
-// lldb-check:[...]$4 = 4
+// lldbg-check:[...]$4 = 4
+// lldbr-check:(u16) e = 4
 
 // lldb-command:print f
-// lldb-check:[...]$5 = 5
+// lldbg-check:[...]$5 = 5
+// lldbr-check:(isize) f = 5
 // lldb-command:print g
-// lldb-check:[...]$6 = (6, 7)
+// lldbg-check:[...]$6 = (6, 7)
+// lldbr-check:((u32, u32)) g = { = 6 = 7 }
 
 // lldb-command:print h
-// lldb-check:[...]$7 = 8
+// lldbg-check:[...]$7 = 8
+// lldbr-check:(i16) h = 8
 // lldb-command:print i
-// lldb-check:[...]$8 = Struct { a: 9, b: 10 }
+// lldbg-check:[...]$8 = Struct { a: 9, b: 10 }
+// lldbr-check:(destructured_local::Struct) i = Struct { a: 9, b: 10 }
 // lldb-command:print j
-// lldb-check:[...]$9 = 11
+// lldbg-check:[...]$9 = 11
+// lldbr-check:(i16) j = 11
 
 // lldb-command:print k
-// lldb-check:[...]$10 = 12
+// lldbg-check:[...]$10 = 12
+// lldbr-check:(i64) k = 12
 // lldb-command:print l
-// lldb-check:[...]$11 = 13
+// lldbg-check:[...]$11 = 13
+// lldbr-check:(i32) l = 13
 
 // lldb-command:print m
-// lldb-check:[...]$12 = 14
+// lldbg-check:[...]$12 = 14
+// lldbr-check:(i32) m = 14
 // lldb-command:print n
-// lldb-check:[...]$13 = 16
+// lldbg-check:[...]$13 = 16
+// lldbr-check:(i32) n = 16
 
 // lldb-command:print o
-// lldb-check:[...]$14 = 18
+// lldbg-check:[...]$14 = 18
+// lldbr-check:(i32) o = 18
 
 // lldb-command:print p
-// lldb-check:[...]$15 = 19
+// lldbg-check:[...]$15 = 19
+// lldbr-check:(i64) p = 19
 // lldb-command:print q
-// lldb-check:[...]$16 = 20
+// lldbg-check:[...]$16 = 20
+// lldbr-check:(i32) q = 20
 // lldb-command:print r
-// lldb-check:[...]$17 = Struct { a: 21, b: 22 }
+// lldbg-check:[...]$17 = Struct { a: 21, b: 22 }
+// lldbr-check:(destructured_local::Struct) r = Struct { a: 21, b: 22 }
 
 // lldb-command:print s
-// lldb-check:[...]$18 = 24
+// lldbg-check:[...]$18 = 24
+// lldbr-check:(i32) s = 24
 // lldb-command:print t
-// lldb-check:[...]$19 = 23
+// lldbg-check:[...]$19 = 23
+// lldbr-check:(i64) t = 23
 
 // lldb-command:print u
-// lldb-check:[...]$20 = 25
+// lldbg-check:[...]$20 = 25
+// lldbr-check:(i32) u = 25
 // lldb-command:print v
-// lldb-check:[...]$21 = 26
+// lldbg-check:[...]$21 = 26
+// lldbr-check:(i32) v = 26
 // lldb-command:print w
-// lldb-check:[...]$22 = 27
+// lldbg-check:[...]$22 = 27
+// lldbr-check:(i32) w = 27
 // lldb-command:print x
-// lldb-check:[...]$23 = 28
+// lldbg-check:[...]$23 = 28
+// lldbr-check:(i32) x = 28
 // lldb-command:print y
-// lldb-check:[...]$24 = 29
+// lldbg-check:[...]$24 = 29
+// lldbr-check:(i64) y = 29
 // lldb-command:print z
-// lldb-check:[...]$25 = 30
+// lldbg-check:[...]$25 = 30
+// lldbr-check:(i32) z = 30
 // lldb-command:print ae
-// lldb-check:[...]$26 = 31
+// lldbg-check:[...]$26 = 31
+// lldbr-check:(i64) ae = 31
 // lldb-command:print oe
-// lldb-check:[...]$27 = 32
+// lldbg-check:[...]$27 = 32
+// lldbr-check:(i32) oe = 32
 // lldb-command:print ue
-// lldb-check:[...]$28 = 33
+// lldbg-check:[...]$28 = 33
+// lldbr-check:(i32) ue = 33
 
 // lldb-command:print aa
-// lldb-check:[...]$29 = (34, 35)
+// lldbg-check:[...]$29 = (34, 35)
+// lldbr-check:((i32, i32)) aa = { = 34 = 35 }
 
 // lldb-command:print bb
-// lldb-check:[...]$30 = (36, 37)
+// lldbg-check:[...]$30 = (36, 37)
+// lldbr-check:((i32, i32)) bb = { = 36 = 37 }
 
 // lldb-command:print cc
-// lldb-check:[...]$31 = 38
+// lldbg-check:[...]$31 = 38
+// lldbr-check:(i32) cc = 38
 
 // lldb-command:print dd
-// lldb-check:[...]$32 = (40, 41, 42)
+// lldbg-check:[...]$32 = (40, 41, 42)
+// lldbr-check:((i32, i32, i32)) dd = { = 40 = 41 = 42 }
 
 // lldb-command:print *ee
-// lldb-check:[...]$33 = (43, 44, 45)
+// lldbg-check:[...]$33 = (43, 44, 45)
+// lldbr-check:((i32, i32, i32)) *ee = { = 43 = 44 = 45 }
 
 // lldb-command:print *ff
-// lldb-check:[...]$34 = 46
+// lldbg-check:[...]$34 = 46
+// lldbr-check:(i32) *ff = 46
 
 // lldb-command:print gg
-// lldb-check:[...]$35 = (47, 48)
+// lldbg-check:[...]$35 = (47, 48)
+// lldbr-check:((i32, i32)) gg = { = 47 = 48 }
 
 // lldb-command:print *hh
-// lldb-check:[...]$36 = 50
+// lldbg-check:[...]$36 = 50
+// lldbr-check:(i32) *hh = 50
 
 // lldb-command:print ii
-// lldb-check:[...]$37 = 51
+// lldbg-check:[...]$37 = 51
+// lldbr-check:(i32) ii = 51
 
 // lldb-command:print *jj
-// lldb-check:[...]$38 = 52
+// lldbg-check:[...]$38 = 52
+// lldbr-check:(i32) *jj = 52
 
 // lldb-command:print kk
-// lldb-check:[...]$39 = 53
+// lldbg-check:[...]$39 = 53
+// lldbr-check:(f64) kk = 53
 
 // lldb-command:print ll
-// lldb-check:[...]$40 = 54
+// lldbg-check:[...]$40 = 54
+// lldbr-check:(isize) ll = 54
 
 // lldb-command:print mm
-// lldb-check:[...]$41 = 55
+// lldbg-check:[...]$41 = 55
+// lldbr-check:(f64) mm = 55
 
 // lldb-command:print *nn
-// lldb-check:[...]$42 = 56
+// lldbg-check:[...]$42 = 56
+// lldbr-check:(isize) *nn = 56
 
 
 #![allow(unused_variables)]
index 2e151577590b3647ded4c70aee82c8940b414c99..c5460c69944f1535128af557dec11aa821a44ce2 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-tidy-linelength
+
 // min-lldb-version: 310
 
 // compile-flags:-g
 // lldb-command:run
 
 // lldb-command:print no_padding1
-// lldb-check:[...]$0 = NoPadding1 { x: [0, 1, 2], y: -3, z: [4.5, 5.5] }
+// lldbg-check:[...]$0 = NoPadding1 { x: [0, 1, 2], y: -3, z: [4.5, 5.5] }
+// lldbr-check:(evec_in_struct::NoPadding1) no_padding1 = NoPadding1 { x: [0, 1, 2], y: -3, z: [4.5, 5.5] }
 // lldb-command:print no_padding2
-// lldb-check:[...]$1 = NoPadding2 { x: [6, 7, 8], y: [[9, 10], [11, 12]] }
+// lldbg-check:[...]$1 = NoPadding2 { x: [6, 7, 8], y: [[9, 10], [11, 12]] }
+// lldbr-check:(evec_in_struct::NoPadding2) no_padding2 = NoPadding2 { x: [6, 7, 8], y: [[9, 10], [11, 12]] }
 
 // lldb-command:print struct_internal_padding
-// lldb-check:[...]$2 = StructInternalPadding { x: [13, 14], y: [15, 16] }
+// lldbg-check:[...]$2 = StructInternalPadding { x: [13, 14], y: [15, 16] }
+// lldbr-check:(evec_in_struct::StructInternalPadding) struct_internal_padding = StructInternalPadding { x: [13, 14], y: [15, 16] }
 
 // lldb-command:print single_vec
-// lldb-check:[...]$3 = SingleVec { x: [17, 18, 19, 20, 21] }
+// lldbg-check:[...]$3 = SingleVec { x: [17, 18, 19, 20, 21] }
+// lldbr-check:(evec_in_struct::SingleVec) single_vec = SingleVec { x: [17, 18, 19, 20, 21] }
 
 // lldb-command:print struct_padded_at_end
-// lldb-check:[...]$4 = StructPaddedAtEnd { x: [22, 23], y: [24, 25] }
+// lldbg-check:[...]$4 = StructPaddedAtEnd { x: [22, 23], y: [24, 25] }
+// lldbr-check:(evec_in_struct::StructPaddedAtEnd) struct_padded_at_end = StructPaddedAtEnd { x: [22, 23], y: [24, 25] }
 
 #![allow(unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
index 01901b2c42b8e74c693470b5fc1e526541897fad..2e6602c63ff707e2031b2e4142ba6535c658bf05 100644 (file)
 // lldb-command:run
 
 // lldb-command:print len
-// lldb-check:[...]$0 = 20
+// lldbg-check:[...]$0 = 20
+// lldbr-check:(i32) len = 20
 // lldb-command:print local0
-// lldb-check:[...]$1 = 19
+// lldbg-check:[...]$1 = 19
+// lldbr-check:(i32) local0 = 19
 // lldb-command:print local1
-// lldb-check:[...]$2 = true
+// lldbg-check:[...]$2 = true
+// lldbr-check:(bool) local1 = true
 // lldb-command:print local2
-// lldb-check:[...]$3 = 20.5
+// lldbg-check:[...]$3 = 20.5
+// lldbr-check:(f64) local2 = 20.5
 
 // lldb-command:continue
 
index c8f2e385a6e74fbac0dd2d4393743004d900678f..9fc03feec9b6dc5297ce3487561947fde752d592 100644 (file)
 // lldb-command:run
 
 // lldb-command:print x
-// lldb-check:[...]$0 = 111102
+// lldbg-check:[...]$0 = 111102
+// lldbr-check:(isize) x = 111102
 // lldb-command:print y
-// lldb-check:[...]$1 = true
+// lldbg-check:[...]$1 = true
+// lldbr-check:(bool) y = true
 // lldb-command:continue
 
 // lldb-command:print a
-// lldb-check:[...]$2 = 2000
+// lldbg-check:[...]$2 = 2000
+// lldbr-check:(i32) a = 2000
 // lldb-command:print b
-// lldb-check:[...]$3 = 3000
+// lldbg-check:[...]$3 = 3000
+// lldbr-check:(i64) b = 3000
 // lldb-command:continue
 
 
index f1bfc08915edd86258f6e1a0af53dcf2215fffed..89b0e4ca453bf5a573acab158e3a84210d1f4c5b 100644 (file)
 // lldb-command:run
 
 // lldb-command:print *t0
-// lldb-check:[...]$0 = 1
+// lldbg-check:[...]$0 = 1
+// lldbr-check:(i32) *t0 = 1
 // lldb-command:print *t1
-// lldb-check:[...]$1 = 2.5
+// lldbg-check:[...]$1 = 2.5
+// lldbr-check:(f64) *t1 = 2.5
 // lldb-command:print ret
-// lldb-check:[...]$2 = ((1, 2.5), (2.5, 1))
+// lldbg-check:[...]$2 = ((1, 2.5), (2.5, 1))
+// lldbr-check:(((i32, f64), (f64, i32))) ret = { = { = 1 = 2.5 } = { = 2.5 = 1 } }
 // lldb-command:continue
 
 // lldb-command:print *t0
-// lldb-check:[...]$3 = 3.5
+// lldbg-check:[...]$3 = 3.5
+// lldbr-check:(f64) *t0 = 3.5
 // lldb-command:print *t1
-// lldb-check:[...]$4 = 4
+// lldbg-check:[...]$4 = 4
+// lldbr-check:(u16) *t1 = 4
 // lldb-command:print ret
-// lldb-check:[...]$5 = ((3.5, 4), (4, 3.5))
+// lldbg-check:[...]$5 = ((3.5, 4), (4, 3.5))
+// lldbr-check:(((f64, u16), (u16, f64))) ret = { = { = 3.5 = 4 } = { = 4 = 3.5 } }
 // lldb-command:continue
 
 // lldb-command:print *t0
-// lldb-check:[...]$6 = 5
+// lldbg-check:[...]$6 = 5
+// lldbr-check:(i32) *t0 = 5
 // lldb-command:print *t1
-// lldb-check:[...]$7 = Struct { a: 6, b: 7.5 }
+// lldbg-check:[...]$7 = Struct { a: 6, b: 7.5 }
+// lldbr-check:(generic_function::Struct) *t1 = Struct { a: 6, b: 7.5 }
 // lldb-command:print ret
-// lldb-check:[...]$8 = ((5, Struct { a: 6, b: 7.5 }), (Struct { a: 6, b: 7.5 }, 5))
+// lldbg-check:[...]$8 = ((5, Struct { a: 6, b: 7.5 }), (Struct { a: 6, b: 7.5 }, 5))
+// lldbr-check:(((i32, generic_function::Struct), (generic_function::Struct, i32))) ret = { = { = 5 = Struct { a: 6, b: 7.5 } } = { = Struct { a: 6, b: 7.5 } = 5 } }
 // lldb-command:continue
 
 #![feature(omit_gdb_pretty_printer_section)]
index 79ae007a5006285820e37cc016dd47216911095c..ea6dc62eca9eb8278f2b689f64201b236aca5b73 100644 (file)
 // lldb-command:run
 
 // lldb-command:print x
-// lldb-check:[...]$0 = -1
+// lldbg-check:[...]$0 = -1
+// lldbr-check:(i32) x = -1
 // lldb-command:print y
-// lldb-check:[...]$1 = 1
+// lldbg-check:[...]$1 = 1
+// lldbr-check:(i32) y = 1
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$2 = -1
+// lldbg-check:[...]$2 = -1
+// lldbr-check:(i32) x = -1
 // lldb-command:print y
-// lldb-check:[...]$3 = 2.5
+// lldbg-check:[...]$3 = 2.5
+// lldbr-check:(f64) y = 2.5
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$4 = -2.5
+// lldbg-check:[...]$4 = -2.5
+// lldbr-check:(f64) x = -2.5
 // lldb-command:print y
-// lldb-check:[...]$5 = 1
+// lldbg-check:[...]$5 = 1
+// lldbr-check:(i32) y = 1
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$6 = -2.5
+// lldbg-check:[...]$6 = -2.5
+// lldbr-check:(f64) x = -2.5
 // lldb-command:print y
-// lldb-check:[...]$7 = 2.5
+// lldbg-check:[...]$7 = 2.5
+// lldbr-check:(f64) y = 2.5
 // lldb-command:continue
 
 
index 4f3f6dfc821eef4d589405ed70559aaca94c3a3e..97bb9aa98e87b4dd95ef7c39887c95b8610b1cd4 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-tidy-linelength
 
 // compile-flags:-g
 // min-lldb-version: 310
 
 // STACK BY REF
 // lldb-command:print *self
-// lldb-check:[...]$0 = Struct<(u32, i32)> { x: (8888, -8888) }
+// lldbg-check:[...]$0 = Struct<(u32, i32)> { x: (8888, -8888) }
+// lldbr-check:(generic_method_on_generic_struct::Struct<(u32, i32)>) *self = { x = { = 8888 = -8888 } }
 // lldb-command:print arg1
-// lldb-check:[...]$1 = -1
+// lldbg-check:[...]$1 = -1
+// lldbr-check:(isize) arg1 = -1
 // lldb-command:print arg2
-// lldb-check:[...]$2 = 2
+// lldbg-check:[...]$2 = 2
+// lldbr-check:(u16) arg2 = 2
 // lldb-command:continue
 
 // STACK BY VAL
 // lldb-command:print self
-// lldb-check:[...]$3 = Struct<(u32, i32)> { x: (8888, -8888) }
+// lldbg-check:[...]$3 = Struct<(u32, i32)> { x: (8888, -8888) }
+// lldbr-check:(generic_method_on_generic_struct::Struct<(u32, i32)>) self = { x = { = 8888 = -8888 } }
 // lldb-command:print arg1
-// lldb-check:[...]$4 = -3
+// lldbg-check:[...]$4 = -3
+// lldbr-check:(isize) arg1 = -3
 // lldb-command:print arg2
-// lldb-check:[...]$5 = -4
+// lldbg-check:[...]$5 = -4
+// lldbr-check:(i16) arg2 = -4
 // lldb-command:continue
 
 // OWNED BY REF
 // lldb-command:print *self
-// lldb-check:[...]$6 = Struct<f64> { x: 1234.5 }
+// lldbg-check:[...]$6 = Struct<f64> { x: 1234.5 }
+// lldbr-check:(generic_method_on_generic_struct::Struct<f64>) *self = Struct<f64> { x: 1234.5 }
 // lldb-command:print arg1
-// lldb-check:[...]$7 = -5
+// lldbg-check:[...]$7 = -5
+// lldbr-check:(isize) arg1 = -5
 // lldb-command:print arg2
-// lldb-check:[...]$8 = -6
+// lldbg-check:[...]$8 = -6
+// lldbr-check:(i32) arg2 = -6
 // lldb-command:continue
 
 // OWNED BY VAL
 // lldb-command:print self
-// lldb-check:[...]$9 = Struct<f64> { x: 1234.5 }
+// lldbg-check:[...]$9 = Struct<f64> { x: 1234.5 }
+// lldbr-check:(generic_method_on_generic_struct::Struct<f64>) self = Struct<f64> { x: 1234.5 }
 // lldb-command:print arg1
-// lldb-check:[...]$10 = -7
+// lldbg-check:[...]$10 = -7
+// lldbr-check:(isize) arg1 = -7
 // lldb-command:print arg2
-// lldb-check:[...]$11 = -8
+// lldbg-check:[...]$11 = -8
+// lldbr-check:(i64) arg2 = -8
 // lldb-command:continue
 
 // OWNED MOVED
 // lldb-command:print *self
-// lldb-check:[...]$12 = Struct<f64> { x: 1234.5 }
+// lldbg-check:[...]$12 = Struct<f64> { x: 1234.5 }
+// lldbr-check:(generic_method_on_generic_struct::Struct<f64>) *self = Struct<f64> { x: 1234.5 }
 // lldb-command:print arg1
-// lldb-check:[...]$13 = -9
+// lldbg-check:[...]$13 = -9
+// lldbr-check:(isize) arg1 = -9
 // lldb-command:print arg2
-// lldb-check:[...]$14 = -10.5
+// lldbg-check:[...]$14 = -10.5
+// lldbr-check:(f32) arg2 = -10.5
 // lldb-command:continue
 
 #![feature(box_syntax)]
index 35f00ce78717b59901fc5f8cd3cc26725e710c59..4e06a15e1cdf0000239a2f7ef8821ccdacbcab97 100644 (file)
 // lldb-command:run
 
 // lldb-command:print int_int
-// lldb-check:[...]$0 = AGenericStruct<i32, i32> { key: 0, value: 1 }
+// lldbg-check:[...]$0 = AGenericStruct<i32, i32> { key: 0, value: 1 }
+// lldbr-check:(generic_struct::AGenericStruct<i32, i32>) int_int = AGenericStruct<i32, i32> { key: 0, value: 1 }
 // lldb-command:print int_float
-// lldb-check:[...]$1 = AGenericStruct<i32, f64> { key: 2, value: 3.5 }
+// lldbg-check:[...]$1 = AGenericStruct<i32, f64> { key: 2, value: 3.5 }
+// lldbr-check:(generic_struct::AGenericStruct<i32, f64>) int_float = AGenericStruct<i32, f64> { key: 2, value: 3.5 }
 // lldb-command:print float_int
-// lldb-check:[...]$2 = AGenericStruct<f64, i32> { key: 4.5, value: 5 }
+// lldbg-check:[...]$2 = AGenericStruct<f64, i32> { key: 4.5, value: 5 }
+// lldbr-check:(generic_struct::AGenericStruct<f64, i32>) float_int = AGenericStruct<f64, i32> { key: 4.5, value: 5 }
 
 // lldb-command:print float_int_float
-// lldb-check:[...]$3 = AGenericStruct<f64, generic_struct::AGenericStruct<i32, f64>> { key: 6.5, value: AGenericStruct<i32, f64> { key: 7, value: 8.5 } }
+// lldbg-check:[...]$3 = AGenericStruct<f64, generic_struct::AGenericStruct<i32, f64>> { key: 6.5, value: AGenericStruct<i32, f64> { key: 7, value: 8.5 } }
+// lldbr-check:(generic_struct::AGenericStruct<f64, generic_struct::AGenericStruct<i32, f64>>) float_int_float = AGenericStruct<f64, generic_struct::AGenericStruct<i32, f64>> { key: 6.5, value: AGenericStruct<i32, f64> { key: 7, value: 8.5 } }
 
 
 #![feature(omit_gdb_pretty_printer_section)]
index 012bd6140cdbe6470f3f54e92696cad08979c528..62bec28a022af0ab397827956926f5a7edd28fb9 100644 (file)
 // lldb-command:run
 
 // lldb-command:print case1
-// lldb-check:[...]$0 = Case1(0, 31868, 31868, 31868, 31868)
+// lldbg-check:[...]$0 = Case1(0, 31868, 31868, 31868, 31868)
+// lldbr-check:(generic_tuple_style_enum::Regular<u16, u32, u64>::Case1) case1 = { = 0 = 31868 = 31868 = 31868 = 31868 }
 
 // lldb-command:print case2
-// lldb-check:[...]$1 = Case2(0, 286331153, 286331153)
+// lldbg-check:[...]$1 = Case2(0, 286331153, 286331153)
+// lldbr-check:(generic_tuple_style_enum::Regular<i16, i32, i64>::Case2) case2 = Regular<i16, i32, i64>::Case2 { generic_tuple_style_enum::Regular<i16, i32, i64>::Case1: 0, generic_tuple_style_enum::Regular<i16, i32, i64>::Case2: 286331153, generic_tuple_style_enum::Regular<i16, i32, i64>::Case3: 286331153 }
 
 // lldb-command:print case3
-// lldb-check:[...]$2 = Case3(0, 6438275382588823897)
+// lldbg-check:[...]$2 = Case3(0, 6438275382588823897)
+// lldbr-check:(generic_tuple_style_enum::Regular<i16, i32, i64>::Case3) case3 = Regular<i16, i32, i64>::Case3 { generic_tuple_style_enum::Regular<i16, i32, i64>::Case1: 0, generic_tuple_style_enum::Regular<i16, i32, i64>::Case2: 6438275382588823897 }
 
 // lldb-command:print univariant
-// lldb-check:[...]$3 = TheOnlyCase(-1)
+// lldbg-check:[...]$3 = TheOnlyCase(-1)
+// lldbr-check:(generic_tuple_style_enum::Univariant<i64>) univariant = { generic_tuple_style_enum::TheOnlyCase = { = -1 } }
 
 #![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
index 2c75349e5c8c7b18c8252ca26bc6c0b38a5d97d2..e915bf137028b82589fe93d8769e7f9ee9b1cf0f 100644 (file)
 // lldb-command:run
 
 // lldb-command:print string1.length
-// lldb-check:[...]$0 = 48
+// lldbg-check:[...]$0 = 48
+// lldbr-check:(usize) length = 48
 // lldb-command:print string2.length
-// lldb-check:[...]$1 = 49
+// lldbg-check:[...]$1 = 49
+// lldbr-check:(usize) length = 49
 // lldb-command:print string3.length
-// lldb-check:[...]$2 = 50
+// lldbg-check:[...]$2 = 50
+// lldbr-check:(usize) length = 50
 
 // lldb-command:continue
 
index a971e06ed5ec211b4a94f3a461802ffd80027059..6c3988b127ec21ac05aff709c0835e4efed3e1a0 100644 (file)
 // lldb-command:run
 
 // lldb-command:print v
-// lldb-check:[...]$0 = vec![1, 2, 3]
+// lldbg-check:[...]$0 = vec![1, 2, 3]
+// lldbr-check:(alloc::vec::Vec<i32>) v = vec![1, 2, 3]
 // lldb-command:print zs
-// lldb-check:[...]$1 = StructWithZeroSizedField { x: ZeroSizedStruct, y: 123, z: ZeroSizedStruct, w: 456 }
-// lldb-command:continue
+// lldbg-check:[...]$1 = StructWithZeroSizedField { x: ZeroSizedStruct, y: 123, z: ZeroSizedStruct, w: 456 }
+// lldbr-check:(issue_22656::StructWithZeroSizedField) zs = StructWithZeroSizedField { x: ZeroSizedStruct { }, y: 123, z: ZeroSizedStruct { }, w: 456 }
+// lldbr-command:continue
 
 #![allow(unused_variables)]
 #![allow(dead_code)]
index e99e241411bfd3a56e83103bb71fc87bf07ea49f..7a3c30ed8e5d02598ecea2d244948e80390efc5b 100644 (file)
 
 // FIRST ITERATION
 // lldb-command:print x
-// lldb-check:[...]$0 = 1
+// lldbg-check:[...]$0 = 1
+// lldbr-check:(i32) x = 1
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$1 = -1
+// lldbg-check:[...]$1 = -1
+// lldbr-check:(i32) x = -1
 // lldb-command:continue
 
 // SECOND ITERATION
 // lldb-command:print x
-// lldb-check:[...]$2 = 2
+// lldbg-check:[...]$2 = 2
+// lldbr-check:(i32) x = 2
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$3 = -2
+// lldbg-check:[...]$3 = -2
+// lldbr-check:(i32) x = -2
 // lldb-command:continue
 
 // THIRD ITERATION
 // lldb-command:print x
-// lldb-check:[...]$4 = 3
+// lldbg-check:[...]$4 = 3
+// lldbr-check:(i32) x = 3
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$5 = -3
+// lldbg-check:[...]$5 = -3
+// lldbr-check:(i32) x = -3
 // lldb-command:continue
 
 // AFTER LOOP
 // lldb-command:print x
-// lldb-check:[...]$6 = 1000000
+// lldbg-check:[...]$6 = 1000000
+// lldbr-check:(i32) x = 1000000
 // lldb-command:continue
 
 #![feature(omit_gdb_pretty_printer_section)]
index 42e288321e1977366dc266b3701831558a1d4d73..1a21fe6c1a98c35fc73b36f7b1f4aa1bcfb90660 100644 (file)
 
 // BEFORE if
 // lldb-command:print x
-// lldb-check:[...]$0 = 999
+// lldbg-check:[...]$0 = 999
+// lldbr-check:(i32) x = 999
 // lldb-command:print y
-// lldb-check:[...]$1 = -1
+// lldbg-check:[...]$1 = -1
+// lldbr-check:(i32) y = -1
 // lldb-command:continue
 
 // AT BEGINNING of 'then' block
 // lldb-command:print x
-// lldb-check:[...]$2 = 999
+// lldbg-check:[...]$2 = 999
+// lldbr-check:(i32) x = 999
 // lldb-command:print y
-// lldb-check:[...]$3 = -1
+// lldbg-check:[...]$3 = -1
+// lldbr-check:(i32) y = -1
 // lldb-command:continue
 
 // AFTER 1st redeclaration of 'x'
 // lldb-command:print x
-// lldb-check:[...]$4 = 1001
+// lldbg-check:[...]$4 = 1001
+// lldbr-check:(i32) x = 1001
 // lldb-command:print y
-// lldb-check:[...]$5 = -1
+// lldbg-check:[...]$5 = -1
+// lldbr-check:(i32) y = -1
 // lldb-command:continue
 
 // AFTER 2st redeclaration of 'x'
 // lldb-command:print x
-// lldb-check:[...]$6 = 1002
+// lldbg-check:[...]$6 = 1002
+// lldbr-check:(i32) x = 1002
 // lldb-command:print y
-// lldb-check:[...]$7 = 1003
+// lldbg-check:[...]$7 = 1003
+// lldbr-check:(i32) y = 1003
 // lldb-command:continue
 
 // AFTER 1st if expression
 // lldb-command:print x
-// lldb-check:[...]$8 = 999
+// lldbg-check:[...]$8 = 999
+// lldbr-check:(i32) x = 999
 // lldb-command:print y
-// lldb-check:[...]$9 = -1
+// lldbg-check:[...]$9 = -1
+// lldbr-check:(i32) y = -1
 // lldb-command:continue
 
 // BEGINNING of else branch
 // lldb-command:print x
-// lldb-check:[...]$10 = 999
+// lldbg-check:[...]$10 = 999
+// lldbr-check:(i32) x = 999
 // lldb-command:print y
-// lldb-check:[...]$11 = -1
+// lldbg-check:[...]$11 = -1
+// lldbr-check:(i32) y = -1
 // lldb-command:continue
 
 // BEGINNING of else branch
 // lldb-command:print x
-// lldb-check:[...]$12 = 1004
+// lldbg-check:[...]$12 = 1004
+// lldbr-check:(i32) x = 1004
 // lldb-command:print y
-// lldb-check:[...]$13 = 1005
+// lldbg-check:[...]$13 = 1005
+// lldbr-check:(i32) y = 1005
 // lldb-command:continue
 
 // BEGINNING of else branch
 // lldb-command:print x
-// lldb-check:[...]$14 = 999
+// lldbg-check:[...]$14 = 999
+// lldbr-check:(i32) x = 999
 // lldb-command:print y
-// lldb-check:[...]$15 = -1
+// lldbg-check:[...]$15 = -1
+// lldbr-check:(i32) y = -1
 // lldb-command:continue
 
 #![feature(omit_gdb_pretty_printer_section)]
index 597d9837aadcffb3e5571fac494ad60e4596497a..3c10039e76abfb93b25b9dfe1a3122dbff8aa549 100644 (file)
 // lldb-command:run
 
 // lldb-command:print shadowed
-// lldb-check:[...]$0 = 231
+// lldbg-check:[...]$0 = 231
+// lldbr-check:(i32) shadowed = 231
 // lldb-command:print not_shadowed
-// lldb-check:[...]$1 = 232
+// lldbg-check:[...]$1 = 232
+// lldbr-check:(i32) not_shadowed = 232
 // lldb-command:continue
 
 // lldb-command:print shadowed
-// lldb-check:[...]$2 = 233
+// lldbg-check:[...]$2 = 233
+// lldbr-check:(i32) shadowed = 233
 // lldb-command:print not_shadowed
-// lldb-check:[...]$3 = 232
+// lldbg-check:[...]$3 = 232
+// lldbr-check:(i32) not_shadowed = 232
 // lldb-command:print local_to_arm
-// lldb-check:[...]$4 = 234
+// lldbg-check:[...]$4 = 234
+// lldbr-check:(i32) local_to_arm = 234
 // lldb-command:continue
 
 // lldb-command:print shadowed
-// lldb-check:[...]$5 = 236
+// lldbg-check:[...]$5 = 236
+// lldbr-check:(i32) shadowed = 236
 // lldb-command:print not_shadowed
-// lldb-check:[...]$6 = 232
+// lldbg-check:[...]$6 = 232
+// lldbr-check:(i32) not_shadowed = 232
 // lldb-command:continue
 
 // lldb-command:print shadowed
-// lldb-check:[...]$7 = 237
+// lldbg-check:[...]$7 = 237
+// lldbr-check:(isize) shadowed = 237
 // lldb-command:print not_shadowed
-// lldb-check:[...]$8 = 232
+// lldbg-check:[...]$8 = 232
+// lldbr-check:(i32) not_shadowed = 232
 // lldb-command:print local_to_arm
-// lldb-check:[...]$9 = 238
+// lldbg-check:[...]$9 = 238
+// lldbr-check:(isize) local_to_arm = 238
 // lldb-command:continue
 
 // lldb-command:print shadowed
-// lldb-check:[...]$10 = 239
+// lldbg-check:[...]$10 = 239
+// lldbr-check:(isize) shadowed = 239
 // lldb-command:print not_shadowed
-// lldb-check:[...]$11 = 232
+// lldbg-check:[...]$11 = 232
+// lldbr-check:(i32) not_shadowed = 232
 // lldb-command:continue
 
 // lldb-command:print shadowed
-// lldb-check:[...]$12 = 241
+// lldbg-check:[...]$12 = 241
+// lldbr-check:(isize) shadowed = 241
 // lldb-command:print not_shadowed
-// lldb-check:[...]$13 = 232
+// lldbg-check:[...]$13 = 232
+// lldbr-check:(i32) not_shadowed = 232
 // lldb-command:continue
 
 // lldb-command:print shadowed
-// lldb-check:[...]$14 = 243
+// lldbg-check:[...]$14 = 243
+// lldbr-check:(i32) shadowed = 243
 // lldb-command:print *local_to_arm
-// lldb-check:[...]$15 = 244
+// lldbg-check:[...]$15 = 244
+// lldbr-check:(i32) *local_to_arm = 244
 // lldb-command:continue
 
 // lldb-command:print shadowed
-// lldb-check:[...]$16 = 231
+// lldbg-check:[...]$16 = 231
+// lldbr-check:(i32) shadowed = 231
 // lldb-command:print not_shadowed
-// lldb-check:[...]$17 = 232
+// lldbg-check:[...]$17 = 232
+// lldbr-check:(i32) not_shadowed = 232
 // lldb-command:continue
 
 #![feature(omit_gdb_pretty_printer_section)]
index 0a8d3b61a8d8db681aad922b0e89a6f475d705ce..fec9d9af1bacab03286c78a2066d7f7157fae9cf 100644 (file)
 // lldb-command:run
 
 // lldb-command:print x
-// lldb-check:[...]$0 = false
+// lldbg-check:[...]$0 = false
+// lldbr-check:(bool) x = false
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$1 = false
+// lldbg-check:[...]$1 = false
+// lldbr-check:(bool) x = false
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$2 = 1000
+// lldbg-check:[...]$2 = 1000
+// lldbr-check:(isize) x = 1000
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$3 = 2.5
+// lldbg-check:[...]$3 = 2.5
+// lldbr-check:(f64) x = 2.5
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$4 = true
+// lldbg-check:[...]$4 = true
+// lldbr-check:(bool) x = true
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$5 = false
+// lldbg-check:[...]$5 = false
+// lldbr-check:(bool) x = false
 // lldb-command:continue
 
 #![feature(omit_gdb_pretty_printer_section)]
index e55088afd7d9fc739e2c21fcd06482d0159591c5..d160b0250cf32da9ddaf4e76c74406c28489b1ee 100644 (file)
 
 // FIRST ITERATION
 // lldb-command:print x
-// lldb-check:[...]$0 = 0
+// lldbg-check:[...]$0 = 0
+// lldbr-check:(i32) x = 0
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$1 = 1
+// lldbg-check:[...]$1 = 1
+// lldbr-check:(i32) x = 1
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$2 = 101
+// lldbg-check:[...]$2 = 101
+// lldbr-check:(i32) x = 101
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$3 = 101
+// lldbg-check:[...]$3 = 101
+// lldbr-check:(i32) x = 101
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$4 = -987
+// lldbg-check:[...]$4 = -987
+// lldbr-check:(i32) x = -987
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$5 = 101
+// lldbg-check:[...]$5 = 101
+// lldbr-check:(i32) x = 101
 // lldb-command:continue
 
 
 // SECOND ITERATION
 // lldb-command:print x
-// lldb-check:[...]$6 = 1
+// lldbg-check:[...]$6 = 1
+// lldbr-check:(i32) x = 1
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$7 = 2
+// lldbg-check:[...]$7 = 2
+// lldbr-check:(i32) x = 2
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$8 = 102
+// lldbg-check:[...]$8 = 102
+// lldbr-check:(i32) x = 102
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$9 = 102
+// lldbg-check:[...]$9 = 102
+// lldbr-check:(i32) x = 102
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$10 = -987
+// lldbg-check:[...]$10 = -987
+// lldbr-check:(i32) x = -987
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$11 = 102
+// lldbg-check:[...]$11 = 102
+// lldbr-check:(i32) x = 102
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$12 = 2
+// lldbg-check:[...]$12 = 2
+// lldbr-check:(i32) x = 2
 // lldb-command:continue
 
 #![feature(omit_gdb_pretty_printer_section)]
index 70dece865ece02fd36a64a5cede9d9e8fc157172..574752d728f6f7704be6d6241dfaf0bf0a801f80 100644 (file)
 // lldb-command:run
 
 // lldb-command:print x
-// lldb-check:[...]$0 = false
+// lldbg-check:[...]$0 = false
+// lldbr-check:(bool) x = false
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$1 = false
+// lldbg-check:[...]$1 = false
+// lldbr-check:(bool) x = false
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$2 = 1000
+// lldbg-check:[...]$2 = 1000
+// lldbr-check:(isize) x = 1000
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$3 = 2.5
+// lldbg-check:[...]$3 = 2.5
+// lldbr-check:(f64) x = 2.5
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$4 = true
+// lldbg-check:[...]$4 = true
+// lldbr-check:(bool) x = true
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$5 = false
+// lldbg-check:[...]$5 = false
+// lldbr-check:(bool) x = false
 // lldb-command:continue
 
 
index 38d8b75a644fd2d825d8e681d5e3e5baa0ae60aa..7bc0409f2bb02e71098458e7dc833a7b913b532c 100644 (file)
 
 // FIRST ITERATION
 // lldb-command:print x
-// lldb-check:[...]$0 = 0
+// lldbg-check:[...]$0 = 0
+// lldbr-check:(i32) x = 0
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$1 = 1
+// lldbg-check:[...]$1 = 1
+// lldbr-check:(i32) x = 1
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$2 = 101
+// lldbg-check:[...]$2 = 101
+// lldbr-check:(i32) x = 101
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$3 = 101
+// lldbg-check:[...]$3 = 101
+// lldbr-check:(i32) x = 101
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$4 = -987
+// lldbg-check:[...]$4 = -987
+// lldbr-check:(i32) x = -987
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$5 = 101
+// lldbg-check:[...]$5 = 101
+// lldbr-check:(i32) x = 101
 // lldb-command:continue
 
 
 // SECOND ITERATION
 // lldb-command:print x
-// lldb-check:[...]$6 = 1
+// lldbg-check:[...]$6 = 1
+// lldbr-check:(i32) x = 1
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$7 = 2
+// lldbg-check:[...]$7 = 2
+// lldbr-check:(i32) x = 2
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$8 = 102
+// lldbg-check:[...]$8 = 102
+// lldbr-check:(i32) x = 102
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$9 = 102
+// lldbg-check:[...]$9 = 102
+// lldbr-check:(i32) x = 102
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$10 = -987
+// lldbg-check:[...]$10 = -987
+// lldbr-check:(i32) x = -987
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$11 = 102
+// lldbg-check:[...]$11 = 102
+// lldbr-check:(i32) x = 102
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$12 = 2
+// lldbg-check:[...]$12 = 2
+// lldbr-check:(i32) x = 2
 // lldb-command:continue
 
 #![feature(omit_gdb_pretty_printer_section)]
index 32d775168692b8982e23f92533ee35b751fed896..4e88f65ad1d00b1065ddf4d4ee82f9361d5fb452 100644 (file)
 // lldb-command:run
 
 // lldb-command:print a
-// lldb-check:[...]$0 = 10
+// lldbg-check:[...]$0 = 10
+// lldbr-check:(i32) a = 10
 // lldb-command:print b
-// lldb-check:[...]$1 = 34
+// lldbg-check:[...]$1 = 34
+// lldbr-check:(i32) b = 34
 // lldb-command:continue
 
 // lldb-command:print a
-// lldb-check:[...]$2 = 890242
+// lldbg-check:[...]$2 = 890242
+// lldbr-check:(i32) a = 10
 // lldb-command:print b
-// lldb-check:[...]$3 = 34
+// lldbg-check:[...]$3 = 34
+// lldbr-check:(i32) b = 34
 // lldb-command:continue
 
 // lldb-command:print a
-// lldb-check:[...]$4 = 10
+// lldbg-check:[...]$4 = 10
+// lldbr-check:(i32) a = 10
 // lldb-command:print b
-// lldb-check:[...]$5 = 34
+// lldbg-check:[...]$5 = 34
+// lldbr-check:(i32) b = 34
 // lldb-command:continue
 
 // lldb-command:print a
-// lldb-check:[...]$6 = 102
+// lldbg-check:[...]$6 = 102
+// lldbr-check:(i32) a = 10
 // lldb-command:print b
-// lldb-check:[...]$7 = 34
+// lldbg-check:[...]$7 = 34
+// lldbr-check:(i32) b = 34
 // lldb-command:continue
 
-// lldb-command:print a
-// lldb-check:[...]$8 = 110
-// lldb-command:print b
-// lldb-check:[...]$9 = 34
-// lldb-command:continue
-
-// lldb-command:print a
-// lldb-check:[...]$10 = 10
-// lldb-command:print b
-// lldb-check:[...]$11 = 34
-// lldb-command:continue
-
-// lldb-command:print a
-// lldb-check:[...]$12 = 10
-// lldb-command:print b
-// lldb-check:[...]$13 = 34
-// lldb-command:print c
-// lldb-check:[...]$14 = 400
-// lldb-command:continue
+// Don't test this with rust-enabled lldb for now; see issue #48807
+// lldbg-command:print a
+// lldbg-check:[...]$8 = 110
+// lldbg-command:print b
+// lldbg-check:[...]$9 = 34
+// lldbg-command:continue
+
+// lldbg-command:print a
+// lldbg-check:[...]$10 = 10
+// lldbg-command:print b
+// lldbg-check:[...]$11 = 34
+// lldbg-command:continue
+
+// lldbg-command:print a
+// lldbg-check:[...]$12 = 10
+// lldbg-command:print b
+// lldbg-check:[...]$13 = 34
+// lldbg-command:print c
+// lldbg-check:[...]$14 = 400
+// lldbg-command:continue
 
 
 #![feature(omit_gdb_pretty_printer_section)]
index e76f9da1c2505350950064d7ee17ba3e22b2ba43..9cb2a4c546efaab724cfb7c10b5fa24760cab263 100644 (file)
 
 // STRUCT EXPRESSION
 // lldb-command:print val
-// lldb-check:[...]$0 = -1
+// lldbg-check:[...]$0 = -1
+// lldbr-check:(i32) val = -1
 // lldb-command:print ten
-// lldb-check:[...]$1 = 10
+// lldbg-check:[...]$1 = 10
+// lldbr-check:(isize) ten = 10
 // lldb-command:continue
 
 // lldb-command:print val
-// lldb-check:[...]$2 = 11
+// lldbg-check:[...]$2 = 11
+// lldbr-check:(isize) val = 11
 // lldb-command:print ten
-// lldb-check:[...]$3 = 10
+// lldbg-check:[...]$3 = 10
+// lldbr-check:(isize) ten = 10
 // lldb-command:continue
 
 // lldb-command:print val
-// lldb-check:[...]$4 = -1
+// lldbg-check:[...]$4 = -1
+// lldbr-check:(i32) val = -1
 // lldb-command:print ten
-// lldb-check:[...]$5 = 10
+// lldbg-check:[...]$5 = 10
+// lldbr-check:(isize) ten = 10
 // lldb-command:continue
 
 // FUNCTION CALL
 // lldb-command:print val
-// lldb-check:[...]$6 = -1
+// lldbg-check:[...]$6 = -1
+// lldbr-check:(i32) val = -1
 // lldb-command:print ten
-// lldb-check:[...]$7 = 10
+// lldbg-check:[...]$7 = 10
+// lldbr-check:(isize) ten = 10
 // lldb-command:continue
 
 // lldb-command:print val
-// lldb-check:[...]$8 = 12
+// lldbg-check:[...]$8 = 12
+// lldbr-check:(isize) val = 12
 // lldb-command:print ten
-// lldb-check:[...]$9 = 10
+// lldbg-check:[...]$9 = 10
+// lldbr-check:(isize) ten = 10
 // lldb-command:continue
 
 // lldb-command:print val
-// lldb-check:[...]$10 = -1
+// lldbg-check:[...]$10 = -1
+// lldbr-check:(i32) val = -1
 // lldb-command:print ten
-// lldb-check:[...]$11 = 10
+// lldbg-check:[...]$11 = 10
+// lldbr-check:(isize) ten = 10
 // lldb-command:continue
 
 // TUPLE EXPRESSION
 // lldb-command:print val
-// lldb-check:[...]$12 = -1
+// lldbg-check:[...]$12 = -1
+// lldbr-check:(i32) val = -1
 // lldb-command:print ten
-// lldb-check:[...]$13 = 10
+// lldbg-check:[...]$13 = 10
+// lldbr-check:(isize) ten = 10
 // lldb-command:continue
 
 // lldb-command:print val
-// lldb-check:[...]$14 = 13
+// lldbg-check:[...]$14 = 13
+// lldbr-check:(isize) val = 13
 // lldb-command:print ten
-// lldb-check:[...]$15 = 10
+// lldbg-check:[...]$15 = 10
+// lldbr-check:(isize) ten = 10
 // lldb-command:continue
 
 // lldb-command:print val
-// lldb-check:[...]$16 = -1
+// lldbg-check:[...]$16 = -1
+// lldbr-check:(i32) val = -1
 // lldb-command:print ten
-// lldb-check:[...]$17 = 10
+// lldbg-check:[...]$17 = 10
+// lldbr-check:(isize) ten = 10
 // lldb-command:continue
 
 // VEC EXPRESSION
 // lldb-command:print val
-// lldb-check:[...]$18 = -1
+// lldbg-check:[...]$18 = -1
+// lldbr-check:(i32) val = -1
 // lldb-command:print ten
-// lldb-check:[...]$19 = 10
+// lldbg-check:[...]$19 = 10
+// lldbr-check:(isize) ten = 10
 // lldb-command:continue
 
 // lldb-command:print val
-// lldb-check:[...]$20 = 14
+// lldbg-check:[...]$20 = 14
+// lldbr-check:(isize) val = 14
 // lldb-command:print ten
-// lldb-check:[...]$21 = 10
+// lldbg-check:[...]$21 = 10
+// lldbr-check:(isize) ten = 10
 // lldb-command:continue
 
 // lldb-command:print val
-// lldb-check:[...]$22 = -1
+// lldbg-check:[...]$22 = -1
+// lldbr-check:(i32) val = -1
 // lldb-command:print ten
-// lldb-check:[...]$23 = 10
+// lldbg-check:[...]$23 = 10
+// lldbr-check:(isize) ten = 10
 // lldb-command:continue
 
 // REPEAT VEC EXPRESSION
 // lldb-command:print val
-// lldb-check:[...]$24 = -1
+// lldbg-check:[...]$24 = -1
+// lldbr-check:(i32) val = -1
 // lldb-command:print ten
-// lldb-check:[...]$25 = 10
+// lldbg-check:[...]$25 = 10
+// lldbr-check:(isize) ten = 10
 // lldb-command:continue
 
 // lldb-command:print val
-// lldb-check:[...]$26 = 15
+// lldbg-check:[...]$26 = 15
+// lldbr-check:(isize) val = 15
 // lldb-command:print ten
-// lldb-check:[...]$27 = 10
+// lldbg-check:[...]$27 = 10
+// lldbr-check:(isize) ten = 10
 // lldb-command:continue
 
 // lldb-command:print val
-// lldb-check:[...]$28 = -1
+// lldbg-check:[...]$28 = -1
+// lldbr-check:(i32) val = -1
 // lldb-command:print ten
-// lldb-check:[...]$29 = 10
+// lldbg-check:[...]$29 = 10
+// lldbr-check:(isize) ten = 10
 // lldb-command:continue
 
 // ASSIGNMENT EXPRESSION
 // lldb-command:print val
-// lldb-check:[...]$30 = -1
+// lldbg-check:[...]$30 = -1
+// lldbr-check:(i32) val = -1
 // lldb-command:print ten
-// lldb-check:[...]$31 = 10
+// lldbg-check:[...]$31 = 10
+// lldbr-check:(isize) ten = 10
 // lldb-command:continue
 
 // lldb-command:print val
-// lldb-check:[...]$32 = 16
+// lldbg-check:[...]$32 = 16
+// lldbr-check:(isize) val = 16
 // lldb-command:print ten
-// lldb-check:[...]$33 = 10
+// lldbg-check:[...]$33 = 10
+// lldbr-check:(isize) ten = 10
 // lldb-command:continue
 
 // lldb-command:print val
-// lldb-check:[...]$34 = -1
+// lldbg-check:[...]$34 = -1
+// lldbr-check:(i32) val = -1
 // lldb-command:print ten
-// lldb-check:[...]$35 = 10
+// lldbg-check:[...]$35 = 10
+// lldbr-check:(isize) ten = 10
 // lldb-command:continue
 
 
 // ARITHMETIC EXPRESSION
 // lldb-command:print val
-// lldb-check:[...]$36 = -1
+// lldbg-check:[...]$36 = -1
+// lldbr-check:(i32) val = -1
 // lldb-command:print ten
-// lldb-check:[...]$37 = 10
+// lldbg-check:[...]$37 = 10
+// lldbr-check:(isize) ten = 10
 // lldb-command:continue
 
 // lldb-command:print val
-// lldb-check:[...]$38 = 17
+// lldbg-check:[...]$38 = 17
+// lldbr-check:(isize) val = 17
 // lldb-command:print ten
-// lldb-check:[...]$39 = 10
+// lldbg-check:[...]$39 = 10
+// lldbr-check:(isize) ten = 10
 // lldb-command:continue
 
 // lldb-command:print val
-// lldb-check:[...]$40 = -1
+// lldbg-check:[...]$40 = -1
+// lldbr-check:(i32) val = -1
 // lldb-command:print ten
-// lldb-check:[...]$41 = 10
+// lldbg-check:[...]$41 = 10
+// lldbr-check:(isize) ten = 10
 // lldb-command:continue
 
 // INDEX EXPRESSION
 // lldb-command:print val
-// lldb-check:[...]$42 = -1
+// lldbg-check:[...]$42 = -1
+// lldbr-check:(i32) val = -1
 // lldb-command:print ten
-// lldb-check:[...]$43 = 10
+// lldbg-check:[...]$43 = 10
+// lldbr-check:(isize) ten = 10
 // lldb-command:continue
 
 // lldb-command:print val
-// lldb-check:[...]$44 = 18
+// lldbg-check:[...]$44 = 18
+// lldbr-check:(isize) val = 18
 // lldb-command:print ten
-// lldb-check:[...]$45 = 10
+// lldbg-check:[...]$45 = 10
+// lldbr-check:(isize) ten = 10
 // lldb-command:continue
 
 // lldb-command:print val
-// lldb-check:[...]$46 = -1
+// lldbg-check:[...]$46 = -1
+// lldbr-check:(i32) val = -1
 // lldb-command:print ten
-// lldb-check:[...]$47 = 10
+// lldbg-check:[...]$47 = 10
+// lldbr-check:(isize) ten = 10
 // lldb-command:continue
 
 #![allow(unused_variables)]
index 20d419b4ac088357c00520dc58cbc8fe0079cd17..57238961e3fa3dae052fddf17acd3ba4559422dd 100644 (file)
 
 // STACK BY REF
 // lldb-command:print *self
-// lldb-check:[...]$0 = Struct<(u32, i32)> { x: (8888, -8888) }
+// lldbg-check:[...]$0 = Struct<(u32, i32)> { x: (8888, -8888) }
+// lldbr-check:(method_on_generic_struct::Struct<(u32, i32)>) *self = { x = { = 8888 = -8888 } }
 // lldb-command:print arg1
-// lldb-check:[...]$1 = -1
+// lldbg-check:[...]$1 = -1
+// lldbr-check:(isize) arg1 = -1
 // lldb-command:print arg2
-// lldb-check:[...]$2 = -2
+// lldbg-check:[...]$2 = -2
+// lldbr-check:(isize) arg2 = -2
 // lldb-command:continue
 
 // STACK BY VAL
 // lldb-command:print self
-// lldb-check:[...]$3 = Struct<(u32, i32)> { x: (8888, -8888) }
+// lldbg-check:[...]$3 = Struct<(u32, i32)> { x: (8888, -8888) }
+// lldbr-check:(method_on_generic_struct::Struct<(u32, i32)>) self = { x = { = 8888 = -8888 } }
 // lldb-command:print arg1
-// lldb-check:[...]$4 = -3
+// lldbg-check:[...]$4 = -3
+// lldbr-check:(isize) arg1 = -3
 // lldb-command:print arg2
-// lldb-check:[...]$5 = -4
+// lldbg-check:[...]$5 = -4
+// lldbr-check:(isize) arg2 = -4
 // lldb-command:continue
 
 // OWNED BY REF
 // lldb-command:print *self
-// lldb-check:[...]$6 = Struct<f64> { x: 1234.5 }
+// lldbg-check:[...]$6 = Struct<f64> { x: 1234.5 }
+// lldbr-check:(method_on_generic_struct::Struct<f64>) *self = Struct<f64> { x: 1234.5 }
 // lldb-command:print arg1
-// lldb-check:[...]$7 = -5
+// lldbg-check:[...]$7 = -5
+// lldbr-check:(isize) arg1 = -5
 // lldb-command:print arg2
-// lldb-check:[...]$8 = -6
+// lldbg-check:[...]$8 = -6
+// lldbr-check:(isize) arg2 = -6
 // lldb-command:continue
 
 // OWNED BY VAL
 // lldb-command:print self
-// lldb-check:[...]$9 = Struct<f64> { x: 1234.5 }
+// lldbg-check:[...]$9 = Struct<f64> { x: 1234.5 }
+// lldbr-check:(method_on_generic_struct::Struct<f64>) self = Struct<f64> { x: 1234.5 }
 // lldb-command:print arg1
-// lldb-check:[...]$10 = -7
+// lldbg-check:[...]$10 = -7
+// lldbr-check:(isize) arg1 = -7
 // lldb-command:print arg2
-// lldb-check:[...]$11 = -8
+// lldbg-check:[...]$11 = -8
+// lldbr-check:(isize) arg2 = -8
 // lldb-command:continue
 
 // OWNED MOVED
 // lldb-command:print *self
-// lldb-check:[...]$12 = Struct<f64> { x: 1234.5 }
+// lldbg-check:[...]$12 = Struct<f64> { x: 1234.5 }
+// lldbr-check:(method_on_generic_struct::Struct<f64>) *self = Struct<f64> { x: 1234.5 }
 // lldb-command:print arg1
-// lldb-check:[...]$13 = -9
+// lldbg-check:[...]$13 = -9
+// lldbr-check:(isize) arg1 = -9
 // lldb-command:print arg2
-// lldb-check:[...]$14 = -10
+// lldbg-check:[...]$14 = -10
+// lldbr-check:(isize) arg2 = -10
 // lldb-command:continue
 
 
index c7546fe2221ff60365d8e6e1b7ca460f791bb73e..e64962593dfcd066406f91baf1ceb302c48fa5d5 100644 (file)
 
 // STACK BY REF
 // lldb-command:print *self
-// lldb-check:[...]$0 = Struct { x: 100 }
+// lldbg-check:[...]$0 = Struct { x: 100 }
+// lldbr-check:(method_on_struct::Struct) *self = Struct { x: 100 }
 // lldb-command:print arg1
-// lldb-check:[...]$1 = -1
+// lldbg-check:[...]$1 = -1
+// lldbr-check:(isize) arg1 = -1
 // lldb-command:print arg2
-// lldb-check:[...]$2 = -2
+// lldbg-check:[...]$2 = -2
+// lldbr-check:(isize) arg2 = -2
 // lldb-command:continue
 
 // STACK BY VAL
 // lldb-command:print self
-// lldb-check:[...]$3 = Struct { x: 100 }
+// lldbg-check:[...]$3 = Struct { x: 100 }
+// lldbr-check:(method_on_struct::Struct) self = Struct { x: 100 }
 // lldb-command:print arg1
-// lldb-check:[...]$4 = -3
+// lldbg-check:[...]$4 = -3
+// lldbr-check:(isize) arg1 = -3
 // lldb-command:print arg2
-// lldb-check:[...]$5 = -4
+// lldbg-check:[...]$5 = -4
+// lldbr-check:(isize) arg2 = -4
 // lldb-command:continue
 
 // OWNED BY REF
 // lldb-command:print *self
-// lldb-check:[...]$6 = Struct { x: 200 }
+// lldbg-check:[...]$6 = Struct { x: 200 }
+// lldbr-check:(method_on_struct::Struct) *self = Struct { x: 200 }
 // lldb-command:print arg1
-// lldb-check:[...]$7 = -5
+// lldbg-check:[...]$7 = -5
+// lldbr-check:(isize) arg1 = -5
 // lldb-command:print arg2
-// lldb-check:[...]$8 = -6
+// lldbg-check:[...]$8 = -6
+// lldbr-check:(isize) arg2 = -6
 // lldb-command:continue
 
 // OWNED BY VAL
 // lldb-command:print self
-// lldb-check:[...]$9 = Struct { x: 200 }
+// lldbg-check:[...]$9 = Struct { x: 200 }
+// lldbr-check:(method_on_struct::Struct) self = Struct { x: 200 }
 // lldb-command:print arg1
-// lldb-check:[...]$10 = -7
+// lldbg-check:[...]$10 = -7
+// lldbr-check:(isize) arg1 = -7
 // lldb-command:print arg2
-// lldb-check:[...]$11 = -8
+// lldbg-check:[...]$11 = -8
+// lldbr-check:(isize) arg2 = -8
 // lldb-command:continue
 
 // OWNED MOVED
 // lldb-command:print *self
-// lldb-check:[...]$12 = Struct { x: 200 }
+// lldbg-check:[...]$12 = Struct { x: 200 }
+// lldbr-check:(method_on_struct::Struct) *self = Struct { x: 200 }
 // lldb-command:print arg1
-// lldb-check:[...]$13 = -9
+// lldbg-check:[...]$13 = -9
+// lldbr-check:(isize) arg1 = -9
 // lldb-command:print arg2
-// lldb-check:[...]$14 = -10
+// lldbg-check:[...]$14 = -10
+// lldbr-check:(isize) arg2 = -10
 // lldb-command:continue
 
 
index 1dc37bb06ac40eadc8b9668febd69ec21ced572e..4c1e111d3b81dcbcec2a269c128842159560e661 100644 (file)
 
 // STACK BY REF
 // lldb-command:print *self
-// lldb-check:[...]$0 = Struct { x: 100 }
+// lldbg-check:[...]$0 = Struct { x: 100 }
+// lldbr-check:(method_on_trait::Struct) *self = Struct { x: 100 }
 // lldb-command:print arg1
-// lldb-check:[...]$1 = -1
+// lldbg-check:[...]$1 = -1
+// lldbr-check:(isize) arg1 = -1
 // lldb-command:print arg2
-// lldb-check:[...]$2 = -2
+// lldbg-check:[...]$2 = -2
+// lldbr-check:(isize) arg2 = -2
 // lldb-command:continue
 
 // STACK BY VAL
 // lldb-command:print self
-// lldb-check:[...]$3 = Struct { x: 100 }
+// lldbg-check:[...]$3 = Struct { x: 100 }
+// lldbr-check:(method_on_trait::Struct) self = Struct { x: 100 }
 // lldb-command:print arg1
-// lldb-check:[...]$4 = -3
+// lldbg-check:[...]$4 = -3
+// lldbr-check:(isize) arg1 = -3
 // lldb-command:print arg2
-// lldb-check:[...]$5 = -4
+// lldbg-check:[...]$5 = -4
+// lldbr-check:(isize) arg2 = -4
 // lldb-command:continue
 
 // OWNED BY REF
 // lldb-command:print *self
-// lldb-check:[...]$6 = Struct { x: 200 }
+// lldbg-check:[...]$6 = Struct { x: 200 }
+// lldbr-check:(method_on_trait::Struct) *self = Struct { x: 200 }
 // lldb-command:print arg1
-// lldb-check:[...]$7 = -5
+// lldbg-check:[...]$7 = -5
+// lldbr-check:(isize) arg1 = -5
 // lldb-command:print arg2
-// lldb-check:[...]$8 = -6
+// lldbg-check:[...]$8 = -6
+// lldbr-check:(isize) arg2 = -6
 // lldb-command:continue
 
 // OWNED BY VAL
 // lldb-command:print self
-// lldb-check:[...]$9 = Struct { x: 200 }
+// lldbg-check:[...]$9 = Struct { x: 200 }
+// lldbr-check:(method_on_trait::Struct) self = Struct { x: 200 }
 // lldb-command:print arg1
-// lldb-check:[...]$10 = -7
+// lldbg-check:[...]$10 = -7
+// lldbr-check:(isize) arg1 = -7
 // lldb-command:print arg2
-// lldb-check:[...]$11 = -8
+// lldbg-check:[...]$11 = -8
+// lldbr-check:(isize) arg2 = -8
 // lldb-command:continue
 
 // OWNED MOVED
 // lldb-command:print *self
-// lldb-check:[...]$12 = Struct { x: 200 }
+// lldbg-check:[...]$12 = Struct { x: 200 }
+// lldbr-check:(method_on_trait::Struct) *self = Struct { x: 200 }
 // lldb-command:print arg1
-// lldb-check:[...]$13 = -9
+// lldbg-check:[...]$13 = -9
+// lldbr-check:(isize) arg1 = -9
 // lldb-command:print arg2
-// lldb-check:[...]$14 = -10
+// lldbg-check:[...]$14 = -10
+// lldbr-check:(isize) arg2 = -10
 // lldb-command:continue
 
 
index dac762ae0c35bde7d36881afac4369a9bf2452dd..cef7a1cbf1b569c5baedf2c2acc3085f426adeaf 100644 (file)
 
 // STACK BY REF
 // lldb-command:print *self
-// lldb-check:[...]$0 = TupleStruct(100, -100.5)
+// lldbg-check:[...]$0 = TupleStruct(100, -100.5)
+// lldbr-check:(method_on_tuple_struct::TupleStruct) *self = { = 100 = -100.5 }
 // lldb-command:print arg1
-// lldb-check:[...]$1 = -1
+// lldbg-check:[...]$1 = -1
+// lldbr-check:(isize) arg1 = -1
 // lldb-command:print arg2
-// lldb-check:[...]$2 = -2
+// lldbg-check:[...]$2 = -2
+// lldbr-check:(isize) arg2 = -2
 // lldb-command:continue
 
 // STACK BY VAL
 // lldb-command:print self
-// lldb-check:[...]$3 = TupleStruct(100, -100.5)
+// lldbg-check:[...]$3 = TupleStruct(100, -100.5)
+// lldbr-check:(method_on_tuple_struct::TupleStruct) self = { = 100 = -100.5 }
 // lldb-command:print arg1
-// lldb-check:[...]$4 = -3
+// lldbg-check:[...]$4 = -3
+// lldbr-check:(isize) arg1 = -3
 // lldb-command:print arg2
-// lldb-check:[...]$5 = -4
+// lldbg-check:[...]$5 = -4
+// lldbr-check:(isize) arg2 = -4
 // lldb-command:continue
 
 // OWNED BY REF
 // lldb-command:print *self
-// lldb-check:[...]$6 = TupleStruct(200, -200.5)
+// lldbg-check:[...]$6 = TupleStruct(200, -200.5)
+// lldbr-check:(method_on_tuple_struct::TupleStruct) *self = { = 200 = -200.5 }
 // lldb-command:print arg1
-// lldb-check:[...]$7 = -5
+// lldbg-check:[...]$7 = -5
+// lldbr-check:(isize) arg1 = -5
 // lldb-command:print arg2
-// lldb-check:[...]$8 = -6
+// lldbg-check:[...]$8 = -6
+// lldbr-check:(isize) arg2 = -6
 // lldb-command:continue
 
 // OWNED BY VAL
 // lldb-command:print self
-// lldb-check:[...]$9 = TupleStruct(200, -200.5)
+// lldbg-check:[...]$9 = TupleStruct(200, -200.5)
+// lldbr-check:(method_on_tuple_struct::TupleStruct) self = { = 200 = -200.5 }
 // lldb-command:print arg1
-// lldb-check:[...]$10 = -7
+// lldbg-check:[...]$10 = -7
+// lldbr-check:(isize) arg1 = -7
 // lldb-command:print arg2
-// lldb-check:[...]$11 = -8
+// lldbg-check:[...]$11 = -8
+// lldbr-check:(isize) arg2 = -8
 // lldb-command:continue
 
 // OWNED MOVED
 // lldb-command:print *self
-// lldb-check:[...]$12 = TupleStruct(200, -200.5)
+// lldbg-check:[...]$12 = TupleStruct(200, -200.5)
+// lldbr-check:(method_on_tuple_struct::TupleStruct) *self = { = 200 = -200.5 }
 // lldb-command:print arg1
-// lldb-check:[...]$13 = -9
+// lldbg-check:[...]$13 = -9
+// lldbr-check:(isize) arg1 = -9
 // lldb-command:print arg2
-// lldb-check:[...]$14 = -10
+// lldbg-check:[...]$14 = -10
+// lldbr-check:(isize) arg2 = -10
 // lldb-command:continue
 
 
index f4f9f92396f2c20d3fb822eba05b41b247cc116a..7f370954b9053e00b564565ea28c80219d911405 100644 (file)
 // lldb-command:run
 
 // lldb-command:print xxx
-// lldb-check:[...]$0 = 12345
+// lldbg-check:[...]$0 = 12345
+// lldbr-check:(u32) xxx = 12345
 // lldb-command:continue
 
 // lldb-command:print yyy
-// lldb-check:[...]$1 = 67890
+// lldbg-check:[...]$1 = 67890
+// lldbr-check:(u64) yyy = 67890
 // lldb-command:continue
 
 
index 71ba1bcea306a1fac71d64832bd03342e851cf37..b2327e494e7d1359899113199117f409f22a48a5 100644 (file)
 // lldb-command:run
 
 // lldb-command:print abc
-// lldb-check:[...]$0 = 10101
+// lldbg-check:[...]$0 = 10101
+// lldbr-check:(i32) abc = 10101
 // lldb-command:continue
 
 // lldb-command:print abc
-// lldb-check:[...]$1 = 20202
+// lldbg-check:[...]$1 = 20202
+// lldbr-check:(i32) abc = 20202
 // lldb-command:continue
 
 // lldb-command:print abc
-// lldb-check:[...]$2 = 30303
+// lldbg-check:[...]$2 = 30303
+// lldbr-check:(i32) abc = 30303
 
 #![allow(unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
index 7a1b7b19d9f5d1cc5db9d95f3306a268226754eb..d78ef0292c16042279952c016ad60ecbac244c44 100644 (file)
 // lldb-command:run
 
 // lldb-command:print a
-// lldb-check:[...]$0 = 10101
+// lldbg-check:[...]$0 = 10101
+// lldbr-check:(i32) a = 10101
 // lldb-command:continue
 
 // lldb-command:print b
-// lldb-check:[...]$1 = 20202
+// lldbg-check:[...]$1 = 20202
+// lldbr-check:(i32) b = 20202
 // lldb-command:continue
 
 // lldb-command:print c
-// lldb-check:[...]$2 = 30303
+// lldbg-check:[...]$2 = 30303
+// lldbr-check:(i32) c = 30303
 
 #![allow(unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
index 462e1c59aea227929d1ea40698dc911925fa4db5..91f0e14157ee30c2f5ab65df06a48acb667058c5 100644 (file)
 // lldb-command:run
 
 // lldb-command:print x
-// lldb-check:[...]$0 = false
+// lldbg-check:[...]$0 = false
+// lldbr-check:(bool) x = false
 // lldb-command:print y
-// lldb-check:[...]$1 = true
+// lldbg-check:[...]$1 = true
+// lldbr-check:(bool) y = true
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$2 = 10
+// lldbg-check:[...]$2 = 10
+// lldbr-check:(i32) x = 10
 // lldb-command:print y
-// lldb-check:[...]$3 = true
+// lldbg-check:[...]$3 = true
+// lldbr-check:(bool) y = true
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$4 = 10.5
+// lldbg-check:[...]$4 = 10.5
+// lldbr-check:(f64) x = 10.5
 // lldb-command:print y
-// lldb-check:[...]$5 = 20
+// lldbg-check:[...]$5 = 20
+// lldbr-check:(i32) y = 20
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$6 = true
+// lldbg-check:[...]$6 = true
+// lldbr-check:(bool) x = true
 // lldb-command:print y
-// lldb-check:[...]$7 = 2220
+// lldbg-check:[...]$7 = 2220
+// lldbr-check:(i32) y = 2220
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$8 = 203203.5
+// lldbg-check:[...]$8 = 203203.5
+// lldbr-check:(f64) x = 203203.5
 // lldb-command:print y
-// lldb-check:[...]$9 = 2220
+// lldbg-check:[...]$9 = 2220
+// lldbr-check:(i32) y = 2220
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$10 = 10.5
+// lldbg-check:[...]$10 = 10.5
+// lldbr-check:(f64) x = 10.5
 // lldb-command:print y
-// lldb-check:[...]$11 = 20
+// lldbg-check:[...]$11 = 20
+// lldbr-check:(i32) y = 20
 // lldb-command:continue
 
 #![feature(omit_gdb_pretty_printer_section)]
index 50bd857d460763c766cc7f87eda744e7ab153a9a..d5273d53dc59a17b5002a291a8b332d0ad14041b 100644 (file)
 // lldb-command:run
 
 // lldb-command:print packed
-// lldb-check:[...]$0 = Packed { x: 123, y: 234, z: 345 }
+// lldbg-check:[...]$0 = Packed { x: 123, y: 234, z: 345 }
+// lldbr-check:(packed_struct_with_destructor::Packed) packed = Packed { x: 123, y: 234, z: 345 }
 
 // lldb-command:print packedInPacked
-// lldb-check:[...]$1 = PackedInPacked { a: 1111, b: Packed { x: 2222, y: 3333, z: 4444 }, c: 5555, d: Packed { x: 6666, y: 7777, z: 8888 } }
+// lldbg-check:[...]$1 = PackedInPacked { a: 1111, b: Packed { x: 2222, y: 3333, z: 4444 }, c: 5555, d: Packed { x: 6666, y: 7777, z: 8888 } }
+// lldbr-check:(packed_struct_with_destructor::PackedInPacked) packedInPacked = PackedInPacked { a: 1111, b: Packed { x: 2222, y: 3333, z: 4444 }, c: 5555, d: Packed { x: 6666, y: 7777, z: 8888 } }
 
 // lldb-command:print packedInUnpacked
-// lldb-check:[...]$2 = PackedInUnpacked { a: -1111, b: Packed { x: -2222, y: -3333, z: -4444 }, c: -5555, d: Packed { x: -6666, y: -7777, z: -8888 } }
+// lldbg-check:[...]$2 = PackedInUnpacked { a: -1111, b: Packed { x: -2222, y: -3333, z: -4444 }, c: -5555, d: Packed { x: -6666, y: -7777, z: -8888 } }
+// lldbr-check:(packed_struct_with_destructor::PackedInUnpacked) packedInUnpacked = PackedInUnpacked { a: -1111, b: Packed { x: -2222, y: -3333, z: -4444 }, c: -5555, d: Packed { x: -6666, y: -7777, z: -8888 } }
 
 // lldb-command:print unpackedInPacked
-// lldb-check:[...]$3 = UnpackedInPacked { a: 987, b: Unpacked { x: 876, y: 765, z: 654 }, c: Unpacked { x: 543, y: 432, z: 321 }, d: 210 }
+// lldbg-check:[...]$3 = UnpackedInPacked { a: 987, b: Unpacked { x: 876, y: 765, z: 654 }, c: Unpacked { x: 543, y: 432, z: 321 }, d: 210 }
+// lldbr-check:(packed_struct_with_destructor::UnpackedInPacked) unpackedInPacked = UnpackedInPacked { a: 987, b: Unpacked { x: 876, y: 765, z: 654 }, c: Unpacked { x: 543, y: 432, z: 321 }, d: 210 }
 
 // lldb-command:print packedInPackedWithDrop
-// lldb-check:[...]$4 = PackedInPackedWithDrop { a: 11, b: Packed { x: 22, y: 33, z: 44 }, c: 55, d: Packed { x: 66, y: 77, z: 88 } }
+// lldbg-check:[...]$4 = PackedInPackedWithDrop { a: 11, b: Packed { x: 22, y: 33, z: 44 }, c: 55, d: Packed { x: 66, y: 77, z: 88 } }
+// lldbr-check:(packed_struct_with_destructor::PackedInPackedWithDrop) packedInPackedWithDrop = PackedInPackedWithDrop { a: 11, b: Packed { x: 22, y: 33, z: 44 }, c: 55, d: Packed { x: 66, y: 77, z: 88 } }
 
 // lldb-command:print packedInUnpackedWithDrop
-// lldb-check:[...]$5 = PackedInUnpackedWithDrop { a: -11, b: Packed { x: -22, y: -33, z: -44 }, c: -55, d: Packed { x: -66, y: -77, z: -88 } }
+// lldbg-check:[...]$5 = PackedInUnpackedWithDrop { a: -11, b: Packed { x: -22, y: -33, z: -44 }, c: -55, d: Packed { x: -66, y: -77, z: -88 } }
+// lldbr-check:(packed_struct_with_destructor::PackedInUnpackedWithDrop) packedInUnpackedWithDrop = PackedInUnpackedWithDrop { a: -11, b: Packed { x: -22, y: -33, z: -44 }, c: -55, d: Packed { x: -66, y: -77, z: -88 } }
 
 // lldb-command:print unpackedInPackedWithDrop
-// lldb-check:[...]$6 = UnpackedInPackedWithDrop { a: 98, b: Unpacked { x: 87, y: 76, z: 65 }, c: Unpacked { x: 54, y: 43, z: 32 }, d: 21 }
+// lldbg-check:[...]$6 = UnpackedInPackedWithDrop { a: 98, b: Unpacked { x: 87, y: 76, z: 65 }, c: Unpacked { x: 54, y: 43, z: 32 }, d: 21 }
+// lldbr-check:(packed_struct_with_destructor::UnpackedInPackedWithDrop) unpackedInPackedWithDrop = UnpackedInPackedWithDrop { a: 98, b: Unpacked { x: 87, y: 76, z: 65 }, c: Unpacked { x: 54, y: 43, z: 32 }, d: 21 }
 
 // lldb-command:print deeplyNested
-// lldb-check:[...]$7 = DeeplyNested { a: PackedInPacked { a: 1, b: Packed { x: 2, y: 3, z: 4 }, c: 5, d: Packed { x: 6, y: 7, z: 8 } }, b: UnpackedInPackedWithDrop { a: 9, b: Unpacked { x: 10, y: 11, z: 12 }, c: Unpacked { x: 13, y: 14, z: 15 }, d: 16 }, c: PackedInUnpacked { a: 17, b: Packed { x: 18, y: 19, z: 20 }, c: 21, d: Packed { x: 22, y: 23, z: 24 } }, d: PackedInUnpackedWithDrop { a: 25, b: Packed { x: 26, y: 27, z: 28 }, c: 29, d: Packed { x: 30, y: 31, z: 32 } }, e: UnpackedInPacked { a: 33, b: Unpacked { x: 34, y: 35, z: 36 }, c: Unpacked { x: 37, y: 38, z: 39 }, d: 40 }, f: PackedInPackedWithDrop { a: 41, b: Packed { x: 42, y: 43, z: 44 }, c: 45, d: Packed { x: 46, y: 47, z: 48 } } }
+// lldbg-check:[...]$7 = DeeplyNested { a: PackedInPacked { a: 1, b: Packed { x: 2, y: 3, z: 4 }, c: 5, d: Packed { x: 6, y: 7, z: 8 } }, b: UnpackedInPackedWithDrop { a: 9, b: Unpacked { x: 10, y: 11, z: 12 }, c: Unpacked { x: 13, y: 14, z: 15 }, d: 16 }, c: PackedInUnpacked { a: 17, b: Packed { x: 18, y: 19, z: 20 }, c: 21, d: Packed { x: 22, y: 23, z: 24 } }, d: PackedInUnpackedWithDrop { a: 25, b: Packed { x: 26, y: 27, z: 28 }, c: 29, d: Packed { x: 30, y: 31, z: 32 } }, e: UnpackedInPacked { a: 33, b: Unpacked { x: 34, y: 35, z: 36 }, c: Unpacked { x: 37, y: 38, z: 39 }, d: 40 }, f: PackedInPackedWithDrop { a: 41, b: Packed { x: 42, y: 43, z: 44 }, c: 45, d: Packed { x: 46, y: 47, z: 48 } } }
+// lldbr-check:(packed_struct_with_destructor::DeeplyNested) deeplyNested = DeeplyNested { a: PackedInPacked { a: 1, b: Packed { x: 2, y: 3, z: 4 }, c: 5, d: Packed { x: 6, y: 7, z: 8 } }, b: UnpackedInPackedWithDrop { a: 9, b: Unpacked { x: 10, y: 11, z: 12 }, c: Unpacked { x: 13, y: 14, z: 15 }, d: 16 }, c: PackedInUnpacked { a: 17, b: Packed { x: 18, y: 19, z: 20 }, c: 21, d: Packed { x: 22, y: 23, z: 24 } }, d: PackedInUnpackedWithDrop { a: 25, b: Packed { x: 26, y: 27, z: 28 }, c: 29, d: Packed { x: 30, y: 31, z: 32 } }, e: UnpackedInPacked { a: 33, b: Unpacked { x: 34, y: 35, z: 36 }, c: Unpacked { x: 37, y: 38, z: 39 }, d: 40 }, f: PackedInPackedWithDrop { a: 41, b: Packed { x: 42, y: 43, z: 44 }, c: 45, d: Packed { x: 46, y: 47, z: 48 } } }
 
 
 #![allow(unused_variables)]
index 16e6371a9c0a9944db7f6989d8061dd26492f5ff..2ed3711fbde80a6bcf7998b7a7333e1b58eacec3 100644 (file)
 // lldb-command:run
 
 // lldb-command:print packed
-// lldb-check:[...]$0 = Packed { x: 123, y: 234, z: 345 }
+// lldbg-check:[...]$0 = Packed { x: 123, y: 234, z: 345 }
+// lldbr-check:(packed_struct::Packed) packed = Packed { x: 123, y: 234, z: 345 }
 
 // lldb-command:print packedInPacked
-// lldb-check:[...]$1 = PackedInPacked { a: 1111, b: Packed { x: 2222, y: 3333, z: 4444 }, c: 5555, d: Packed { x: 6666, y: 7777, z: 8888 } }
+// lldbg-check:[...]$1 = PackedInPacked { a: 1111, b: Packed { x: 2222, y: 3333, z: 4444 }, c: 5555, d: Packed { x: 6666, y: 7777, z: 8888 } }
+// lldbr-check:(packed_struct::PackedInPacked) packedInPacked = PackedInPacked { a: 1111, b: Packed { x: 2222, y: 3333, z: 4444 }, c: 5555, d: Packed { x: 6666, y: 7777, z: 8888 } }
 
 // lldb-command:print packedInUnpacked
-// lldb-check:[...]$2 = PackedInUnpacked { a: -1111, b: Packed { x: -2222, y: -3333, z: -4444 }, c: -5555, d: Packed { x: -6666, y: -7777, z: -8888 } }
+// lldbg-check:[...]$2 = PackedInUnpacked { a: -1111, b: Packed { x: -2222, y: -3333, z: -4444 }, c: -5555, d: Packed { x: -6666, y: -7777, z: -8888 } }
+// lldbr-check:(packed_struct::PackedInUnpacked) packedInUnpacked = PackedInUnpacked { a: -1111, b: Packed { x: -2222, y: -3333, z: -4444 }, c: -5555, d: Packed { x: -6666, y: -7777, z: -8888 } }
 
 // lldb-command:print unpackedInPacked
-// lldb-check:[...]$3 = UnpackedInPacked { a: 987, b: Unpacked { x: 876, y: 765, z: 654, w: 543 }, c: Unpacked { x: 432, y: 321, z: 210, w: 109 }, d: -98 }
+// lldbg-check:[...]$3 = UnpackedInPacked { a: 987, b: Unpacked { x: 876, y: 765, z: 654, w: 543 }, c: Unpacked { x: 432, y: 321, z: 210, w: 109 }, d: -98 }
+// lldbr-check:(packed_struct::UnpackedInPacked) unpackedInPacked = UnpackedInPacked { a: 987, b: Unpacked { x: 876, y: 765, z: 654, w: 543 }, c: Unpacked { x: 432, y: 321, z: 210, w: 109 }, d: -98 }
 
 // lldb-command:print sizeof(packed)
-// lldb-check:[...]$4 = 14
+// lldbg-check:[...]$4 = 14
+// lldbr-check:(usize) = 14
 
 // lldb-command:print sizeof(packedInPacked)
-// lldb-check:[...]$5 = 40
+// lldbg-check:[...]$5 = 40
+// lldbr-check:(usize) = 40
 
 #![allow(unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
index 796d122cd66baed906c47425376a11cc60e29514..a9acaab7dfc06c330580e7eecbd87c634b90070b 100644 (file)
 
 // STACK BY REF
 // lldb-command:print *self
-// lldb-check:[...]$0 = Struct { x: 100 }
+// lldbg-check:[...]$0 = Struct { x: 100 }
+// lldbr-check:(self_in_default_method::Struct) *self = Struct { x: 100 }
 // lldb-command:print arg1
-// lldb-check:[...]$1 = -1
+// lldbg-check:[...]$1 = -1
+// lldbr-check:(isize) arg1 = -1
 // lldb-command:print arg2
-// lldb-check:[...]$2 = -2
+// lldbg-check:[...]$2 = -2
+// lldbr-check:(isize) arg2 = -2
 // lldb-command:continue
 
 // STACK BY VAL
 // lldb-command:print self
-// lldb-check:[...]$3 = Struct { x: 100 }
+// lldbg-check:[...]$3 = Struct { x: 100 }
+// lldbr-check:(self_in_default_method::Struct) self = Struct { x: 100 }
 // lldb-command:print arg1
-// lldb-check:[...]$4 = -3
+// lldbg-check:[...]$4 = -3
+// lldbr-check:(isize) arg1 = -3
 // lldb-command:print arg2
-// lldb-check:[...]$5 = -4
+// lldbg-check:[...]$5 = -4
+// lldbr-check:(isize) arg2 = -4
 // lldb-command:continue
 
 // OWNED BY REF
 // lldb-command:print *self
-// lldb-check:[...]$6 = Struct { x: 200 }
+// lldbg-check:[...]$6 = Struct { x: 200 }
+// lldbr-check:(self_in_default_method::Struct) *self = Struct { x: 200 }
 // lldb-command:print arg1
-// lldb-check:[...]$7 = -5
+// lldbg-check:[...]$7 = -5
+// lldbr-check:(isize) arg1 = -5
 // lldb-command:print arg2
-// lldb-check:[...]$8 = -6
+// lldbg-check:[...]$8 = -6
+// lldbr-check:(isize) arg2 = -6
 // lldb-command:continue
 
 // OWNED BY VAL
 // lldb-command:print self
-// lldb-check:[...]$9 = Struct { x: 200 }
+// lldbg-check:[...]$9 = Struct { x: 200 }
+// lldbr-check:(self_in_default_method::Struct) self = Struct { x: 200 }
 // lldb-command:print arg1
-// lldb-check:[...]$10 = -7
+// lldbg-check:[...]$10 = -7
+// lldbr-check:(isize) arg1 = -7
 // lldb-command:print arg2
-// lldb-check:[...]$11 = -8
+// lldbg-check:[...]$11 = -8
+// lldbr-check:(isize) arg2 = -8
 // lldb-command:continue
 
 // OWNED MOVED
 // lldb-command:print *self
-// lldb-check:[...]$12 = Struct { x: 200 }
+// lldbg-check:[...]$12 = Struct { x: 200 }
+// lldbr-check:(self_in_default_method::Struct) *self = Struct { x: 200 }
 // lldb-command:print arg1
-// lldb-check:[...]$13 = -9
+// lldbg-check:[...]$13 = -9
+// lldbr-check:(isize) arg1 = -9
 // lldb-command:print arg2
-// lldb-check:[...]$14 = -10
+// lldbg-check:[...]$14 = -10
+// lldbr-check:(isize) arg2 = -10
 // lldb-command:continue
 
 #![feature(box_syntax)]
index b07d7ca5fb7b7c34de917910bda563c3fbf849eb..2613300b8d996000ea1fda80b0ac9f3d5135b0e2 100644 (file)
 
 // STACK BY REF
 // lldb-command:print *self
-// lldb-check:[...]$0 = Struct { x: 987 }
+// lldbg-check:[...]$0 = Struct { x: 987 }
+// lldbr-check:(self_in_generic_default_method::Struct) *self = Struct { x: 987 }
 // lldb-command:print arg1
-// lldb-check:[...]$1 = -1
+// lldbg-check:[...]$1 = -1
+// lldbr-check:(isize) arg1 = -1
 // lldb-command:print arg2
-// lldb-check:[...]$2 = 2
+// lldbg-check:[...]$2 = 2
+// lldbr-check:(u16) arg2 = 2
 // lldb-command:continue
 
 // STACK BY VAL
 // lldb-command:print self
-// lldb-check:[...]$3 = Struct { x: 987 }
+// lldbg-check:[...]$3 = Struct { x: 987 }
+// lldbr-check:(self_in_generic_default_method::Struct) self = Struct { x: 987 }
 // lldb-command:print arg1
-// lldb-check:[...]$4 = -3
+// lldbg-check:[...]$4 = -3
+// lldbr-check:(isize) arg1 = -3
 // lldb-command:print arg2
-// lldb-check:[...]$5 = -4
+// lldbg-check:[...]$5 = -4
+// lldbr-check:(i16) arg2 = -4
 // lldb-command:continue
 
 // OWNED BY REF
 // lldb-command:print *self
-// lldb-check:[...]$6 = Struct { x: 879 }
+// lldbg-check:[...]$6 = Struct { x: 879 }
+// lldbr-check:(self_in_generic_default_method::Struct) *self = Struct { x: 879 }
 // lldb-command:print arg1
-// lldb-check:[...]$7 = -5
+// lldbg-check:[...]$7 = -5
+// lldbr-check:(isize) arg1 = -5
 // lldb-command:print arg2
-// lldb-check:[...]$8 = -6
+// lldbg-check:[...]$8 = -6
+// lldbr-check:(i32) arg2 = -6
 // lldb-command:continue
 
 // OWNED BY VAL
 // lldb-command:print self
-// lldb-check:[...]$9 = Struct { x: 879 }
+// lldbg-check:[...]$9 = Struct { x: 879 }
+// lldbr-check:(self_in_generic_default_method::Struct) self = Struct { x: 879 }
 // lldb-command:print arg1
-// lldb-check:[...]$10 = -7
+// lldbg-check:[...]$10 = -7
+// lldbr-check:(isize) arg1 = -7
 // lldb-command:print arg2
-// lldb-check:[...]$11 = -8
+// lldbg-check:[...]$11 = -8
+// lldbr-check:(i64) arg2 = -8
 // lldb-command:continue
 
 // OWNED MOVED
 // lldb-command:print *self
-// lldb-check:[...]$12 = Struct { x: 879 }
+// lldbg-check:[...]$12 = Struct { x: 879 }
+// lldbr-check:(self_in_generic_default_method::Struct) *self = Struct { x: 879 }
 // lldb-command:print arg1
-// lldb-check:[...]$13 = -9
+// lldbg-check:[...]$13 = -9
+// lldbr-check:(isize) arg1 = -9
 // lldb-command:print arg2
-// lldb-check:[...]$14 = -10.5
+// lldbg-check:[...]$14 = -10.5
+// lldbr-check:(f32) arg2 = -10.5
 // lldb-command:continue
 
 #![feature(box_syntax)]
index baf782b7e678a182f67613cd1daff1b6f1fc91d3..49d876d4530b91245892bae31e1bd06fcb80a695 100644 (file)
 // lldb-command:run
 
 // lldb-command:print x
-// lldb-check:[...]$0 = false
+// lldbg-check:[...]$0 = false
+// lldbr-check:(bool) x = false
 // lldb-command:print y
-// lldb-check:[...]$1 = true
+// lldbg-check:[...]$1 = true
+// lldbr-check:(bool) y = true
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$2 = 10
+// lldbg-check:[...]$2 = 10
+// lldbr-check:(i32) x = 10
 // lldb-command:print y
-// lldb-check:[...]$3 = true
+// lldbg-check:[...]$3 = true
+// lldbr-check:(bool) y = true
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$4 = 10.5
+// lldbg-check:[...]$4 = 10.5
+// lldbr-check:(f64) x = 10.5
 // lldb-command:print y
-// lldb-check:[...]$5 = 20
+// lldbg-check:[...]$5 = 20
+// lldbr-check:(i32) y = 20
 // lldb-command:continue
 
 
index 6e4d94d26cdeb0a66889e6df60ea48f15de5cb8d..3a8f6d3b70d16b5d692e905f268d1b6e899e037b 100644 (file)
 // lldb-command:run
 
 // lldb-command:print x
-// lldb-check:[...]$0 = false
+// lldbg-check:[...]$0 = false
+// lldbr-check:(bool) x = false
 // lldb-command:print y
-// lldb-check:[...]$1 = true
+// lldbg-check:[...]$1 = true
+// lldbr-check:(bool) y = true
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$2 = 10
+// lldbg-check:[...]$2 = 10
+// lldbr-check:(i32) x = 10
 // lldb-command:print y
-// lldb-check:[...]$3 = true
+// lldbg-check:[...]$3 = true
+// lldbr-check:(bool) y = true
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$4 = 10.5
+// lldbg-check:[...]$4 = 10.5
+// lldbr-check:(f64) x = 10.5
 // lldb-command:print y
-// lldb-check:[...]$5 = 20
+// lldbg-check:[...]$5 = 20
+// lldbr-check:(i32) y = 20
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$6 = 10.5
+// lldbg-check:[...]$6 = 10.5
+// lldbr-check:(f64) x = 10.5
 // lldb-command:print y
-// lldb-check:[...]$7 = 20
+// lldbg-check:[...]$7 = 20
+// lldbr-check:(i32) y = 20
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$8 = 11.5
+// lldbg-check:[...]$8 = 11.5
+// lldbr-check:(f64) x = 11.5
 // lldb-command:print y
-// lldb-check:[...]$9 = 20
+// lldbg-check:[...]$9 = 20
+// lldbr-check:(i32) y = 20
 // lldb-command:continue
 
 #![feature(omit_gdb_pretty_printer_section)]
index 5f9a4fd08053404d685e708d876db3bb490a064c..935a0bb2ae443bba450a1e08917add6c7b52e839 100644 (file)
 // lldb-command:run
 
 // lldb-command:print x
-// lldb-check:[...]$0 = false
+// lldbg-check:[...]$0 = false
+// lldbr-check:(bool) x = false
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$1 = false
+// lldbg-check:[...]$1 = false
+// lldbr-check:(bool) x = false
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$2 = 10
+// lldbg-check:[...]$2 = 10
+// lldbr-check:(i32) x = 10
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$3 = 10
+// lldbg-check:[...]$3 = 10
+// lldbr-check:(i32) x = 10
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$4 = 10.5
+// lldbg-check:[...]$4 = 10.5
+// lldbr-check:(f64) x = 10.5
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$5 = 10
+// lldbg-check:[...]$5 = 10
+// lldbr-check:(i32) x = 10
 // lldb-command:continue
 
 // lldb-command:print x
-// lldb-check:[...]$6 = false
+// lldbg-check:[...]$6 = false
+// lldbr-check:(bool) x = false
 // lldb-command:continue
 
 
index 8fdf204d30ab57761e5a6b3890c2cbe855dd793e..e27324fe330663229473b30cdd3863135f5f6528 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-tidy-linelength
+
 // min-lldb-version: 310
 // ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
 
 // lldb-command:run
 
 // lldb-command:print no_padding16
-// lldb-check:[...]$0 = NoPadding16 { x: 10000, y: -10001 }
+// lldbg-check:[...]$0 = NoPadding16 { x: 10000, y: -10001 }
+// lldbr-check:(simple_struct::NoPadding16) no_padding16 = NoPadding16 { x: 10000, y: -10001 }
 
 // lldb-command:print no_padding32
-// lldb-check:[...]$1 = NoPadding32 { x: -10002, y: -10003.5, z: 10004 }
+// lldbg-check:[...]$1 = NoPadding32 { x: -10002, y: -10003.5, z: 10004 }
+// lldbr-check:(simple_struct::NoPadding32) no_padding32 = NoPadding32 { x: -10002, y: -10003.5, z: 10004 }
 
 // lldb-command:print no_padding64
-// lldb-check:[...]$2 = NoPadding64 { x: -10005.5, y: 10006, z: 10007 }
+// lldbg-check:[...]$2 = NoPadding64 { x: -10005.5, y: 10006, z: 10007 }
+// lldbr-check:(simple_struct::NoPadding64) no_padding64 = NoPadding64 { x: -10005.5, y: 10006, z: 10007 }
 
 // lldb-command:print no_padding163264
-// lldb-check:[...]$3 = NoPadding163264 { a: -10008, b: 10009, c: 10010, d: 10011 }
+// lldbg-check:[...]$3 = NoPadding163264 { a: -10008, b: 10009, c: 10010, d: 10011 }
+// lldbr-check:(simple_struct::NoPadding163264) no_padding163264 = NoPadding163264 { a: -10008, b: 10009, c: 10010, d: 10011 }
 
 // lldb-command:print internal_padding
-// lldb-check:[...]$4 = InternalPadding { x: 10012, y: -10013 }
+// lldbg-check:[...]$4 = InternalPadding { x: 10012, y: -10013 }
+// lldbr-check:(simple_struct::InternalPadding) internal_padding = InternalPadding { x: 10012, y: -10013 }
 
 // lldb-command:print padding_at_end
-// lldb-check:[...]$5 = PaddingAtEnd { x: -10014, y: 10015 }
+// lldbg-check:[...]$5 = PaddingAtEnd { x: -10014, y: 10015 }
+// lldbr-check:(simple_struct::PaddingAtEnd) padding_at_end = PaddingAtEnd { x: -10014, y: 10015 }
 
 #![allow(unused_variables)]
 #![allow(dead_code)]
index 8f69672c888440e30986dfd28e2d2f1ea7b65b47..ea0fd4e37fd422299c4effb24a2a96ff488b81b7 100644 (file)
 // lldb-command:run
 
 // lldb-command:print/d noPadding8
-// lldb-check:[...]$0 = (-100, 100)
+// lldbg-check:[...]$0 = (-100, 100)
+// lldbr-check:((i8, u8)) noPadding8 = { = -100 -100 = 100 100 }
 // lldb-command:print noPadding16
-// lldb-check:[...]$1 = (0, 1, 2)
+// lldbg-check:[...]$1 = (0, 1, 2)
+// lldbr-check:((i16, i16, u16)) noPadding16 = { = 0 = 1 = 2 }
 // lldb-command:print noPadding32
-// lldb-check:[...]$2 = (3, 4.5, 5)
+// lldbg-check:[...]$2 = (3, 4.5, 5)
+// lldbr-check:((i32, f32, u32)) noPadding32 = { = 3 = 4.5 = 5 }
 // lldb-command:print noPadding64
-// lldb-check:[...]$3 = (6, 7.5, 8)
+// lldbg-check:[...]$3 = (6, 7.5, 8)
+// lldbr-check:((i64, f64, u64)) noPadding64 = { = 6 = 7.5 = 8 }
 
 // lldb-command:print internalPadding1
-// lldb-check:[...]$4 = (9, 10)
+// lldbg-check:[...]$4 = (9, 10)
+// lldbr-check:((i16, i32)) internalPadding1 = { = 9 = 10 }
 // lldb-command:print internalPadding2
-// lldb-check:[...]$5 = (11, 12, 13, 14)
+// lldbg-check:[...]$5 = (11, 12, 13, 14)
+// lldbr-check:((i16, i32, u32, u64)) internalPadding2 = { = 11 = 12 = 13 = 14 }
 
 // lldb-command:print paddingAtEnd
-// lldb-check:[...]$6 = (15, 16)
+// lldbg-check:[...]$6 = (15, 16)
+// lldbr-check:((i32, i16)) paddingAtEnd = { = 15 = 16 }
 
 #![allow(unused_variables)]
 #![allow(dead_code)]
index dab4ab515d9954e4c931f5462b69b1fac776825d..75a67c6b84bce623019fcd440808c1f12fc560ab 100644 (file)
 
 // STRUCT
 // lldb-command:print arg1
-// lldb-check:[...]$0 = 1
+// lldbg-check:[...]$0 = 1
+// lldbr-check:(isize) arg1 = 1
 // lldb-command:print arg2
-// lldb-check:[...]$1 = 2
+// lldbg-check:[...]$1 = 2
+// lldbr-check:(isize) arg2 = 2
 // lldb-command:continue
 
 // ENUM
 // lldb-command:print arg1
-// lldb-check:[...]$2 = -3
+// lldbg-check:[...]$2 = -3
+// lldbr-check:(isize) arg1 = -3
 // lldb-command:print arg2
-// lldb-check:[...]$3 = 4.5
+// lldbg-check:[...]$3 = 4.5
+// lldbr-check:(f64) arg2 = 4.5
 // lldb-command:print arg3
-// lldb-check:[...]$4 = 5
+// lldbg-check:[...]$4 = 5
+// lldbr-check:(usize) arg3 = 5
 // lldb-command:continue
 
 #![feature(omit_gdb_pretty_printer_section)]
index 46524cf1d029a98b1180f6831ec6be2dc904382c..129500860c82f47888100915a5846e675c70a12c 100644 (file)
 // lldb-command:run
 
 // lldb-command:print three_simple_structs
-// lldb-check:[...]$0 = ThreeSimpleStructs { x: Simple { x: 1 }, y: Simple { x: 2 }, z: Simple { x: 3 } }
+// lldbg-check:[...]$0 = ThreeSimpleStructs { x: Simple { x: 1 }, y: Simple { x: 2 }, z: Simple { x: 3 } }
+// lldbr-check:(struct_in_struct::ThreeSimpleStructs) three_simple_structs = ThreeSimpleStructs { x: Simple { x: 1 }, y: Simple { x: 2 }, z: Simple { x: 3 } }
 
 // lldb-command:print internal_padding_parent
-// lldb-check:[...]$1 = InternalPaddingParent { x: InternalPadding { x: 4, y: 5 }, y: InternalPadding { x: 6, y: 7 }, z: InternalPadding { x: 8, y: 9 } }
+// lldbg-check:[...]$1 = InternalPaddingParent { x: InternalPadding { x: 4, y: 5 }, y: InternalPadding { x: 6, y: 7 }, z: InternalPadding { x: 8, y: 9 } }
+// lldbr-check:(struct_in_struct::InternalPaddingParent) internal_padding_parent = InternalPaddingParent { x: InternalPadding { x: 4, y: 5 }, y: InternalPadding { x: 6, y: 7 }, z: InternalPadding { x: 8, y: 9 } }
 
 // lldb-command:print padding_at_end_parent
-// lldb-check:[...]$2 = PaddingAtEndParent { x: PaddingAtEnd { x: 10, y: 11 }, y: PaddingAtEnd { x: 12, y: 13 }, z: PaddingAtEnd { x: 14, y: 15 } }
+// lldbg-check:[...]$2 = PaddingAtEndParent { x: PaddingAtEnd { x: 10, y: 11 }, y: PaddingAtEnd { x: 12, y: 13 }, z: PaddingAtEnd { x: 14, y: 15 } }
+// lldbr-check:(struct_in_struct::PaddingAtEndParent) padding_at_end_parent = PaddingAtEndParent { x: PaddingAtEnd { x: 10, y: 11 }, y: PaddingAtEnd { x: 12, y: 13 }, z: PaddingAtEnd { x: 14, y: 15 } }
 
 // lldb-command:print mixed
-// lldb-check:[...]$3 = Mixed { x: PaddingAtEnd { x: 16, y: 17 }, y: InternalPadding { x: 18, y: 19 }, z: Simple { x: 20 }, w: 21 }
+// lldbg-check:[...]$3 = Mixed { x: PaddingAtEnd { x: 16, y: 17 }, y: InternalPadding { x: 18, y: 19 }, z: Simple { x: 20 }, w: 21 }
+// lldbr-check:(struct_in_struct::Mixed) mixed = Mixed { x: PaddingAtEnd { x: 16, y: 17 }, y: InternalPadding { x: 18, y: 19 }, z: Simple { x: 20 }, w: 21 }
 
 // lldb-command:print bag
-// lldb-check:[...]$4 = Bag { x: Simple { x: 22 } }
+// lldbg-check:[...]$4 = Bag { x: Simple { x: 22 } }
+// lldbr-check:(struct_in_struct::Bag) bag = Bag { x: Simple { x: 22 } }
 
 // lldb-command:print bag_in_bag
-// lldb-check:[...]$5 = BagInBag { x: Bag { x: Simple { x: 23 } } }
+// lldbg-check:[...]$5 = BagInBag { x: Bag { x: Simple { x: 23 } } }
+// lldbr-check:(struct_in_struct::BagInBag) bag_in_bag = BagInBag { x: Bag { x: Simple { x: 23 } } }
 
 // lldb-command:print tjo
-// lldb-check:[...]$6 = ThatsJustOverkill { x: BagInBag { x: Bag { x: Simple { x: 24 } } } }
+// lldbg-check:[...]$6 = ThatsJustOverkill { x: BagInBag { x: Bag { x: Simple { x: 24 } } } }
+// lldbr-check:(struct_in_struct::ThatsJustOverkill) tjo = ThatsJustOverkill { x: BagInBag { x: Bag { x: Simple { x: 24 } } } }
 
 // lldb-command:print tree
-// lldb-check:[...]$7 = Tree { x: Simple { x: 25 }, y: InternalPaddingParent { x: InternalPadding { x: 26, y: 27 }, y: InternalPadding { x: 28, y: 29 }, z: InternalPadding { x: 30, y: 31 } }, z: BagInBag { x: Bag { x: Simple { x: 32 } } } }
+// lldbg-check:[...]$7 = Tree { x: Simple { x: 25 }, y: InternalPaddingParent { x: InternalPadding { x: 26, y: 27 }, y: InternalPadding { x: 28, y: 29 }, z: InternalPadding { x: 30, y: 31 } }, z: BagInBag { x: Bag { x: Simple { x: 32 } } } }
+// lldbr-check:(struct_in_struct::Tree) tree = Tree { x: Simple { x: 25 }, y: InternalPaddingParent { x: InternalPadding { x: 26, y: 27 }, y: InternalPadding { x: 28, y: 29 }, z: InternalPadding { x: 30, y: 31 } }, z: BagInBag { x: Bag { x: Simple { x: 32 } } } }
 
 #![allow(unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
index 3fd4cf57b2a802c63847a444a0991f3af3f77e28..efa415c7100b8e144582325b1ae74ba2734b2cdc 100644 (file)
 
 // lldb-command:run
 // lldb-command:p struct1
-// lldb-check:(struct_namespace::Struct1) $0 = [...]
+// lldbg-check:(struct_namespace::Struct1) $0 = [...]
+// lldbr-check:(struct_namespace::Struct1) struct1 = Struct1 { a: 0, b: 1 }
 // lldb-command:p struct2
-// lldb-check:(struct_namespace::Struct2) $1 = [...]
+// lldbg-check:(struct_namespace::Struct2) $1 = [...]
+// lldbr-check:(struct_namespace::Struct2) struct2 = { = 2 }
 
 // lldb-command:p mod1_struct1
-// lldb-check:(struct_namespace::mod1::Struct1) $2 = [...]
+// lldbg-check:(struct_namespace::mod1::Struct1) $2 = [...]
+// lldbr-check:(struct_namespace::mod1::Struct1) mod1_struct1 = Struct1 { a: 3, b: 4 }
 // lldb-command:p mod1_struct2
-// lldb-check:(struct_namespace::mod1::Struct2) $3 = [...]
+// lldbg-check:(struct_namespace::mod1::Struct2) $3 = [...]
+// lldbr-check:(struct_namespace::mod1::Struct2) mod1_struct2 = { = 5 }
 
 #![allow(unused_variables)]
 #![allow(dead_code)]
index b156a3be699e3359490962ebe9c755824aaee5e3..36cd85fb4dc6503945c48f94bd5ad0026ad917fd 100644 (file)
 // lldb-command:run
 
 // lldb-command:print case1
-// lldb-check:[...]$0 = Case1 { a: 0, b: 31868, c: 31868, d: 31868, e: 31868 }
+// lldbg-check:[...]$0 = Case1 { a: 0, b: 31868, c: 31868, d: 31868, e: 31868 }
+// lldbr-check:(struct_style_enum::Regular::Case1) case1 = { a = 0 b = 31868 c = 31868 d = 31868 e = 31868 }
 
 // lldb-command:print case2
-// lldb-check:[...]$1 = Case2 { a: 0, b: 286331153, c: 286331153 }
+// lldbg-check:[...]$1 = Case2 { a: 0, b: 286331153, c: 286331153 }
+// lldbr-check:(struct_style_enum::Regular::Case2) case2 = Case2 { struct_style_enum::Regular::Case1: 0, struct_style_enum::Regular::Case2: 286331153, struct_style_enum::Regular::Case3: 286331153 }
 
 // lldb-command:print case3
-// lldb-check:[...]$2 = Case3 { a: 0, b: 6438275382588823897 }
+// lldbg-check:[...]$2 = Case3 { a: 0, b: 6438275382588823897 }
+// lldbr-check:(struct_style_enum::Regular::Case3) case3 = Case3 { struct_style_enum::Regular::Case1: 0, struct_style_enum::Regular::Case2: 6438275382588823897 }
 
 // lldb-command:print univariant
-// lldb-check:[...]$3 = TheOnlyCase { a: -1 }
+// lldbg-check:[...]$3 = TheOnlyCase { a: -1 }
+// lldbr-check:(struct_style_enum::Univariant) univariant = Univariant { struct_style_enum::TheOnlyCase: TheOnlyCase { a: -1 } }
 
 #![allow(unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
index ab935a07d650fc3164fa47edd1673b35d8b4e3ea..f7722bb377531721a369ebbe0259b137d3c205b5 100644 (file)
 
 // lldb-command:run
 // lldb-command:print simple
-// lldb-check:[...]$0 = WithDestructor { x: 10, y: 20 }
+// lldbg-check:[...]$0 = WithDestructor { x: 10, y: 20 }
+// lldbr-check:(struct_with_destructor::WithDestructor) simple = WithDestructor { x: 10, y: 20 }
 
 // lldb-command:print noDestructor
-// lldb-check:[...]$1 = NoDestructorGuarded { a: NoDestructor { x: 10, y: 20 }, guard: -1 }
+// lldbg-check:[...]$1 = NoDestructorGuarded { a: NoDestructor { x: 10, y: 20 }, guard: -1 }
+// lldbr-check:(struct_with_destructor::NoDestructorGuarded) noDestructor = NoDestructorGuarded { a: NoDestructor { x: 10, y: 20 }, guard: -1 }
 
 // lldb-command:print withDestructor
-// lldb-check:[...]$2 = WithDestructorGuarded { a: WithDestructor { x: 10, y: 20 }, guard: -1 }
+// lldbg-check:[...]$2 = WithDestructorGuarded { a: WithDestructor { x: 10, y: 20 }, guard: -1 }
+// lldbr-check:(struct_with_destructor::WithDestructorGuarded) withDestructor = WithDestructorGuarded { a: WithDestructor { x: 10, y: 20 }, guard: -1 }
 
 // lldb-command:print nested
-// lldb-check:[...]$3 = NestedOuter { a: NestedInner { a: WithDestructor { x: 7890, y: 9870 } } }
+// lldbg-check:[...]$3 = NestedOuter { a: NestedInner { a: WithDestructor { x: 7890, y: 9870 } } }
+// lldbr-check:(struct_with_destructor::NestedOuter) nested = NestedOuter { a: NestedInner { a: WithDestructor { x: 7890, y: 9870 } } }
 
 #![allow(unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
index 4ebc740b9c0f7a55c625666275a8cd4fae3a3cbb..79335a3d0e139e6fd393921fcf450105dbecafa4 100644 (file)
 // lldb-command:run
 
 // lldb-command:print no_padding1
-// lldb-check:[...]$0 = ((0, 1), 2, 3)
+// lldbg-check:[...]$0 = ((0, 1), 2, 3)
+// lldbr-check:(((u32, u32), u32, u32)) no_padding1 = { = { = 0 = 1 } = 2 = 3 }
 // lldb-command:print no_padding2
-// lldb-check:[...]$1 = (4, (5, 6), 7)
+// lldbg-check:[...]$1 = (4, (5, 6), 7)
+// lldbr-check:((u32, (u32, u32), u32)) no_padding2 = { = 4 = { = 5 = 6 } = 7 }
 // lldb-command:print no_padding3
-// lldb-check:[...]$2 = (8, 9, (10, 11))
+// lldbg-check:[...]$2 = (8, 9, (10, 11))
+// lldbr-check:((u32, u32, (u32, u32))) no_padding3 = { = 8 = 9 = { = 10 = 11 } }
 
 // lldb-command:print internal_padding1
-// lldb-check:[...]$3 = (12, (13, 14))
+// lldbg-check:[...]$3 = (12, (13, 14))
+// lldbr-check:((i16, (i32, i32))) internal_padding1 = { = 12 = { = 13 = 14 } }
 // lldb-command:print internal_padding2
-// lldb-check:[...]$4 = (15, (16, 17))
+// lldbg-check:[...]$4 = (15, (16, 17))
+// lldbr-check:((i16, (i16, i32))) internal_padding2 = { = 15 = { = 16 = 17 } }
 
 // lldb-command:print padding_at_end1
-// lldb-check:[...]$5 = (18, (19, 20))
+// lldbg-check:[...]$5 = (18, (19, 20))
+// lldbr-check:((i32, (i32, i16))) padding_at_end1 = { = 18 = { = 19 = 20 } }
 // lldb-command:print padding_at_end2
-// lldb-check:[...]$6 = ((21, 22), 23)
+// lldbg-check:[...]$6 = ((21, 22), 23)
+// lldbr-check:(((i32, i16), i32)) padding_at_end2 = { = { = 21 = 22 } = 23 }
 
 #![allow(unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
index aa644d8419b54f72a3aac5334cb1ac83eb639ffd..def48c84488dc333b7b3f05909536576d8cfc596 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-tidy-linelength
+
 // min-lldb-version: 310
 
 // compile-flags:-g
 // lldb-command:run
 
 // lldb-command:print no_padding16
-// lldb-check:[...]$0 = NoPadding16(10000, -10001)
+// lldbg-check:[...]$0 = NoPadding16(10000, -10001)
+// lldbr-check:(tuple_struct::NoPadding16) no_padding16 = { = 10000 = -10001 }
 
 // lldb-command:print no_padding32
-// lldb-check:[...]$1 = NoPadding32(-10002, -10003.5, 10004)
+// lldbg-check:[...]$1 = NoPadding32(-10002, -10003.5, 10004)
+// lldbr-check:(tuple_struct::NoPadding32) no_padding32 = { = -10002 = -10003.5 = 10004 }
 
 // lldb-command:print no_padding64
-// lldb-check:[...]$2 = NoPadding64(-10005.5, 10006, 10007)
+// lldbg-check:[...]$2 = NoPadding64(-10005.5, 10006, 10007)
+// lldbr-check:(tuple_struct::NoPadding64) no_padding64 = { = -10005.5 = 10006 = 10007 }
 
 // lldb-command:print no_padding163264
-// lldb-check:[...]$3 = NoPadding163264(-10008, 10009, 10010, 10011)
+// lldbg-check:[...]$3 = NoPadding163264(-10008, 10009, 10010, 10011)
+// lldbr-check:(tuple_struct::NoPadding163264) no_padding163264 = { = -10008 = 10009 = 10010 = 10011 }
 
 // lldb-command:print internal_padding
-// lldb-check:[...]$4 = InternalPadding(10012, -10013)
+// lldbg-check:[...]$4 = InternalPadding(10012, -10013)
+// lldbr-check:(tuple_struct::InternalPadding) internal_padding = { = 10012 = -10013 }
 
 // lldb-command:print padding_at_end
-// lldb-check:[...]$5 = PaddingAtEnd(-10014, 10015)
+// lldbg-check:[...]$5 = PaddingAtEnd(-10014, 10015)
+// lldbr-check:(tuple_struct::PaddingAtEnd) padding_at_end = { = -10014 = 10015 }
 
 // This test case mainly makes sure that no field names are generated for tuple structs (as opposed
 // to all fields having the name "<unnamed_field>"). Otherwise they are handled the same a normal
index f36153d1f5c5a8eca5d52aa027edf3d4f559ce27..682e74601b0a11b7f15f2a3357ec22e175dd8c66 100644 (file)
 // lldb-command:run
 
 // lldb-command:print case1
-// lldb-check:[...]$0 = Case1(0, 31868, 31868, 31868, 31868)
+// lldbg-check:[...]$0 = Case1(0, 31868, 31868, 31868, 31868)
+// lldbr-check:(tuple_style_enum::Regular::Case1) case1 = { = 0 = 31868 = 31868 = 31868 = 31868 }
 
 // lldb-command:print case2
-// lldb-check:[...]$1 = Case2(0, 286331153, 286331153)
+// lldbg-check:[...]$1 = Case2(0, 286331153, 286331153)
+// lldbr-check:(tuple_style_enum::Regular::Case2) case2 = Case2 { tuple_style_enum::Regular::Case1: 0, tuple_style_enum::Regular::Case2: 286331153, tuple_style_enum::Regular::Case3: 286331153 }
 
 // lldb-command:print case3
-// lldb-check:[...]$2 = Case3(0, 6438275382588823897)
+// lldbg-check:[...]$2 = Case3(0, 6438275382588823897)
+// lldbr-check:(tuple_style_enum::Regular::Case3) case3 = Case3 { tuple_style_enum::Regular::Case1: 0, tuple_style_enum::Regular::Case2: 6438275382588823897 }
 
 // lldb-command:print univariant
-// lldb-check:[...]$3 = TheOnlyCase(-1)
+// lldbg-check:[...]$3 = TheOnlyCase(-1)
+// lldbr-check:(tuple_style_enum::Univariant) univariant = { tuple_style_enum::TheOnlyCase = { = -1 } }
 
 #![allow(unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
index 622c7cf0d333423dd8784d42d18aac38c1f97ec2..7772127bad295ee012d121721d58050a5ab9435d 100644 (file)
 
 // lldb-command:run
 // lldb-command:print u
-// lldb-check:[...]$0 = U { a: ('\x02', '\x02'), b: 514 }
-// lldb-command:print union_smoke::SU
-// lldb-check:[...]$1 = U { a: ('\x01', '\x01'), b: 257 }
+// lldbg-check:[...]$0 = U { a: ('\x02', '\x02'), b: 514 }
+// lldbr-check:(union_smoke::U) u = { a = { = 2 = 2 } b = 514 }
+
+// Don't test this with rust-enabled lldb for now; see
+// https://github.com/rust-lang-nursery/lldb/issues/18
+// lldbg-command:print union_smoke::SU
+// lldbg-check:[...]$1 = U { a: ('\x01', '\x01'), b: 257 }
 
 #![allow(unused)]
 #![feature(omit_gdb_pretty_printer_section)]
index 5a99de7779cffd3972190b807d7981b2db6b3e68..6b62c304513944ea0ea0f7abd220493c0258d084 100644 (file)
 // lldb-command:run
 
 // lldb-command:print *the_a
-// lldb-check:[...]$0 = TheA { x: 0, y: 8970181431921507452 }
+// lldbg-check:[...]$0 = TheA { x: 0, y: 8970181431921507452 }
+// lldbr-check:(unique_enum::ABC::TheA) *the_a = TheA { unique_enum::ABC::TheA: 0, unique_enum::ABC::TheB: 8970181431921507452 }
 
 // lldb-command:print *the_b
-// lldb-check:[...]$1 = TheB(0, 286331153, 286331153)
+// lldbg-check:[...]$1 = TheB(0, 286331153, 286331153)
+// lldbr-check:(unique_enum::ABC::TheB) *the_b = { = 0 = 286331153 = 286331153 }
 
 // lldb-command:print *univariant
-// lldb-check:[...]$2 = TheOnlyCase(123234)
+// lldbg-check:[...]$2 = TheOnlyCase(123234)
+// lldbr-check:(unique_enum::Univariant) *univariant = { unique_enum::TheOnlyCase = { = 123234 } }
 
 #![allow(unused_variables)]
 #![feature(box_syntax)]
index b9a1d73b6d8696de85d1c44237e1678be2e89562..02c836bb6ac47503590c65f59c1d46f64dbcf0b5 100644 (file)
 // lldb-command:run
 
 // lldb-command:print variable
-// lldb-check:[...]$0 = 1
+// lldbg-check:[...]$0 = 1
+// lldbr-check:(isize) variable = 1
 // lldb-command:print constant
-// lldb-check:[...]$1 = 2
+// lldbg-check:[...]$1 = 2
+// lldbr-check:(isize) constant = 2
 // lldb-command:print a_struct
-// lldb-check:[...]$2 = Struct { a: -3, b: 4.5, c: 5 }
+// lldbg-check:[...]$2 = Struct { a: -3, b: 4.5, c: 5 }
+// lldbr-check:(var_captured_in_nested_closure::Struct) a_struct = Struct { a: -3, b: 4.5, c: 5 }
 // lldb-command:print *struct_ref
-// lldb-check:[...]$3 = Struct { a: -3, b: 4.5, c: 5 }
+// lldbg-check:[...]$3 = Struct { a: -3, b: 4.5, c: 5 }
+// lldbr-check:(var_captured_in_nested_closure::Struct) *struct_ref = Struct { a: -3, b: 4.5, c: 5 }
 // lldb-command:print *owned
-// lldb-check:[...]$4 = 6
+// lldbg-check:[...]$4 = 6
+// lldbr-check:(isize) *owned = 6
 // lldb-command:print closure_local
-// lldb-check:[...]$5 = 8
+// lldbg-check:[...]$5 = 8
+// lldbr-check:(isize) closure_local = 8
 // lldb-command:continue
 
 // lldb-command:print variable
-// lldb-check:[...]$6 = 1
+// lldbg-check:[...]$6 = 1
+// lldbr-check:(isize) variable = 1
 // lldb-command:print constant
-// lldb-check:[...]$7 = 2
+// lldbg-check:[...]$7 = 2
+// lldbr-check:(isize) constant = 2
 // lldb-command:print a_struct
-// lldb-check:[...]$8 = Struct { a: -3, b: 4.5, c: 5 }
+// lldbg-check:[...]$8 = Struct { a: -3, b: 4.5, c: 5 }
+// lldbr-check:(var_captured_in_nested_closure::Struct) a_struct = Struct { a: -3, b: 4.5, c: 5 }
 // lldb-command:print *struct_ref
-// lldb-check:[...]$9 = Struct { a: -3, b: 4.5, c: 5 }
+// lldbg-check:[...]$9 = Struct { a: -3, b: 4.5, c: 5 }
+// lldbr-check:(var_captured_in_nested_closure::Struct) *struct_ref = Struct { a: -3, b: 4.5, c: 5 }
 // lldb-command:print *owned
-// lldb-check:[...]$10 = 6
+// lldbg-check:[...]$10 = 6
+// lldbr-check:(isize) *owned = 6
 // lldb-command:print closure_local
-// lldb-check:[...]$11 = 8
+// lldbg-check:[...]$11 = 8
+// lldbr-check:(isize) closure_local = 8
 // lldb-command:continue
 
 #![allow(unused_variables)]
index 9aeb3bc91336a67b17f9b6f4eb8a790c254fa034..a562584dfd028c18cfa07766d41929063348e78a 100644 (file)
 // lldb-command:run
 
 // lldb-command:print constant
-// lldb-check:[...]$0 = 1
+// lldbg-check:[...]$0 = 1
+// lldbr-check:(isize) constant = 1
 // lldb-command:print a_struct
-// lldb-check:[...]$1 = Struct { a: -2, b: 3.5, c: 4 }
+// lldbg-check:[...]$1 = Struct { a: -2, b: 3.5, c: 4 }
+// lldbr-check:(var_captured_in_sendable_closure::Struct) a_struct = Struct { a: -2, b: 3.5, c: 4 }
 // lldb-command:print *owned
-// lldb-check:[...]$2 = 5
+// lldbg-check:[...]$2 = 5
+// lldbr-check:(isize) *owned = 5
 
 #![allow(unused_variables)]
 #![feature(box_syntax)]
index c795a095b9769a095d1ffb7a95a7cc185e24cbda..cf4eaf393e9562f8c9702bda3996a40430b1dee4 100644 (file)
 // lldb-command:run
 
 // lldb-command:print variable
-// lldb-check:[...]$0 = 1
+// lldbg-check:[...]$0 = 1
+// lldbr-check:(isize) variable = 1
 // lldb-command:print constant
-// lldb-check:[...]$1 = 2
+// lldbg-check:[...]$1 = 2
+// lldbr-check:(isize) constant = 2
 // lldb-command:print a_struct
-// lldb-check:[...]$2 = Struct { a: -3, b: 4.5, c: 5 }
+// lldbg-check:[...]$2 = Struct { a: -3, b: 4.5, c: 5 }
+// lldbr-check:(var_captured_in_stack_closure::Struct) a_struct = Struct { a: -3, b: 4.5, c: 5 }
 // lldb-command:print *struct_ref
-// lldb-check:[...]$3 = Struct { a: -3, b: 4.5, c: 5 }
+// lldbg-check:[...]$3 = Struct { a: -3, b: 4.5, c: 5 }
+// lldbr-check:(var_captured_in_stack_closure::Struct) *struct_ref = Struct { a: -3, b: 4.5, c: 5 }
 // lldb-command:print *owned
-// lldb-check:[...]$4 = 6
+// lldbg-check:[...]$4 = 6
+// lldbr-check:(isize) *owned = 6
 
 // lldb-command:continue
 
 // lldb-command:print variable
-// lldb-check:[...]$5 = 2
+// lldbg-check:[...]$5 = 2
+// lldbr-check:(isize) variable = 2
 // lldb-command:print constant
-// lldb-check:[...]$6 = 2
+// lldbg-check:[...]$6 = 2
+// lldbr-check:(isize) constant = 2
 // lldb-command:print a_struct
-// lldb-check:[...]$7 = Struct { a: -3, b: 4.5, c: 5 }
+// lldbg-check:[...]$7 = Struct { a: -3, b: 4.5, c: 5 }
+// lldbr-check:(var_captured_in_stack_closure::Struct) a_struct = Struct { a: -3, b: 4.5, c: 5 }
 // lldb-command:print *struct_ref
-// lldb-check:[...]$8 = Struct { a: -3, b: 4.5, c: 5 }
+// lldbg-check:[...]$8 = Struct { a: -3, b: 4.5, c: 5 }
+// lldbr-check:(var_captured_in_stack_closure::Struct) *struct_ref = Struct { a: -3, b: 4.5, c: 5 }
 // lldb-command:print *owned
-// lldb-check:[...]$9 = 6
+// lldbg-check:[...]$9 = 6
+// lldbr-check:(isize) *owned = 6
 
 #![feature(box_syntax)]
 #![allow(unused_variables)]
index 888d9b28506b3608b585018e0fd0a9824e8cce9a..39bf0c175ebcb7ea41eb7401ee965b3d42888f5a 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-tidy-linelength
+
 // ignore-windows
 // ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
 // min-lldb-version: 310
 // lldb-command:run
 
 // lldb-command:print empty
-// lldb-check:[...]$0 = &[]
+// lldbg-check:[...]$0 = &[]
+// lldbr-check:(&[i64]) empty = &[]
 
 // lldb-command:print singleton
-// lldb-check:[...]$1 = &[1]
+// lldbg-check:[...]$1 = &[1]
+// lldbr-check:(&[i64]) singleton = &[1]
 
 // lldb-command:print multiple
-// lldb-check:[...]$2 = &[2, 3, 4, 5]
+// lldbg-check:[...]$2 = &[2, 3, 4, 5]
+// lldbr-check:(&[i64]) multiple = &[2, 3, 4, 5]
 
 // lldb-command:print slice_of_slice
-// lldb-check:[...]$3 = &[3, 4]
+// lldbg-check:[...]$3 = &[3, 4]
+// lldbr-check:(&[i64]) slice_of_slice = &[3, 4]
 
 // lldb-command:print padded_tuple
-// lldb-check:[...]$4 = &[(6, 7), (8, 9)]
+// lldbg-check:[...]$4 = &[(6, 7), (8, 9)]
+// lldbr-check:(&[(i32, i16)]) padded_tuple = { data_ptr = *0x555555554ff0 length = 2 }
 
 // lldb-command:print padded_struct
-// lldb-check:[...]$5 = &[AStruct { x: 10, y: 11, z: 12 }, AStruct { x: 13, y: 14, z: 15 }]
+// lldbg-check:[...]$5 = &[AStruct { x: 10, y: 11, z: 12 }, AStruct { x: 13, y: 14, z: 15 }]
+// lldbr-check:(&[vec_slices::AStruct]) padded_struct = &[AStruct { x: 10, y: 11, z: 12 }, AStruct { x: 13, y: 14, z: 15 }]
 
 #![allow(dead_code, unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
index dba947530fea8fdeac0451a9641f867d32c8bc81..752f3f1cba1ecec6e48b74cf815ff6fc59e72434 100644 (file)
@@ -28,7 +28,8 @@
 
 // lldb-command:run
 // lldb-command:print a
-// lldb-check:[...]$0 = [1, 2, 3]
+// lldbg-check:[...]$0 = [1, 2, 3]
+// lldbr-check:([i32; 3]) a = [1, 2, 3]
 
 #![allow(unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
index 751f4113fbf60a9f1fe49f00bc381aeb5deb70e9..7be9345b6b423c8a87f12d9c6be030488f0ca5cc 100644 (file)
@@ -2,7 +2,7 @@ error[E0080]: this constant likely exhibits undefined behavior
   --> $DIR/const-pointer-values-in-various-types.rs:24:5
    |
 LL |     const I32_REF_USIZE_UNION: usize = unsafe { Nonsense { int_32_ref: &3 }.u };
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected the type usize
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain bits
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
 
@@ -36,7 +36,7 @@ error[E0080]: this constant likely exhibits undefined behavior
   --> $DIR/const-pointer-values-in-various-types.rs:36:5
    |
 LL |     const I32_REF_U64_UNION: u64 = unsafe { Nonsense { int_32_ref: &3 }.uint_64 };
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected the type u64
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain bits
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
 
@@ -74,7 +74,7 @@ error[E0080]: this constant likely exhibits undefined behavior
   --> $DIR/const-pointer-values-in-various-types.rs:51:5
    |
 LL |     const I32_REF_I64_UNION: i64 = unsafe { Nonsense { int_32_ref: &3 }.int_64 };
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected the type i64
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain bits
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
 
@@ -96,7 +96,7 @@ error[E0080]: this constant likely exhibits undefined behavior
   --> $DIR/const-pointer-values-in-various-types.rs:60:5
    |
 LL |     const I32_REF_F64_UNION: f64 = unsafe { Nonsense { int_32_ref: &3 }.float_64 };
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected the type f64
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain bits
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
 
@@ -144,7 +144,7 @@ error[E0080]: this constant likely exhibits undefined behavior
   --> $DIR/const-pointer-values-in-various-types.rs:78:5
    |
 LL |     const STR_U64_UNION: u64 = unsafe { Nonsense { stringy: "3" }.uint_64 };
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected the type u64
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain bits
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
 
@@ -184,7 +184,7 @@ error[E0080]: this constant likely exhibits undefined behavior
   --> $DIR/const-pointer-values-in-various-types.rs:93:5
    |
 LL |     const STR_I64_UNION: i64 = unsafe { Nonsense { stringy: "3" }.int_64 };
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected the type i64
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain bits
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
 
@@ -208,7 +208,7 @@ error[E0080]: this constant likely exhibits undefined behavior
   --> $DIR/const-pointer-values-in-various-types.rs:102:5
    |
 LL |     const STR_F64_UNION: f64 = unsafe { Nonsense { stringy: "3" }.float_64 };
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected the type f64
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain bits
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
 
index a585a4404adf6487a65d98f095a99ae39a449d5c..477e7119ba93735f0cf4203fc4f3a945408f2596 100644 (file)
@@ -14,6 +14,5 @@
 
 static FOO: bool = unsafe { mem::transmute(3u8) };
 //~^ ERROR this static likely exhibits undefined behavior
-//~^^ type validation failed: encountered 3, but expected something in the range 0..=1
 
 fn main() {}
index 572d08ddfeebd0958d9db040dc249c98ac783ed2..243343c94b065b0131dc4b30f4f9ff24916d2cca 100644 (file)
@@ -18,7 +18,7 @@ error[E0080]: this constant likely exhibits undefined behavior
   --> $DIR/ub-enum.rs:45:1
    |
 LL | const BAD_ENUM_CHAR : Option<(char, char)> = Some(('x', unsafe { TransmuteChar { a: !0 }.b }));
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered character at .Some.0.1, but expected a valid unicode codepoint
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 4294967295 at .Some.0.1, but expected something in the range 0..=1114111
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
 
diff --git a/src/test/ui/consts/const-eval/ub-nonnull.rs b/src/test/ui/consts/const-eval/ub-nonnull.rs
new file mode 100644 (file)
index 0000000..2b07eee
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(const_transmute)]
+
+use std::mem;
+use std::ptr::NonNull;
+use std::num::{NonZeroU8, NonZeroUsize};
+
+const NULL_PTR: NonNull<u8> = unsafe { mem::transmute(0usize) };
+//~^ ERROR this constant likely exhibits undefined behavior
+
+const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) };
+//~^ ERROR this constant likely exhibits undefined behavior
+const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) };
+//~^ ERROR this constant likely exhibits undefined behavior
+
+fn main() {}
diff --git a/src/test/ui/consts/const-eval/ub-nonnull.stderr b/src/test/ui/consts/const-eval/ub-nonnull.stderr
new file mode 100644 (file)
index 0000000..8d1ca88
--- /dev/null
@@ -0,0 +1,27 @@
+error[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/ub-nonnull.rs:17:1
+   |
+LL | const NULL_PTR: NonNull<u8> = unsafe { mem::transmute(0usize) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/ub-nonnull.rs:20:1
+   |
+LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/ub-nonnull.rs:22:1
+   |
+LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/ub-ref.rs b/src/test/ui/consts/const-eval/ub-ref.rs
new file mode 100644 (file)
index 0000000..7ee13f2
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(const_transmute)]
+
+use std::mem;
+
+const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) };
+//~^ ERROR this constant likely exhibits undefined behavior
+
+const NULL: &u16 = unsafe { mem::transmute(0usize) };
+//~^ ERROR this constant likely exhibits undefined behavior
+
+const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) };
+//~^ ERROR this constant likely exhibits undefined behavior
+
+const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
+//~^ ERROR this constant likely exhibits undefined behavior
+
+fn main() {}
diff --git a/src/test/ui/consts/const-eval/ub-ref.stderr b/src/test/ui/consts/const-eval/ub-ref.stderr
new file mode 100644 (file)
index 0000000..9907c78
--- /dev/null
@@ -0,0 +1,35 @@
+error[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/ub-ref.rs:15:1
+   |
+LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered unaligned reference
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/ub-ref.rs:18:1
+   |
+LL | const NULL: &u16 = unsafe { mem::transmute(0usize) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/ub-ref.rs:21:1
+   |
+LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain bits
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/ub-ref.rs:24:1
+   |
+LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered integer pointer in non-ZST reference
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
index a5e341524bc7312b0911d0624f12112adb56cf1c..99305beee52814c58bd999e3d005d93fa5cab671 100644 (file)
@@ -8,15 +8,20 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-union Foo {
-    a: u8,
-    b: Bar,
-}
+#![feature(const_transmute)]
+
+use std::mem;
 
 #[derive(Copy, Clone)]
 enum Bar {}
 
-const BAD_BAD_BAD: Bar = unsafe { Foo { a: 1 }.b};
+const BAD_BAD_BAD: Bar = unsafe { mem::transmute(()) };
+//~^ ERROR this constant likely exhibits undefined behavior
+
+const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) };
+//~^ ERROR this constant likely exhibits undefined behavior
+
+const BAD_BAD_ARRAY: [Bar; 1] = unsafe { mem::transmute(()) };
 //~^ ERROR this constant likely exhibits undefined behavior
 
 fn main() {
index 623b98dc4531b797054f177d80704d035a9b4f4b..136d5f29199467a284a8ae9b000a68399691ad03 100644 (file)
@@ -1,11 +1,27 @@
 error[E0080]: this constant likely exhibits undefined behavior
-  --> $DIR/ub-uninhabit.rs:19:1
+  --> $DIR/ub-uninhabit.rs:18:1
    |
-LL | const BAD_BAD_BAD: Bar = unsafe { Foo { a: 1 }.b};
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type
+LL | const BAD_BAD_BAD: Bar = unsafe { mem::transmute(()) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
 
-error: aborting due to previous error
+error[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/ub-uninhabit.rs:21:1
+   |
+LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type at .<deref>
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/ub-uninhabit.rs:24:1
+   |
+LL | const BAD_BAD_ARRAY: [Bar; 1] = unsafe { mem::transmute(()) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type at [0]
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/ub-usize-in-ref.rs b/src/test/ui/consts/const-eval/ub-usize-in-ref.rs
deleted file mode 100644 (file)
index aaff2f2..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// compile-pass
-
-union Foo {
-    a: &'static u8,
-    b: usize,
-}
-
-// This might point to an invalid address, but that's the user's problem
-const USIZE_AS_STATIC_REF: &'static u8 = unsafe { Foo { b: 1337 }.a};
-
-fn main() {
-}
index ec51802681e0df40295b55d80407b9800539969f..4484dd6a14740f12cf06feb11faa1b2361e96e3d 100644 (file)
@@ -13,7 +13,7 @@ LL | / const FIELD_PATH: Struct = Struct { //~ ERROR this constant likely exhibi
 LL | |     a: 42,
 LL | |     b: unsafe { UNION.field3 },
 LL | | };
-   | |__^ type validation failed: encountered undefined bytes at .b
+   | |__^ type validation failed: encountered uninitialized bytes at .b, but expected initialized plain bits
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
 
diff --git a/src/test/ui/consts/const-eval/union-ub-fat-ptr.rs b/src/test/ui/consts/const-eval/union-ub-fat-ptr.rs
new file mode 100644 (file)
index 0000000..0c42d28
--- /dev/null
@@ -0,0 +1,139 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![allow(unused)]
+
+// normalize-stderr-test "alignment \d+" -> "alignment N"
+// normalize-stderr-test "offset \d+" -> "offset N"
+// normalize-stderr-test "allocation \d+" -> "allocation N"
+// normalize-stderr-test "size \d+" -> "size N"
+
+union BoolTransmute {
+  val: u8,
+  bl: bool,
+}
+
+#[repr(C)]
+#[derive(Copy, Clone)]
+struct SliceRepr {
+    ptr: *const u8,
+    len: usize,
+}
+
+#[repr(C)]
+#[derive(Copy, Clone)]
+struct BadSliceRepr {
+    ptr: *const u8,
+    len: &'static u8,
+}
+
+union SliceTransmute {
+    repr: SliceRepr,
+    bad: BadSliceRepr,
+    slice: &'static [u8],
+    str: &'static str,
+    my_str: &'static MyStr,
+    my_slice: &'static MySliceBool,
+}
+
+#[repr(C)]
+#[derive(Copy, Clone)]
+struct DynRepr {
+    ptr: *const u8,
+    vtable: *const u8,
+}
+
+#[repr(C)]
+#[derive(Copy, Clone)]
+struct DynRepr2 {
+    ptr: *const u8,
+    vtable: *const u64,
+}
+
+#[repr(C)]
+#[derive(Copy, Clone)]
+struct BadDynRepr {
+    ptr: *const u8,
+    vtable: usize,
+}
+
+union DynTransmute {
+    repr: DynRepr,
+    repr2: DynRepr2,
+    bad: BadDynRepr,
+    rust: &'static Trait,
+}
+
+trait Trait {}
+impl Trait for bool {}
+
+// custom unsized type
+struct MyStr(str);
+
+// custom unsized type with sized fields
+struct MySlice<T: ?Sized>(bool, T);
+type MySliceBool = MySlice<[bool]>;
+
+// OK
+const A: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 1 } }.str};
+// bad str
+const B: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.str};
+//~^ ERROR this constant likely exhibits undefined behavior
+// bad str
+const C: &str = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.str};
+//~^ ERROR this constant likely exhibits undefined behavior
+// bad str in user-defined unsized type
+const C2: &MyStr = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.my_str};
+//~^ ERROR this constant likely exhibits undefined behavior
+
+// OK
+const A2: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 1 } }.slice};
+// bad slice
+const B2: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.slice};
+//~^ ERROR this constant likely exhibits undefined behavior
+// bad slice
+const C3: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.slice};
+//~^ ERROR this constant likely exhibits undefined behavior
+
+// bad trait object
+const D: &Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust};
+//~^ ERROR this constant likely exhibits undefined behavior
+// bad trait object
+const E: &Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust};
+//~^ ERROR this constant likely exhibits undefined behavior
+// bad trait object
+const F: &Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust};
+//~^ ERROR this constant likely exhibits undefined behavior
+
+// bad data *inside* the trait object
+const G: &Trait = &unsafe { BoolTransmute { val: 3 }.bl };
+//~^ ERROR this constant likely exhibits undefined behavior
+// bad data *inside* the slice
+const H: &[bool] = &[unsafe { BoolTransmute { val: 3 }.bl }];
+//~^ ERROR this constant likely exhibits undefined behavior
+
+// good MySliceBool
+const I1: &MySliceBool = &MySlice(true, [false]);
+// bad: sized field is not okay
+const I2: &MySliceBool = &MySlice(unsafe { BoolTransmute { val: 3 }.bl }, [false]);
+//~^ ERROR this constant likely exhibits undefined behavior
+// bad: unsized part is not okay
+const I3: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }.bl }]);
+//~^ ERROR this constant likely exhibits undefined behavior
+
+// invalid UTF-8
+const J1: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str };
+//~^ ERROR this constant likely exhibits undefined behavior
+// invalid UTF-8 in user-defined str-like
+const J2: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str };
+//~^ ERROR this constant likely exhibits undefined behavior
+
+fn main() {
+}
diff --git a/src/test/ui/consts/const-eval/union-ub-fat-ptr.stderr b/src/test/ui/consts/const-eval/union-ub-fat-ptr.stderr
new file mode 100644 (file)
index 0000000..c4632ff
--- /dev/null
@@ -0,0 +1,115 @@
+error[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/union-ub-fat-ptr.rs:87:1
+   |
+LL | const B: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.str};
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling (not entirely in bounds) reference
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/union-ub-fat-ptr.rs:90:1
+   |
+LL | const C: &str = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.str};
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in fat pointer
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/union-ub-fat-ptr.rs:93:1
+   |
+LL | const C2: &MyStr = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.my_str};
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in fat pointer
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/union-ub-fat-ptr.rs:99:1
+   |
+LL | const B2: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.slice};
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling (not entirely in bounds) reference
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/union-ub-fat-ptr.rs:102:1
+   |
+LL | const C3: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.slice};
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in fat pointer
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/union-ub-fat-ptr.rs:106:1
+   |
+LL | const D: &Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust};
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid drop fn in vtable
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/union-ub-fat-ptr.rs:109:1
+   |
+LL | const E: &Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust};
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid drop fn in vtable
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/union-ub-fat-ptr.rs:112:1
+   |
+LL | const F: &Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust};
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-pointer vtable in fat pointer
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/union-ub-fat-ptr.rs:116:1
+   |
+LL | const G: &Trait = &unsafe { BoolTransmute { val: 3 }.bl };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>, but expected something in the range 0..=1
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/union-ub-fat-ptr.rs:119:1
+   |
+LL | const H: &[bool] = &[unsafe { BoolTransmute { val: 3 }.bl }];
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>[0], but expected something in the range 0..=1
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/union-ub-fat-ptr.rs:125:1
+   |
+LL | const I2: &MySliceBool = &MySlice(unsafe { BoolTransmute { val: 3 }.bl }, [false]);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>.0, but expected something in the range 0..=1
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/union-ub-fat-ptr.rs:128:1
+   |
+LL | const I3: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }.bl }]);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>.1[0], but expected something in the range 0..=1
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/union-ub-fat-ptr.rs:132:1
+   |
+LL | const J1: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at .<deref>
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: this constant likely exhibits undefined behavior
+  --> $DIR/union-ub-fat-ptr.rs:135:1
+   |
+LL | const J2: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at .<deref>.0
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error: aborting due to 14 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
index db36764c4a30693f280666512ff10a16a3fd991a..86b3bdaa6b79ec82d41cb0e9a8b9208501dd6b5b 100644 (file)
@@ -41,5 +41,4 @@ union Bar {
 const BAD_UNION: Foo = unsafe { Bar { u8: 42 }.foo };
 
 
-fn main() {
-}
+fn main() {}
diff --git a/src/test/ui/consts/const-eval/valid-const.rs b/src/test/ui/consts/const-eval/valid-const.rs
new file mode 100644 (file)
index 0000000..a195e12
--- /dev/null
@@ -0,0 +1,18 @@
+// compile-pass
+
+// Some constants that *are* valid
+#![feature(const_transmute)]
+
+use std::mem;
+use std::ptr::NonNull;
+use std::num::{NonZeroU8, NonZeroUsize};
+
+const NON_NULL_PTR1: NonNull<u8> = unsafe { mem::transmute(1usize) };
+const NON_NULL_PTR2: NonNull<u8> = unsafe { mem::transmute(&0) };
+
+const NON_NULL_U8: NonZeroU8 = unsafe { mem::transmute(1u8) };
+const NON_NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(1usize) };
+
+const UNIT: () = ();
+
+fn main() {}
index 21fc4079d5b59d29626e162a04f1d6c2aba956a9..ebd44d46eb2ce544eb8e082a9e58dfc194d64ac0 100644 (file)
@@ -1,6 +1,9 @@
 error[E0596]: cannot borrow `*self.s` as mutable, as it is behind a `&` reference
   --> $DIR/issue-38147-2.rs:17:9
    |
+LL |     s: &'a String
+   |        ---------- help: consider changing this to be mutable: `&'a mut String`
+...
 LL |         self.s.push('x');
    |         ^^^^^^ cannot borrow as mutable
 
index d426c1f37fc1c667a3a44f339ed19d44b0fdbae1..d644a84c7bbcec2da5723cf079f523f68c0746ae 100644 (file)
@@ -1,6 +1,9 @@
 error[E0596]: cannot borrow `*self.s` as mutable, as it is behind a `&` reference
   --> $DIR/issue-38147-3.rs:17:9
    |
+LL |     s: &'a String
+   |        ---------- help: consider changing this to be mutable: `&'a mut String`
+...
 LL |         self.s.push('x');
    |         ^^^^^^ cannot borrow as mutable
 
index 250e78ce2464005d9837f07fe7d7e4178cb4d369..857db50edbbc166f3971cb611b3674291251f33c 100644 (file)
@@ -11,9 +11,9 @@
 #![allow(safe_extern_statics, warnings)]
 
 extern {
-    pub static symbol: ();
+    pub static symbol: u32;
 }
-static CRASH: () = symbol;
+static CRASH: u32 = symbol;
 //~^ ERROR could not evaluate static initializer
 //~| tried to read from foreign (extern) static
 
index f5f39465b187b6bf95755e014607b25657197b5d..dc6c72d8a725620a92b6d0935565f5908683ca0d 100644 (file)
@@ -1,8 +1,8 @@
 error[E0080]: could not evaluate static initializer
-  --> $DIR/issue-14227.rs:16:20
+  --> $DIR/issue-14227.rs:16:21
    |
-LL | static CRASH: () = symbol;
-   |                    ^^^^^^ tried to read from foreign (extern) static
+LL | static CRASH: u32 = symbol;
+   |                     ^^^^^^ tried to read from foreign (extern) static
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.rs b/src/test/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.rs
new file mode 100644 (file)
index 0000000..526134b
--- /dev/null
@@ -0,0 +1,24 @@
+#![feature(nll)]
+
+enum Foo<'a> {
+    Bar { field: &'a u32 }
+}
+
+fn in_let() {
+    let y = 22;
+    let foo = Foo::Bar { field: &y };
+    //~^ ERROR `y` does not live long enough
+    let Foo::Bar::<'static> { field: _z } = foo;
+}
+
+fn in_match() {
+    let y = 22;
+    let foo = Foo::Bar { field: &y };
+    //~^ ERROR `y` does not live long enough
+    match foo {
+        Foo::Bar::<'static> { field: _z } => {
+        }
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.stderr b/src/test/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.stderr
new file mode 100644 (file)
index 0000000..5dbbf7c
--- /dev/null
@@ -0,0 +1,25 @@
+error[E0597]: `y` does not live long enough
+  --> $DIR/pattern_substs_on_brace_enum_variant.rs:9:33
+   |
+LL |     let foo = Foo::Bar { field: &y };
+   |                                 ^^ borrowed value does not live long enough
+...
+LL | }
+   | - `y` dropped here while still borrowed
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: `y` does not live long enough
+  --> $DIR/pattern_substs_on_brace_enum_variant.rs:16:33
+   |
+LL |     let foo = Foo::Bar { field: &y };
+   |                                 ^^ borrowed value does not live long enough
+...
+LL | }
+   | - `y` dropped here while still borrowed
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/user-annotations/pattern_substs_on_brace_struct.rs b/src/test/ui/nll/user-annotations/pattern_substs_on_brace_struct.rs
new file mode 100644 (file)
index 0000000..1c92858
--- /dev/null
@@ -0,0 +1,22 @@
+#![feature(nll)]
+
+struct Foo<'a> { field: &'a u32 }
+
+fn in_let() {
+    let y = 22;
+    let foo = Foo { field: &y };
+    //~^ ERROR `y` does not live long enough
+    let Foo::<'static> { field: _z } = foo;
+}
+
+fn in_main() {
+    let y = 22;
+    let foo = Foo { field: &y };
+    //~^ ERROR `y` does not live long enough
+    match foo {
+        Foo::<'static> { field: _z } => {
+        }
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/user-annotations/pattern_substs_on_brace_struct.stderr b/src/test/ui/nll/user-annotations/pattern_substs_on_brace_struct.stderr
new file mode 100644 (file)
index 0000000..0108a18
--- /dev/null
@@ -0,0 +1,25 @@
+error[E0597]: `y` does not live long enough
+  --> $DIR/pattern_substs_on_brace_struct.rs:7:28
+   |
+LL |     let foo = Foo { field: &y };
+   |                            ^^ borrowed value does not live long enough
+...
+LL | }
+   | - `y` dropped here while still borrowed
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: `y` does not live long enough
+  --> $DIR/pattern_substs_on_brace_struct.rs:14:28
+   |
+LL |     let foo = Foo { field: &y };
+   |                            ^^ borrowed value does not live long enough
+...
+LL | }
+   | - `y` dropped here while still borrowed
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.rs b/src/test/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.rs
new file mode 100644 (file)
index 0000000..d6c364f
--- /dev/null
@@ -0,0 +1,24 @@
+#![feature(nll)]
+
+enum Foo<'a> {
+    Bar(&'a u32)
+}
+
+fn in_let() {
+    let y = 22;
+    let foo = Foo::Bar(&y);
+    //~^ ERROR `y` does not live long enough
+    let Foo::Bar::<'static>(_z) = foo;
+}
+
+fn in_match() {
+    let y = 22;
+    let foo = Foo::Bar(&y);
+    //~^ ERROR `y` does not live long enough
+    match foo {
+        Foo::Bar::<'static>(_z) => {
+        }
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.stderr b/src/test/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.stderr
new file mode 100644 (file)
index 0000000..b18fdc3
--- /dev/null
@@ -0,0 +1,25 @@
+error[E0597]: `y` does not live long enough
+  --> $DIR/pattern_substs_on_tuple_enum_variant.rs:9:24
+   |
+LL |     let foo = Foo::Bar(&y);
+   |                        ^^ borrowed value does not live long enough
+...
+LL | }
+   | - `y` dropped here while still borrowed
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: `y` does not live long enough
+  --> $DIR/pattern_substs_on_tuple_enum_variant.rs:16:24
+   |
+LL |     let foo = Foo::Bar(&y);
+   |                        ^^ borrowed value does not live long enough
+...
+LL | }
+   | - `y` dropped here while still borrowed
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/user-annotations/pattern_substs_on_tuple_struct.rs b/src/test/ui/nll/user-annotations/pattern_substs_on_tuple_struct.rs
new file mode 100644 (file)
index 0000000..626ca90
--- /dev/null
@@ -0,0 +1,22 @@
+#![feature(nll)]
+
+struct Foo<'a>(&'a u32);
+
+fn in_let() {
+    let y = 22;
+    let foo = Foo(&y);
+    //~^ ERROR `y` does not live long enough
+    let Foo::<'static>(_z) = foo;
+}
+
+fn in_match() {
+    let y = 22;
+    let foo = Foo(&y);
+    //~^ ERROR `y` does not live long enough
+    match foo {
+        Foo::<'static>(_z) => {
+        }
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/user-annotations/pattern_substs_on_tuple_struct.stderr b/src/test/ui/nll/user-annotations/pattern_substs_on_tuple_struct.stderr
new file mode 100644 (file)
index 0000000..b72fda9
--- /dev/null
@@ -0,0 +1,25 @@
+error[E0597]: `y` does not live long enough
+  --> $DIR/pattern_substs_on_tuple_struct.rs:7:19
+   |
+LL |     let foo = Foo(&y);
+   |                   ^^ borrowed value does not live long enough
+...
+LL | }
+   | - `y` dropped here while still borrowed
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: `y` does not live long enough
+  --> $DIR/pattern_substs_on_tuple_struct.rs:14:19
+   |
+LL |     let foo = Foo(&y);
+   |                   ^^ borrowed value does not live long enough
+...
+LL | }
+   | - `y` dropped here while still borrowed
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/range/issue-54505-no-literals.fixed b/src/test/ui/range/issue-54505-no-literals.fixed
new file mode 100644 (file)
index 0000000..4d8f671
--- /dev/null
@@ -0,0 +1,75 @@
+// run-rustfix
+
+// Regression test for changes introduced while fixing #54505
+
+// This test uses non-literals for Ranges
+// (expecting no parens with borrow suggestion)
+
+use std::ops::RangeBounds;
+
+
+// take a reference to any built-in range
+fn take_range(_r: &impl RangeBounds<i8>) {}
+
+
+fn main() {
+    take_range(&std::ops::Range { start: 0, end: 1 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &std::ops::Range { start: 0, end: 1 }
+
+    take_range(&::std::ops::Range { start: 0, end: 1 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &::std::ops::Range { start: 0, end: 1 }
+
+    take_range(&std::ops::RangeFrom { start: 1 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &std::ops::RangeFrom { start: 1 }
+
+    take_range(&::std::ops::RangeFrom { start: 1 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &::std::ops::RangeFrom { start: 1 }
+
+    take_range(&std::ops::RangeFull {});
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &std::ops::RangeFull {}
+
+    take_range(&::std::ops::RangeFull {});
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &::std::ops::RangeFull {}
+
+    take_range(&std::ops::RangeInclusive::new(0, 1));
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &std::ops::RangeInclusive::new(0, 1)
+
+    take_range(&::std::ops::RangeInclusive::new(0, 1));
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &::std::ops::RangeInclusive::new(0, 1)
+
+    take_range(&std::ops::RangeTo { end: 5 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &std::ops::RangeTo { end: 5 }
+
+    take_range(&::std::ops::RangeTo { end: 5 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &::std::ops::RangeTo { end: 5 }
+
+    take_range(&std::ops::RangeToInclusive { end: 5 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &std::ops::RangeToInclusive { end: 5 }
+
+    take_range(&::std::ops::RangeToInclusive { end: 5 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &::std::ops::RangeToInclusive { end: 5 }
+}
diff --git a/src/test/ui/range/issue-54505-no-literals.rs b/src/test/ui/range/issue-54505-no-literals.rs
new file mode 100644 (file)
index 0000000..dc21dcb
--- /dev/null
@@ -0,0 +1,75 @@
+// run-rustfix
+
+// Regression test for changes introduced while fixing #54505
+
+// This test uses non-literals for Ranges
+// (expecting no parens with borrow suggestion)
+
+use std::ops::RangeBounds;
+
+
+// take a reference to any built-in range
+fn take_range(_r: &impl RangeBounds<i8>) {}
+
+
+fn main() {
+    take_range(std::ops::Range { start: 0, end: 1 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &std::ops::Range { start: 0, end: 1 }
+
+    take_range(::std::ops::Range { start: 0, end: 1 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &::std::ops::Range { start: 0, end: 1 }
+
+    take_range(std::ops::RangeFrom { start: 1 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &std::ops::RangeFrom { start: 1 }
+
+    take_range(::std::ops::RangeFrom { start: 1 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &::std::ops::RangeFrom { start: 1 }
+
+    take_range(std::ops::RangeFull {});
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &std::ops::RangeFull {}
+
+    take_range(::std::ops::RangeFull {});
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &::std::ops::RangeFull {}
+
+    take_range(std::ops::RangeInclusive::new(0, 1));
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &std::ops::RangeInclusive::new(0, 1)
+
+    take_range(::std::ops::RangeInclusive::new(0, 1));
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &::std::ops::RangeInclusive::new(0, 1)
+
+    take_range(std::ops::RangeTo { end: 5 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &std::ops::RangeTo { end: 5 }
+
+    take_range(::std::ops::RangeTo { end: 5 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &::std::ops::RangeTo { end: 5 }
+
+    take_range(std::ops::RangeToInclusive { end: 5 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &std::ops::RangeToInclusive { end: 5 }
+
+    take_range(::std::ops::RangeToInclusive { end: 5 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &::std::ops::RangeToInclusive { end: 5 }
+}
diff --git a/src/test/ui/range/issue-54505-no-literals.stderr b/src/test/ui/range/issue-54505-no-literals.stderr
new file mode 100644 (file)
index 0000000..b8811c9
--- /dev/null
@@ -0,0 +1,147 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-literals.rs:16:16
+   |
+LL |     take_range(std::ops::Range { start: 0, end: 1 });
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::Range`
+   |                help: consider borrowing here: `&std::ops::Range { start: 0, end: 1 }`
+   |
+   = note: expected type `&_`
+              found type `std::ops::Range<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-literals.rs:21:16
+   |
+LL |     take_range(::std::ops::Range { start: 0, end: 1 });
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::Range`
+   |                help: consider borrowing here: `&::std::ops::Range { start: 0, end: 1 }`
+   |
+   = note: expected type `&_`
+              found type `std::ops::Range<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-literals.rs:26:16
+   |
+LL |     take_range(std::ops::RangeFrom { start: 1 });
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeFrom`
+   |                help: consider borrowing here: `&std::ops::RangeFrom { start: 1 }`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeFrom<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-literals.rs:31:16
+   |
+LL |     take_range(::std::ops::RangeFrom { start: 1 });
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeFrom`
+   |                help: consider borrowing here: `&::std::ops::RangeFrom { start: 1 }`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeFrom<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-literals.rs:36:16
+   |
+LL |     take_range(std::ops::RangeFull {});
+   |                ^^^^^^^^^^^^^^^^^^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeFull`
+   |                help: consider borrowing here: `&std::ops::RangeFull {}`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeFull`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-literals.rs:41:16
+   |
+LL |     take_range(::std::ops::RangeFull {});
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeFull`
+   |                help: consider borrowing here: `&::std::ops::RangeFull {}`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeFull`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-literals.rs:46:16
+   |
+LL |     take_range(std::ops::RangeInclusive::new(0, 1));
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeInclusive`
+   |                help: consider borrowing here: `&std::ops::RangeInclusive::new(0, 1)`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeInclusive<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-literals.rs:51:16
+   |
+LL |     take_range(::std::ops::RangeInclusive::new(0, 1));
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeInclusive`
+   |                help: consider borrowing here: `&::std::ops::RangeInclusive::new(0, 1)`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeInclusive<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-literals.rs:56:16
+   |
+LL |     take_range(std::ops::RangeTo { end: 5 });
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeTo`
+   |                help: consider borrowing here: `&std::ops::RangeTo { end: 5 }`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeTo<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-literals.rs:61:16
+   |
+LL |     take_range(::std::ops::RangeTo { end: 5 });
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeTo`
+   |                help: consider borrowing here: `&::std::ops::RangeTo { end: 5 }`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeTo<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-literals.rs:66:16
+   |
+LL |     take_range(std::ops::RangeToInclusive { end: 5 });
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeToInclusive`
+   |                help: consider borrowing here: `&std::ops::RangeToInclusive { end: 5 }`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeToInclusive<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-literals.rs:71:16
+   |
+LL |     take_range(::std::ops::RangeToInclusive { end: 5 });
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeToInclusive`
+   |                help: consider borrowing here: `&::std::ops::RangeToInclusive { end: 5 }`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeToInclusive<{integer}>`
+
+error: aborting due to 12 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/range/issue-54505-no-std.rs b/src/test/ui/range/issue-54505-no-std.rs
new file mode 100644 (file)
index 0000000..1915fd8
--- /dev/null
@@ -0,0 +1,57 @@
+// error-pattern: `#[panic_handler]` function required, but not found
+
+// Regression test for #54505 - range borrowing suggestion had
+// incorrect syntax (missing parentheses).
+
+// This test doesn't use std
+// (so all Ranges resolve to core::ops::Range...)
+
+#![no_std]
+#![feature(lang_items)]
+
+use core::ops::RangeBounds;
+
+#[cfg(not(target_arch = "wasm32"))]
+#[lang = "eh_personality"]
+extern fn eh_personality() {}
+
+#[cfg(target_os = "windows")]
+#[lang = "eh_unwind_resume"]
+extern fn eh_unwind_resume() {}
+
+
+// take a reference to any built-in range
+fn take_range(_r: &impl RangeBounds<i8>) {}
+
+
+fn main() {
+    take_range(0..1);
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(0..1)
+
+    take_range(1..);
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(1..)
+
+    take_range(..);
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(..)
+
+    take_range(0..=1);
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(0..=1)
+
+    take_range(..5);
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(..5)
+
+    take_range(..=42);
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(..=42)
+}
diff --git a/src/test/ui/range/issue-54505-no-std.stderr b/src/test/ui/range/issue-54505-no-std.stderr
new file mode 100644 (file)
index 0000000..4922e59
--- /dev/null
@@ -0,0 +1,77 @@
+error: `#[panic_handler]` function required, but not found
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-std.rs:28:16
+   |
+LL |     take_range(0..1);
+   |                ^^^^
+   |                |
+   |                expected reference, found struct `core::ops::Range`
+   |                help: consider borrowing here: `&(0..1)`
+   |
+   = note: expected type `&_`
+              found type `core::ops::Range<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-std.rs:33:16
+   |
+LL |     take_range(1..);
+   |                ^^^
+   |                |
+   |                expected reference, found struct `core::ops::RangeFrom`
+   |                help: consider borrowing here: `&(1..)`
+   |
+   = note: expected type `&_`
+              found type `core::ops::RangeFrom<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-std.rs:38:16
+   |
+LL |     take_range(..);
+   |                ^^
+   |                |
+   |                expected reference, found struct `core::ops::RangeFull`
+   |                help: consider borrowing here: `&(..)`
+   |
+   = note: expected type `&_`
+              found type `core::ops::RangeFull`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-std.rs:43:16
+   |
+LL |     take_range(0..=1);
+   |                ^^^^^
+   |                |
+   |                expected reference, found struct `core::ops::RangeInclusive`
+   |                help: consider borrowing here: `&(0..=1)`
+   |
+   = note: expected type `&_`
+              found type `core::ops::RangeInclusive<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-std.rs:48:16
+   |
+LL |     take_range(..5);
+   |                ^^^
+   |                |
+   |                expected reference, found struct `core::ops::RangeTo`
+   |                help: consider borrowing here: `&(..5)`
+   |
+   = note: expected type `&_`
+              found type `core::ops::RangeTo<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-std.rs:53:16
+   |
+LL |     take_range(..=42);
+   |                ^^^^^
+   |                |
+   |                expected reference, found struct `core::ops::RangeToInclusive`
+   |                help: consider borrowing here: `&(..=42)`
+   |
+   = note: expected type `&_`
+              found type `core::ops::RangeToInclusive<{integer}>`
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/range/issue-54505.fixed b/src/test/ui/range/issue-54505.fixed
new file mode 100644 (file)
index 0000000..f8298c0
--- /dev/null
@@ -0,0 +1,43 @@
+// run-rustfix
+
+// Regression test for #54505 - range borrowing suggestion had
+// incorrect syntax (missing parentheses).
+
+use std::ops::RangeBounds;
+
+
+// take a reference to any built-in range
+fn take_range(_r: &impl RangeBounds<i8>) {}
+
+
+fn main() {
+    take_range(&(0..1));
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(0..1)
+
+    take_range(&(1..));
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(1..)
+
+    take_range(&(..));
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(..)
+
+    take_range(&(0..=1));
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(0..=1)
+
+    take_range(&(..5));
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(..5)
+
+    take_range(&(..=42));
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(..=42)
+}
diff --git a/src/test/ui/range/issue-54505.rs b/src/test/ui/range/issue-54505.rs
new file mode 100644 (file)
index 0000000..0367325
--- /dev/null
@@ -0,0 +1,43 @@
+// run-rustfix
+
+// Regression test for #54505 - range borrowing suggestion had
+// incorrect syntax (missing parentheses).
+
+use std::ops::RangeBounds;
+
+
+// take a reference to any built-in range
+fn take_range(_r: &impl RangeBounds<i8>) {}
+
+
+fn main() {
+    take_range(0..1);
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(0..1)
+
+    take_range(1..);
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(1..)
+
+    take_range(..);
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(..)
+
+    take_range(0..=1);
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(0..=1)
+
+    take_range(..5);
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(..5)
+
+    take_range(..=42);
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(..=42)
+}
diff --git a/src/test/ui/range/issue-54505.stderr b/src/test/ui/range/issue-54505.stderr
new file mode 100644 (file)
index 0000000..d6e1fb0
--- /dev/null
@@ -0,0 +1,75 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-54505.rs:14:16
+   |
+LL |     take_range(0..1);
+   |                ^^^^
+   |                |
+   |                expected reference, found struct `std::ops::Range`
+   |                help: consider borrowing here: `&(0..1)`
+   |
+   = note: expected type `&_`
+              found type `std::ops::Range<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505.rs:19:16
+   |
+LL |     take_range(1..);
+   |                ^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeFrom`
+   |                help: consider borrowing here: `&(1..)`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeFrom<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505.rs:24:16
+   |
+LL |     take_range(..);
+   |                ^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeFull`
+   |                help: consider borrowing here: `&(..)`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeFull`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505.rs:29:16
+   |
+LL |     take_range(0..=1);
+   |                ^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeInclusive`
+   |                help: consider borrowing here: `&(0..=1)`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeInclusive<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505.rs:34:16
+   |
+LL |     take_range(..5);
+   |                ^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeTo`
+   |                help: consider borrowing here: `&(..5)`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeTo<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505.rs:39:16
+   |
+LL |     take_range(..=42);
+   |                ^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeToInclusive`
+   |                help: consider borrowing here: `&(..=42)`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeToInclusive<{integer}>`
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/union-ub-fat-ptr.rs b/src/test/ui/union-ub-fat-ptr.rs
deleted file mode 100644 (file)
index 0c42d28..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![allow(unused)]
-
-// normalize-stderr-test "alignment \d+" -> "alignment N"
-// normalize-stderr-test "offset \d+" -> "offset N"
-// normalize-stderr-test "allocation \d+" -> "allocation N"
-// normalize-stderr-test "size \d+" -> "size N"
-
-union BoolTransmute {
-  val: u8,
-  bl: bool,
-}
-
-#[repr(C)]
-#[derive(Copy, Clone)]
-struct SliceRepr {
-    ptr: *const u8,
-    len: usize,
-}
-
-#[repr(C)]
-#[derive(Copy, Clone)]
-struct BadSliceRepr {
-    ptr: *const u8,
-    len: &'static u8,
-}
-
-union SliceTransmute {
-    repr: SliceRepr,
-    bad: BadSliceRepr,
-    slice: &'static [u8],
-    str: &'static str,
-    my_str: &'static MyStr,
-    my_slice: &'static MySliceBool,
-}
-
-#[repr(C)]
-#[derive(Copy, Clone)]
-struct DynRepr {
-    ptr: *const u8,
-    vtable: *const u8,
-}
-
-#[repr(C)]
-#[derive(Copy, Clone)]
-struct DynRepr2 {
-    ptr: *const u8,
-    vtable: *const u64,
-}
-
-#[repr(C)]
-#[derive(Copy, Clone)]
-struct BadDynRepr {
-    ptr: *const u8,
-    vtable: usize,
-}
-
-union DynTransmute {
-    repr: DynRepr,
-    repr2: DynRepr2,
-    bad: BadDynRepr,
-    rust: &'static Trait,
-}
-
-trait Trait {}
-impl Trait for bool {}
-
-// custom unsized type
-struct MyStr(str);
-
-// custom unsized type with sized fields
-struct MySlice<T: ?Sized>(bool, T);
-type MySliceBool = MySlice<[bool]>;
-
-// OK
-const A: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 1 } }.str};
-// bad str
-const B: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.str};
-//~^ ERROR this constant likely exhibits undefined behavior
-// bad str
-const C: &str = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.str};
-//~^ ERROR this constant likely exhibits undefined behavior
-// bad str in user-defined unsized type
-const C2: &MyStr = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.my_str};
-//~^ ERROR this constant likely exhibits undefined behavior
-
-// OK
-const A2: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 1 } }.slice};
-// bad slice
-const B2: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.slice};
-//~^ ERROR this constant likely exhibits undefined behavior
-// bad slice
-const C3: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.slice};
-//~^ ERROR this constant likely exhibits undefined behavior
-
-// bad trait object
-const D: &Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust};
-//~^ ERROR this constant likely exhibits undefined behavior
-// bad trait object
-const E: &Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust};
-//~^ ERROR this constant likely exhibits undefined behavior
-// bad trait object
-const F: &Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust};
-//~^ ERROR this constant likely exhibits undefined behavior
-
-// bad data *inside* the trait object
-const G: &Trait = &unsafe { BoolTransmute { val: 3 }.bl };
-//~^ ERROR this constant likely exhibits undefined behavior
-// bad data *inside* the slice
-const H: &[bool] = &[unsafe { BoolTransmute { val: 3 }.bl }];
-//~^ ERROR this constant likely exhibits undefined behavior
-
-// good MySliceBool
-const I1: &MySliceBool = &MySlice(true, [false]);
-// bad: sized field is not okay
-const I2: &MySliceBool = &MySlice(unsafe { BoolTransmute { val: 3 }.bl }, [false]);
-//~^ ERROR this constant likely exhibits undefined behavior
-// bad: unsized part is not okay
-const I3: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }.bl }]);
-//~^ ERROR this constant likely exhibits undefined behavior
-
-// invalid UTF-8
-const J1: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str };
-//~^ ERROR this constant likely exhibits undefined behavior
-// invalid UTF-8 in user-defined str-like
-const J2: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str };
-//~^ ERROR this constant likely exhibits undefined behavior
-
-fn main() {
-}
diff --git a/src/test/ui/union-ub-fat-ptr.stderr b/src/test/ui/union-ub-fat-ptr.stderr
deleted file mode 100644 (file)
index 5d817dc..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-error[E0080]: this constant likely exhibits undefined behavior
-  --> $DIR/union-ub-fat-ptr.rs:87:1
-   |
-LL | const B: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.str};
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or out-of-bounds memory at .<deref>
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
-
-error[E0080]: this constant likely exhibits undefined behavior
-  --> $DIR/union-ub-fat-ptr.rs:90:1
-   |
-LL | const C: &str = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.str};
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in fat pointer
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
-
-error[E0080]: this constant likely exhibits undefined behavior
-  --> $DIR/union-ub-fat-ptr.rs:93:1
-   |
-LL | const C2: &MyStr = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.my_str};
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in fat pointer
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
-
-error[E0080]: this constant likely exhibits undefined behavior
-  --> $DIR/union-ub-fat-ptr.rs:99:1
-   |
-LL | const B2: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.slice};
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or out-of-bounds memory at .<deref>[1]
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
-
-error[E0080]: this constant likely exhibits undefined behavior
-  --> $DIR/union-ub-fat-ptr.rs:102:1
-   |
-LL | const C3: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.slice};
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in fat pointer
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
-
-error[E0080]: this constant likely exhibits undefined behavior
-  --> $DIR/union-ub-fat-ptr.rs:106:1
-   |
-LL | const D: &Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust};
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid vtable in fat pointer at .<deref>
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
-
-error[E0080]: this constant likely exhibits undefined behavior
-  --> $DIR/union-ub-fat-ptr.rs:109:1
-   |
-LL | const E: &Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust};
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid vtable in fat pointer at .<deref>
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
-
-error[E0080]: this constant likely exhibits undefined behavior
-  --> $DIR/union-ub-fat-ptr.rs:112:1
-   |
-LL | const F: &Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust};
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-pointer vtable in fat pointer
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
-
-error[E0080]: this constant likely exhibits undefined behavior
-  --> $DIR/union-ub-fat-ptr.rs:116:1
-   |
-LL | const G: &Trait = &unsafe { BoolTransmute { val: 3 }.bl };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>, but expected something in the range 0..=1
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
-
-error[E0080]: this constant likely exhibits undefined behavior
-  --> $DIR/union-ub-fat-ptr.rs:119:1
-   |
-LL | const H: &[bool] = &[unsafe { BoolTransmute { val: 3 }.bl }];
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>[0], but expected something in the range 0..=1
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
-
-error[E0080]: this constant likely exhibits undefined behavior
-  --> $DIR/union-ub-fat-ptr.rs:125:1
-   |
-LL | const I2: &MySliceBool = &MySlice(unsafe { BoolTransmute { val: 3 }.bl }, [false]);
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>.0, but expected something in the range 0..=1
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
-
-error[E0080]: this constant likely exhibits undefined behavior
-  --> $DIR/union-ub-fat-ptr.rs:128:1
-   |
-LL | const I3: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }.bl }]);
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>.1[0], but expected something in the range 0..=1
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
-
-error[E0080]: this constant likely exhibits undefined behavior
-  --> $DIR/union-ub-fat-ptr.rs:132:1
-   |
-LL | const J1: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-UTF-8 data in str at .<deref>
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
-
-error[E0080]: this constant likely exhibits undefined behavior
-  --> $DIR/union-ub-fat-ptr.rs:135:1
-   |
-LL | const J2: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-UTF-8 data in str at .<deref>.0
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
-
-error: aborting due to 14 previous errors
-
-For more information about this error, try `rustc --explain E0080`.
index a4d839275c3ebc4bb5f8da11c6b21ce41dd2461a..7006fb9427e1cec2332ee8d4afa2e9d7fcc9c249 100644 (file)
@@ -205,6 +205,9 @@ pub struct Config {
     /// Version of LLDB
     pub lldb_version: Option<String>,
 
+    /// Whether LLDB has native rust support
+    pub lldb_native_rust: bool,
+
     /// Version of LLVM
     pub llvm_version: Option<String>,
 
index 8829d8808366b87f027b2c6df347e800966773f0..688f2babe6e8c2c570306107660cd54db7128269 100644 (file)
@@ -133,6 +133,8 @@ fn ignore_lldb(config: &Config, line: &str) -> bool {
                     // Ignore if actual version is smaller the minimum required
                     // version
                     lldb_version_to_int(actual_version) < lldb_version_to_int(min_version)
+                } else if line.starts_with("rust-lldb") && !config.lldb_native_rust {
+                    true
                 } else {
                     false
                 }
index 2fa459bec9455d930b8f5d3176078fba774e2d1c..f46e031d768bd9f6284175d9fe0d9f5345b2baef 100644 (file)
@@ -282,6 +282,7 @@ fn make_absolute(path: PathBuf) -> PathBuf {
     let android_cross_path = opt_path(matches, "android-cross-path");
     let (gdb, gdb_version, gdb_native_rust) = analyze_gdb(matches.opt_str("gdb"), &target,
                                                           &android_cross_path);
+    let (lldb_version, lldb_native_rust) = extract_lldb_version(matches.opt_str("lldb-version"));
 
     let color = match matches.opt_str("color").as_ref().map(|x| &**x) {
         Some("auto") | None => ColorConfig::AutoColor,
@@ -326,7 +327,8 @@ fn make_absolute(path: PathBuf) -> PathBuf {
         gdb,
         gdb_version,
         gdb_native_rust,
-        lldb_version: extract_lldb_version(matches.opt_str("lldb-version")),
+        lldb_version,
+        lldb_native_rust,
         llvm_version: matches.opt_str("llvm-version"),
         system_llvm: matches.opt_present("system-llvm"),
         android_cross_path: android_cross_path,
@@ -906,17 +908,27 @@ fn extract_gdb_version(full_version_line: &str) -> Option<u32> {
     None
 }
 
-fn extract_lldb_version(full_version_line: Option<String>) -> Option<String> {
+/// Returns (LLDB version, LLDB is rust-enabled)
+fn extract_lldb_version(full_version_line: Option<String>) -> (Option<String>, bool) {
     // Extract the major LLDB version from the given version string.
     // LLDB version strings are different for Apple and non-Apple platforms.
-    // At the moment, this function only supports the Apple variant, which looks
-    // like this:
+    // The Apple variant looks like this:
     //
     // LLDB-179.5 (older versions)
     // lldb-300.2.51 (new versions)
     //
     // We are only interested in the major version number, so this function
     // will return `Some("179")` and `Some("300")` respectively.
+    //
+    // Upstream versions look like:
+    // lldb version 6.0.1
+    //
+    // There doesn't seem to be a way to correlate the Apple version
+    // with the upstream version, and since the tests were originally
+    // written against Apple versions, we make a fake Apple version by
+    // multiplying the first number by 100.  This is a hack, but
+    // normally fine because the only non-Apple version we test is
+    // rust-enabled.
 
     if let Some(ref full_version_line) = full_version_line {
         if !full_version_line.trim().is_empty() {
@@ -951,12 +963,22 @@ fn extract_lldb_version(full_version_line: Option<String>) -> Option<String> {
                     .take_while(|c| c.is_digit(10))
                     .collect::<String>();
                 if !vers.is_empty() {
-                    return Some(vers);
+                    return (Some(vers), full_version_line.contains("rust-enabled"));
+                }
+            }
+
+            if full_version_line.starts_with("lldb version ") {
+                let vers = full_version_line[13..]
+                    .chars()
+                    .take_while(|c| c.is_digit(10))
+                    .collect::<String>();
+                if !vers.is_empty() {
+                    return (Some(vers + "00"), full_version_line.contains("rust-enabled"));
                 }
             }
         }
     }
-    None
+    (None, false)
 }
 
 fn is_blacklisted_lldb_version(version: &str) -> bool {
index 63a282c227c246b764ccb46abaaaceb747993fe2..4cb6f6b83bdd10e40a1ce0f576acdf109e85688f 100644 (file)
@@ -945,13 +945,23 @@ fn run_debuginfo_lldb_test_no_opt(&self) {
             }
         }
 
+        let prefixes = if self.config.lldb_native_rust {
+            static PREFIXES: &'static [&'static str] = &["lldb", "lldbr"];
+            println!("NOTE: compiletest thinks it is using LLDB with native rust support");
+            PREFIXES
+        } else {
+            static PREFIXES: &'static [&'static str] = &["lldb", "lldbg"];
+            println!("NOTE: compiletest thinks it is using LLDB without native rust support");
+            PREFIXES
+        };
+
         // Parse debugger commands etc from test files
         let DebuggerCommands {
             commands,
             check_lines,
             breakpoint_lines,
             ..
-        } = self.parse_debugger_commands(&["lldb"]);
+        } = self.parse_debugger_commands(prefixes);
 
         // Write debugger script:
         // We don't want to hang when calling `quit` while the process is still running
index e8f6973e2d40ab39e30cdbe0cf8e77a72c867d4f..cc275c63a90d4bea394e76607b2e10611eb1be36 160000 (submodule)
@@ -1 +1 @@
-Subproject commit e8f6973e2d40ab39e30cdbe0cf8e77a72c867d4f
+Subproject commit cc275c63a90d4bea394e76607b2e10611eb1be36