diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 594550dd967a..ec7c49464abd 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -906,6 +906,52 @@ pub trait PrettyPrinter<'tcx>: let u8 = self.tcx().types.u8; + if let ty::Ref(_, ref_ty, _) = ty.kind { + // &str is a special case of references, and should override the general case, so we + // check for and handle that first. + + let byte_str = match (ct, &ref_ty.kind) { + (ConstValue::Scalar(Scalar::Ptr(ptr)), ty::Array(t, n)) if *t == u8 => { + let n = n.eval_usize(self.tcx(), ty::ParamEnv::empty()); + Some(self.tcx() + .alloc_map.lock() + .unwrap_memory(ptr.alloc_id) + .get_bytes(&self.tcx(), ptr, Size::from_bytes(n)).unwrap()) + }, + (ConstValue::Slice { data, start, end }, ty::Slice(t)) if *t == u8 => { + // The `inspect` here is okay since we checked the bounds, and there are + // no relocations (we have an active slice reference here). We don't use + // this result to affect interpreter execution. + Some(data.inspect_with_undef_and_ptr_outside_interpreter(start..end)) + }, + _ => None, + }; + + if let Some(byte_str) = byte_str { + p!(write("b\"")); + for &c in byte_str { + for e in std::ascii::escape_default(c) { + self.write_char(e as char)?; + } + } + p!(write("\"")); + return Ok(self); + } + + if let (ConstValue::Slice { data, start, end }, ty::Str) = + (ct, &ref_ty.kind) + { + // The `inspect` here is okay since we checked the bounds, and there are no + // relocations (we have an active `str` reference here). We don't use this + // result to affect interpreter execution. + let slice = data.inspect_with_undef_and_ptr_outside_interpreter(start..end); + let s = ::std::str::from_utf8(slice) + .expect("non utf8 str from miri"); + p!(write("{:?}", s)); + return Ok(self); + } + }; + match (ct, &ty.kind) { (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Bool) => p!(write("{}", if data == 0 { "false" } else { "true" })), @@ -943,7 +989,18 @@ pub trait PrettyPrinter<'tcx>: }, (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Char) => p!(write("{:?}", ::std::char::from_u32(data as u32).unwrap())), - (ConstValue::Scalar(_), ty::RawPtr(_)) => p!(write("{{pointer}}")), + (ConstValue::Scalar(value), ty::Ref(..)) | + (ConstValue::Scalar(value), ty::RawPtr(_)) => { + // &str should already have been handled, so this is a general representation of a + // reference. + match value { + Scalar::Raw { data, size } => { + p!(write("0x{:01$x} : ", data, size as usize * 2)); + } + _ => p!(write("{{pointer}} : ")) + }; + p!(print(ty)); + } (ConstValue::Scalar(Scalar::Ptr(ptr)), ty::FnPtr(_)) => { let instance = { let alloc_map = self.tcx().alloc_map.lock(); @@ -952,54 +1009,8 @@ pub trait PrettyPrinter<'tcx>: p!(print_value_path(instance.def_id(), instance.substs)); }, _ => { - let printed = if let ty::Ref(_, ref_ty, _) = ty.kind { - let byte_str = match (ct, &ref_ty.kind) { - (ConstValue::Scalar(Scalar::Ptr(ptr)), ty::Array(t, n)) if *t == u8 => { - let n = n.eval_usize(self.tcx(), ty::ParamEnv::empty()); - Some(self.tcx() - .alloc_map.lock() - .unwrap_memory(ptr.alloc_id) - .get_bytes(&self.tcx(), ptr, Size::from_bytes(n)).unwrap()) - }, - (ConstValue::Slice { data, start, end }, ty::Slice(t)) if *t == u8 => { - // The `inspect` here is okay since we checked the bounds, and there are - // no relocations (we have an active slice reference here). We don't use - // this result to affect interpreter execution. - Some(data.inspect_with_undef_and_ptr_outside_interpreter(start..end)) - }, - _ => None, - }; - - if let Some(byte_str) = byte_str { - p!(write("b\"")); - for &c in byte_str { - for e in std::ascii::escape_default(c) { - self.write_char(e as char)?; - } - } - p!(write("\"")); - true - } else if let (ConstValue::Slice { data, start, end }, ty::Str) = - (ct, &ref_ty.kind) - { - // The `inspect` here is okay since we checked the bounds, and there are no - // relocations (we have an active `str` reference here). We don't use this - // result to affect interpreter execution. - let slice = data.inspect_with_undef_and_ptr_outside_interpreter(start..end); - let s = ::std::str::from_utf8(slice) - .expect("non utf8 str from miri"); - p!(write("{:?}", s)); - true - } else { - false - } - } else { - false - }; - if !printed { - // fallback - p!(write("{:?} : ", ct), print(ty)) - } + // fallback + p!(write("{:?} : ", ct), print(ty)) } }; Ok(self) diff --git a/src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs b/src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs index 34d4a534ad9f..d2636299d3e2 100644 --- a/src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs +++ b/src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs @@ -23,8 +23,8 @@ fn main() { // START rustc.main.ConstProp.after.mir // bb0: { // ... -// _4 = const Scalar(AllocId(1).0x0) : &i32; -// _3 = const Scalar(AllocId(1).0x0) : &i32; +// _4 = const {pointer} : &i32; +// _3 = const {pointer} : &i32; // _2 = const Value(Scalar(AllocId(1).0x0)) : *const i32; // ... // _1 = move _2 as usize (Misc); diff --git a/src/test/mir-opt/const_prop/ref_deref.rs b/src/test/mir-opt/const_prop/ref_deref.rs index 2d04822c0e78..e92fe98761f9 100644 --- a/src/test/mir-opt/const_prop/ref_deref.rs +++ b/src/test/mir-opt/const_prop/ref_deref.rs @@ -14,7 +14,7 @@ fn main() { // START rustc.main.ConstProp.after.mir // bb0: { // ... -// _2 = const Scalar(AllocId(0).0x0) : &i32; +// _2 = const {pointer} : &i32; // _1 = const 4i32; // ... // } diff --git a/src/test/mir-opt/const_prop/slice_len.rs b/src/test/mir-opt/const_prop/slice_len.rs index 05595ce147c9..cae66f7994aa 100644 --- a/src/test/mir-opt/const_prop/slice_len.rs +++ b/src/test/mir-opt/const_prop/slice_len.rs @@ -24,8 +24,8 @@ fn main() { // START rustc.main.ConstProp.after.mir // bb0: { // ... -// _4 = const Scalar(AllocId(0).0x0) : &[u32; 3]; -// _3 = const Scalar(AllocId(0).0x0) : &[u32; 3]; +// _4 = const {pointer} : &[u32; 3]; +// _3 = const {pointer} : &[u32; 3]; // _2 = move _3 as &[u32] (Pointer(Unsize)); // ... // _6 = const 1usize; diff --git a/src/test/ui/const-generics/int-as-ref-const-param.rs b/src/test/ui/const-generics/int-as-ref-const-param.rs new file mode 100644 index 000000000000..539b86b30a4b --- /dev/null +++ b/src/test/ui/const-generics/int-as-ref-const-param.rs @@ -0,0 +1,26 @@ +// normalize-stderr-32bit: "0x" -> "$$PREFIX" +// normalize-stderr-64bit: "0x00000000" -> "$$PREFIX" + +#![feature(const_generics, const_compare_raw_pointers)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +struct Const; + +#[repr(C)] +union Transmuter { + pointer: *const (), + reference: &'static (), +} + +fn main() { + const A: &'static () = { + unsafe { Transmuter { pointer: 10 as *const () }.reference } + }; + const B: &'static () = { + unsafe { Transmuter { pointer: 11 as *const () }.reference } + }; + + let _: Const<{A}> = Const::<{B}>; //~ mismatched types + let _: Const<{A}> = Const::<{&()}>; //~ mismatched types + let _: Const<{A}> = Const::<{A}>; +} diff --git a/src/test/ui/const-generics/int-as-ref-const-param.stderr b/src/test/ui/const-generics/int-as-ref-const-param.stderr new file mode 100644 index 000000000000..4a9ab615601d --- /dev/null +++ b/src/test/ui/const-generics/int-as-ref-const-param.stderr @@ -0,0 +1,29 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/int-as-ref-const-param.rs:4:12 + | +LL | #![feature(const_generics, const_compare_raw_pointers)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + +error[E0308]: mismatched types + --> $DIR/int-as-ref-const-param.rs:23:25 + | +LL | let _: Const<{A}> = Const::<{B}>; + | ^^^^^^^^^^^^ expected `$PREFIX0000000a : &()`, found `$PREFIX0000000b : &()` + | + = note: expected type `Const<$PREFIX0000000a : &()>` + found type `Const<$PREFIX0000000b : &()>` + +error[E0308]: mismatched types + --> $DIR/int-as-ref-const-param.rs:24:25 + | +LL | let _: Const<{A}> = Const::<{&()}>; + | ^^^^^^^^^^^^^^ expected `$PREFIX0000000a : &()`, found `{pointer} : &()` + | + = note: expected type `Const<$PREFIX0000000a : &()>` + found type `Const<{pointer} : &()>` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/const-generics/raw-ptr-const-param.rs b/src/test/ui/const-generics/raw-ptr-const-param.rs index f69c37fbb8f3..fd494daa85b0 100644 --- a/src/test/ui/const-generics/raw-ptr-const-param.rs +++ b/src/test/ui/const-generics/raw-ptr-const-param.rs @@ -1,3 +1,6 @@ +// normalize-stderr-32bit: "0x" -> "$$PREFIX" +// normalize-stderr-64bit: "0x00000000" -> "$$PREFIX" + #![feature(const_generics, const_compare_raw_pointers)] //~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash @@ -6,4 +9,6 @@ struct Const; fn main() { let _: Const<{15 as *const _}> = Const::<{10 as *const _}>; //~ mismatched types let _: Const<{10 as *const _}> = Const::<{10 as *const _}>; + + let _: Const<{10 as *const _}> = Const::<{&8_u32 as *const _}>; //~ mismatched types } diff --git a/src/test/ui/const-generics/raw-ptr-const-param.stderr b/src/test/ui/const-generics/raw-ptr-const-param.stderr index 75b4c0a0a3de..47e9cd534b3a 100644 --- a/src/test/ui/const-generics/raw-ptr-const-param.stderr +++ b/src/test/ui/const-generics/raw-ptr-const-param.stderr @@ -1,5 +1,5 @@ warning: the feature `const_generics` is incomplete and may cause the compiler to crash - --> $DIR/raw-ptr-const-param.rs:1:12 + --> $DIR/raw-ptr-const-param.rs:4:12 | LL | #![feature(const_generics, const_compare_raw_pointers)] | ^^^^^^^^^^^^^^ @@ -7,14 +7,23 @@ LL | #![feature(const_generics, const_compare_raw_pointers)] = note: `#[warn(incomplete_features)]` on by default error[E0308]: mismatched types - --> $DIR/raw-ptr-const-param.rs:7:38 + --> $DIR/raw-ptr-const-param.rs:10:38 | LL | let _: Const<{15 as *const _}> = Const::<{10 as *const _}>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{pointer}`, found `{pointer}` + | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `$PREFIX0000000f : *const u32`, found `$PREFIX0000000a : *const u32` | - = note: expected type `Const<{pointer}>` - found type `Const<{pointer}>` + = note: expected type `Const<$PREFIX0000000f : *const u32>` + found type `Const<$PREFIX0000000a : *const u32>` -error: aborting due to previous error +error[E0308]: mismatched types + --> $DIR/raw-ptr-const-param.rs:13:38 + | +LL | let _: Const<{10 as *const _}> = Const::<{&8_u32 as *const _}>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `$PREFIX0000000a : *const u32`, found `{pointer} : *const u32` + | + = note: expected type `Const<$PREFIX0000000a : *const u32>` + found type `Const<{pointer} : *const u32>` + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0308`.