diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs
index ece2d7b4f3793..7b50132f5ff32 100644
--- a/compiler/rustc_typeck/src/check/demand.rs
+++ b/compiler/rustc_typeck/src/check/demand.rs
@@ -1173,6 +1173,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 }
                 true
             }
+            (
+                &ty::Uint(ty::UintTy::U32 | ty::UintTy::U64 | ty::UintTy::U128)
+                | &ty::Int(ty::IntTy::I32 | ty::IntTy::I64 | ty::IntTy::I128),
+                &ty::Char,
+            ) => {
+                err.multipart_suggestion_verbose(
+                    &format!("{}, since a `char` always occupies 4 bytes", cast_msg,),
+                    cast_suggestion,
+                    Applicability::MachineApplicable,
+                );
+                true
+            }
             _ => false,
         }
     }
diff --git a/src/test/ui/cast/cast-int-to-char.rs b/src/test/ui/cast/cast-int-to-char.rs
new file mode 100644
index 0000000000000..379956968bd56
--- /dev/null
+++ b/src/test/ui/cast/cast-int-to-char.rs
@@ -0,0 +1,9 @@
+fn foo<T>(_t: T) {}
+
+fn main() {
+    foo::<u32>('0');  //~ ERROR
+    foo::<i32>('0');  //~ ERROR
+    foo::<u64>('0');  //~ ERROR
+    foo::<i64>('0');  //~ ERROR
+    foo::<char>(0u32);  //~ ERROR
+}
diff --git a/src/test/ui/cast/cast-int-to-char.stderr b/src/test/ui/cast/cast-int-to-char.stderr
new file mode 100644
index 0000000000000..55b9462db8df8
--- /dev/null
+++ b/src/test/ui/cast/cast-int-to-char.stderr
@@ -0,0 +1,53 @@
+error[E0308]: mismatched types
+  --> $DIR/cast-int-to-char.rs:4:16
+   |
+LL |     foo::<u32>('0');
+   |                ^^^ expected `u32`, found `char`
+   |
+help: you can cast a `char` to a `u32`, since a `char` always occupies 4 bytes
+   |
+LL |     foo::<u32>('0' as u32);
+   |                    ++++++
+
+error[E0308]: mismatched types
+  --> $DIR/cast-int-to-char.rs:5:16
+   |
+LL |     foo::<i32>('0');
+   |                ^^^ expected `i32`, found `char`
+   |
+help: you can cast a `char` to an `i32`, since a `char` always occupies 4 bytes
+   |
+LL |     foo::<i32>('0' as i32);
+   |                    ++++++
+
+error[E0308]: mismatched types
+  --> $DIR/cast-int-to-char.rs:6:16
+   |
+LL |     foo::<u64>('0');
+   |                ^^^ expected `u64`, found `char`
+   |
+help: you can cast a `char` to a `u64`, since a `char` always occupies 4 bytes
+   |
+LL |     foo::<u64>('0' as u64);
+   |                    ++++++
+
+error[E0308]: mismatched types
+  --> $DIR/cast-int-to-char.rs:7:16
+   |
+LL |     foo::<i64>('0');
+   |                ^^^ expected `i64`, found `char`
+   |
+help: you can cast a `char` to an `i64`, since a `char` always occupies 4 bytes
+   |
+LL |     foo::<i64>('0' as i64);
+   |                    ++++++
+
+error[E0308]: mismatched types
+  --> $DIR/cast-int-to-char.rs:8:17
+   |
+LL |     foo::<char>(0u32);
+   |                 ^^^^ expected `char`, found `u32`
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/match/match-type-err-first-arm.stderr b/src/test/ui/match/match-type-err-first-arm.stderr
index fd489afa84db4..1cfe7ce1ed726 100644
--- a/src/test/ui/match/match-type-err-first-arm.stderr
+++ b/src/test/ui/match/match-type-err-first-arm.stderr
@@ -6,6 +6,11 @@ LL | fn test_func1(n: i32) -> i32 {
 LL |     match n {
 LL |         12 => 'b',
    |               ^^^ expected `i32`, found `char`
+   |
+help: you can cast a `char` to an `i32`, since a `char` always occupies 4 bytes
+   |
+LL |         12 => 'b' as i32,
+   |                   ++++++
 
 error[E0308]: `match` arms have incompatible types
   --> $DIR/match-type-err-first-arm.rs:18:14
diff --git a/src/test/ui/proc-macro/macro-brackets.stderr b/src/test/ui/proc-macro/macro-brackets.stderr
index 9aaf612eb54a1..d3516375291b9 100644
--- a/src/test/ui/proc-macro/macro-brackets.stderr
+++ b/src/test/ui/proc-macro/macro-brackets.stderr
@@ -3,6 +3,11 @@ error[E0308]: mismatched types
    |
 LL | id![static X: u32 = 'a';];
    |                     ^^^ expected `u32`, found `char`
+   |
+help: you can cast a `char` to a `u32`, since a `char` always occupies 4 bytes
+   |
+LL | id![static X: u32 = 'a' as u32;];
+   |                         ++++++
 
 error: aborting due to previous error