diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs
index 470dcb4bd61e1..2beb40d6b2f1a 100644
--- a/src/librustc/diagnostics.rs
+++ b/src/librustc/diagnostics.rs
@@ -1871,7 +1871,9 @@ makes a difference in practice.)
 
 E0593: r##"
 You tried to supply an `Fn`-based type with an incorrect number of arguments
-than what was expected. Erroneous code example:
+than what was expected.
+
+Erroneous code example:
 
 ```compile_fail,E0593
 fn foo<F: Fn()>(x: F) { }
@@ -1883,6 +1885,21 @@ fn main() {
 ```
 "##,
 
+E0601: r##"
+No `main` function was found in a binary crate. To fix this error, just add a
+`main` function. For example:
+
+```
+fn main() {
+    // Your program will start here.
+    println!("Hello world!");
+}
+```
+
+If you don't know the basics of Rust, you can go look to the Rust Book to get
+started: https://doc.rust-lang.org/book/
+"##,
+
 }
 
 
diff --git a/src/librustc/middle/entry.rs b/src/librustc/middle/entry.rs
index 24748b6cf65b8..b26cccf5f1617 100644
--- a/src/librustc/middle/entry.rs
+++ b/src/librustc/middle/entry.rs
@@ -162,7 +162,7 @@ fn configure_main(this: &mut EntryContext) {
         this.session.entry_type.set(Some(config::EntryMain));
     } else {
         // No main function
-        let mut err = this.session.struct_err("main function not found");
+        let mut err = struct_err!(this.session, E0601, "main function not found");
         if !this.non_main_fns.is_empty() {
             // There were some functions named 'main' though. Try to give the user a hint.
             err.note("the main function must be defined at the crate level \
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index 28531893659e6..827fa72f03404 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -158,14 +158,14 @@ impl Session {
     pub fn struct_span_warn<'a, S: Into<MultiSpan>>(&'a self,
                                                     sp: S,
                                                     msg: &str)
-                                                    -> DiagnosticBuilder<'a>  {
+                                                    -> DiagnosticBuilder<'a> {
         self.diagnostic().struct_span_warn(sp, msg)
     }
     pub fn struct_span_warn_with_code<'a, S: Into<MultiSpan>>(&'a self,
                                                               sp: S,
                                                               msg: &str,
                                                               code: &str)
-                                                              -> DiagnosticBuilder<'a>  {
+                                                              -> DiagnosticBuilder<'a> {
         self.diagnostic().struct_span_warn_with_code(sp, msg, code)
     }
     pub fn struct_warn<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a>  {
@@ -174,30 +174,34 @@ impl Session {
     pub fn struct_span_err<'a, S: Into<MultiSpan>>(&'a self,
                                                    sp: S,
                                                    msg: &str)
-                                                   -> DiagnosticBuilder<'a>  {
+                                                   -> DiagnosticBuilder<'a> {
         self.diagnostic().struct_span_err(sp, msg)
     }
     pub fn struct_span_err_with_code<'a, S: Into<MultiSpan>>(&'a self,
                                                              sp: S,
                                                              msg: &str,
                                                              code: &str)
-                                                             -> DiagnosticBuilder<'a>  {
+                                                             -> DiagnosticBuilder<'a> {
         self.diagnostic().struct_span_err_with_code(sp, msg, code)
     }
-    pub fn struct_err<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a>  {
+    // FIXME: This method should be removed (every error should have an associated error code).
+    pub fn struct_err<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> {
         self.diagnostic().struct_err(msg)
     }
+    pub fn struct_err_with_code<'a>(&'a self, msg: &str, code: &str) -> DiagnosticBuilder<'a> {
+        self.diagnostic().struct_err_with_code(msg, code)
+    }
     pub fn struct_span_fatal<'a, S: Into<MultiSpan>>(&'a self,
                                                      sp: S,
                                                      msg: &str)
-                                                     -> DiagnosticBuilder<'a>  {
+                                                     -> DiagnosticBuilder<'a> {
         self.diagnostic().struct_span_fatal(sp, msg)
     }
     pub fn struct_span_fatal_with_code<'a, S: Into<MultiSpan>>(&'a self,
                                                                sp: S,
                                                                msg: &str,
                                                                code: &str)
-                                                               -> DiagnosticBuilder<'a>  {
+                                                               -> DiagnosticBuilder<'a> {
         self.diagnostic().struct_span_fatal_with_code(sp, msg, code)
     }
     pub fn struct_fatal<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a>  {
diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs
index f7191e4921637..d1aaaf4ba7b37 100644
--- a/src/librustc_errors/lib.rs
+++ b/src/librustc_errors/lib.rs
@@ -345,9 +345,15 @@ impl Handler {
         result.code(code.to_owned());
         result
     }
+    // FIXME: This method should be removed (every error should have an associated error code).
     pub fn struct_err<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> {
         DiagnosticBuilder::new(self, Level::Error, msg)
     }
+    pub fn struct_err_with_code<'a>(&'a self, msg: &str, code: &str) -> DiagnosticBuilder<'a> {
+        let mut result = DiagnosticBuilder::new(self, Level::Error, msg);
+        result.code(code.to_owned());
+        result
+    }
     pub fn struct_span_fatal<'a, S: Into<MultiSpan>>(&'a self,
                                                      sp: S,
                                                      msg: &str)
