Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 7bdf7d0

Browse files
authoredJun 11, 2020
Rollup merge of #73195 - ayazhafiz:i/73145, r=estebank
Provide suggestion to convert numeric op LHS rather than unwrapping RHS Given a code ```rust fn foo(x: u8, y: u32) -> bool { x > y } fn main() {} ``` it could be more helpful to provide a suggestion to do "u32::from(x)" rather than "y.try_into().unwrap()", since the latter may panic. We do this by passing the LHS of a binary expression up the stack into the coercion checker. Closes #73145
2 parents 838d25b + 0c02f8a commit 7bdf7d0

File tree

8 files changed

+2126
-50
lines changed

8 files changed

+2126
-50
lines changed
 

‎src/librustc_typeck/check/coercion.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1377,7 +1377,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
13771377
}
13781378

13791379
if let Some(expr) = expression {
1380-
fcx.emit_coerce_suggestions(&mut err, expr, found, expected);
1380+
fcx.emit_coerce_suggestions(&mut err, expr, found, expected, None);
13811381
}
13821382

13831383
// Error possibly reported in `check_assign` so avoid emitting error again.

‎src/librustc_typeck/check/demand.rs

Lines changed: 79 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2424
expr: &hir::Expr<'_>,
2525
expr_ty: Ty<'tcx>,
2626
expected: Ty<'tcx>,
27+
expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
2728
) {
2829
self.annotate_expected_due_to_let_ty(err, expr);
2930
self.suggest_compatible_variants(err, expr, expected, expr_ty);
30-
self.suggest_deref_ref_or_into(err, expr, expected, expr_ty);
31+
self.suggest_deref_ref_or_into(err, expr, expected, expr_ty, expected_ty_expr);
3132
if self.suggest_calling_boxed_future_when_appropriate(err, expr, expected, expr_ty) {
3233
return;
3334
}
@@ -102,9 +103,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
102103
expr: &hir::Expr<'_>,
103104
checked_ty: Ty<'tcx>,
104105
expected: Ty<'tcx>,
106+
expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
105107
allow_two_phase: AllowTwoPhase,
106108
) -> Ty<'tcx> {
107-
let (ty, err) = self.demand_coerce_diag(expr, checked_ty, expected, allow_two_phase);
109+
let (ty, err) =
110+
self.demand_coerce_diag(expr, checked_ty, expected, expected_ty_expr, allow_two_phase);
108111
if let Some(mut err) = err {
109112
err.emit();
110113
}
@@ -121,6 +124,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
121124
expr: &hir::Expr<'_>,
122125
checked_ty: Ty<'tcx>,
123126
expected: Ty<'tcx>,
127+
expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
124128
allow_two_phase: AllowTwoPhase,
125129
) -> (Ty<'tcx>, Option<DiagnosticBuilder<'tcx>>) {
126130
let expected = self.resolve_vars_with_obligations(expected);
@@ -141,7 +145,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
141145
return (expected, None);
142146
}
143147

144-
self.emit_coerce_suggestions(&mut err, expr, expr_ty, expected);
148+
self.emit_coerce_suggestions(&mut err, expr, expr_ty, expected, expected_ty_expr);
145149

