Rollup merge of #37442 - estebank:cast-deref-hint, r=jonathandturner
Provide hint when cast needs a dereference For a given code: ``` rust vec![0.0].iter().map(|s| s as i16).collect::<Vec<i16>>(); ``` display: ``` nocode error: casting `&f64` as `i16` is invalid --> file3.rs:2:35 | 2 | vec![0.0].iter().map(|s| s as i16).collect::<Vec<i16>>(); | - ^^^ | | | did you mean `*s`? ``` instead of: ``` nocode error: casting `&f64` as `i16` is invalid --> <anon>:2:30 | 2 | vec![0.0].iter().map(|s| s as i16).collect(); | ^^^^^^^^ | = help: cast through a raw pointer first ``` Fixes #37338.
This commit is contained in:
commit
464cce99f1
@ -102,6 +102,7 @@ enum CastError {
|
||||
/// Cast of thin to fat raw ptr (eg. `*const () as *const [u8]`)
|
||||
SizedUnsizedCast,
|
||||
IllegalCast,
|
||||
NeedDeref,
|
||||
NeedViaPtr,
|
||||
NeedViaThinPtr,
|
||||
NeedViaInt,
|
||||
@ -138,6 +139,25 @@ pub fn new(fcx: &FnCtxt<'a, 'gcx, 'tcx>,
|
||||
|
||||
fn report_cast_error(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>, e: CastError) {
|
||||
match e {
|
||||
CastError::NeedDeref => {
|
||||
let cast_ty = fcx.ty_to_string(self.cast_ty);
|
||||
let mut err = fcx.type_error_struct(self.cast_span,
|
||||
|actual| {
|
||||
format!("casting `{}` as `{}` is invalid",
|
||||
actual,
|
||||
cast_ty)
|
||||
},
|
||||
self.expr_ty);
|
||||
err.span_label(self.expr.span,
|
||||
&format!("cannot cast `{}` as `{}`",
|
||||
fcx.ty_to_string(self.expr_ty),
|
||||
cast_ty));
|
||||
if let Ok(snippet) = fcx.sess().codemap().span_to_snippet(self.expr.span) {
|
||||
err.span_label(self.expr.span,
|
||||
&format!("did you mean `*{}`?", snippet));
|
||||
}
|
||||
err.emit();
|
||||
}
|
||||
CastError::NeedViaThinPtr |
|
||||
CastError::NeedViaPtr => {
|
||||
let mut err = fcx.type_error_struct(self.span,
|
||||
@ -390,8 +410,28 @@ fn do_check(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> Result<CastKind, CastError>
|
||||
(Ptr(m_e), Ptr(m_c)) => self.check_ptr_ptr_cast(fcx, m_e, m_c), // ptr-ptr-cast
|
||||
(Ptr(m_expr), Int(_)) => self.check_ptr_addr_cast(fcx, m_expr), // ptr-addr-cast
|
||||
(FnPtr, Int(_)) => Ok(CastKind::FnPtrAddrCast),
|
||||
(RPtr(_), Int(_)) |
|
||||
(RPtr(_), Float) => Err(CastError::NeedViaPtr),
|
||||
(RPtr(p), Int(_)) |
|
||||
(RPtr(p), Float) => {
|
||||
match p.ty.sty {
|
||||
ty::TypeVariants::TyInt(_) |
|
||||
ty::TypeVariants::TyUint(_) |
|
||||
ty::TypeVariants::TyFloat(_) => {
|
||||
Err(CastError::NeedDeref)
|
||||
}
|
||||
ty::TypeVariants::TyInfer(t) => {
|
||||
match t {
|
||||
ty::InferTy::IntVar(_) |
|
||||
ty::InferTy::FloatVar(_) |
|
||||
ty::InferTy::FreshIntTy(_) |
|
||||
ty::InferTy::FreshFloatTy(_) => {
|
||||
Err(CastError::NeedDeref)
|
||||
}
|
||||
_ => Err(CastError::NeedViaPtr),
|
||||
}
|
||||
}
|
||||
_ => Err(CastError::NeedViaPtr),
|
||||
}
|
||||
}
|
||||
// * -> ptr
|
||||
(Int(_), Ptr(mt)) => self.check_addr_ptr_cast(fcx, mt), // addr-ptr-cast
|
||||
(FnPtr, Ptr(mt)) => self.check_fptr_ptr_cast(fcx, mt),
|
||||
|
@ -115,4 +115,9 @@ fn main()
|
||||
let _ = cf as *const Bar;
|
||||
//~^ ERROR casting
|
||||
//~^^ NOTE vtable kinds
|
||||
|
||||
vec![0.0].iter().map(|s| s as f32).collect::<Vec<f32>>();
|
||||
//~^ ERROR casting `&{float}` as `f32` is invalid
|
||||
//~| NOTE cannot cast `&{float}` as `f32`
|
||||
//~| NOTE did you mean `*s`?
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user