-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
More accurate error for binop errors after identifying RHS type #90006
Changes from all commits
9d8fb13
dc7785c
2f499dd
2e6cab8
86aeb23
56b12d7
bee8752
1e48ab4
5b0c7f6
7110131
c8506a8
e938489
777e477
4797ad9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -844,6 +844,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | |||||
let mut into_suggestion = sugg.clone(); | ||||||
into_suggestion.push((expr.span.shrink_to_hi(), format!("{}.into()", close_paren))); | ||||||
let mut suffix_suggestion = sugg.clone(); | ||||||
|
||||||
if matches!( | ||||||
(&expected_ty.kind(), &checked_ty.kind()), | ||||||
(ty::Float(_), ty::Int(_) | ty::Uint(_)) | ||||||
) { | ||||||
// Add fractional part from literal, for example `42.0f32` into `42` | ||||||
estebank marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
let len = src.trim_end_matches(&checked_ty.to_string()).len(); | ||||||
let len = src[..len].trim_end_matches("_").len(); | ||||||
let pos = expr.span.lo() + BytePos(len as u32); | ||||||
let span = expr.span.with_lo(pos).with_hi(pos); | ||||||
suffix_suggestion.push((span, ".0".to_string())); | ||||||
}; | ||||||
|
||||||
suffix_suggestion.push(( | ||||||
if matches!( | ||||||
(&expected_ty.kind(), &checked_ty.kind()), | ||||||
|
@@ -915,19 +928,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | |||||
suggestion, | ||||||
Applicability::MachineApplicable, | ||||||
); | ||||||
true | ||||||
}; | ||||||
|
||||||
let suggest_to_change_suffix_or_into = | ||||||
|err: &mut DiagnosticBuilder<'_>, | ||||||
found_to_exp_is_fallible: bool, | ||||||
exp_to_found_is_fallible: bool| { | ||||||
let exp_is_lhs = | ||||||
let exp_is_assign_lhs = | ||||||
expected_ty_expr.map(|e| self.tcx.hir().is_lhs(e.hir_id)).unwrap_or(false); | ||||||
|
||||||
if exp_is_lhs { | ||||||
return; | ||||||
if exp_is_assign_lhs { | ||||||
return false; | ||||||
} | ||||||
|
||||||
let always_fallible = found_to_exp_is_fallible | ||||||
&& (exp_to_found_is_fallible || expected_ty_expr.is_none()); | ||||||
let msg = if literal_is_ty_suffixed(expr) { | ||||||
|
@@ -938,10 +951,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | |||||
// expected type. | ||||||
let msg = format!("`{}` cannot fit into type `{}`", src, expected_ty); | ||||||
err.note(&msg); | ||||||
return; | ||||||
return false; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you add a comment to |
||||||
} else if in_const_context { | ||||||
// Do not recommend `into` or `try_into` in const contexts. | ||||||
return; | ||||||
return false; | ||||||
} else if found_to_exp_is_fallible { | ||||||
return suggest_fallible_into_or_lhs_from(err, exp_to_found_is_fallible); | ||||||
} else { | ||||||
|
@@ -953,6 +966,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | |||||
into_suggestion.clone() | ||||||
}; | ||||||
err.multipart_suggestion_verbose(msg, suggestion, Applicability::MachineApplicable); | ||||||
true | ||||||
}; | ||||||
|
||||||
match (&expected_ty.kind(), &checked_ty.kind()) { | ||||||
|
@@ -966,8 +980,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | |||||
(None, _) | (_, None) => (true, true), | ||||||
_ => (false, false), | ||||||
}; | ||||||
suggest_to_change_suffix_or_into(err, f2e_is_fallible, e2f_is_fallible); | ||||||
true | ||||||
suggest_to_change_suffix_or_into(err, f2e_is_fallible, e2f_is_fallible) | ||||||
} | ||||||
(&ty::Uint(ref exp), &ty::Uint(ref found)) => { | ||||||
let (f2e_is_fallible, e2f_is_fallible) = match (exp.bit_width(), found.bit_width()) | ||||||
|
@@ -979,8 +992,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | |||||
(None, _) | (_, None) => (true, true), | ||||||
_ => (false, false), | ||||||
}; | ||||||
suggest_to_change_suffix_or_into(err, f2e_is_fallible, e2f_is_fallible); | ||||||
true | ||||||
suggest_to_change_suffix_or_into(err, f2e_is_fallible, e2f_is_fallible) | ||||||
} | ||||||
(&ty::Int(exp), &ty::Uint(found)) => { | ||||||
let (f2e_is_fallible, e2f_is_fallible) = match (exp.bit_width(), found.bit_width()) | ||||||
|
@@ -989,8 +1001,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | |||||
(None, Some(8)) => (false, true), | ||||||
_ => (true, true), | ||||||
}; | ||||||
suggest_to_change_suffix_or_into(err, f2e_is_fallible, e2f_is_fallible); | ||||||
true | ||||||
suggest_to_change_suffix_or_into(err, f2e_is_fallible, e2f_is_fallible) | ||||||
} | ||||||
(&ty::Uint(exp), &ty::Int(found)) => { | ||||||
let (f2e_is_fallible, e2f_is_fallible) = match (exp.bit_width(), found.bit_width()) | ||||||
|
@@ -999,12 +1010,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | |||||
(Some(8), None) => (true, false), | ||||||
_ => (true, true), | ||||||
}; | ||||||
suggest_to_change_suffix_or_into(err, f2e_is_fallible, e2f_is_fallible); | ||||||
true | ||||||
suggest_to_change_suffix_or_into(err, f2e_is_fallible, e2f_is_fallible) | ||||||
} | ||||||
(&ty::Float(ref exp), &ty::Float(ref found)) => { | ||||||
if found.bit_width() < exp.bit_width() { | ||||||
suggest_to_change_suffix_or_into(err, false, true); | ||||||
return suggest_to_change_suffix_or_into(err, false, true); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
? |
||||||
} else if literal_is_ty_suffixed(expr) { | ||||||
err.multipart_suggestion_verbose( | ||||||
&lit_msg, | ||||||
|
@@ -1028,15 +1038,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | |||||
suffix_suggestion, | ||||||
Applicability::MachineApplicable, | ||||||
); | ||||||
true | ||||||
} else if can_cast { | ||||||
// Missing try_into implementation for `{float}` to `{integer}` | ||||||
err.multipart_suggestion_verbose( | ||||||
&format!("{}, rounding the float towards zero", msg), | ||||||
cast_suggestion, | ||||||
Applicability::MaybeIncorrect, // lossy conversion | ||||||
); | ||||||
true | ||||||
} else { | ||||||
false | ||||||
} | ||||||
true | ||||||
} | ||||||
(&ty::Float(ref exp), &ty::Uint(ref found)) => { | ||||||
// if `found` is `None` (meaning found is `usize`), don't suggest `.into()` | ||||||
|
@@ -1059,8 +1072,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | |||||
// Missing try_into implementation for `{integer}` to `{float}` | ||||||
err.multipart_suggestion_verbose( | ||||||
&format!( | ||||||
"{}, producing the floating point representation of the integer, | ||||||
rounded if necessary", | ||||||
"{}, producing the floating point representation of the integer, \ | ||||||
rounded if necessary", | ||||||
cast_msg, | ||||||
), | ||||||
cast_suggestion, | ||||||
|
@@ -1091,7 +1104,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | |||||
err.multipart_suggestion_verbose( | ||||||
&format!( | ||||||
"{}, producing the floating point representation of the integer, \ | ||||||
rounded if necessary", | ||||||
rounded if necessary", | ||||||
&msg, | ||||||
), | ||||||
cast_suggestion, | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
T: Trait<OneType> + Trait<AnotherType>
is a legitimate combination of bounds, so with filtering based on def-ids the suggestions will perpetually recommend replacingTrait<OneType>
withTrait<AnotherType>
and vice versa in case of one of the bounds missing.