146150
(expected, Some(err))
147151
}
@@ -671,6 +675,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
671675
expr: &hir::Expr<'_>,
672676
checked_ty: Ty<'tcx>,
673677
expected_ty: Ty<'tcx>,
678+
expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
674679
) -> bool {
675680
if self.tcx.sess.source_map().is_imported(expr.span) {
676681
// Ignore if span is from within a macro.
@@ -747,7 +752,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
747752

748753
let msg = format!("you can convert an `{}` to `{}`", checked_ty, expected_ty);
749754
let cast_msg = format!("you can cast an `{} to `{}`", checked_ty, expected_ty);
750-
let try_msg = format!("{} and panic if the converted value wouldn't fit", msg);
751755
let lit_msg = format!(
752756
"change the type of the numeric literal from `{}` to `{}`",
753757
checked_ty, expected_ty,
@@ -761,7 +765,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
761765
};
762766

763767
let cast_suggestion = format!("{}{} as {}", prefix, with_opt_paren(&src), expected_ty);
764-
let try_into_suggestion = format!("{}{}.try_into().unwrap()", prefix, with_opt_paren(&src));
765768
let into_suggestion = format!("{}{}.into()", prefix, with_opt_paren(&src));
766769
let suffix_suggestion = with_opt_paren(&format_args!(
767770
"{}{}",
@@ -782,22 +785,55 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
782785
};
783786

784787
let in_const_context = self.tcx.hir().is_inside_const_context(expr.hir_id);
788+
789+
let suggest_fallible_into_or_lhs_from =
790+
|err: &mut DiagnosticBuilder<'_>, exp_to_found_is_fallible: bool| {
791+
// If we know the expression the expected type is derived from, we might be able
792+
// to suggest a widening conversion rather than a narrowing one (which may
793+
// panic). For example, given x: u8 and y: u32, if we know the span of "x",
794+
// x > y
795+
// can be given the suggestion "u32::from(x) > y" rather than
796+
// "x > y.try_into().unwrap()".
797+
let lhs_expr_and_src = expected_ty_expr.and_then(|expr| {
798+
match self.tcx.sess.source_map().span_to_snippet(expr.span).ok() {
799+
Some(src) => Some((expr, src)),
800+
None => None,
801+
}
802+
});
803+
let (span, msg, suggestion) = if let (Some((lhs_expr, lhs_src)), false) =
804+
(lhs_expr_and_src, exp_to_found_is_fallible)
805+
{
806+
let msg = format!(
807+
"you can convert `{}` from `{}` to `{}`, matching the type of `{}`",
808+
lhs_src, expected_ty, checked_ty, src
809+
);
810+
let suggestion = format!("{}::from({})", checked_ty, lhs_src,);
811+
(lhs_expr.span, msg, suggestion)
812+
} else {
813+
let msg = format!("{} and panic if the converted value wouldn't fit", msg);
814+
let suggestion =
815+
format!("{}{}.try_into().unwrap()", prefix, with_opt_paren(&src));
816+
(expr.span, msg, suggestion)
817+
};
818+
err.span_suggestion(span, &msg, suggestion, Applicability::MachineApplicable);
819+
};
820+
785821
let suggest_to_change_suffix_or_into =
786-
|err: &mut DiagnosticBuilder<'_>, is_fallible: bool| {
822+
|err: &mut DiagnosticBuilder<'_>,
823+
found_to_exp_is_fallible: bool,
824+
exp_to_found_is_fallible: bool| {
787825
let msg = if literal_is_ty_suffixed(expr) {
788826
&lit_msg
789827
} else if in_const_context {
790828
// Do not recommend `into` or `try_into` in const contexts.
791829
return;
792-
} else if is_fallible {
793-
&try_msg
830+
} else if found_to_exp_is_fallible {
831+
return suggest_fallible_into_or_lhs_from(err, exp_to_found_is_fallible);
794832
} else {
795833
&msg
796834
};
797835
let suggestion = if literal_is_ty_suffixed(expr) {
798836
suffix_suggestion.clone()
799-
} else if is_fallible {
800-
try_into_suggestion
801837
} else {
802838
into_suggestion.clone()
803839
};
@@ -806,41 +842,54 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
806842

807843
match (&expected_ty.kind, &checked_ty.kind) {
808844
(&ty::Int(ref exp), &ty::Int(ref found)) => {
809-
let is_fallible = match (exp.bit_width(), found.bit_width()) {
810-
(Some(exp), Some(found)) if exp < found => true,
811-
(None, Some(8 | 16)) => false,
812-
(None, _) | (_, None) => true,
813-
_ => false,
845+
let (f2e_is_fallible, e2f_is_fallible) = match (exp.bit_width(), found.bit_width())
846+
{
847+
(Some(exp), Some(found)) if exp < found => (true, false),
848+
(Some(exp), Some(found)) if exp > found => (false, true),
849+
(None, Some(8 | 16)) => (false, true),
850+
(Some(8 | 16), None) => (true, false),
851+
(None, _) | (_, None) => (true, true),
852+
_ => (false, false),
814853
};
815-
suggest_to_change_suffix_or_into(err, is_fallible);
854+
suggest_to_change_suffix_or_into(err, f2e_is_fallible, e2f_is_fallible);
816855
true
817856
}
818857
(&ty::Uint(ref exp), &ty::Uint(ref found)) => {
819-
let is_fallible = match (exp.bit_width(), found.bit_width()) {
820-
(Some(exp), Some(found)) if exp < found => true,
821-
(None, Some(8 | 16)) => false,
822-
(None, _) | (_, None) => true,
823-
_ => false,
858+
let (f2e_is_fallible, e2f_is_fallible) = match (exp.bit_width(), found.bit_width())
859+
{
860+
(Some(exp), Some(found)) if exp < found => (true, false),
861+
(Some(exp), Some(found)) if exp > found => (false, true),
862+
(None, Some(8 | 16)) => (false, true),
863+
(Some(8 | 16), None) => (true, false),
864+
(None, _) | (_, None) => (true, true),
865+
_ => (false, false),
824866
};
825-
suggest_to_change_suffix_or_into(err, is_fallible);
867+
suggest_to_change_suffix_or_into(err, f2e_is_fallible, e2f_is_fallible);
826868
true
827869
}
828870
(&ty::Int(exp), &ty::Uint(found)) => {
829-
let is_fallible = match (exp.bit_width(), found.bit_width()) {
830-
(Some(exp), Some(found)) if found < exp => false,
831-
(None, Some(8)) => false,
832-
_ => true,
871+
let (f2e_is_fallible, e2f_is_fallible) = match (exp.bit_width(), found.bit_width())
872+
{
873+
(Some(exp), Some(found)) if found < exp => (false, true),
874+
(None, Some(8)) => (false, true),
875+
_ => (true, true),
833876
};
834-
suggest_to_change_suffix_or_into(err, is_fallible);
877+
suggest_to_change_suffix_or_into(err, f2e_is_fallible, e2f_is_fallible);
835878
true
836879
}
837-
(&ty::Uint(_), &ty::Int(_)) => {
838-
suggest_to_change_suffix_or_into(err, true);
880+
(&ty::Uint(exp), &ty::Int(found)) => {
881+
let (f2e_is_fallible, e2f_is_fallible) = match (exp.bit_width(), found.bit_width())
882+
{
883+
(Some(exp), Some(found)) if found > exp => (true, false),
884+
(Some(8), None) => (true, false),
885+
_ => (true, true),
886+
};
887+
suggest_to_change_suffix_or_into(err, f2e_is_fallible, e2f_is_fallible);
839888
true
840889
}
841890
(&ty::Float(ref exp), &ty::Float(ref found)) => {
842891
if found.bit_width() < exp.bit_width() {
843-
suggest_to_change_suffix_or_into(err, false);
892+
suggest_to_change_suffix_or_into(err, false, true);
844893
} else if literal_is_ty_suffixed(expr) {
845894
err.span_suggestion(
846895
expr.span,

‎src/librustc_typeck/check/expr.rs

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
8686

8787
if let Some(mut err) = self.demand_suptype_diag(expr.span, expected_ty, ty) {
8888
let expr = expr.peel_drop_temps();
89-
self.suggest_deref_ref_or_into(&mut err, expr, expected_ty, ty);
89+
self.suggest_deref_ref_or_into(&mut err, expr, expected_ty, ty, None);
9090
extend_err(&mut err);
9191
// Error possibly reported in `check_assign` so avoid emitting error again.
9292
err.emit_unless(self.is_assign_to_bool(expr, expected_ty));
@@ -98,10 +98,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
9898
&self,
9999
expr: &'tcx hir::Expr<'tcx>,
100100
expected: Ty<'tcx>,
101+
expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
101102
) -> Ty<'tcx> {
102103
let ty = self.check_expr_with_hint(expr, expected);
103104
// checks don't need two phase
104-
self.demand_coerce(expr, ty, expected, AllowTwoPhase::No)
105+
self.demand_coerce(expr, ty, expected, expected_ty_expr, AllowTwoPhase::No)
105106
}
106107

107108
pub(super) fn check_expr_with_hint(
@@ -776,7 +777,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
776777
span: &Span,
777778
) -> Ty<'tcx> {
778779
let lhs_ty = self.check_expr_with_needs(&lhs, Needs::MutPlace);
779-
let rhs_ty = self.check_expr_coercable_to_type(&rhs, lhs_ty);
780+
let rhs_ty = self.check_expr_coercable_to_type(&rhs, lhs_ty, Some(lhs));
780781

781782
let expected_ty = expected.coercion_target_type(self, expr.span);
782783
if expected_ty == self.tcx.types.bool {
@@ -1026,7 +1027,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10261027

10271028
let (element_ty, t) = match uty {
10281029
Some(uty) => {
1029-
self.check_expr_coercable_to_type(&element, uty);
1030+
self.check_expr_coercable_to_type(&element, uty, None);
10301031
(uty, uty)
10311032
}
10321033
None => {
@@ -1063,7 +1064,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10631064
let elt_ts_iter = elts.iter().enumerate().map(|(i, e)| match flds {
10641065
Some(ref fs) if i < fs.len() => {
10651066
let ety = fs[i].expect_ty();
1066-
self.check_expr_coercable_to_type(&e, ety);
1067+
self.check_expr_coercable_to_type(&e, ety, None);
10671068
ety
10681069
}
10691070
_ => self.check_expr_with_expectation(&e, NoExpectation),
@@ -1237,7 +1238,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12371238

12381239
// Make sure to give a type to the field even if there's
12391240
// an error, so we can continue type-checking.
1240-
self.check_expr_coercable_to_type(&field.expr, field_type);
1241+
self.check_expr_coercable_to_type(&field.expr, field_type, None);
12411242
}
12421243

12431244
// Make sure the programmer specified correct number of fields.
@@ -1735,7 +1736,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
17351736
match self.lookup_indexing(expr, base, base_t, idx_t, needs) {
17361737
Some((index_ty, element_ty)) => {
17371738
// two-phase not needed because index_ty is never mutable
1738-
self.demand_coerce(idx, idx_t, index_ty, AllowTwoPhase::No);
1739+
self.demand_coerce(idx, idx_t, index_ty, None, AllowTwoPhase::No);
17391740
element_ty
17401741
}
17411742
None => {
@@ -1788,7 +1789,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
17881789
) -> Ty<'tcx> {
17891790
match self.resume_yield_tys {
17901791
Some((resume_ty, yield_ty)) => {
1791-
self.check_expr_coercable_to_type(&value, yield_ty);
1792+
self.check_expr_coercable_to_type(&value, yield_ty, None);
17921793

17931794
resume_ty
17941795
}
@@ -1797,7 +1798,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
17971798
// information. Hence, we check the source of the yield expression here and check its
17981799
// value's type against `()` (this check should always hold).
17991800
None if src.is_await() => {
1800-
self.check_expr_coercable_to_type(&value, self.tcx.mk_unit());
1801+
self.check_expr_coercable_to_type(&value, self.tcx.mk_unit(), None);
18011802
self.tcx.mk_unit()
18021803
}
18031804
_ => {
@@ -1836,11 +1837,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
18361837
match ty.kind {
18371838
ty::FnDef(..) => {
18381839
let fnptr_ty = self.tcx.mk_fn_ptr(ty.fn_sig(self.tcx));
1839-
self.demand_coerce(expr, ty, fnptr_ty, AllowTwoPhase::No);
1840+
self.demand_coerce(expr, ty, fnptr_ty, None, AllowTwoPhase::No);
18401841
}
18411842
ty::Ref(_, base_ty, mutbl) => {
18421843
let ptr_ty = self.tcx.mk_ptr(ty::TypeAndMut { ty: base_ty, mutbl });
1843-
self.demand_coerce(expr, ty, ptr_ty, AllowTwoPhase::No);
1844+
self.demand_coerce(expr, ty, ptr_ty, None, AllowTwoPhase::No);
18441845
}
18451846
_ => {}
18461847
}

‎src/librustc_typeck/check/mod.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1046,7 +1046,7 @@ fn typeck_tables_of_with_fallback<'tcx>(
10461046
// Gather locals in statics (because of block expressions).
10471047
GatherLocalsVisitor { fcx: &fcx, parent_id: id }.visit_body(body);
10481048

1049-
fcx.check_expr_coercable_to_type(&body.value, revealed_ty);
1049+
fcx.check_expr_coercable_to_type(&body.value, revealed_ty, None);
10501050

10511051
fcx.write_ty(id, revealed_ty);
10521052

@@ -4123,7 +4123,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
41234123
let coerce_ty = expected.only_has_type(self).unwrap_or(formal_ty);
41244124
// We're processing function arguments so we definitely want to use
41254125
// two-phase borrows.
4126-
self.demand_coerce(&arg, checked_ty, coerce_ty, AllowTwoPhase::Yes);
4126+
self.demand_coerce(&arg, checked_ty, coerce_ty, None, AllowTwoPhase::Yes);
41274127
final_arg_types.push((i, checked_ty, coerce_ty));
41284128

41294129
// 3. Relate the expected type and the formal one,
@@ -4541,7 +4541,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
45414541
self.demand_eqtype(init.span, local_ty, init_ty);
45424542
init_ty
45434543
} else {
4544-
self.check_expr_coercable_to_type(init, local_ty)
4544+
self.check_expr_coercable_to_type(init, local_ty, None)
45454545
}
45464546
}
45474547

@@ -5027,6 +5027,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
50275027
expr: &hir::Expr<'_>,
50285028
expected: Ty<'tcx>,
50295029
found: Ty<'tcx>,
5030+
expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
50305031
) {
50315032
if let Some((sp, msg, suggestion, applicability)) = self.check_ref(expr, found, expected) {
50325033
err.span_suggestion(sp, msg, suggestion, applicability);
@@ -5037,7 +5038,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
50375038
let sp = self.sess().source_map().guess_head_span(sp);
50385039
err.span_label(sp, &format!("{} defined here", found));
50395040
}
5040-
} else if !self.check_for_cast(err, expr, found, expected) {
5041+
} else if !self.check_for_cast(err, expr, found, expected, expected_ty_expr) {
50415042
let is_struct_pat_shorthand_field =
50425043
self.is_hir_id_from_struct_pattern_shorthand_field(expr.hir_id, expr.span);
50435044
let methods = self.get_conversion_methods(expr.span, expected, found, expr.hir_id);

‎src/librustc_typeck/check/op.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
5757
match BinOpCategory::from(op) {
5858
BinOpCategory::Shortcircuit => {
5959
// && and || are a simple case.
60-
self.check_expr_coercable_to_type(lhs_expr, tcx.types.bool);
60+
self.check_expr_coercable_to_type(lhs_expr, tcx.types.bool, None);
6161
let lhs_diverges = self.diverges.get();
62-
self.check_expr_coercable_to_type(rhs_expr, tcx.types.bool);
62+
self.check_expr_coercable_to_type(rhs_expr, tcx.types.bool, None);
6363

6464
// Depending on the LHS' value, the RHS can never execute.
6565
self.diverges.set(lhs_diverges);
@@ -170,7 +170,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
170170
kind: TypeVariableOriginKind::MiscVariable,
171171
span: lhs_expr.span,
172172
});
173-
self.demand_coerce(lhs_expr, lhs_ty, fresh_var, AllowTwoPhase::No)
173+
self.demand_coerce(lhs_expr, lhs_ty, fresh_var, Some(rhs_expr), AllowTwoPhase::No)
174174
}
175175
IsAssign::Yes => {
176176
// rust-lang/rust#52126: We have to use strict
@@ -196,7 +196,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
196196
let result = self.lookup_op_method(lhs_ty, &[rhs_ty_var], Op::Binary(op, is_assign));
197197

198198
// see `NB` above
199-
let rhs_ty = self.check_expr_coercable_to_type(rhs_expr, rhs_ty_var);
199+
let rhs_ty = self.check_expr_coercable_to_type(rhs_expr, rhs_ty_var, Some(lhs_expr));
200200
let rhs_ty = self.resolve_vars_with_obligations(rhs_ty);
201201

202202
let return_ty = match result {
Lines changed: 320 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,320 @@
1+
// run-rustfix
2+
3+
// The `try_into` suggestion doesn't include this, but we do suggest it after applying it
4+
use std::convert::TryInto;
5+
6+
#[allow(unused_must_use)]
7+
fn main() {
8+
let x_usize: usize = 1;
9+
let x_u128: u128 = 2;
10+
let x_u64: u64 = 3;
11+
let x_u32: u32 = 4;
12+
let x_u16: u16 = 5;
13+
let x_u8: u8 = 6;
14+
let x_isize: isize = 7;
15+
let x_i64: i64 = 8;
16+
let x_i32: i32 = 9;
17+
let x_i16: i16 = 10;
18+
let x_i8: i8 = 11;
19+
let x_i128: i128 = 12;
20+
21+
/* u<->u */
22+
{
23+
u16::from(x_u8) > x_u16;
24+
//~^ ERROR mismatched types
25+
u32::from(x_u8) > x_u32;
26+
//~^ ERROR mismatched types
27+
u64::from(x_u8) > x_u64;
28+
//~^ ERROR mismatched types
29+
u128::from(x_u8) > x_u128;
30+
//~^ ERROR mismatched types
31+
usize::from(x_u8) > x_usize;
32+
//~^ ERROR mismatched types
33+
34+
x_u16 > x_u8.into();
35+
//~^ ERROR mismatched types
36+
u32::from(x_u16) > x_u32;
37+
//~^ ERROR mismatched types
38+
u64::from(x_u16) > x_u64;
39+
//~^ ERROR mismatched types
40+
u128::from(x_u16) > x_u128;
41+
//~^ ERROR mismatched types
42+
usize::from(x_u16) > x_usize;
43+
//~^ ERROR mismatched types
44+
45+
x_u32 > x_u8.into();
46+
//~^ ERROR mismatched types
47+
x_u32 > x_u16.into();
48+
//~^ ERROR mismatched types
49+
u64::from(x_u32) > x_u64;
50+
//~^ ERROR mismatched types
51+
u128::from(x_u32) > x_u128;
52+
//~^ ERROR mismatched types
53+
x_u32 > x_usize.try_into().unwrap();
54+
//~^ ERROR mismatched types
55+
56+
x_u64 > x_u8.into();
57+
//~^ ERROR mismatched types
58+
x_u64 > x_u16.into();
59+
//~^ ERROR mismatched types
60+
x_u64 > x_u32.into();
61+
//~^ ERROR mismatched types
62+
u128::from(x_u64) > x_u128;
63+
//~^ ERROR mismatched types
64+
x_u64 > x_usize.try_into().unwrap();
65+
//~^ ERROR mismatched types
66+
67+
x_u128 > x_u8.into();
68+
//~^ ERROR mismatched types
69+
x_u128 > x_u16.into();
70+
//~^ ERROR mismatched types
71+
x_u128 > x_u32.into();
72+
//~^ ERROR mismatched types
73+
x_u128 > x_u64.into();
74+
//~^ ERROR mismatched types
75+
x_u128 > x_usize.try_into().unwrap();
76+
//~^ ERROR mismatched types
77+
78+
x_usize > x_u8.into();
79+
//~^ ERROR mismatched types
80+
x_usize > x_u16.into();
81+
//~^ ERROR mismatched types
82+
x_usize > x_u32.try_into().unwrap();
83+
//~^ ERROR mismatched types
84+
x_usize > x_u64.try_into().unwrap();
85+
//~^ ERROR mismatched types
86+
x_usize > x_u128.try_into().unwrap();
87+
//~^ ERROR mismatched types
88+
}
89+
90+
/* i<->i */
91+
{
92+
i16::from(x_i8) > x_i16;
93+
//~^ ERROR mismatched types
94+
i32::from(x_i8) > x_i32;
95+
//~^ ERROR mismatched types
96+
i64::from(x_i8) > x_i64;
97+
//~^ ERROR mismatched types
98+
i128::from(x_i8) > x_i128;
99+
//~^ ERROR mismatched types
100+
isize::from(x_i8) > x_isize;
101+
//~^ ERROR mismatched types
102+
103+
x_i16 > x_i8.into();
104+
//~^ ERROR mismatched types
105+
i32::from(x_i16) > x_i32;
106+
//~^ ERROR mismatched types
107+
i64::from(x_i16) > x_i64;
108+
//~^ ERROR mismatched types
109+
i128::from(x_i16) > x_i128;
110+
//~^ ERROR mismatched types
111+
isize::from(x_i16) > x_isize;
112+
//~^ ERROR mismatched types
113+
114+
x_i32 > x_i8.into();
115+
//~^ ERROR mismatched types
116+
x_i32 > x_i16.into();
117+
//~^ ERROR mismatched types
118+
i64::from(x_i32) > x_i64;
119+
//~^ ERROR mismatched types
120+
i128::from(x_i32) > x_i128;
121+
//~^ ERROR mismatched types
122+
x_i32 > x_isize.try_into().unwrap();
123+
//~^ ERROR mismatched types
124+
125+
x_i64 > x_i8.into();
126+
//~^ ERROR mismatched types
127+
x_i64 > x_i16.into();
128+
//~^ ERROR mismatched types
129+
x_i64 > x_i32.into();
130+
//~^ ERROR mismatched types
131+
i128::from(x_i64) > x_i128;
132+
//~^ ERROR mismatched types
133+
x_i64 > x_isize.try_into().unwrap();
134+
//~^ ERROR mismatched types
135+
136+
x_i128 > x_i8.into();
137+
//~^ ERROR mismatched types
138+
x_i128 > x_i16.into();
139+
//~^ ERROR mismatched types
140+
x_i128 > x_i32.into();
141+
//~^ ERROR mismatched types
142+
x_i128 > x_i64.into();
143+
//~^ ERROR mismatched types
144+
x_i128 > x_isize.try_into().unwrap();
145+
//~^ ERROR mismatched types
146+
147+
x_isize > x_i8.into();
148+
//~^ ERROR mismatched types
149+
x_isize > x_i16.into();
150+
//~^ ERROR mismatched types
151+
x_isize > x_i32.try_into().unwrap();
152+
//~^ ERROR mismatched types
153+
x_isize > x_i64.try_into().unwrap();
154+
//~^ ERROR mismatched types
155+
x_isize > x_i128.try_into().unwrap();
156+
//~^ ERROR mismatched types
157+
}
158+
159+
/* u<->i */
160+
{
161+
x_u8 > x_i8.try_into().unwrap();
162+
//~^ ERROR mismatched types
163+
i16::from(x_u8) > x_i16;
164+
//~^ ERROR mismatched types
165+
i32::from(x_u8) > x_i32;
166+
//~^ ERROR mismatched types
167+
i64::from(x_u8) > x_i64;
168+
//~^ ERROR mismatched types
169+
i128::from(x_u8) > x_i128;
170+
//~^ ERROR mismatched types
171+
isize::from(x_u8) > x_isize;
172+
//~^ ERROR mismatched types
173+
174+
x_u16 > x_i8.try_into().unwrap();
175+
//~^ ERROR mismatched types
176+
x_u16 > x_i16.try_into().unwrap();
177+
//~^ ERROR mismatched types
178+
i32::from(x_u16) > x_i32;
179+
//~^ ERROR mismatched types
180+
i64::from(x_u16) > x_i64;
181+
//~^ ERROR mismatched types
182+
i128::from(x_u16) > x_i128;
183+
//~^ ERROR mismatched types
184+
x_u16 > x_isize.try_into().unwrap();
185+
//~^ ERROR mismatched types
186+
187+
x_u32 > x_i8.try_into().unwrap();
188+
//~^ ERROR mismatched types
189+
x_u32 > x_i16.try_into().unwrap();
190+
//~^ ERROR mismatched types
191+
x_u32 > x_i32.try_into().unwrap();
192+
//~^ ERROR mismatched types
193+
i64::from(x_u32) > x_i64;
194+
//~^ ERROR mismatched types
195+
i128::from(x_u32) > x_i128;
196+
//~^ ERROR mismatched types
197+
x_u32 > x_isize.try_into().unwrap();
198+
//~^ ERROR mismatched types
199+
200+
x_u64 > x_i8.try_into().unwrap();
201+
//~^ ERROR mismatched types
202+
x_u64 > x_i16.try_into().unwrap();
203+
//~^ ERROR mismatched types
204+
x_u64 > x_i32.try_into().unwrap();
205+
//~^ ERROR mismatched types
206+
x_u64 > x_i64.try_into().unwrap();
207+
//~^ ERROR mismatched types
208+
i128::from(x_u64) > x_i128;
209+
//~^ ERROR mismatched types
210+
x_u64 > x_isize.try_into().unwrap();
211+
//~^ ERROR mismatched types
212+
213+
x_u128 > x_i8.try_into().unwrap();
214+
//~^ ERROR mismatched types
215+
x_u128 > x_i16.try_into().unwrap();
216+
//~^ ERROR mismatched types
217+
x_u128 > x_i32.try_into().unwrap();
218+
//~^ ERROR mismatched types
219+
x_u128 > x_i64.try_into().unwrap();
220+
//~^ ERROR mismatched types
221+
x_u128 > x_i128.try_into().unwrap();
222+
//~^ ERROR mismatched types
223+
x_u128 > x_isize.try_into().unwrap();
224+
//~^ ERROR mismatched types
225+
226+
x_usize > x_i8.try_into().unwrap();
227+
//~^ ERROR mismatched types
228+
x_usize > x_i16.try_into().unwrap();
229+
//~^ ERROR mismatched types
230+
x_usize > x_i32.try_into().unwrap();
231+
//~^ ERROR mismatched types
232+
x_usize > x_i64.try_into().unwrap();
233+
//~^ ERROR mismatched types
234+
x_usize > x_i128.try_into().unwrap();
235+
//~^ ERROR mismatched types
236+
x_usize > x_isize.try_into().unwrap();
237+
//~^ ERROR mismatched types
238+
}
239+
240+
/* i<->u */
241+
{
242+
x_i8 > x_u8.try_into().unwrap();
243+
//~^ ERROR mismatched types
244+
x_i8 > x_u16.try_into().unwrap();
245+
//~^ ERROR mismatched types
246+
x_i8 > x_u32.try_into().unwrap();
247+
//~^ ERROR mismatched types
248+
x_i8 > x_u64.try_into().unwrap();
249+
//~^ ERROR mismatched types
250+
x_i8 > x_u128.try_into().unwrap();
251+
//~^ ERROR mismatched types
252+
x_i8 > x_usize.try_into().unwrap();
253+
//~^ ERROR mismatched types
254+
255+
x_i16 > x_u8.into();
256+
//~^ ERROR mismatched types
257+
x_i16 > x_u16.try_into().unwrap();
258+
//~^ ERROR mismatched types
259+
x_i16 > x_u32.try_into().unwrap();
260+
//~^ ERROR mismatched types
261+
x_i16 > x_u64.try_into().unwrap();
262+
//~^ ERROR mismatched types
263+
x_i16 > x_u128.try_into().unwrap();
264+
//~^ ERROR mismatched types
265+
x_i16 > x_usize.try_into().unwrap();
266+
//~^ ERROR mismatched types
267+
268+
x_i32 > x_u8.into();
269+
//~^ ERROR mismatched types
270+
x_i32 > x_u16.into();
271+
//~^ ERROR mismatched types
272+
x_i32 > x_u32.try_into().unwrap();
273+
//~^ ERROR mismatched types
274+
x_i32 > x_u64.try_into().unwrap();
275+
//~^ ERROR mismatched types
276+
x_i32 > x_u128.try_into().unwrap();
277+
//~^ ERROR mismatched types
278+
x_i32 > x_usize.try_into().unwrap();
279+
//~^ ERROR mismatched types
280+
281+
x_i64 > x_u8.into();
282+
//~^ ERROR mismatched types
283+
x_i64 > x_u16.into();
284+
//~^ ERROR mismatched types
285+
x_i64 > x_u32.into();
286+
//~^ ERROR mismatched types
287+
x_i64 > x_u64.try_into().unwrap();
288+
//~^ ERROR mismatched types
289+
x_i64 > x_u128.try_into().unwrap();
290+
//~^ ERROR mismatched types
291+
x_i64 > x_usize.try_into().unwrap();
292+
//~^ ERROR mismatched types
293+
294+
x_i128 > x_u8.into();
295+
//~^ ERROR mismatched types
296+
x_i128 > x_u16.into();
297+
//~^ ERROR mismatched types
298+
x_i128 > x_u32.into();
299+
//~^ ERROR mismatched types
300+
x_i128 > x_u64.into();
301+
//~^ ERROR mismatched types
302+
x_i128 > x_u128.try_into().unwrap();
303+
//~^ ERROR mismatched types
304+
x_i128 > x_usize.try_into().unwrap();
305+
//~^ ERROR mismatched types
306+
307+
x_isize > x_u8.into();
308+
//~^ ERROR mismatched types
309+
x_isize > x_u16.try_into().unwrap();
310+
//~^ ERROR mismatched types
311+
x_isize > x_u32.try_into().unwrap();
312+
//~^ ERROR mismatched types
313+
x_isize > x_u64.try_into().unwrap();
314+
//~^ ERROR mismatched types
315+
x_isize > x_u128.try_into().unwrap();
316+
//~^ ERROR mismatched types
317+
x_isize > x_usize.try_into().unwrap();
318+
//~^ ERROR mismatched types
319+
}
320+
}
Lines changed: 320 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,320 @@
1+
// run-rustfix
2+
3+
// The `try_into` suggestion doesn't include this, but we do suggest it after applying it
4+
use std::convert::TryInto;
5+
6+
#[allow(unused_must_use)]
7+
fn main() {
8+
let x_usize: usize = 1;
9+
let x_u128: u128 = 2;
10+
let x_u64: u64 = 3;
11+
let x_u32: u32 = 4;
12+
let x_u16: u16 = 5;
13+
let x_u8: u8 = 6;
14+
let x_isize: isize = 7;
15+
let x_i64: i64 = 8;
16+
let x_i32: i32 = 9;
17+
let x_i16: i16 = 10;
18+
let x_i8: i8 = 11;
19+
let x_i128: i128 = 12;
20+
21+
/* u<->u */
22+
{
23+
x_u8 > x_u16;
24+
//~^ ERROR mismatched types
25+
x_u8 > x_u32;
26+
//~^ ERROR mismatched types
27+
x_u8 > x_u64;
28+
//~^ ERROR mismatched types
29+
x_u8 > x_u128;
30+
//~^ ERROR mismatched types
31+
x_u8 > x_usize;
32+
//~^ ERROR mismatched types
33+
34+
x_u16 > x_u8;
35+
//~^ ERROR mismatched types
36+
x_u16 > x_u32;
37+
//~^ ERROR mismatched types
38+
x_u16 > x_u64;
39+
//~^ ERROR mismatched types
40+
x_u16 > x_u128;
41+
//~^ ERROR mismatched types
42+
x_u16 > x_usize;
43+
//~^ ERROR mismatched types
44+
45+
x_u32 > x_u8;
46+
//~^ ERROR mismatched types
47+
x_u32 > x_u16;
48+
//~^ ERROR mismatched types
49+
x_u32 > x_u64;
50+
//~^ ERROR mismatched types
51+
x_u32 > x_u128;
52+
//~^ ERROR mismatched types
53+
x_u32 > x_usize;
54+
//~^ ERROR mismatched types
55+
56+
x_u64 > x_u8;
57+
//~^ ERROR mismatched types
58+
x_u64 > x_u16;
59+
//~^ ERROR mismatched types
60+
x_u64 > x_u32;
61+
//~^ ERROR mismatched types
62+
x_u64 > x_u128;
63+
//~^ ERROR mismatched types
64+
x_u64 > x_usize;
65+
//~^ ERROR mismatched types
66+
67+
x_u128 > x_u8;
68+
//~^ ERROR mismatched types
69+
x_u128 > x_u16;
70+
//~^ ERROR mismatched types
71+
x_u128 > x_u32;
72+
//~^ ERROR mismatched types
73+
x_u128 > x_u64;
74+
//~^ ERROR mismatched types
75+
x_u128 > x_usize;
76+
//~^ ERROR mismatched types
77+
78+
x_usize > x_u8;
79+
//~^ ERROR mismatched types
80+
x_usize > x_u16;
81+
//~^ ERROR mismatched types
82+
x_usize > x_u32;
83+
//~^ ERROR mismatched types
84+
x_usize > x_u64;
85+
//~^ ERROR mismatched types
86+
x_usize > x_u128;
87+
//~^ ERROR mismatched types
88+
}
89+
90+
/* i<->i */
91+
{
92+
x_i8 > x_i16;
93+
//~^ ERROR mismatched types
94+
x_i8 > x_i32;
95+
//~^ ERROR mismatched types
96+
x_i8 > x_i64;
97+
//~^ ERROR mismatched types
98+
x_i8 > x_i128;
99+
//~^ ERROR mismatched types
100+
x_i8 > x_isize;
101+
//~^ ERROR mismatched types
102+
103+
x_i16 > x_i8;
104+
//~^ ERROR mismatched types
105+
x_i16 > x_i32;
106+
//~^ ERROR mismatched types
107+
x_i16 > x_i64;
108+
//~^ ERROR mismatched types
109+
x_i16 > x_i128;
110+
//~^ ERROR mismatched types
111+
x_i16 > x_isize;
112+
//~^ ERROR mismatched types
113+
114+
x_i32 > x_i8;
115+
//~^ ERROR mismatched types
116+
x_i32 > x_i16;
117+
//~^ ERROR mismatched types
118+
x_i32 > x_i64;
119+
//~^ ERROR mismatched types
120+
x_i32 > x_i128;
121+
//~^ ERROR mismatched types
122+
x_i32 > x_isize;
123+
//~^ ERROR mismatched types
124+
125+
x_i64 > x_i8;
126+
//~^ ERROR mismatched types
127+
x_i64 > x_i16;
128+
//~^ ERROR mismatched types
129+
x_i64 > x_i32;
130+
//~^ ERROR mismatched types
131+
x_i64 > x_i128;
132+
//~^ ERROR mismatched types
133+
x_i64 > x_isize;
134+
//~^ ERROR mismatched types
135+
136+
x_i128 > x_i8;
137+
//~^ ERROR mismatched types
138+
x_i128 > x_i16;
139+
//~^ ERROR mismatched types
140+
x_i128 > x_i32;
141+
//~^ ERROR mismatched types
142+
x_i128 > x_i64;
143+
//~^ ERROR mismatched types
144+
x_i128 > x_isize;
145+
//~^ ERROR mismatched types
146+
147+
x_isize > x_i8;
148+
//~^ ERROR mismatched types
149+
x_isize > x_i16;
150+
//~^ ERROR mismatched types
151+
x_isize > x_i32;
152+
//~^ ERROR mismatched types
153+
x_isize > x_i64;
154+
//~^ ERROR mismatched types
155+
x_isize > x_i128;
156+
//~^ ERROR mismatched types
157+
}
158+
159+
/* u<->i */
160+
{
161+
x_u8 > x_i8;
162+
//~^ ERROR mismatched types
163+
x_u8 > x_i16;
164+
//~^ ERROR mismatched types
165+
x_u8 > x_i32;
166+
//~^ ERROR mismatched types
167+
x_u8 > x_i64;
168+
//~^ ERROR mismatched types
169+
x_u8 > x_i128;
170+
//~^ ERROR mismatched types
171+
x_u8 > x_isize;
172+
//~^ ERROR mismatched types
173+
174+
x_u16 > x_i8;
175+
//~^ ERROR mismatched types
176+
x_u16 > x_i16;
177+
//~^ ERROR mismatched types
178+
x_u16 > x_i32;
179+
//~^ ERROR mismatched types
180+
x_u16 > x_i64;
181+
//~^ ERROR mismatched types
182+
x_u16 > x_i128;
183+
//~^ ERROR mismatched types
184+
x_u16 > x_isize;
185+
//~^ ERROR mismatched types
186+
187+
x_u32 > x_i8;
188+
//~^ ERROR mismatched types
189+
x_u32 > x_i16;
190+
//~^ ERROR mismatched types
191+
x_u32 > x_i32;
192+
//~^ ERROR mismatched types
193+
x_u32 > x_i64;
194+
//~^ ERROR mismatched types
195+
x_u32 > x_i128;
196+
//~^ ERROR mismatched types
197+
x_u32 > x_isize;
198+
//~^ ERROR mismatched types
199+
200+
x_u64 > x_i8;
201+
//~^ ERROR mismatched types
202+
x_u64 > x_i16;
203+
//~^ ERROR mismatched types
204+
x_u64 > x_i32;
205+
//~^ ERROR mismatched types
206+
x_u64 > x_i64;
207+
//~^ ERROR mismatched types
208+
x_u64 > x_i128;
209+
//~^ ERROR mismatched types
210+
x_u64 > x_isize;
211+
//~^ ERROR mismatched types
212+
213+
x_u128 > x_i8;
214+
//~^ ERROR mismatched types
215+
x_u128 > x_i16;
216+
//~^ ERROR mismatched types
217+
x_u128 > x_i32;
218+
//~^ ERROR mismatched types
219+
x_u128 > x_i64;
220+
//~^ ERROR mismatched types
221+
x_u128 > x_i128;
222+
//~^ ERROR mismatched types
223+
x_u128 > x_isize;
224+
//~^ ERROR mismatched types
225+
226+
x_usize > x_i8;
227+
//~^ ERROR mismatched types
228+
x_usize > x_i16;
229+
//~^ ERROR mismatched types
230+
x_usize > x_i32;
231+
//~^ ERROR mismatched types
232+
x_usize > x_i64;
233+
//~^ ERROR mismatched types
234+
x_usize > x_i128;
235+
//~^ ERROR mismatched types
236+
x_usize > x_isize;
237+
//~^ ERROR mismatched types
238+
}
239+
240+
/* i<->u */
241+
{
242+
x_i8 > x_u8;
243+
//~^ ERROR mismatched types
244+
x_i8 > x_u16;
245+
//~^ ERROR mismatched types
246+
x_i8 > x_u32;
247+
//~^ ERROR mismatched types
248+
x_i8 > x_u64;
249+
//~^ ERROR mismatched types
250+
x_i8 > x_u128;
251+
//~^ ERROR mismatched types
252+
x_i8 > x_usize;
253+
//~^ ERROR mismatched types
254+
255+
x_i16 > x_u8;
256+
//~^ ERROR mismatched types
257+
x_i16 > x_u16;
258+
//~^ ERROR mismatched types
259+
x_i16 > x_u32;
260+
//~^ ERROR mismatched types
261+
x_i16 > x_u64;
262+
//~^ ERROR mismatched types
263+
x_i16 > x_u128;
264+
//~^ ERROR mismatched types
265+
x_i16 > x_usize;
266+
//~^ ERROR mismatched types
267+
268+
x_i32 > x_u8;
269+
//~^ ERROR mismatched types
270+
x_i32 > x_u16;
271+
//~^ ERROR mismatched types
272+
x_i32 > x_u32;
273+
//~^ ERROR mismatched types
274+
x_i32 > x_u64;
275+
//~^ ERROR mismatched types
276+
x_i32 > x_u128;
277+
//~^ ERROR mismatched types
278+
x_i32 > x_usize;
279+
//~^ ERROR mismatched types
280+
281+
x_i64 > x_u8;
282+
//~^ ERROR mismatched types
283+
x_i64 > x_u16;
284+
//~^ ERROR mismatched types
285+
x_i64 > x_u32;
286+
//~^ ERROR mismatched types
287+
x_i64 > x_u64;
288+
//~^ ERROR mismatched types
289+
x_i64 > x_u128;
290+
//~^ ERROR mismatched types
291+
x_i64 > x_usize;
292+
//~^ ERROR mismatched types
293+
294+
x_i128 > x_u8;
295+
//~^ ERROR mismatched types
296+
x_i128 > x_u16;
297+
//~^ ERROR mismatched types
298+
x_i128 > x_u32;
299+
//~^ ERROR mismatched types
300+
x_i128 > x_u64;
301+
//~^ ERROR mismatched types
302+
x_i128 > x_u128;
303+
//~^ ERROR mismatched types
304+
x_i128 > x_usize;
305+
//~^ ERROR mismatched types
306+
307+
x_isize > x_u8;
308+
//~^ ERROR mismatched types
309+
x_isize > x_u16;
310+
//~^ ERROR mismatched types
311+
x_isize > x_u32;
312+
//~^ ERROR mismatched types
313+
x_isize > x_u64;
314+
//~^ ERROR mismatched types
315+
x_isize > x_u128;
316+
//~^ ERROR mismatched types
317+
x_isize > x_usize;
318+
//~^ ERROR mismatched types
319+
}
320+
}

‎src/test/ui/numeric/numeric-cast-binop.stderr

Lines changed: 1385 additions & 0 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)
Please sign in to comment.