X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Flibrustc_typeck%2Fcheck%2Fdemand.rs;h=7110a1ba81d8f4888891ca60ef464136e54e662c;hb=21d4ba2ea66ee297e556af9b1e4e96130e2e1bcf;hp=fc241c023cdaf25f6e3c8f3fe4e51db2e357ee38;hpb=11e75fd1150daafb39e769d6df2db73062edef06;p=rust.git diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index fc241c023cd..7110a1ba81d 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -207,7 +207,29 @@ fn check_ref(&self, expected: Ty<'tcx>) -> Option { match (&expected.sty, &checked_ty.sty) { - (&ty::TyRef(_, _), &ty::TyRef(_, _)) => None, + (&ty::TyRef(_, exp), &ty::TyRef(_, check)) => match (&exp.ty.sty, &check.ty.sty) { + (&ty::TyStr, &ty::TyArray(arr, _)) | + (&ty::TyStr, &ty::TySlice(arr)) if arr == self.tcx.types.u8 => { + if let hir::ExprLit(_) = expr.node { + let sp = self.sess().codemap().call_span_if_macro(expr.span); + if let Ok(src) = self.tcx.sess.codemap().span_to_snippet(sp) { + return Some(format!("try `{}`", &src[1..])); + } + } + None + }, + (&ty::TyArray(arr, _), &ty::TyStr) | + (&ty::TySlice(arr), &ty::TyStr) if arr == self.tcx.types.u8 => { + if let hir::ExprLit(_) = expr.node { + let sp = self.sess().codemap().call_span_if_macro(expr.span); + if let Ok(src) = self.tcx.sess.codemap().span_to_snippet(sp) { + return Some(format!("try `b{}`", src)); + } + } + None + } + _ => None, + }, (&ty::TyRef(_, mutability), _) => { // Check if it can work when put into a ref. For example: // @@ -239,6 +261,39 @@ fn check_ref(&self, } None } + (_, &ty::TyRef(_, checked)) => { + // We have `&T`, check if what was expected was `T`. If so, + // we may want to suggest adding a `*`, or removing + // a `&`. + // + // (But, also check check the `expn_info()` to see if this is + // a macro; if so, it's hard to extract the text and make a good + // suggestion, so don't bother.) + if self.infcx.can_sub(self.param_env, checked.ty, &expected).is_ok() && + expr.span.ctxt().outer().expn_info().is_none() { + match expr.node { + // Maybe remove `&`? + hir::ExprAddrOf(_, ref expr) => { + if let Ok(code) = self.tcx.sess.codemap().span_to_snippet(expr.span) { + return Some(format!("try with `{}`", code)); + } + } + + // Maybe add `*`? Only if `T: Copy`. + _ => { + if !self.infcx.type_moves_by_default(self.param_env, + checked.ty, + expr.span) { + let sp = self.sess().codemap().call_span_if_macro(expr.span); + if let Ok(code) = self.tcx.sess.codemap().span_to_snippet(sp) { + return Some(format!("try with `*{}`", code)); + } + } + }, + } + } + None + } _ => None, } }