diff --git a/src/libsyntax/diagnostics/macros.rs b/src/libsyntax/diagnostics/macros.rs
index 25e0428248df4..13016d72127ea 100644
--- a/src/libsyntax/diagnostics/macros.rs
+++ b/src/libsyntax/diagnostics/macros.rs
@@ -38,6 +38,14 @@ macro_rules! span_warn {
     })
 }
 
+#[macro_export]
+macro_rules! struct_err {
+    ($session:expr, $code:ident, $($message:tt)*) => ({
+        __diagnostic_used!($code);
+        $session.struct_err_with_code(&format!($($message)*), stringify!($code))
+    })
+}
+
 #[macro_export]
 macro_rules! span_err_or_warn {
     ($is_warning:expr, $session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
diff --git a/src/test/ui/missing-items/m2.stderr b/src/test/ui/missing-items/m2.stderr
index 26748d18ffa95..2d699c66359d8 100644
--- a/src/test/ui/missing-items/m2.stderr
+++ b/src/test/ui/missing-items/m2.stderr
@@ -1,4 +1,4 @@
-error: main function not found
+error[E0601]: main function not found
 
 error[E0046]: not all trait items implemented, missing: `CONSTANT`, `Type`, `method`
   --> $DIR/m2.rs:20:1
diff --git a/src/test/ui/resolve/issue-14254.stderr b/src/test/ui/resolve/issue-14254.stderr
index 8aaad906ea28a..009d969fc285d 100644
--- a/src/test/ui/resolve/issue-14254.stderr
+++ b/src/test/ui/resolve/issue-14254.stderr
@@ -142,7 +142,7 @@ error[E0425]: cannot find value `bah` in this scope
 133 |         bah;
     |         ^^^ did you mean `Self::bah`?
 
-error: main function not found
+error[E0601]: main function not found
 
 error: aborting due to previous error(s)
 
diff --git a/src/test/ui/resolve/issue-21221-2.stderr b/src/test/ui/resolve/issue-21221-2.stderr
index f0b22754e6444..b35f1bd26706c 100644
--- a/src/test/ui/resolve/issue-21221-2.stderr
+++ b/src/test/ui/resolve/issue-21221-2.stderr
@@ -7,7 +7,7 @@ error[E0405]: cannot find trait `T` in this scope
 help: possible candidate is found in another module, you can import it into scope
    | use foo::bar::T;
 
-error: main function not found
+error[E0601]: main function not found
 
 error: cannot continue compilation due to previous error
 
diff --git a/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr b/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr
index 24cef694737e0..a34c27a47da82 100644
--- a/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr
+++ b/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr
@@ -72,7 +72,7 @@ error[E0423]: expected function, found module `a::b`
    |        |
    |        did you mean `I`?
 
-error: main function not found
+error[E0601]: main function not found
 
 error: aborting due to previous error(s)
 
diff --git a/src/test/ui/span/issue-35987.stderr b/src/test/ui/span/issue-35987.stderr
index e53ea6a55afb5..a2597aba0bd29 100644
--- a/src/test/ui/span/issue-35987.stderr
+++ b/src/test/ui/span/issue-35987.stderr
@@ -7,7 +7,7 @@ error[E0404]: expected trait, found type parameter `Add`
 help: possible better candidate is found in another module, you can import it into scope
    | use std::ops::Add;
 
-error: main function not found
+error[E0601]: main function not found
 
 error: cannot continue compilation due to previous error
 
diff --git a/src/test/ui/token/issue-10636-2.stderr b/src/test/ui/token/issue-10636-2.stderr
index faa30dca94581..4b0b05ca65adc 100644
--- a/src/test/ui/token/issue-10636-2.stderr
+++ b/src/test/ui/token/issue-10636-2.stderr
@@ -22,7 +22,7 @@ error: expected expression, found `)`
 19 | } //~ ERROR: incorrect close delimiter
    | ^
 
-error: main function not found
+error[E0601]: main function not found
 
 error: aborting due to previous error(s)
 
diff --git a/src/test/ui/token/issue-41155.stderr b/src/test/ui/token/issue-41155.stderr
index 96c2d764e7101..56f71a2995382 100644
--- a/src/test/ui/token/issue-41155.stderr
+++ b/src/test/ui/token/issue-41155.stderr
@@ -12,7 +12,7 @@ error[E0412]: cannot find type `S` in this scope
 11 | impl S {
    |      ^ not found in this scope
 
-error: main function not found
+error[E0601]: main function not found
 
 error: aborting due to previous error(s)