Skip to content

Print the two types in the span label for transmute errors. #42304

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 23, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/librustc/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1631,7 +1631,7 @@ fn takes_u8(_: u8) {}

fn main() {
unsafe { takes_u8(::std::mem::transmute(0u16)); }
// error: transmute called with differently sized types
// error: transmute called with types of different sizes
}
```

Expand Down
26 changes: 10 additions & 16 deletions src/librustc/middle/intrinsicck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,17 +86,16 @@ impl<'a, 'tcx> ExprVisitor<'a, 'tcx> {
// Special-case transmutting from `typeof(function)` and
// `Option<typeof(function)>` to present a clearer error.
let from = unpack_option_like(self.tcx.global_tcx(), from);
match (&from.sty, sk_to) {
(&ty::TyFnDef(..), SizeSkeleton::Known(size_to))
if size_to == Pointer.size(self.tcx) => {
if let (&ty::TyFnDef(..), SizeSkeleton::Known(size_to)) = (&from.sty, sk_to) {
if size_to == Pointer.size(self.tcx) {
struct_span_err!(self.tcx.sess, span, E0591,
"`{}` is zero-sized and can't be transmuted to `{}`",
from, to)
.span_note(span, "cast with `as` to a pointer instead")
"can't transmute zero-sized type")
.note(&format!("source type: {}", from))
.note(&format!("target type: {}", to))
.help("cast with `as` to a pointer instead")
.emit();
return;
}
_ => {}
}
}

Expand All @@ -111,7 +110,7 @@ impl<'a, 'tcx> ExprVisitor<'a, 'tcx> {
}
Err(LayoutError::Unknown(bad)) => {
if bad == ty {
format!("size can vary")
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if there's much point to this branch myself; I can't come up with an example that would follow it.

format!("this type's size can vary")
} else {
format!("size can vary because of {}", bad)
}
Expand All @@ -121,14 +120,9 @@ impl<'a, 'tcx> ExprVisitor<'a, 'tcx> {
};

struct_span_err!(self.tcx.sess, span, E0512,
"transmute called with differently sized types: \
{} ({}) to {} ({})",
from, skeleton_string(from, sk_from),
to, skeleton_string(to, sk_to))
.span_label(span,
format!("transmuting between {} and {}",
skeleton_string(from, sk_from),
skeleton_string(to, sk_to)))
"transmute called with types of different sizes")
.note(&format!("source type: {} ({})", from, skeleton_string(from, sk_from)))
.note(&format!("target type: {} ({})", to, skeleton_string(to, sk_to)))
.emit();
}
}
Expand Down
1 change: 0 additions & 1 deletion src/test/compile-fail/E0512.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,4 @@ fn takes_u8(_: u8) {}

fn main() {
unsafe { takes_u8(::std::mem::transmute(0u16)); } //~ ERROR E0512
//~| transmuting between 16 bits and 8 bits
}
2 changes: 1 addition & 1 deletion src/test/compile-fail/issue-21174.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ trait Trait<'a> {

fn foo<'a, T: Trait<'a>>(value: T::A) {
let new: T::B = unsafe { std::mem::transmute(value) };
//~^ ERROR: transmute called with differently sized types
//~^ ERROR: transmute called with types of different sizes
}

fn main() { }
2 changes: 1 addition & 1 deletion src/test/compile-fail/issue-28625.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ struct ArrayPeano<T: Bar> {
}

fn foo<T>(a: &ArrayPeano<T>) -> &[T] where T: Bar {
unsafe { std::mem::transmute(a) } //~ ERROR transmute called with differently sized types
unsafe { std::mem::transmute(a) } //~ ERROR transmute called with types of different sizes
}

impl Bar for () {
Expand Down
2 changes: 1 addition & 1 deletion src/test/compile-fail/issue-32377.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ struct Bar<U: Foo> {

fn foo<U: Foo>(x: [usize; 2]) -> Bar<U> {
unsafe { mem::transmute(x) }
//~^ ERROR transmute called with differently sized types
//~^ ERROR transmute called with types of different sizes
}

fn main() {}
2 changes: 1 addition & 1 deletion src/test/compile-fail/packed-struct-generic-transmute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
// the error points to the start of the file, not the line with the
// transmute

// error-pattern: transmute called with differently sized types
// error-pattern: transmute called with types of different sizes

use std::mem;

Expand Down
2 changes: 1 addition & 1 deletion src/test/compile-fail/packed-struct-transmute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
// the error points to the start of the file, not the line with the
// transmute

// error-pattern: transmute called with differently sized types
// error-pattern: transmute called with types of different sizes

use std::mem;

Expand Down
6 changes: 3 additions & 3 deletions src/test/compile-fail/transmute-different-sizes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ use std::mem::transmute;

unsafe fn f() {
let _: i8 = transmute(16i16);
//~^ ERROR transmute called with differently sized types
//~^ ERROR transmute called with types of different sizes
}

unsafe fn g<T>(x: &T) {
let _: i8 = transmute(x);
//~^ ERROR transmute called with differently sized types
//~^ ERROR transmute called with types of different sizes
}

trait Specializable { type Output; }
Expand All @@ -33,7 +33,7 @@ impl<T> Specializable for T {

unsafe fn specializable<T>(x: u16) -> <T as Specializable>::Output {
transmute(x)
//~^ ERROR transmute called with differently sized types
//~^ ERROR transmute called with types of different sizes
}

fn main() {}
8 changes: 4 additions & 4 deletions src/test/compile-fail/transmute-fat-pointers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@
use std::mem::transmute;

fn a<T, U: ?Sized>(x: &[T]) -> &U {
unsafe { transmute(x) } //~ ERROR transmute called with differently sized types
unsafe { transmute(x) } //~ ERROR transmute called with types of different sizes
}

fn b<T: ?Sized, U: ?Sized>(x: &T) -> &U {
unsafe { transmute(x) } //~ ERROR transmute called with differently sized types
unsafe { transmute(x) } //~ ERROR transmute called with types of different sizes
}

fn c<T, U>(x: &T) -> &U {
Expand All @@ -31,11 +31,11 @@ fn d<T, U>(x: &[T]) -> &[U] {
}

fn e<T: ?Sized, U>(x: &T) -> &U {
unsafe { transmute(x) } //~ ERROR transmute called with differently sized types
unsafe { transmute(x) } //~ ERROR transmute called with types of different sizes
}

fn f<T, U: ?Sized>(x: &T) -> &U {
unsafe { transmute(x) } //~ ERROR transmute called with differently sized types
unsafe { transmute(x) } //~ ERROR transmute called with types of different sizes
}

fn main() { }
2 changes: 1 addition & 1 deletion src/test/compile-fail/transmute-impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ impl<T: ?Sized> Foo<T> {

fn n(x: &T) -> &isize {
// Not OK here, because T : Sized is not in scope.
unsafe { transmute(x) } //~ ERROR transmute called with differently sized types
unsafe { transmute(x) } //~ ERROR transmute called with types of different sizes
}
}

Expand Down
42 changes: 42 additions & 0 deletions src/test/ui/transmute/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright 2017 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.

// ignore-x86
// ignore-arm
// ignore-emscripten
// ignore 32-bit platforms (test output is different)

#![feature(untagged_unions)]
use std::mem::transmute;

pub trait TypeConstructor<'a> {
type T;
}

unsafe fn transmute_lifetime<'a, 'b, C>(x: <C as TypeConstructor<'a>>::T)
-> <C as TypeConstructor<'b>>::T
where for<'z> C: TypeConstructor<'z> {
transmute(x) //~ ERROR transmute called with types of different sizes
}

unsafe fn sizes() {
let x: u8 = transmute(10u16); //~ ERROR transmute called with types of different sizes
}

unsafe fn ptrs() {
let x: u8 = transmute("test"); //~ ERROR transmute called with types of different sizes
}

union Foo { x: () }
unsafe fn vary() {
let x: Foo = transmute(10); //~ ERROR transmute called with types of different sizes
}

fn main() {}
38 changes: 38 additions & 0 deletions src/test/ui/transmute/main.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
error[E0512]: transmute called with types of different sizes
--> $DIR/main.rs:26:5
|
26 | transmute(x) //~ ERROR transmute called with types of different sizes
| ^^^^^^^^^
|
= note: source type: <C as TypeConstructor<'a>>::T (size can vary because of <C as TypeConstructor>::T)
= note: target type: <C as TypeConstructor<'b>>::T (size can vary because of <C as TypeConstructor>::T)

error[E0512]: transmute called with types of different sizes
--> $DIR/main.rs:30:17
|
30 | let x: u8 = transmute(10u16); //~ ERROR transmute called with types of different sizes
| ^^^^^^^^^
|
= note: source type: u16 (16 bits)
= note: target type: u8 (8 bits)

error[E0512]: transmute called with types of different sizes
--> $DIR/main.rs:34:17
|
34 | let x: u8 = transmute("test"); //~ ERROR transmute called with types of different sizes
| ^^^^^^^^^
|
= note: source type: &str (128 bits)
= note: target type: u8 (8 bits)

error[E0512]: transmute called with types of different sizes
--> $DIR/main.rs:39:18
|
39 | let x: Foo = transmute(10); //~ ERROR transmute called with types of different sizes
| ^^^^^^^^^
|
= note: source type: i32 (32 bits)
= note: target type: Foo (0 bits)

error: aborting due to previous error(s)

Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,14 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// ignore-x86
// ignore-arm
// ignore-emscripten
// ignore 32-bit platforms (test output is different)

use std::mem;

unsafe fn foo() -> (isize, *const (), Option<fn()>) {
unsafe fn foo() -> (i32, *const (), Option<fn()>) {
let i = mem::transmute(bar);
//~^ ERROR is zero-sized and can't be transmuted
//~^^ NOTE cast with `as` to a pointer instead
Expand All @@ -29,8 +34,8 @@ unsafe fn foo() -> (isize, *const (), Option<fn()>) {
unsafe fn bar() {
// Error as usual if the resulting type is not pointer-sized.
mem::transmute::<_, u8>(main);
//~^ ERROR transmute called with differently sized types
//~^^ NOTE transmuting between 0 bits and 8 bits
//~^ ERROR transmute called with types of different sizes
//~^^ NOTE transmuting between fn() {main} and u8

mem::transmute::<_, *mut ()>(foo);
//~^ ERROR is zero-sized and can't be transmuted
Expand All @@ -41,7 +46,7 @@ unsafe fn bar() {
//~^^ NOTE cast with `as` to a pointer instead

// No error if a coercion would otherwise occur.
mem::transmute::<fn(), usize>(main);
mem::transmute::<fn(), u32>(main);
}

unsafe fn baz() {
Expand All @@ -58,7 +63,7 @@ unsafe fn baz() {
//~^^ NOTE cast with `as` to a pointer instead

// No error if a coercion would otherwise occur.
mem::transmute::<Option<fn()>, usize>(Some(main));
mem::transmute::<Option<fn()>, u32>(Some(main));
}

fn main() {
Expand Down
Loading