Skip to content

Commit

Permalink
Rollup merge of rust-lang#42304 - Mark-Simulacrum:issue-37157, r=niko…
Browse files Browse the repository at this point in the history
…matsakis

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

Fixes rust-lang#37157. I'm not entirely happy with the changes here but overall it's better in my opinion; we certainly avoid the odd language in that issue, which changes to:

```
error[E0512]: transmute called with differently sized types: <C as TypeConstructor<'a>>::T (size can vary because of <C as TypeConstructor>::T) to <C as TypeConstructor<'b>>::T (size can vary because of <C as TypeConstructor>::T)
 --> test.rs:8:5
  |
8 |     ::std::mem::transmute(x)
  |     ^^^^^^^^^^^^^^^^^^^^^ transmuting between <C as TypeConstructor<'a>>::T and <C as TypeConstructor<'b>>::T

error: aborting due to previous error(s)
```
  • Loading branch information
Mark-Simulacrum committed Jun 5, 2017
2 parents 13eb0ec + 7898f41 commit 6836562
Show file tree
Hide file tree
Showing 17 changed files with 282 additions and 49 deletions.
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")
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
36 changes: 36 additions & 0 deletions src/test/ui/transmute/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// 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.
#![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:20:5
|
20 | 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:24:17
|
24 | 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:28:17
|
28 | 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:33:18
|
33 | 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,11 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// ignore-x86 fn() has different sizes dependent on platform

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 +31,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 +43,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 +60,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
108 changes: 108 additions & 0 deletions src/test/ui/transmute/transmute-from-fn-item-types-error.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
error[E0512]: transmute called with types of different sizes
--> $DIR/transmute-from-fn-item-types-error.rs:16:13
|
16 | let i = mem::transmute(bar);
| ^^^^^^^^^^^^^^
|
= note: source type: unsafe fn() {bar} (0 bits)
= note: target type: i32 (32 bits)

error[E0591]: can't transmute zero-sized type
--> $DIR/transmute-from-fn-item-types-error.rs:20:13
|
20 | let p = mem::transmute(foo);
| ^^^^^^^^^^^^^^
|
= note: source type: unsafe fn() -> (i32, *const (), std::option::Option<fn()>) {foo}
= note: target type: *const ()
= help: cast with `as` to a pointer instead

error[E0591]: can't transmute zero-sized type
--> $DIR/transmute-from-fn-item-types-error.rs:24:14
|
24 | let of = mem::transmute(main);
| ^^^^^^^^^^^^^^
|
= note: source type: fn() {main}
= note: target type: std::option::Option<fn()>
= help: cast with `as` to a pointer instead

error[E0512]: transmute called with types of different sizes
--> $DIR/transmute-from-fn-item-types-error.rs:33:5
|
33 | mem::transmute::<_, u8>(main);
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= note: source type: fn() {main} (0 bits)
= note: target type: u8 (8 bits)

error[E0591]: can't transmute zero-sized type
--> $DIR/transmute-from-fn-item-types-error.rs:37:5
|
37 | mem::transmute::<_, *mut ()>(foo);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: source type: unsafe fn() -> (i32, *const (), std::option::Option<fn()>) {foo}
= note: target type: *mut ()
= help: cast with `as` to a pointer instead

error[E0591]: can't transmute zero-sized type
--> $DIR/transmute-from-fn-item-types-error.rs:41:5
|
41 | mem::transmute::<_, fn()>(bar);
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: source type: unsafe fn() {bar}
= note: target type: fn()
= help: cast with `as` to a pointer instead

error[E0512]: transmute called with types of different sizes
--> $DIR/transmute-from-fn-item-types-error.rs:46:5
|
46 | mem::transmute::<fn(), u32>(main);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: source type: fn() (64 bits)
= note: target type: u32 (32 bits)

error[E0591]: can't transmute zero-sized type
--> $DIR/transmute-from-fn-item-types-error.rs:50:5
|
50 | mem::transmute::<_, *mut ()>(Some(foo));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: source type: unsafe fn() -> (i32, *const (), std::option::Option<fn()>) {foo}
= note: target type: *mut ()
= help: cast with `as` to a pointer instead

error[E0591]: can't transmute zero-sized type
--> $DIR/transmute-from-fn-item-types-error.rs:54:5
|
54 | mem::transmute::<_, fn()>(Some(bar));
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: source type: unsafe fn() {bar}
= note: target type: fn()
= help: cast with `as` to a pointer instead

error[E0591]: can't transmute zero-sized type
--> $DIR/transmute-from-fn-item-types-error.rs:58:5
|
58 | mem::transmute::<_, Option<fn()>>(Some(baz));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: source type: unsafe fn() {baz}
= note: target type: std::option::Option<fn()>
= help: cast with `as` to a pointer instead

error[E0512]: transmute called with types of different sizes
--> $DIR/transmute-from-fn-item-types-error.rs:63:5
|
63 | mem::transmute::<Option<fn()>, u32>(Some(main));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: source type: std::option::Option<fn()> (64 bits)
= note: target type: u32 (32 bits)

error: aborting due to previous error(s)

Loading

0 comments on commit 6836562

Please sign in to comment.