From ebe71fdd53b47b2f1e684454e71e42062dbdf6a4 Mon Sep 17 00:00:00 2001 From: Andre Bogus Date: Fri, 23 Jun 2017 18:23:23 +0200 Subject: [PATCH 01/12] change binding name of for loop lowering to appease clippy With the latest change to for loop lowering, a `_next` binding was introduced. Unfortunately, this disturbs clippy's `used_underscore_binding` lint. This commit just renames the binding to `__next` so clippy will be happy. It should have no other effect. --- src/librustc/hir/lowering.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 62bedcdfcbe..873d39ec9e9 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -2170,12 +2170,12 @@ impl<'a> LoweringContext<'a> { // let result = match ::std::iter::IntoIterator::into_iter() { // mut iter => { // [opt_ident]: loop { - // let mut _next; + // let mut __next; // match ::std::iter::Iterator::next(&mut iter) { - // ::std::option::Option::Some(val) => _next = val, + // ::std::option::Option::Some(val) => __next = val, // ::std::option::Option::None => break // }; - // let = _next; + // let = __next; // StmtExpr(); // } // } @@ -2188,7 +2188,7 @@ impl<'a> LoweringContext<'a> { let iter = self.str_to_ident("iter"); - let next_ident = self.str_to_ident("_next"); + let next_ident = self.str_to_ident("__next"); let next_pat = self.pat_ident_binding_mode(e.span, next_ident, hir::BindByValue(hir::MutMutable)); @@ -2237,13 +2237,13 @@ impl<'a> LoweringContext<'a> { let next_expr = P(self.expr_ident(e.span, next_ident, next_pat.id)); - // `let mut _next` + // `let mut __next` let next_let = self.stmt_let_pat(e.span, None, next_pat, hir::LocalSource::ForLoopDesugar); - // `let = _next` + // `let = __next` let pat = self.lower_pat(pat); let pat_let = self.stmt_let_pat(e.span, Some(next_expr), From 426331b9e44a955b0e43da9b1542b7cf15fac31e Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Fri, 23 Jun 2017 18:29:30 -0700 Subject: [PATCH 02/12] remove unused parameters from LintStore.find_lint Long ago, in the before-time, the find_lint method was created with the unused_variables ("unused_variable" in the singular, as it was called at the time) attribute in anticipation of using the session and span in the handling of renamed lints (31b7d64fd), and indeed, the session and span came to be used in this method, while the unused_variables attribute remained (1ad1e2e29). In modern times, the session and span are again no longer used (ca81d3dd); it seems we can safely prune them from the method signature, for justice, and mercy. --- src/librustc/lint/context.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index a9e0ef51102..a550db34d6f 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -291,16 +291,13 @@ impl LintStore { self.by_name.insert(name.into(), Removed(reason.into())); } - #[allow(unused_variables)] - fn find_lint(&self, lint_name: &str, sess: &Session, span: Option) - -> Result - { + fn find_lint(&self, lint_name: &str) -> Result { match self.by_name.get(lint_name) { Some(&Id(lint_id)) => Ok(lint_id), Some(&Renamed(_, lint_id)) => { Ok(lint_id) }, - Some(&Removed(ref reason)) => { + Some(&Removed(_)) => { Err(FindLintError::Removed) }, None => Err(FindLintError::NotFound) @@ -313,7 +310,7 @@ impl LintStore { &lint_name[..], level); let lint_flag_val = Symbol::intern(&lint_name); - match self.find_lint(&lint_name[..], sess, None) { + match self.find_lint(&lint_name[..]) { Ok(lint_id) => self.levels.set(lint_id, (level, CommandLine(lint_flag_val))), Err(FindLintError::Removed) => { } Err(_) => { @@ -731,7 +728,7 @@ pub trait LintContext<'tcx>: Sized { continue; } Ok((lint_name, level, span)) => { - match self.lints().find_lint(&lint_name.as_str(), &self.sess(), Some(span)) { + match self.lints().find_lint(&lint_name.as_str()) { Ok(lint_id) => vec![(lint_id, level, span)], Err(FindLintError::NotFound) => { match self.lints().lint_groups.get(&*lint_name.as_str()) { @@ -1420,7 +1417,7 @@ impl Decodable for LintId { fn decode(d: &mut D) -> Result { let s = d.read_str()?; ty::tls::with(|tcx| { - match tcx.sess.lint_store.borrow().find_lint(&s, tcx.sess, None) { + match tcx.sess.lint_store.borrow().find_lint(&s) { Ok(id) => Ok(id), Err(_) => panic!("invalid lint-id `{}`", s), } From 890a76f479e32d7509b85aadd48301634508de39 Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Fri, 23 Jun 2017 19:22:06 -0700 Subject: [PATCH 03/12] only set "overruled by outer forbid" once for lint groups, by group name Previously, conflicting forbid/allow attributes for a lint group would result in a separate "allow(L) overruled by outer forbid(L)" error for every lint L in the group. This was needlessly and annoyingly verbose; we prefer to just have one error pointing out the conflicting attributes. Resolves #42873. --- src/librustc/lint/context.rs | 26 ++++++++++++++++--------- src/test/ui/lint/outer-forbid.rs | 22 +++++++++++++++++++++ src/test/ui/lint/outer-forbid.stderr | 29 ++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 9 deletions(-) create mode 100644 src/test/ui/lint/outer-forbid.rs create mode 100644 src/test/ui/lint/outer-forbid.stderr diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index a550db34d6f..466d163854f 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -721,7 +721,7 @@ pub trait LintContext<'tcx>: Sized { let mut pushed = 0; for result in gather_attrs(attrs) { - let v = match result { + let (is_group, lint_level_spans) = match result { Err(span) => { span_err!(self.sess(), span, E0452, "malformed lint attribute"); @@ -729,13 +729,14 @@ pub trait LintContext<'tcx>: Sized { } Ok((lint_name, level, span)) => { match self.lints().find_lint(&lint_name.as_str()) { - Ok(lint_id) => vec![(lint_id, level, span)], + Ok(lint_id) => (false, vec![(lint_id, level, span)]), Err(FindLintError::NotFound) => { match self.lints().lint_groups.get(&*lint_name.as_str()) { - Some(&(ref v, _)) => v.iter() + Some(&(ref v, _)) => (true, + v.iter() .map(|lint_id: &LintId| (*lint_id, level, span)) - .collect(), + .collect()), None => { // The lint or lint group doesn't exist. // This is an error, but it was handled @@ -751,14 +752,18 @@ pub trait LintContext<'tcx>: Sized { let lint_attr_name = result.expect("lint attribute should be well-formed").0; - for (lint_id, level, span) in v { + for (lint_id, level, span) in lint_level_spans { let (now, now_source) = self.lint_sess().get_source(lint_id); if now == Forbid && level != Forbid { - let lint_name = lint_id.to_string(); + let forbidden_lint_name = match now_source { + LintSource::Default => lint_id.to_string(), + LintSource::Node(name, _) => name.to_string(), + LintSource::CommandLine(name) => name.to_string(), + }; let mut diag_builder = struct_span_err!(self.sess(), span, E0453, "{}({}) overruled by outer forbid({})", - level.as_str(), lint_name, - lint_name); + level.as_str(), lint_attr_name, + forbidden_lint_name); diag_builder.span_label(span, "overruled by previous forbid"); match now_source { LintSource::Default => &mut diag_builder, @@ -769,7 +774,10 @@ pub trait LintContext<'tcx>: Sized { LintSource::CommandLine(_) => { diag_builder.note("`forbid` lint level was set on command line") } - }.emit() + }.emit(); + if is_group { // don't set a separate error for every lint in the group + break; + } } else if now != level { let cx = self.lint_sess_mut(); cx.stack.push((lint_id, (now, now_source))); diff --git a/src/test/ui/lint/outer-forbid.rs b/src/test/ui/lint/outer-forbid.rs new file mode 100644 index 00000000000..d71da58829a --- /dev/null +++ b/src/test/ui/lint/outer-forbid.rs @@ -0,0 +1,22 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Forbidding a group (here, `unused`) overrules subsequent allowance of both +// the group, and an individual lint in the group (here, `unused_variables`); +// and, forbidding an individual lint (here, `non_snake_case`) overrules +// subsequent allowance of a lint group containing it (here, `bad_style`). See +// Issue #42873. + +#![forbid(unused, non_snake_case)] + +#[allow(unused, unused_variables, bad_style)] +fn main() { + println!("hello forbidden world") +} diff --git a/src/test/ui/lint/outer-forbid.stderr b/src/test/ui/lint/outer-forbid.stderr new file mode 100644 index 00000000000..831b3f65634 --- /dev/null +++ b/src/test/ui/lint/outer-forbid.stderr @@ -0,0 +1,29 @@ +error[E0453]: allow(unused) overruled by outer forbid(unused) + --> $DIR/outer-forbid.rs:19:9 + | +17 | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +18 | +19 | #[allow(unused, unused_variables, bad_style)] + | ^^^^^^ overruled by previous forbid + +error[E0453]: allow(unused_variables) overruled by outer forbid(unused) + --> $DIR/outer-forbid.rs:19:17 + | +17 | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +18 | +19 | #[allow(unused, unused_variables, bad_style)] + | ^^^^^^^^^^^^^^^^ overruled by previous forbid + +error[E0453]: allow(bad_style) overruled by outer forbid(non_snake_case) + --> $DIR/outer-forbid.rs:19:35 + | +17 | #![forbid(unused, non_snake_case)] + | -------------- `forbid` level set here +18 | +19 | #[allow(unused, unused_variables, bad_style)] + | ^^^^^^^^^ overruled by previous forbid + +error: aborting due to previous error(s) + From d5977df1c1a934f9892e26a17b38065412ba31d1 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 7 Jun 2017 20:58:09 +0200 Subject: [PATCH 04/12] Add E0604 --- src/librustc_typeck/check/cast.rs | 8 ++------ src/librustc_typeck/diagnostics.rs | 17 +++++++++++++++++ src/test/compile-fail/E0604.rs | 13 +++++++++++++ .../ui/mismatched_types/cast-rfc0401.stderr | 2 +- 4 files changed, 33 insertions(+), 7 deletions(-) create mode 100644 src/test/compile-fail/E0604.rs diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 91aeade65aa..cff61df52cd 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -205,12 +205,8 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { .emit(); } CastError::CastToChar => { - fcx.type_error_message(self.span, - |actual| { - format!("only `u8` can be cast as `char`, not `{}`", - actual) - }, - self.expr_ty); + struct_span_err!(fcx.tcx.sess, self.span, E0604, + "only `u8` can be cast as `char`, not `{}`", self.expr_ty).emit(); } CastError::NonScalar => { fcx.type_error_message(self.span, diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index bc5ba4c323d..e750a897844 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -4208,6 +4208,23 @@ println!("{}", v[2]); ``` "##, +E0604: r##" +A cast to `char` was attempted on another type than `u8`. + +Erroneous code example: + +```compile_fail,E0604 +0u32 as char; // error: only `u8` can be cast as `char`, not `u32` +``` + +As the error message indicates, only `u8` can be casted into `char`. Example: + +``` +let c = 86u8 as char; // ok! +assert!(c, 'V'); +``` +"##, + E0609: r##" Attempted to access a non-existent field in a struct. diff --git a/src/test/compile-fail/E0604.rs b/src/test/compile-fail/E0604.rs new file mode 100644 index 00000000000..c5bf3a77b6c --- /dev/null +++ b/src/test/compile-fail/E0604.rs @@ -0,0 +1,13 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + 1u32 as char; //~ ERROR E0604 +} diff --git a/src/test/ui/mismatched_types/cast-rfc0401.stderr b/src/test/ui/mismatched_types/cast-rfc0401.stderr index 58cd130dcc2..82672d5d873 100644 --- a/src/test/ui/mismatched_types/cast-rfc0401.stderr +++ b/src/test/ui/mismatched_types/cast-rfc0401.stderr @@ -92,7 +92,7 @@ error[E0054]: cannot cast as `bool` | = help: compare with zero instead -error: only `u8` can be cast as `char`, not `u32` +error[E0604]: only `u8` can be cast as `char`, not `u32` --> $DIR/cast-rfc0401.rs:51:13 | 51 | let _ = 0x61u32 as char; From 0e4b8ffccdfaa48e7ec61d8f8dc06f15f31c800f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 7 Jun 2017 22:24:15 +0200 Subject: [PATCH 05/12] Add E0605 --- src/librustc_typeck/check/cast.rs | 14 +++++----- src/librustc_typeck/diagnostics.rs | 26 +++++++++++++++++++ src/test/compile-fail/E0605.rs | 19 ++++++++++++++ .../ui/mismatched_types/cast-rfc0401.stderr | 20 ++++++++++---- .../ui/mismatched_types/issue-26480.stderr | 4 ++- 5 files changed, 70 insertions(+), 13 deletions(-) create mode 100644 src/test/compile-fail/E0605.rs diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index cff61df52cd..69174dacaaa 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -209,13 +209,13 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { "only `u8` can be cast as `char`, not `{}`", self.expr_ty).emit(); } CastError::NonScalar => { - fcx.type_error_message(self.span, - |actual| { - format!("non-scalar cast: `{}` as `{}`", - actual, - fcx.ty_to_string(self.cast_ty)) - }, - self.expr_ty); + struct_span_err!(fcx.tcx.sess, self.span, E0605, + "non-scalar cast: `{}` as `{}`", + self.expr_ty, + fcx.ty_to_string(self.cast_ty)) + .note("an `as` expression can only be used to convert between \ + primitive types. Consider using the `From` trait") + .emit(); } CastError::IllegalCast => { fcx.type_error_message(self.span, diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index e750a897844..a787aadc678 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -4225,6 +4225,32 @@ assert!(c, 'V'); ``` "##, +E0605: r##" +An invalid cast was attempted. + +Erroneous code examples: + +```compile_fail,E0605 +let x = 0u8; +x as Vec; // error: non-scalar cast: `u8` as `std::vec::Vec` + +// Another example + +let v = 0 as *const u8; // So here, `v` is a `*const u8`. +v as &u8; // error: non-scalar cast: `*const u8` as `&u8` +``` + +Only primitive types cast be casted into each others. Examples: + +``` +let x = 0u8; +x as u32; // ok! + +let v = 0 as *const u8; +v as *const i8; // ok! +``` +"##, + E0609: r##" Attempted to access a non-existent field in a struct. diff --git a/src/test/compile-fail/E0605.rs b/src/test/compile-fail/E0605.rs new file mode 100644 index 00000000000..add3fd8fd8a --- /dev/null +++ b/src/test/compile-fail/E0605.rs @@ -0,0 +1,19 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + let x = 0u8; + x as Vec; //~ ERROR E0605 + //~| NOTE an `as` expression can only be used to convert between primitive types + + let v = 0 as *const u8; + v as &u8; //~ ERROR E0605 + //~| NOTE an `as` expression can only be used to convert between primitive types +} diff --git a/src/test/ui/mismatched_types/cast-rfc0401.stderr b/src/test/ui/mismatched_types/cast-rfc0401.stderr index 82672d5d873..c79d242dc5e 100644 --- a/src/test/ui/mismatched_types/cast-rfc0401.stderr +++ b/src/test/ui/mismatched_types/cast-rfc0401.stderr @@ -20,35 +20,45 @@ error[E0609]: no field `f` on type `fn() {main}` 75 | let _ = main.f as *const u32; | ^ -error: non-scalar cast: `*const u8` as `&u8` +error[E0605]: non-scalar cast: `*const u8` as `&u8` --> $DIR/cast-rfc0401.rs:39:13 | 39 | let _ = v as &u8; | ^^^^^^^^ + | + = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait -error: non-scalar cast: `*const u8` as `E` +error[E0605]: non-scalar cast: `*const u8` as `E` --> $DIR/cast-rfc0401.rs:40:13 | 40 | let _ = v as E; | ^^^^^^ + | + = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait -error: non-scalar cast: `*const u8` as `fn()` +error[E0605]: non-scalar cast: `*const u8` as `fn()` --> $DIR/cast-rfc0401.rs:41:13 | 41 | let _ = v as fn(); | ^^^^^^^^^ + | + = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait -error: non-scalar cast: `*const u8` as `(u32,)` +error[E0605]: non-scalar cast: `*const u8` as `(u32,)` --> $DIR/cast-rfc0401.rs:42:13 | 42 | let _ = v as (u32,); | ^^^^^^^^^^^ + | + = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait -error: non-scalar cast: `std::option::Option<&*const u8>` as `*const u8` +error[E0605]: non-scalar cast: `std::option::Option<&*const u8>` as `*const u8` --> $DIR/cast-rfc0401.rs:43:13 | 43 | let _ = Some(&v) as *const u8; | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait error: casting `*const u8` as `f32` is invalid --> $DIR/cast-rfc0401.rs:45:13 diff --git a/src/test/ui/mismatched_types/issue-26480.stderr b/src/test/ui/mismatched_types/issue-26480.stderr index dc3764a376c..06b88069002 100644 --- a/src/test/ui/mismatched_types/issue-26480.stderr +++ b/src/test/ui/mismatched_types/issue-26480.stderr @@ -7,7 +7,7 @@ error[E0308]: mismatched types 37 | write!(hello); | -------------- in this macro invocation -error: non-scalar cast: `{integer}` as `()` +error[E0605]: non-scalar cast: `{integer}` as `()` --> $DIR/issue-26480.rs:32:19 | 32 | ($x:expr) => ($x as ()) @@ -15,6 +15,8 @@ error: non-scalar cast: `{integer}` as `()` ... 38 | cast!(2); | --------- in this macro invocation + | + = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait error: aborting due to previous error(s) From 30effc14e4ae23a682495ceadf7f56039b02e747 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 7 Jun 2017 23:54:51 +0200 Subject: [PATCH 06/12] Add E0606 --- src/librustc_typeck/check/cast.rs | 71 ++++++++----------- src/librustc_typeck/diagnostics.rs | 19 +++++ src/test/compile-fail/E0606.rs | 13 ++++ .../ui/mismatched_types/cast-rfc0401.stderr | 44 ++++++------ 4 files changed, 83 insertions(+), 64 deletions(-) create mode 100644 src/test/compile-fail/E0606.rs diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 69174dacaaa..5c255364311 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -40,9 +40,11 @@ use super::{Diverges, FnCtxt}; -use lint; +use errors::DiagnosticBuilder; use hir::def_id::DefId; +use lint; use rustc::hir; +use rustc::session::Session; use rustc::traits; use rustc::ty::{self, Ty, TypeFoldable}; use rustc::ty::cast::{CastKind, CastTy}; @@ -112,6 +114,18 @@ enum CastError { NonScalar, } +fn make_invalid_casting_error<'a, 'gcx, 'tcx>(sess: &'a Session, + span: Span, + expr_ty: Ty<'tcx>, + cast_ty: Ty<'tcx>, + fcx: &FnCtxt<'a, 'gcx, 'tcx>) + -> DiagnosticBuilder<'a> { + struct_span_err!(sess, span, E0606, + "casting `{}` as `{}` is invalid", + fcx.ty_to_string(expr_ty), + fcx.ty_to_string(cast_ty)) +} + impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { pub fn new(fcx: &FnCtxt<'a, 'gcx, 'tcx>, expr: &'tcx hir::Expr, @@ -146,14 +160,9 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { match e { CastError::NeedDeref => { let error_span = self.span; + let mut err = make_invalid_casting_error(fcx.tcx.sess, self.span, self.expr_ty, + self.cast_ty, fcx); let cast_ty = fcx.ty_to_string(self.cast_ty); - let mut err = fcx.type_error_struct(error_span, - |actual| { - format!("casting `{}` as `{}` is invalid", - actual, - cast_ty) - }, - self.expr_ty); err.span_label(error_span, format!("cannot cast `{}` as `{}`", fcx.ty_to_string(self.expr_ty), @@ -166,13 +175,8 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { } CastError::NeedViaThinPtr | CastError::NeedViaPtr => { - let mut err = fcx.type_error_struct(self.span, - |actual| { - format!("casting `{}` as `{}` is invalid", - actual, - fcx.ty_to_string(self.cast_ty)) - }, - self.expr_ty); + let mut err = make_invalid_casting_error(fcx.tcx.sess, self.span, self.expr_ty, + self.cast_ty, fcx); if self.cast_ty.is_uint() { err.help(&format!("cast through {} first", match e { @@ -184,13 +188,7 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { err.emit(); } CastError::NeedViaInt => { - fcx.type_error_struct(self.span, - |actual| { - format!("casting `{}` as `{}` is invalid", - actual, - fcx.ty_to_string(self.cast_ty)) - }, - self.expr_ty) + make_invalid_casting_error(fcx.tcx.sess, self.span, self.expr_ty, self.cast_ty, fcx) .help(&format!("cast through {} first", match e { CastError::NeedViaInt => "an integer", @@ -198,6 +196,15 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { })) .emit(); } + CastError::IllegalCast => { + make_invalid_casting_error(fcx.tcx.sess, self.span, self.expr_ty, self.cast_ty, fcx) + .emit(); + } + CastError::DifferingKinds => { + make_invalid_casting_error(fcx.tcx.sess, self.span, self.expr_ty, self.cast_ty, fcx) + .note("vtable kinds may not match") + .emit(); + } CastError::CastToBool => { struct_span_err!(fcx.tcx.sess, self.span, E0054, "cannot cast as `bool`") .span_label(self.span, "unsupported cast") @@ -217,15 +224,6 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { primitive types. Consider using the `From` trait") .emit(); } - CastError::IllegalCast => { - fcx.type_error_message(self.span, - |actual| { - format!("casting `{}` as `{}` is invalid", - actual, - fcx.ty_to_string(self.cast_ty)) - }, - self.expr_ty); - } CastError::SizedUnsizedCast => { fcx.type_error_message(self.span, |actual| { @@ -236,17 +234,6 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { }, self.expr_ty) } - CastError::DifferingKinds => { - fcx.type_error_struct(self.span, - |actual| { - format!("casting `{}` as `{}` is invalid", - actual, - fcx.ty_to_string(self.cast_ty)) - }, - self.expr_ty) - .note("vtable kinds may not match") - .emit(); - } } } diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index a787aadc678..d3138af978a 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -4251,6 +4251,25 @@ v as *const i8; // ok! ``` "##, +E0606: r##" +An incompatible cast was attempted. + +Erroneous code example: + +```compile_fail,E0606 +let x = &0u8; // Here, `x` is a `&u8`. +let y: u32 = x as u32; // error: casting `&u8` as `u32` is invalid +``` + +When casting, keep in mind that only primitive types cast be casted into each +others. Example: + +``` +let x = &0u8; +let y: u32 = *x as u32; // We dereference it first and then cast it. +``` +"##, + E0609: r##" Attempted to access a non-existent field in a struct. diff --git a/src/test/compile-fail/E0606.rs b/src/test/compile-fail/E0606.rs new file mode 100644 index 00000000000..55071736bfe --- /dev/null +++ b/src/test/compile-fail/E0606.rs @@ -0,0 +1,13 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + &0u8 as u8; //~ ERROR E0606 +} diff --git a/src/test/ui/mismatched_types/cast-rfc0401.stderr b/src/test/ui/mismatched_types/cast-rfc0401.stderr index c79d242dc5e..b4c3106253e 100644 --- a/src/test/ui/mismatched_types/cast-rfc0401.stderr +++ b/src/test/ui/mismatched_types/cast-rfc0401.stderr @@ -1,4 +1,4 @@ -error: casting `*const U` as `*const V` is invalid +error[E0606]: casting `*const U` as `*const V` is invalid --> $DIR/cast-rfc0401.rs:13:5 | 13 | u as *const V @@ -6,7 +6,7 @@ error: casting `*const U` as `*const V` is invalid | = note: vtable kinds may not match -error: casting `*const U` as `*const str` is invalid +error[E0606]: casting `*const U` as `*const str` is invalid --> $DIR/cast-rfc0401.rs:18:5 | 18 | u as *const str @@ -60,19 +60,19 @@ error[E0605]: non-scalar cast: `std::option::Option<&*const u8>` as `*const u8` | = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait -error: casting `*const u8` as `f32` is invalid +error[E0606]: casting `*const u8` as `f32` is invalid --> $DIR/cast-rfc0401.rs:45:13 | 45 | let _ = v as f32; | ^^^^^^^^ -error: casting `fn() {main}` as `f64` is invalid +error[E0606]: casting `fn() {main}` as `f64` is invalid --> $DIR/cast-rfc0401.rs:46:13 | 46 | let _ = main as f64; | ^^^^^^^^^^^ -error: casting `&*const u8` as `usize` is invalid +error[E0606]: casting `&*const u8` as `usize` is invalid --> $DIR/cast-rfc0401.rs:47:13 | 47 | let _ = &v as usize; @@ -80,7 +80,7 @@ error: casting `&*const u8` as `usize` is invalid | = help: cast through a raw pointer first -error: casting `f32` as `*const u8` is invalid +error[E0606]: casting `f32` as `*const u8` is invalid --> $DIR/cast-rfc0401.rs:48:13 | 48 | let _ = f as *const u8; @@ -108,7 +108,7 @@ error[E0604]: only `u8` can be cast as `char`, not `u32` 51 | let _ = 0x61u32 as char; | ^^^^^^^^^^^^^^^ -error: casting `bool` as `f32` is invalid +error[E0606]: casting `bool` as `f32` is invalid --> $DIR/cast-rfc0401.rs:53:13 | 53 | let _ = false as f32; @@ -116,7 +116,7 @@ error: casting `bool` as `f32` is invalid | = help: cast through an integer first -error: casting `E` as `f32` is invalid +error[E0606]: casting `E` as `f32` is invalid --> $DIR/cast-rfc0401.rs:54:13 | 54 | let _ = E::A as f32; @@ -124,7 +124,7 @@ error: casting `E` as `f32` is invalid | = help: cast through an integer first -error: casting `char` as `f32` is invalid +error[E0606]: casting `char` as `f32` is invalid --> $DIR/cast-rfc0401.rs:55:13 | 55 | let _ = 'a' as f32; @@ -132,25 +132,25 @@ error: casting `char` as `f32` is invalid | = help: cast through an integer first -error: casting `bool` as `*const u8` is invalid +error[E0606]: casting `bool` as `*const u8` is invalid --> $DIR/cast-rfc0401.rs:57:13 | 57 | let _ = false as *const u8; | ^^^^^^^^^^^^^^^^^^ -error: casting `E` as `*const u8` is invalid +error[E0606]: casting `E` as `*const u8` is invalid --> $DIR/cast-rfc0401.rs:58:13 | 58 | let _ = E::A as *const u8; | ^^^^^^^^^^^^^^^^^ -error: casting `char` as `*const u8` is invalid +error[E0606]: casting `char` as `*const u8` is invalid --> $DIR/cast-rfc0401.rs:59:13 | 59 | let _ = 'a' as *const u8; | ^^^^^^^^^^^^^^^^ -error: casting `usize` as `*const [u8]` is invalid +error[E0606]: casting `usize` as `*const [u8]` is invalid --> $DIR/cast-rfc0401.rs:61:13 | 61 | let _ = 42usize as *const [u8]; @@ -162,37 +162,37 @@ error: cannot cast thin pointer `*const u8` to fat pointer `*const [u8]` 62 | let _ = v as *const [u8]; | ^^^^^^^^^^^^^^^^ -error: casting `&Foo` as `*const str` is invalid +error[E0606]: casting `&Foo` as `*const str` is invalid --> $DIR/cast-rfc0401.rs:64:13 | 64 | let _ = foo as *const str; | ^^^^^^^^^^^^^^^^^ -error: casting `&Foo` as `*mut str` is invalid +error[E0606]: casting `&Foo` as `*mut str` is invalid --> $DIR/cast-rfc0401.rs:65:13 | 65 | let _ = foo as *mut str; | ^^^^^^^^^^^^^^^ -error: casting `fn() {main}` as `*mut str` is invalid +error[E0606]: casting `fn() {main}` as `*mut str` is invalid --> $DIR/cast-rfc0401.rs:66:13 | 66 | let _ = main as *mut str; | ^^^^^^^^^^^^^^^^ -error: casting `&f32` as `*mut f32` is invalid +error[E0606]: casting `&f32` as `*mut f32` is invalid --> $DIR/cast-rfc0401.rs:67:13 | 67 | let _ = &f as *mut f32; | ^^^^^^^^^^^^^^ -error: casting `&f32` as `*const f64` is invalid +error[E0606]: casting `&f32` as `*const f64` is invalid --> $DIR/cast-rfc0401.rs:68:13 | 68 | let _ = &f as *const f64; | ^^^^^^^^^^^^^^^^ -error: casting `*const [i8]` as `usize` is invalid +error[E0606]: casting `*const [i8]` as `usize` is invalid --> $DIR/cast-rfc0401.rs:69:13 | 69 | let _ = fat_sv as usize; @@ -200,7 +200,7 @@ error: casting `*const [i8]` as `usize` is invalid | = help: cast through a thin pointer first -error: casting `*const Foo` as `*const [u16]` is invalid +error[E0606]: casting `*const Foo` as `*const [u16]` is invalid --> $DIR/cast-rfc0401.rs:78:13 | 78 | let _ = cf as *const [u16]; @@ -208,7 +208,7 @@ error: casting `*const Foo` as `*const [u16]` is invalid | = note: vtable kinds may not match -error: casting `*const Foo` as `*const Bar` is invalid +error[E0606]: casting `*const Foo` as `*const Bar` is invalid --> $DIR/cast-rfc0401.rs:79:13 | 79 | let _ = cf as *const Bar; @@ -234,7 +234,7 @@ error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied = help: the trait `std::marker::Sized` is not implemented for `str` = note: required for the cast to the object type `Foo` -error: casting `&{float}` as `f32` is invalid +error[E0606]: casting `&{float}` as `f32` is invalid --> $DIR/cast-rfc0401.rs:81:30 | 81 | vec![0.0].iter().map(|s| s as f32).collect::>(); From 7b8c6a2d30f7e6acee89a735ad8fd86c1e1c2370 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 8 Jun 2017 00:13:28 +0200 Subject: [PATCH 07/12] Add E0607 --- src/librustc_typeck/check/cast.rs | 12 ++++------ src/librustc_typeck/diagnostics.rs | 23 +++++++++++++++++++ src/test/compile-fail/E0607.rs | 14 +++++++++++ .../ui/mismatched_types/cast-rfc0401.stderr | 2 +- 4 files changed, 42 insertions(+), 9 deletions(-) create mode 100644 src/test/compile-fail/E0607.rs diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 5c255364311..52962e1e478 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -225,14 +225,10 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { .emit(); } CastError::SizedUnsizedCast => { - fcx.type_error_message(self.span, - |actual| { - format!("cannot cast thin pointer `{}` to fat pointer \ - `{}`", - actual, - fcx.ty_to_string(self.cast_ty)) - }, - self.expr_ty) + struct_span_err!(fcx.tcx.sess, self.span, E0607, + "cannot cast thin pointer `{}` to fat pointer `{}`", + self.expr_ty, + fcx.ty_to_string(self.cast_ty)).emit(); } } } diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index d3138af978a..ae13e236743 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -4270,6 +4270,29 @@ let y: u32 = *x as u32; // We dereference it first and then cast it. ``` "##, +E0607: r##" +A cast between a thin and a fat pointer was attempted. + +Erroneous code example: + +```compile_fail,E0607 +let v = 0 as *const u8; +v as *const [u8]; +``` + +First: what are thin and fat pointers? + +Thin pointers are "simple" pointers that simply reference a memory address. + +Fat pointers are pointers referencing Dynamically Sized Types (also called DST). +They don't have a statically known size, therefore they can only exist behind +some kind of pointers that contain additional information. Slices and trait +objects are DSTs. + +So in order to fix this error, don't try to cast directly between thin and fat +pointers. +"##, + E0609: r##" Attempted to access a non-existent field in a struct. diff --git a/src/test/compile-fail/E0607.rs b/src/test/compile-fail/E0607.rs new file mode 100644 index 00000000000..fa761f2c178 --- /dev/null +++ b/src/test/compile-fail/E0607.rs @@ -0,0 +1,14 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + let v = 0 as *const u8; + v as *const [u8]; //~ ERROR E0607 +} diff --git a/src/test/ui/mismatched_types/cast-rfc0401.stderr b/src/test/ui/mismatched_types/cast-rfc0401.stderr index b4c3106253e..50e18150579 100644 --- a/src/test/ui/mismatched_types/cast-rfc0401.stderr +++ b/src/test/ui/mismatched_types/cast-rfc0401.stderr @@ -156,7 +156,7 @@ error[E0606]: casting `usize` as `*const [u8]` is invalid 61 | let _ = 42usize as *const [u8]; | ^^^^^^^^^^^^^^^^^^^^^^ -error: cannot cast thin pointer `*const u8` to fat pointer `*const [u8]` +error[E0607]: cannot cast thin pointer `*const u8` to fat pointer `*const [u8]` --> $DIR/cast-rfc0401.rs:62:13 | 62 | let _ = v as *const [u8]; From deb1eb6134a8ac22c55dc3e9713d667ff352ecf5 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 9 Jun 2017 22:04:29 +0200 Subject: [PATCH 08/12] wording improvement --- src/librustc_typeck/check/cast.rs | 2 +- src/librustc_typeck/diagnostics.rs | 27 ++++++++++--------- src/test/compile-fail/cast-from-nil.rs | 2 +- src/test/compile-fail/cast-to-bare-fn.rs | 4 +-- src/test/compile-fail/cast-to-nil.rs | 2 +- src/test/compile-fail/closure-no-fn-3.rs | 2 +- src/test/compile-fail/coerce-to-bang-cast.rs | 2 +- src/test/compile-fail/fat-ptr-cast.rs | 2 +- src/test/compile-fail/issue-10991.rs | 2 +- src/test/compile-fail/issue-22289.rs | 2 +- src/test/compile-fail/issue-22312.rs | 2 +- src/test/compile-fail/issue-2995.rs | 2 +- src/test/compile-fail/nonscalar-cast.rs | 4 +-- .../tag-variant-cast-non-nullary.rs | 4 +-- .../compile-fail/uninhabited-enum-cast.rs | 2 +- .../ui/mismatched_types/cast-rfc0401.stderr | 10 +++---- .../ui/mismatched_types/issue-26480.stderr | 2 +- 17 files changed, 35 insertions(+), 38 deletions(-) diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 52962e1e478..aec9d6f16d2 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -217,7 +217,7 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { } CastError::NonScalar => { struct_span_err!(fcx.tcx.sess, self.span, E0605, - "non-scalar cast: `{}` as `{}`", + "non-primitive cast: `{}` as `{}`", self.expr_ty, fcx.ty_to_string(self.cast_ty)) .note("an `as` expression can only be used to convert between \ diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index ae13e236743..f9b44f0395f 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -4209,7 +4209,7 @@ println!("{}", v[2]); "##, E0604: r##" -A cast to `char` was attempted on another type than `u8`. +A cast to `char` was attempted on a type other than `u8`. Erroneous code example: @@ -4217,11 +4217,11 @@ Erroneous code example: 0u32 as char; // error: only `u8` can be cast as `char`, not `u32` ``` -As the error message indicates, only `u8` can be casted into `char`. Example: +As the error message indicates, only `u8` can be cast into `char`. Example: ``` let c = 86u8 as char; // ok! -assert!(c, 'V'); +assert_eq!(c, 'V'); ``` "##, @@ -4232,15 +4232,15 @@ Erroneous code examples: ```compile_fail,E0605 let x = 0u8; -x as Vec; // error: non-scalar cast: `u8` as `std::vec::Vec` +x as Vec; // error: non-primitive cast: `u8` as `std::vec::Vec` // Another example let v = 0 as *const u8; // So here, `v` is a `*const u8`. -v as &u8; // error: non-scalar cast: `*const u8` as `&u8` +v as &u8; // error: non-primitive cast: `*const u8` as `&u8` ``` -Only primitive types cast be casted into each others. Examples: +Only primitive types can be cast into each other. Examples: ``` let x = 0u8; @@ -4261,8 +4261,8 @@ let x = &0u8; // Here, `x` is a `&u8`. let y: u32 = x as u32; // error: casting `&u8` as `u32` is invalid ``` -When casting, keep in mind that only primitive types cast be casted into each -others. Example: +When casting, keep in mind that only primitive types can be cast into each +other. Example: ``` let x = &0u8; @@ -4282,15 +4282,16 @@ v as *const [u8]; First: what are thin and fat pointers? -Thin pointers are "simple" pointers that simply reference a memory address. +Thin pointers are "simple" pointers: they are purely a reference to a memory +address. Fat pointers are pointers referencing Dynamically Sized Types (also called DST). -They don't have a statically known size, therefore they can only exist behind +DST don't have a statically known size, therefore they can only exist behind some kind of pointers that contain additional information. Slices and trait -objects are DSTs. +objects are DSTs. In the case of slices, the additional information the fat +pointer holds is their size. -So in order to fix this error, don't try to cast directly between thin and fat -pointers. +To fix this error, don't try to cast directly between thin and fat pointers. "##, E0609: r##" diff --git a/src/test/compile-fail/cast-from-nil.rs b/src/test/compile-fail/cast-from-nil.rs index 4c6dcaccc9a..ab22d352480 100644 --- a/src/test/compile-fail/cast-from-nil.rs +++ b/src/test/compile-fail/cast-from-nil.rs @@ -8,5 +8,5 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern: non-scalar cast: `()` as `u32` +// error-pattern: non-primitive cast: `()` as `u32` fn main() { let u = (assert!(true) as u32); } diff --git a/src/test/compile-fail/cast-to-bare-fn.rs b/src/test/compile-fail/cast-to-bare-fn.rs index 7cc5c727bc7..d5a998c6e4b 100644 --- a/src/test/compile-fail/cast-to-bare-fn.rs +++ b/src/test/compile-fail/cast-to-bare-fn.rs @@ -13,8 +13,8 @@ fn foo(_x: isize) { } fn main() { let v: u64 = 5; let x = foo as extern "C" fn() -> isize; - //~^ ERROR non-scalar cast + //~^ ERROR non-primitive cast let y = v as extern "Rust" fn(isize) -> (isize, isize); - //~^ ERROR non-scalar cast + //~^ ERROR non-primitive cast y(x()); } diff --git a/src/test/compile-fail/cast-to-nil.rs b/src/test/compile-fail/cast-to-nil.rs index e5fd5bb33eb..27d9e8a42b1 100644 --- a/src/test/compile-fail/cast-to-nil.rs +++ b/src/test/compile-fail/cast-to-nil.rs @@ -8,5 +8,5 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern: non-scalar cast: `u32` as `()` +// error-pattern: non-primitive cast: `u32` as `()` fn main() { let u = 0u32 as (); } diff --git a/src/test/compile-fail/closure-no-fn-3.rs b/src/test/compile-fail/closure-no-fn-3.rs index 85dbc899208..6584c16c9de 100644 --- a/src/test/compile-fail/closure-no-fn-3.rs +++ b/src/test/compile-fail/closure-no-fn-3.rs @@ -14,5 +14,5 @@ fn main() { let b = 0u8; let baz: fn() -> u8 = (|| { b }) as fn() -> u8; - //~^ ERROR non-scalar cast + //~^ ERROR non-primitive cast } diff --git a/src/test/compile-fail/coerce-to-bang-cast.rs b/src/test/compile-fail/coerce-to-bang-cast.rs index 57d2192e635..0479f5cce65 100644 --- a/src/test/compile-fail/coerce-to-bang-cast.rs +++ b/src/test/compile-fail/coerce-to-bang-cast.rs @@ -17,7 +17,7 @@ fn cast_a() { } fn cast_b() { - let y = 22 as !; //~ ERROR non-scalar cast + let y = 22 as !; //~ ERROR non-primitive cast } fn main() { } diff --git a/src/test/compile-fail/fat-ptr-cast.rs b/src/test/compile-fail/fat-ptr-cast.rs index c62987a5b90..bc2dc1cc5d4 100644 --- a/src/test/compile-fail/fat-ptr-cast.rs +++ b/src/test/compile-fail/fat-ptr-cast.rs @@ -22,7 +22,7 @@ fn main() { a as isize; //~ ERROR casting a as i16; //~ ERROR casting `&[i32]` as `i16` is invalid a as u32; //~ ERROR casting `&[i32]` as `u32` is invalid - b as usize; //~ ERROR non-scalar cast + b as usize; //~ ERROR non-primitive cast p as usize; //~^ ERROR casting //~^^ HELP cast through a thin pointer diff --git a/src/test/compile-fail/issue-10991.rs b/src/test/compile-fail/issue-10991.rs index 25060b94dcf..2d00f339f33 100644 --- a/src/test/compile-fail/issue-10991.rs +++ b/src/test/compile-fail/issue-10991.rs @@ -10,5 +10,5 @@ fn main() { let nil = (); - let _t = nil as usize; //~ ERROR: non-scalar cast: `()` as `usize` + let _t = nil as usize; //~ ERROR: non-primitive cast: `()` as `usize` } diff --git a/src/test/compile-fail/issue-22289.rs b/src/test/compile-fail/issue-22289.rs index bcbc414d353..c23fc4f3344 100644 --- a/src/test/compile-fail/issue-22289.rs +++ b/src/test/compile-fail/issue-22289.rs @@ -9,5 +9,5 @@ // except according to those terms. fn main() { - 0 as &std::any::Any; //~ ERROR non-scalar cast + 0 as &std::any::Any; //~ ERROR non-primitive cast } diff --git a/src/test/compile-fail/issue-22312.rs b/src/test/compile-fail/issue-22312.rs index 4d6e6eded21..2128c420630 100644 --- a/src/test/compile-fail/issue-22312.rs +++ b/src/test/compile-fail/issue-22312.rs @@ -19,7 +19,7 @@ pub trait Array2D: Index { } let i = y * self.columns() + x; let indexer = &(*self as &Index>::Output>); - //~^ERROR non-scalar cast + //~^ERROR non-primitive cast Some(indexer.index(i)) } } diff --git a/src/test/compile-fail/issue-2995.rs b/src/test/compile-fail/issue-2995.rs index 8fbf97411cc..d735e184d5c 100644 --- a/src/test/compile-fail/issue-2995.rs +++ b/src/test/compile-fail/issue-2995.rs @@ -9,7 +9,7 @@ // except according to those terms. fn bad (p: *const isize) { - let _q: &isize = p as &isize; //~ ERROR non-scalar cast + let _q: &isize = p as &isize; //~ ERROR non-primitive cast } fn main() { } diff --git a/src/test/compile-fail/nonscalar-cast.rs b/src/test/compile-fail/nonscalar-cast.rs index d6f274da967..0abbc05eef0 100644 --- a/src/test/compile-fail/nonscalar-cast.rs +++ b/src/test/compile-fail/nonscalar-cast.rs @@ -8,13 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern:non-scalar cast - #[derive(Debug)] struct foo { x: isize } fn main() { - println!("{}", foo{ x: 1 } as isize); + println!("{}", foo{ x: 1 } as isize); //~ non-primitive cast: `foo` as `isize` [E0605] } diff --git a/src/test/compile-fail/tag-variant-cast-non-nullary.rs b/src/test/compile-fail/tag-variant-cast-non-nullary.rs index b0106329126..220537633ea 100644 --- a/src/test/compile-fail/tag-variant-cast-non-nullary.rs +++ b/src/test/compile-fail/tag-variant-cast-non-nullary.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//error-pattern: non-scalar cast - enum non_nullary { nullary, other(isize), @@ -17,5 +15,5 @@ enum non_nullary { fn main() { let v = non_nullary::nullary; - let val = v as isize; + let val = v as isize; //~ ERROR non-primitive cast: `non_nullary` as `isize` [E0605] } diff --git a/src/test/compile-fail/uninhabited-enum-cast.rs b/src/test/compile-fail/uninhabited-enum-cast.rs index b4df5fb1e2a..2a5d25e6b98 100644 --- a/src/test/compile-fail/uninhabited-enum-cast.rs +++ b/src/test/compile-fail/uninhabited-enum-cast.rs @@ -11,7 +11,7 @@ enum E {} fn f(e: E) { - println!("{}", (e as isize).to_string()); //~ ERROR non-scalar cast + println!("{}", (e as isize).to_string()); //~ ERROR non-primitive cast } fn main() {} diff --git a/src/test/ui/mismatched_types/cast-rfc0401.stderr b/src/test/ui/mismatched_types/cast-rfc0401.stderr index 50e18150579..879acbcf9d9 100644 --- a/src/test/ui/mismatched_types/cast-rfc0401.stderr +++ b/src/test/ui/mismatched_types/cast-rfc0401.stderr @@ -20,7 +20,7 @@ error[E0609]: no field `f` on type `fn() {main}` 75 | let _ = main.f as *const u32; | ^ -error[E0605]: non-scalar cast: `*const u8` as `&u8` +error[E0605]: non-primitive cast: `*const u8` as `&u8` --> $DIR/cast-rfc0401.rs:39:13 | 39 | let _ = v as &u8; @@ -28,7 +28,7 @@ error[E0605]: non-scalar cast: `*const u8` as `&u8` | = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait -error[E0605]: non-scalar cast: `*const u8` as `E` +error[E0605]: non-primitive cast: `*const u8` as `E` --> $DIR/cast-rfc0401.rs:40:13 | 40 | let _ = v as E; @@ -36,7 +36,7 @@ error[E0605]: non-scalar cast: `*const u8` as `E` | = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait -error[E0605]: non-scalar cast: `*const u8` as `fn()` +error[E0605]: non-primitive cast: `*const u8` as `fn()` --> $DIR/cast-rfc0401.rs:41:13 | 41 | let _ = v as fn(); @@ -44,7 +44,7 @@ error[E0605]: non-scalar cast: `*const u8` as `fn()` | = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait -error[E0605]: non-scalar cast: `*const u8` as `(u32,)` +error[E0605]: non-primitive cast: `*const u8` as `(u32,)` --> $DIR/cast-rfc0401.rs:42:13 | 42 | let _ = v as (u32,); @@ -52,7 +52,7 @@ error[E0605]: non-scalar cast: `*const u8` as `(u32,)` | = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait -error[E0605]: non-scalar cast: `std::option::Option<&*const u8>` as `*const u8` +error[E0605]: non-primitive cast: `std::option::Option<&*const u8>` as `*const u8` --> $DIR/cast-rfc0401.rs:43:13 | 43 | let _ = Some(&v) as *const u8; diff --git a/src/test/ui/mismatched_types/issue-26480.stderr b/src/test/ui/mismatched_types/issue-26480.stderr index 06b88069002..9da9042e78e 100644 --- a/src/test/ui/mismatched_types/issue-26480.stderr +++ b/src/test/ui/mismatched_types/issue-26480.stderr @@ -7,7 +7,7 @@ error[E0308]: mismatched types 37 | write!(hello); | -------------- in this macro invocation -error[E0605]: non-scalar cast: `{integer}` as `()` +error[E0605]: non-primitive cast: `{integer}` as `()` --> $DIR/issue-26480.rs:32:19 | 32 | ($x:expr) => ($x as ()) From 9137153e4725649443ac02f742424aa5737d15b6 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 12 Jun 2017 18:58:11 +0200 Subject: [PATCH 09/12] Use new macro instead --- src/librustc_typeck/check/cast.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index aec9d6f16d2..ea08f1f624e 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -120,10 +120,10 @@ fn make_invalid_casting_error<'a, 'gcx, 'tcx>(sess: &'a Session, cast_ty: Ty<'tcx>, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> DiagnosticBuilder<'a> { - struct_span_err!(sess, span, E0606, - "casting `{}` as `{}` is invalid", - fcx.ty_to_string(expr_ty), - fcx.ty_to_string(cast_ty)) + type_error_struct!(sess, span, expr_ty, E0606, + "casting `{}` as `{}` is invalid", + fcx.ty_to_string(expr_ty), + fcx.ty_to_string(cast_ty)) } impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { @@ -212,11 +212,11 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { .emit(); } CastError::CastToChar => { - struct_span_err!(fcx.tcx.sess, self.span, E0604, + type_error_struct!(fcx.tcx.sess, self.span, self.expr_ty, E0604, "only `u8` can be cast as `char`, not `{}`", self.expr_ty).emit(); } CastError::NonScalar => { - struct_span_err!(fcx.tcx.sess, self.span, E0605, + type_error_struct!(fcx.tcx.sess, self.span, self.expr_ty, E0605, "non-primitive cast: `{}` as `{}`", self.expr_ty, fcx.ty_to_string(self.cast_ty)) @@ -225,7 +225,7 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { .emit(); } CastError::SizedUnsizedCast => { - struct_span_err!(fcx.tcx.sess, self.span, E0607, + type_error_struct!(fcx.tcx.sess, self.span, self.expr_ty, E0607, "cannot cast thin pointer `{}` to fat pointer `{}`", self.expr_ty, fcx.ty_to_string(self.cast_ty)).emit(); From bcf0d600f3884709c5faef21219a7613e254b7e0 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 25 Jun 2017 09:25:37 +0200 Subject: [PATCH 10/12] Add reference link --- src/librustc_typeck/diagnostics.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index f9b44f0395f..b2fa2cc7c61 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -4223,6 +4223,9 @@ As the error message indicates, only `u8` can be cast into `char`. Example: let c = 86u8 as char; // ok! assert_eq!(c, 'V'); ``` + +For more information about casts, take a look at The Book: +https://doc.rust-lang.org/book/first-edition/casting-between-types.html "##, E0605: r##" @@ -4249,6 +4252,9 @@ x as u32; // ok! let v = 0 as *const u8; v as *const i8; // ok! ``` + +For more information about casts, take a look at The Book: +https://doc.rust-lang.org/book/first-edition/casting-between-types.html "##, E0606: r##" @@ -4268,6 +4274,9 @@ other. Example: let x = &0u8; let y: u32 = *x as u32; // We dereference it first and then cast it. ``` + +For more information about casts, take a look at The Book: +https://doc.rust-lang.org/book/first-edition/casting-between-types.html "##, E0607: r##" @@ -4292,6 +4301,9 @@ objects are DSTs. In the case of slices, the additional information the fat pointer holds is their size. To fix this error, don't try to cast directly between thin and fat pointers. + +For more information about casts, take a look at The Book: +https://doc.rust-lang.org/book/first-edition/casting-between-types.html "##, E0609: r##" From 0d985c9e8760da77b0df8920465700728e2da4f1 Mon Sep 17 00:00:00 2001 From: Casey Rodarmor Date: Sun, 25 Jun 2017 14:23:43 -0700 Subject: [PATCH 11/12] Reword OsStr docs to clarify that utf8 may contain nulls --- src/libstd/ffi/os_str.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index f54d79c201f..e9296f33b9e 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -29,7 +29,7 @@ use sys_common::{AsInner, IntoInner, FromInner}; /// * On Windows, strings are often arbitrary sequences of non-zero 16-bit /// values, interpreted as UTF-16 when it is valid to do so. /// -/// * In Rust, strings are always valid UTF-8, but may contain zeros. +/// * In Rust, strings are always valid UTF-8, which may contain zeros. /// /// `OsString` and [`OsStr`] bridge this gap by simultaneously representing Rust /// and platform-native string values, and in particular allowing a Rust string From 3f1cb30b14aed8ce1e7567e47981cf602f74aea4 Mon Sep 17 00:00:00 2001 From: kennytm Date: Tue, 27 Jun 2017 02:44:42 +0800 Subject: [PATCH 12/12] compiletest: show details if GDB failed to execute. --- src/tools/compiletest/src/runtest.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 0692e07253f..4961609c77f 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -692,7 +692,7 @@ actual:\n\ } if !debugger_run_result.status.success() { - self.fatal("gdb failed to execute"); + self.fatal_proc_rec("gdb failed to execute", &debugger_run_result); } self.check_debugger_output(&debugger_run_result, &check_lines);