提交 6bb1b0dd 编写于 作者: G Guillaume Gomez 提交者: GitHub

Rollup merge of #47247 - estebank:suggest-cast, r=petrochenkov

Suggest casting on numeric type error

Re #47168.
......@@ -34,13 +34,14 @@
use syntax_pos::{Span, DUMMY_SP};
use syntax::codemap::{self, Spanned};
use syntax::abi::Abi;
use syntax::ast::{Ident, Name, NodeId, DUMMY_NODE_ID, AsmDialect};
use syntax::ast::{self, Ident, Name, NodeId, DUMMY_NODE_ID, AsmDialect};
use syntax::ast::{Attribute, Lit, StrStyle, FloatTy, IntTy, UintTy, MetaItem};
use syntax::ext::hygiene::SyntaxContext;
use syntax::ptr::P;
use syntax::symbol::{Symbol, keywords};
use syntax::tokenstream::TokenStream;
use syntax::util::ThinVec;
use syntax::util::parser::ExprPrecedence;
use ty::AdtKind;
use rustc_data_structures::indexed_vec;
......@@ -958,6 +959,31 @@ pub fn is_by_value(self) -> bool {
}
}
impl Into<ast::BinOpKind> for BinOp_ {
fn into(self) -> ast::BinOpKind {
match self {
BiAdd => ast::BinOpKind::Add,
BiSub => ast::BinOpKind::Sub,
BiMul => ast::BinOpKind::Mul,
BiDiv => ast::BinOpKind::Div,
BiRem => ast::BinOpKind::Rem,
BiAnd => ast::BinOpKind::And,
BiOr => ast::BinOpKind::Or,
BiBitXor => ast::BinOpKind::BitXor,
BiBitAnd => ast::BinOpKind::BitAnd,
BiBitOr => ast::BinOpKind::BitOr,
BiShl => ast::BinOpKind::Shl,
BiShr => ast::BinOpKind::Shr,
BiEq => ast::BinOpKind::Eq,
BiLt => ast::BinOpKind::Lt,
BiLe => ast::BinOpKind::Le,
BiNe => ast::BinOpKind::Ne,
BiGe => ast::BinOpKind::Ge,
BiGt => ast::BinOpKind::Gt,
}
}
}
pub type BinOp = Spanned<BinOp_>;
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
......@@ -1166,6 +1192,42 @@ pub struct Expr {
pub hir_id: HirId,
}
impl Expr {
pub fn precedence(&self) -> ExprPrecedence {
match self.node {
ExprBox(_) => ExprPrecedence::Box,
ExprArray(_) => ExprPrecedence::Array,
ExprCall(..) => ExprPrecedence::Call,
ExprMethodCall(..) => ExprPrecedence::MethodCall,
ExprTup(_) => ExprPrecedence::Tup,
ExprBinary(op, ..) => ExprPrecedence::Binary(op.node.into()),
ExprUnary(..) => ExprPrecedence::Unary,
ExprLit(_) => ExprPrecedence::Lit,
ExprType(..) | ExprCast(..) => ExprPrecedence::Cast,
ExprIf(..) => ExprPrecedence::If,
ExprWhile(..) => ExprPrecedence::While,
ExprLoop(..) => ExprPrecedence::Loop,
ExprMatch(..) => ExprPrecedence::Match,
ExprClosure(..) => ExprPrecedence::Closure,
ExprBlock(..) => ExprPrecedence::Block,
ExprAssign(..) => ExprPrecedence::Assign,
ExprAssignOp(..) => ExprPrecedence::AssignOp,
ExprField(..) => ExprPrecedence::Field,
ExprTupField(..) => ExprPrecedence::TupField,
ExprIndex(..) => ExprPrecedence::Index,
ExprPath(..) => ExprPrecedence::Path,
ExprAddrOf(..) => ExprPrecedence::AddrOf,
ExprBreak(..) => ExprPrecedence::Break,
ExprAgain(..) => ExprPrecedence::Continue,
ExprRet(..) => ExprPrecedence::Ret,
ExprInlineAsm(..) => ExprPrecedence::InlineAsm,
ExprStruct(..) => ExprPrecedence::Struct,
ExprRepeat(..) => ExprPrecedence::Repeat,
ExprYield(..) => ExprPrecedence::Yield,
}
}
}
impl fmt::Debug for Expr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "expr({}: {})", self.id,
......
......@@ -1104,7 +1104,7 @@ fn print_call_post(&mut self, args: &[hir::Expr]) -> io::Result<()> {
}
pub fn print_expr_maybe_paren(&mut self, expr: &hir::Expr, prec: i8) -> io::Result<()> {
let needs_par = expr_precedence(expr) < prec;
let needs_par = expr.precedence().order() < prec;
if needs_par {
self.popen()?;
}
......@@ -2318,55 +2318,6 @@ fn stmt_ends_with_semi(stmt: &hir::Stmt_) -> bool {
}
}
fn expr_precedence(expr: &hir::Expr) -> i8 {
use syntax::util::parser::*;
match expr.node {
hir::ExprClosure(..) => PREC_CLOSURE,
hir::ExprBreak(..) |
hir::ExprAgain(..) |
hir::ExprRet(..) |
hir::ExprYield(..) => PREC_JUMP,
// Binop-like expr kinds, handled by `AssocOp`.
hir::ExprBinary(op, _, _) => bin_op_to_assoc_op(op.node).precedence() as i8,
hir::ExprCast(..) => AssocOp::As.precedence() as i8,
hir::ExprType(..) => AssocOp::Colon.precedence() as i8,
hir::ExprAssign(..) |
hir::ExprAssignOp(..) => AssocOp::Assign.precedence() as i8,
// Unary, prefix
hir::ExprBox(..) |
hir::ExprAddrOf(..) |
hir::ExprUnary(..) => PREC_PREFIX,
// Unary, postfix
hir::ExprCall(..) |
hir::ExprMethodCall(..) |
hir::ExprField(..) |
hir::ExprTupField(..) |
hir::ExprIndex(..) |
hir::ExprInlineAsm(..) => PREC_POSTFIX,
// Never need parens
hir::ExprArray(..) |
hir::ExprRepeat(..) |
hir::ExprTup(..) |
hir::ExprLit(..) |
hir::ExprPath(..) |
hir::ExprIf(..) |
hir::ExprWhile(..) |
hir::ExprLoop(..) |
hir::ExprMatch(..) |
hir::ExprBlock(..) |
hir::ExprStruct(..) => PREC_PAREN,
}
}
fn bin_op_to_assoc_op(op: hir::BinOp_) -> AssocOp {
use hir::BinOp_::*;
match op {
......
......@@ -15,6 +15,7 @@
use rustc::traits::ObligationCause;
use syntax::ast;
use syntax::util::parser::AssocOp;
use syntax_pos::{self, Span};
use rustc::hir;
use rustc::hir::print;
......@@ -137,7 +138,7 @@ pub fn demand_coerce_diag(&self,
if let Some((msg, suggestion)) = self.check_ref(expr, checked_ty, expected) {
err.span_suggestion(expr.span, msg, suggestion);
} else {
} else if !self.check_for_cast(&mut err, expr, expr_ty, expected) {
let methods = self.get_conversion_methods(expected, checked_ty);
if let Ok(expr_text) = self.tcx.sess.codemap().span_to_snippet(expr.span) {
let suggestions = iter::repeat(expr_text).zip(methods.iter())
......@@ -287,8 +288,7 @@ fn check_ref(&self,
// Maybe remove `&`?
hir::ExprAddrOf(_, ref expr) => {
if let Ok(code) = self.tcx.sess.codemap().span_to_snippet(expr.span) {
return Some(("consider removing the borrow",
code));
return Some(("consider removing the borrow", code));
}
}
......@@ -303,7 +303,7 @@ fn check_ref(&self,
format!("*{}", code)));
}
}
},
}
}
}
None
......@@ -311,4 +311,240 @@ fn check_ref(&self,
_ => None,
}
}
fn check_for_cast(&self,
err: &mut DiagnosticBuilder<'tcx>,
expr: &hir::Expr,
checked_ty: Ty<'tcx>,
expected_ty: Ty<'tcx>)
-> bool {
let will_truncate = "will truncate the source value";
let depending_on_isize = "will truncate or zero-extend depending on the bit width of \
`isize`";
let depending_on_usize = "will truncate or zero-extend depending on the bit width of \
`usize`";
let will_sign_extend = "will sign-extend the source value";
let will_zero_extend = "will zero-extend the source value";
// If casting this expression to a given numeric type would be appropriate in case of a type
// mismatch.
//
// We want to minimize the amount of casting operations that are suggested, as it can be a
// lossy operation with potentially bad side effects, so we only suggest when encountering
// an expression that indicates that the original type couldn't be directly changed.
//
// For now, don't suggest casting with `as`.
let can_cast = false;
let needs_paren = expr.precedence().order() < (AssocOp::As.precedence() as i8);
if let Ok(src) = self.tcx.sess.codemap().span_to_snippet(expr.span) {
let msg = format!("you can cast an `{}` to `{}`", checked_ty, expected_ty);
let cast_suggestion = format!("{}{}{} as {}",
if needs_paren { "(" } else { "" },
src,
if needs_paren { ")" } else { "" },
expected_ty);
let into_suggestion = format!("{}{}{}.into()",
if needs_paren { "(" } else { "" },
src,
if needs_paren { ")" } else { "" });
match (&expected_ty.sty, &checked_ty.sty) {
(&ty::TyInt(ref exp), &ty::TyInt(ref found)) => {
match (found.bit_width(), exp.bit_width()) {
(Some(found), Some(exp)) if found > exp => {
if can_cast {
err.span_suggestion(expr.span,
&format!("{}, which {}", msg, will_truncate),
cast_suggestion);
}
}
(None, _) | (_, None) => {
if can_cast {
err.span_suggestion(expr.span,
&format!("{}, which {}",
msg,
depending_on_isize),
cast_suggestion);
}
}
_ => {
err.span_suggestion(expr.span,
&format!("{}, which {}", msg, will_sign_extend),
into_suggestion);
}
}
true
}
(&ty::TyUint(ref exp), &ty::TyUint(ref found)) => {
match (found.bit_width(), exp.bit_width()) {
(Some(found), Some(exp)) if found > exp => {
if can_cast {
err.span_suggestion(expr.span,
&format!("{}, which {}", msg, will_truncate),
cast_suggestion);
}
}
(None, _) | (_, None) => {
if can_cast {
err.span_suggestion(expr.span,
&format!("{}, which {}",
msg,
depending_on_usize),
cast_suggestion);
}
}
_ => {
err.span_suggestion(expr.span,
&format!("{}, which {}", msg, will_zero_extend),
into_suggestion);
}
}
true
}
(&ty::TyInt(ref exp), &ty::TyUint(ref found)) => {
if can_cast {
match (found.bit_width(), exp.bit_width()) {
(Some(found), Some(exp)) if found > exp - 1 => {
err.span_suggestion(expr.span,
&format!("{}, which {}", msg, will_truncate),
cast_suggestion);
}
(None, None) => {
err.span_suggestion(expr.span,
&format!("{}, which {}", msg, will_truncate),
cast_suggestion);
}
(None, _) => {
err.span_suggestion(expr.span,
&format!("{}, which {}",
msg,
depending_on_isize),
cast_suggestion);
}
(_, None) => {
err.span_suggestion(expr.span,
&format!("{}, which {}",
msg,
depending_on_usize),
cast_suggestion);
}
_ => {
err.span_suggestion(expr.span,
&format!("{}, which {}", msg, will_zero_extend),
cast_suggestion);
}
}
}
true
}
(&ty::TyUint(ref exp), &ty::TyInt(ref found)) => {
if can_cast {
match (found.bit_width(), exp.bit_width()) {
(Some(found), Some(exp)) if found - 1 > exp => {
err.span_suggestion(expr.span,
&format!("{}, which {}", msg, will_truncate),
cast_suggestion);
}
(None, None) => {
err.span_suggestion(expr.span,
&format!("{}, which {}", msg, will_sign_extend),
cast_suggestion);
}
(None, _) => {
err.span_suggestion(expr.span,
&format!("{}, which {}",
msg,
depending_on_usize),
cast_suggestion);
}
(_, None) => {
err.span_suggestion(expr.span,
&format!("{}, which {}",
msg,
depending_on_isize),
cast_suggestion);
}
_ => {
err.span_suggestion(expr.span,
&format!("{}, which {}", msg, will_sign_extend),
cast_suggestion);
}
}
}
true
}
(&ty::TyFloat(ref exp), &ty::TyFloat(ref found)) => {
if found.bit_width() < exp.bit_width() {
err.span_suggestion(expr.span,
&format!("{} in a lossless way",
msg),
into_suggestion);
} else if can_cast {
err.span_suggestion(expr.span,
&format!("{}, producing the closest possible value",
msg),
cast_suggestion);
err.warn("casting here will cause undefined behavior if the value is \
finite but larger or smaller than the largest or smallest \
finite value representable by `f32` (this is a bug and will be \
fixed)");
}
true
}
(&ty::TyUint(_), &ty::TyFloat(_)) | (&ty::TyInt(_), &ty::TyFloat(_)) => {
if can_cast {
err.span_suggestion(expr.span,
&format!("{}, rounding the float towards zero",
msg),
cast_suggestion);
err.warn("casting here will cause undefined behavior if the rounded value \
cannot be represented by the target integer type, including \
`Inf` and `NaN` (this is a bug and will be fixed)");
}
true
}
(&ty::TyFloat(ref exp), &ty::TyUint(ref found)) => {
// if `found` is `None` (meaning found is `usize`), don't suggest `.into()`
if exp.bit_width() > found.bit_width().unwrap_or(256) {
err.span_suggestion(expr.span,
&format!("{}, producing the floating point \
representation of the integer",
msg),
into_suggestion);
} else if can_cast {
err.span_suggestion(expr.span,
&format!("{}, producing the floating point \
representation of the integer, rounded if \
necessary",
msg),
cast_suggestion);
}
true
}
(&ty::TyFloat(ref exp), &ty::TyInt(ref found)) => {
// if `found` is `None` (meaning found is `isize`), don't suggest `.into()`
if exp.bit_width() > found.bit_width().unwrap_or(256) {
err.span_suggestion(expr.span,
&format!("{}, producing the floating point \
representation of the integer",
msg),
into_suggestion);
} else if can_cast {
err.span_suggestion(expr.span,
&format!("{}, producing the floating point \
representation of the integer, rounded if \
necessary",
msg),
cast_suggestion);
}
true
}
_ => false,
}
} else {
false
}
}
}
......@@ -15,6 +15,7 @@
pub use self::PathParameters::*;
pub use symbol::{Ident, Symbol as Name};
pub use util::ThinVec;
pub use util::parser::ExprPrecedence;
use syntax_pos::{Span, DUMMY_SP};
use codemap::{respan, Spanned};
......@@ -730,6 +731,7 @@ pub fn is_shift(&self) -> bool {
_ => false
}
}
pub fn is_comparison(&self) -> bool {
use self::BinOpKind::*;
match *self {
......@@ -740,6 +742,7 @@ pub fn is_comparison(&self) -> bool {
false,
}
}
/// Returns `true` if the binary operator takes its arguments by value
pub fn is_by_value(&self) -> bool {
!self.is_comparison()
......@@ -966,6 +969,49 @@ pub(super) fn to_ty(&self) -> Option<P<Ty>> {
Some(P(Ty { node, id: self.id, span: self.span }))
}
pub fn precedence(&self) -> ExprPrecedence {
match self.node {
ExprKind::Box(_) => ExprPrecedence::Box,
ExprKind::InPlace(..) => ExprPrecedence::InPlace,
ExprKind::Array(_) => ExprPrecedence::Array,
ExprKind::Call(..) => ExprPrecedence::Call,
ExprKind::MethodCall(..) => ExprPrecedence::MethodCall,
ExprKind::Tup(_) => ExprPrecedence::Tup,
ExprKind::Binary(op, ..) => ExprPrecedence::Binary(op.node),
ExprKind::Unary(..) => ExprPrecedence::Unary,
ExprKind::Lit(_) => ExprPrecedence::Lit,
ExprKind::Type(..) | ExprKind::Cast(..) => ExprPrecedence::Cast,
ExprKind::If(..) => ExprPrecedence::If,
ExprKind::IfLet(..) => ExprPrecedence::IfLet,
ExprKind::While(..) => ExprPrecedence::While,
ExprKind::WhileLet(..) => ExprPrecedence::WhileLet,
ExprKind::ForLoop(..) => ExprPrecedence::ForLoop,
ExprKind::Loop(..) => ExprPrecedence::Loop,
ExprKind::Match(..) => ExprPrecedence::Match,
ExprKind::Closure(..) => ExprPrecedence::Closure,
ExprKind::Block(..) => ExprPrecedence::Block,
ExprKind::Catch(..) => ExprPrecedence::Catch,
ExprKind::Assign(..) => ExprPrecedence::Assign,
ExprKind::AssignOp(..) => ExprPrecedence::AssignOp,
ExprKind::Field(..) => ExprPrecedence::Field,
ExprKind::TupField(..) => ExprPrecedence::TupField,
ExprKind::Index(..) => ExprPrecedence::Index,
ExprKind::Range(..) => ExprPrecedence::Range,
ExprKind::Path(..) => ExprPrecedence::Path,
ExprKind::AddrOf(..) => ExprPrecedence::AddrOf,
ExprKind::Break(..) => ExprPrecedence::Break,
ExprKind::Continue(..) => ExprPrecedence::Continue,
ExprKind::Ret(..) => ExprPrecedence::Ret,
ExprKind::InlineAsm(..) => ExprPrecedence::InlineAsm,
ExprKind::Mac(..) => ExprPrecedence::Mac,
ExprKind::Struct(..) => ExprPrecedence::Struct,
ExprKind::Repeat(..) => ExprPrecedence::Repeat,
ExprKind::Paren(..) => ExprPrecedence::Paren,
ExprKind::Try(..) => ExprPrecedence::Try,
ExprKind::Yield(..) => ExprPrecedence::Yield,
}
}
}
impl fmt::Debug for Expr {
......
......@@ -1839,7 +1839,7 @@ fn print_call_post(&mut self, args: &[P<ast::Expr>]) -> io::Result<()> {
}
pub fn print_expr_maybe_paren(&mut self, expr: &ast::Expr, prec: i8) -> io::Result<()> {
let needs_par = parser::expr_precedence(expr) < prec;
let needs_par = expr.precedence().order() < prec;
if needs_par {
self.popen()?;
}
......
......@@ -9,7 +9,9 @@
// except according to those terms.
use parse::token::{Token, BinOpToken};
use symbol::keywords;
use ast::{self, BinOpKind, ExprKind};
use ast::{self, BinOpKind};
use std::cmp::Ordering;
/// Associative operator with precedence.
///
......@@ -228,66 +230,130 @@ pub fn to_ast_binop(&self) -> Option<BinOpKind> {
pub const PREC_PAREN: i8 = 99;
pub const PREC_FORCE_PAREN: i8 = 100;
pub fn expr_precedence(expr: &ast::Expr) -> i8 {
match expr.node {
ExprKind::Closure(..) => PREC_CLOSURE,
ExprKind::Break(..) |
ExprKind::Continue(..) |
ExprKind::Ret(..) |
ExprKind::Yield(..) => PREC_JUMP,
// `Range` claims to have higher precedence than `Assign`, but `x .. x = x` fails to parse,
// instead of parsing as `(x .. x) = x`. Giving `Range` a lower precedence ensures that
// `pprust` will add parentheses in the right places to get the desired parse.
ExprKind::Range(..) => PREC_RANGE,
// Binop-like expr kinds, handled by `AssocOp`.
ExprKind::Binary(op, _, _) =>
AssocOp::from_ast_binop(op.node).precedence() as i8,
ExprKind::InPlace(..) => AssocOp::Inplace.precedence() as i8,
ExprKind::Cast(..) => AssocOp::As.precedence() as i8,
ExprKind::Type(..) => AssocOp::Colon.precedence() as i8,
ExprKind::Assign(..) |
ExprKind::AssignOp(..) => AssocOp::Assign.precedence() as i8,
// Unary, prefix
ExprKind::Box(..) |
ExprKind::AddrOf(..) |
ExprKind::Unary(..) => PREC_PREFIX,
// Unary, postfix
ExprKind::Call(..) |
ExprKind::MethodCall(..) |
ExprKind::Field(..) |
ExprKind::TupField(..) |
ExprKind::Index(..) |
ExprKind::Try(..) |
ExprKind::InlineAsm(..) |
ExprKind::Mac(..) => PREC_POSTFIX,
// Never need parens
ExprKind::Array(..) |
ExprKind::Repeat(..) |
ExprKind::Tup(..) |
ExprKind::Lit(..) |
ExprKind::Path(..) |
ExprKind::Paren(..) |
ExprKind::If(..) |
ExprKind::IfLet(..) |
ExprKind::While(..) |
ExprKind::WhileLet(..) |
ExprKind::ForLoop(..) |
ExprKind::Loop(..) |
ExprKind::Match(..) |
ExprKind::Block(..) |
ExprKind::Catch(..) |
ExprKind::Struct(..) => PREC_PAREN,
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ExprPrecedence {
Closure,
Break,
Continue,
Ret,
Yield,
Range,
Binary(BinOpKind),
InPlace,
Cast,
Type,
Assign,
AssignOp,
Box,
AddrOf,
Unary,
Call,
MethodCall,
Field,
TupField,
Index,
Try,
InlineAsm,
Mac,
Array,
Repeat,
Tup,
Lit,
Path,
Paren,
If,
IfLet,
While,
WhileLet,
ForLoop,
Loop,
Match,
Block,
Catch,
Struct,
}
impl PartialOrd for ExprPrecedence {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.order().cmp(&other.order()))
}
}
impl Ord for ExprPrecedence {
fn cmp(&self, other: &Self) -> Ordering {
self.order().cmp(&other.order())
}
}
impl ExprPrecedence {
pub fn order(self) -> i8 {
match self {
ExprPrecedence::Closure => PREC_CLOSURE,
ExprPrecedence::Break |
ExprPrecedence::Continue |
ExprPrecedence::Ret |
ExprPrecedence::Yield => PREC_JUMP,
// `Range` claims to have higher precedence than `Assign`, but `x .. x = x` fails to
// parse, instead of parsing as `(x .. x) = x`. Giving `Range` a lower precedence
// ensures that `pprust` will add parentheses in the right places to get the desired
// parse.
ExprPrecedence::Range => PREC_RANGE,
// Binop-like expr kinds, handled by `AssocOp`.
ExprPrecedence::Binary(op) => AssocOp::from_ast_binop(op).precedence() as i8,
ExprPrecedence::InPlace => AssocOp::Inplace.precedence() as i8,
ExprPrecedence::Cast => AssocOp::As.precedence() as i8,
ExprPrecedence::Type => AssocOp::Colon.precedence() as i8,
ExprPrecedence::Assign |
ExprPrecedence::AssignOp => AssocOp::Assign.precedence() as i8,
// Unary, prefix
ExprPrecedence::Box |
ExprPrecedence::AddrOf |
ExprPrecedence::Unary => PREC_PREFIX,
// Unary, postfix
ExprPrecedence::Call |
ExprPrecedence::MethodCall |
ExprPrecedence::Field |
ExprPrecedence::TupField |
ExprPrecedence::Index |
ExprPrecedence::Try |
ExprPrecedence::InlineAsm |
ExprPrecedence::Mac => PREC_POSTFIX,
// Never need parens
ExprPrecedence::Array |
ExprPrecedence::Repeat |
ExprPrecedence::Tup |
ExprPrecedence::Lit |
ExprPrecedence::Path |
ExprPrecedence::Paren |
ExprPrecedence::If |
ExprPrecedence::IfLet |
ExprPrecedence::While |
ExprPrecedence::WhileLet |
ExprPrecedence::ForLoop |
ExprPrecedence::Loop |
ExprPrecedence::Match |
ExprPrecedence::Block |
ExprPrecedence::Catch |
ExprPrecedence::Struct => PREC_PAREN,
}
}
}
/// Expressions that syntactically contain an "exterior" struct literal i.e. not surrounded by any
/// parens or other delimiters, e.g. `X { y: 1 }`, `X { y: 1 }.method()`, `foo == X { y: 1 }` and
/// `X { y: 1 } == foo` all do, but `(X { y: 1 }) == foo` does not.
......
// 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.
fn foo() -> i32 {
4
}
fn main() {
let x: u16 = foo();
//~^ ERROR mismatched types
let y: i64 = x + x;
//~^ ERROR mismatched types
let z: i32 = x + x;
//~^ ERROR mismatched types
}
error[E0308]: mismatched types
--> $DIR/numeric-cast-2.rs:15:18
|
15 | let x: u16 = foo();
| ^^^^^ expected u16, found i32
error[E0308]: mismatched types
--> $DIR/numeric-cast-2.rs:17:18
|
17 | let y: i64 = x + x;
| ^^^^^ expected i64, found u16
error[E0308]: mismatched types
--> $DIR/numeric-cast-2.rs:19:18
|
19 | let z: i32 = x + x;
| ^^^^^ expected i32, found u16
error: aborting due to 3 previous errors
// 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.
fn foo<N>(_x: N) {}
fn main() {
let x_usize: usize = 1;
let x_u64: u64 = 2;
let x_u32: u32 = 3;
let x_u16: u16 = 4;
let x_u8: u8 = 5;
let x_isize: isize = 6;
let x_i64: i64 = 7;
let x_i32: i32 = 8;
let x_i16: i16 = 9;
let x_i8: i8 = 10;
let x_f64: f64 = 11.0;
let x_f32: f32 = 12.0;
foo::<usize>(x_usize);
foo::<usize>(x_u64);
//~^ ERROR mismatched types
foo::<usize>(x_u32);
//~^ ERROR mismatched types
foo::<usize>(x_u16);
//~^ ERROR mismatched types
foo::<usize>(x_u8);
//~^ ERROR mismatched types
foo::<usize>(x_isize);
//~^ ERROR mismatched types
foo::<usize>(x_i64);
//~^ ERROR mismatched types
foo::<usize>(x_i32);
//~^ ERROR mismatched types
foo::<usize>(x_i16);
//~^ ERROR mismatched types
foo::<usize>(x_i8);
//~^ ERROR mismatched types
foo::<usize>(x_f64);
//~^ ERROR mismatched types
foo::<usize>(x_f32);
//~^ ERROR mismatched types
foo::<isize>(x_usize);
//~^ ERROR mismatched types
foo::<isize>(x_u64);
//~^ ERROR mismatched types
foo::<isize>(x_u32);
//~^ ERROR mismatched types
foo::<isize>(x_u16);
//~^ ERROR mismatched types
foo::<isize>(x_u8);
//~^ ERROR mismatched types
foo::<isize>(x_isize);
foo::<isize>(x_i64);
//~^ ERROR mismatched types
foo::<isize>(x_i32);
//~^ ERROR mismatched types
foo::<isize>(x_i16);
//~^ ERROR mismatched types
foo::<isize>(x_i8);
//~^ ERROR mismatched types
foo::<isize>(x_f64);
//~^ ERROR mismatched types
foo::<isize>(x_f32);
//~^ ERROR mismatched types
foo::<u64>(x_usize);
//~^ ERROR mismatched types
foo::<u64>(x_u64);
foo::<u64>(x_u32);
//~^ ERROR mismatched types
foo::<u64>(x_u16);
//~^ ERROR mismatched types
foo::<u64>(x_u8);
//~^ ERROR mismatched types
foo::<u64>(x_isize);
//~^ ERROR mismatched types
foo::<u64>(x_i64);
//~^ ERROR mismatched types
foo::<u64>(x_i32);
//~^ ERROR mismatched types
foo::<u64>(x_i16);
//~^ ERROR mismatched types
foo::<u64>(x_i8);
//~^ ERROR mismatched types
foo::<u64>(x_f64);
//~^ ERROR mismatched types
foo::<u64>(x_f32);
//~^ ERROR mismatched types
foo::<i64>(x_usize);
//~^ ERROR mismatched types
foo::<i64>(x_u64);
//~^ ERROR mismatched types
foo::<i64>(x_u32);
//~^ ERROR mismatched types
foo::<i64>(x_u16);
//~^ ERROR mismatched types
foo::<i64>(x_u8);
//~^ ERROR mismatched types
foo::<i64>(x_isize);
//~^ ERROR mismatched types
foo::<i64>(x_i64);
foo::<i64>(x_i32);
//~^ ERROR mismatched types
foo::<i64>(x_i16);
//~^ ERROR mismatched types
foo::<i64>(x_i8);
//~^ ERROR mismatched types
foo::<i64>(x_f64);
//~^ ERROR mismatched types
foo::<i64>(x_f32);
//~^ ERROR mismatched types
foo::<u32>(x_usize);
//~^ ERROR mismatched types
foo::<u32>(x_u64);
//~^ ERROR mismatched types
foo::<u32>(x_u32);
foo::<u32>(x_u16);
//~^ ERROR mismatched types
foo::<u32>(x_u8);
//~^ ERROR mismatched types
foo::<u32>(x_isize);
//~^ ERROR mismatched types
foo::<u32>(x_i64);
//~^ ERROR mismatched types
foo::<u32>(x_i32);
//~^ ERROR mismatched types
foo::<u32>(x_i16);
//~^ ERROR mismatched types
foo::<u32>(x_i8);
//~^ ERROR mismatched types
foo::<u32>(x_f64);
//~^ ERROR mismatched types
foo::<u32>(x_f32);
//~^ ERROR mismatched types
foo::<i32>(x_usize);
//~^ ERROR mismatched types
foo::<i32>(x_u64);
//~^ ERROR mismatched types
foo::<i32>(x_u32);
//~^ ERROR mismatched types
foo::<i32>(x_u16);
//~^ ERROR mismatched types
foo::<i32>(x_u8);
//~^ ERROR mismatched types
foo::<i32>(x_isize);
//~^ ERROR mismatched types
foo::<i32>(x_i64);
//~^ ERROR mismatched types
foo::<i32>(x_i32);
foo::<i32>(x_i16);
//~^ ERROR mismatched types
foo::<i32>(x_i8);
//~^ ERROR mismatched types
foo::<i32>(x_f64);
//~^ ERROR mismatched types
foo::<i32>(x_f32);
//~^ ERROR mismatched types
foo::<u16>(x_usize);
//~^ ERROR mismatched types
foo::<u16>(x_u64);
//~^ ERROR mismatched types
foo::<u16>(x_u32);
//~^ ERROR mismatched types
foo::<u16>(x_u16);
foo::<u16>(x_u8);
//~^ ERROR mismatched types
foo::<u16>(x_isize);
//~^ ERROR mismatched types
foo::<u16>(x_i64);
//~^ ERROR mismatched types
foo::<u16>(x_i32);
//~^ ERROR mismatched types
foo::<u16>(x_i16);
//~^ ERROR mismatched types
foo::<u16>(x_i8);
//~^ ERROR mismatched types
foo::<u16>(x_f64);
//~^ ERROR mismatched types
foo::<u16>(x_f32);
//~^ ERROR mismatched types
foo::<i16>(x_usize);
//~^ ERROR mismatched types
foo::<i16>(x_u64);
//~^ ERROR mismatched types
foo::<i16>(x_u32);
//~^ ERROR mismatched types
foo::<i16>(x_u16);
//~^ ERROR mismatched types
foo::<i16>(x_u8);
//~^ ERROR mismatched types
foo::<i16>(x_isize);
//~^ ERROR mismatched types
foo::<i16>(x_i64);
//~^ ERROR mismatched types
foo::<i16>(x_i32);
//~^ ERROR mismatched types
foo::<i16>(x_i16);
foo::<i16>(x_i8);
//~^ ERROR mismatched types
foo::<i16>(x_f64);
//~^ ERROR mismatched types
foo::<i16>(x_f32);
//~^ ERROR mismatched types
foo::<u8>(x_usize);
//~^ ERROR mismatched types
foo::<u8>(x_u64);
//~^ ERROR mismatched types
foo::<u8>(x_u32);
//~^ ERROR mismatched types
foo::<u8>(x_u16);
//~^ ERROR mismatched types
foo::<u8>(x_u8);
foo::<u8>(x_isize);
//~^ ERROR mismatched types
foo::<u8>(x_i64);
//~^ ERROR mismatched types
foo::<u8>(x_i32);
//~^ ERROR mismatched types
foo::<u8>(x_i16);
//~^ ERROR mismatched types
foo::<u8>(x_i8);
//~^ ERROR mismatched types
foo::<u8>(x_f64);
//~^ ERROR mismatched types
foo::<u8>(x_f32);
//~^ ERROR mismatched types
foo::<i8>(x_usize);
//~^ ERROR mismatched types
foo::<i8>(x_u64);
//~^ ERROR mismatched types
foo::<i8>(x_u32);
//~^ ERROR mismatched types
foo::<i8>(x_u16);
//~^ ERROR mismatched types
foo::<i8>(x_u8);
//~^ ERROR mismatched types
foo::<i8>(x_isize);
//~^ ERROR mismatched types
foo::<i8>(x_i64);
//~^ ERROR mismatched types
foo::<i8>(x_i32);
//~^ ERROR mismatched types
foo::<i8>(x_i16);
//~^ ERROR mismatched types
foo::<i8>(x_i8);
foo::<i8>(x_f64);
//~^ ERROR mismatched types
foo::<i8>(x_f32);
//~^ ERROR mismatched types
foo::<f64>(x_usize);
//~^ ERROR mismatched types
foo::<f64>(x_u64);
//~^ ERROR mismatched types
foo::<f64>(x_u32);
//~^ ERROR mismatched types
foo::<f64>(x_u16);
//~^ ERROR mismatched types
foo::<f64>(x_u8);
//~^ ERROR mismatched types
foo::<f64>(x_isize);
//~^ ERROR mismatched types
foo::<f64>(x_i64);
//~^ ERROR mismatched types
foo::<f64>(x_i32);
//~^ ERROR mismatched types
foo::<f64>(x_i16);
//~^ ERROR mismatched types
foo::<f64>(x_i8);
//~^ ERROR mismatched types
foo::<f64>(x_f64);
foo::<f64>(x_f32);
//~^ ERROR mismatched types
foo::<f32>(x_usize);
//~^ ERROR mismatched types
foo::<f32>(x_u64);
//~^ ERROR mismatched types
foo::<f32>(x_u32);
//~^ ERROR mismatched types
foo::<f32>(x_u16);
//~^ ERROR mismatched types
foo::<f32>(x_u8);
//~^ ERROR mismatched types
foo::<f32>(x_isize);
//~^ ERROR mismatched types
foo::<f32>(x_i64);
//~^ ERROR mismatched types
foo::<f32>(x_i32);
//~^ ERROR mismatched types
foo::<f32>(x_i16);
//~^ ERROR mismatched types
foo::<f32>(x_i8);
//~^ ERROR mismatched types
foo::<f32>(x_f64);
//~^ ERROR mismatched types
foo::<f32>(x_f32);
}
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册