about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2019-12-31 21:25:16 +0100
committerMazdak Farrokhzad <twingoow@gmail.com>2020-01-08 04:25:33 +0100
commit2c3e5d3de023c0bfbf4a4c4d3b0d7a9844e96ffe (patch)
treed8a6e6281016eab3b52f1e0bbd0b89b7ea09035e /src
parent7e393b5b3b543d355ae16c1940cf98b6c7fcb8aa (diff)
downloadrust-2c3e5d3de023c0bfbf4a4c4d3b0d7a9844e96ffe.tar.gz
rust-2c3e5d3de023c0bfbf4a4c4d3b0d7a9844e96ffe.zip
- remove syntax::{span_warn!, span_err!, span_fatal!. struct_err!}
- remove syntax::{help!, span_help!, span_note!}
- remove unused syntax::{struct_span_fatal, struct_span_err_or_warn!, span_err_or_warn!}
- lintify check_for_bindings_named_same_as_variants + conflicting_repr_hints
- inline syntax::{struct_span_warn!, diagnostic_used!}
- stringify_error_code! -> error_code! & use it more.
- find_plugin_registrar: de-fatalize an error
- de-fatalize metadata errors
- move type_error_struct! to rustc_typeck
- struct_span_err! -> rustc_errors
Diffstat (limited to 'src')
-rw-r--r--src/librustc/hir/check_attr.rs16
-rw-r--r--src/librustc/infer/error_reporting/mod.rs2
-rw-r--r--src/librustc/infer/error_reporting/need_type_info.rs15
-rw-r--r--src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs1
-rw-r--r--src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs2
-rw-r--r--src/librustc/infer/error_reporting/note.rs2
-rw-r--r--src/librustc/infer/opaque_types/mod.rs8
-rw-r--r--src/librustc/lint/builtin.rs7
-rw-r--r--src/librustc/lint/context.rs11
-rw-r--r--src/librustc/lint/levels.rs7
-rw-r--r--src/librustc/middle/lang_items.rs6
-rw-r--r--src/librustc/middle/weak_lang_items.rs10
-rw-r--r--src/librustc/mir/interpret/error.rs2
-rw-r--r--src/librustc/traits/error_reporting.rs3
-rw-r--r--src/librustc/traits/on_unimplemented.rs12
-rw-r--r--src/librustc/traits/query/dropck_outlives.rs8
-rw-r--r--src/librustc/traits/specialize/mod.rs1
-rw-r--r--src/librustc/ty/query/plumbing.rs6
-rw-r--r--src/librustc_ast_lowering/expr.rs18
-rw-r--r--src/librustc_ast_lowering/item.rs2
-rw-r--r--src/librustc_ast_lowering/lib.rs9
-rw-r--r--src/librustc_builtin_macros/asm.rs33
-rw-r--r--src/librustc_builtin_macros/deriving/default.rs10
-rw-r--r--src/librustc_codegen_ssa/common.rs3
-rw-r--r--src/librustc_codegen_ssa/lib.rs2
-rw-r--r--src/librustc_codegen_ssa/mir/statement.rs11
-rw-r--r--src/librustc_error_codes/error_codes/E0566.md4
-rw-r--r--src/librustc_errors/diagnostic_builder.rs19
-rw-r--r--src/librustc_metadata/creader.rs8
-rw-r--r--src/librustc_metadata/locator.rs17
-rw-r--r--src/librustc_metadata/native_libs.rs7
-rw-r--r--src/librustc_mir/borrow_check/type_check/mod.rs1
-rw-r--r--src/librustc_mir/hair/pattern/check_match.rs40
-rw-r--r--src/librustc_mir/hair/pattern/mod.rs6
-rw-r--r--src/librustc_mir/lib.rs2
-rw-r--r--src/librustc_mir/transform/check_consts/ops.rs18
-rw-r--r--src/librustc_mir/transform/check_consts/validation.rs1
-rw-r--r--src/librustc_mir/transform/check_unsafety.rs1
-rw-r--r--src/librustc_mir/util/borrowck_errors.rs5
-rw-r--r--src/librustc_parse/parser/diagnostics.rs4
-rw-r--r--src/librustc_parse/parser/item.rs3
-rw-r--r--src/librustc_parse/parser/mod.rs3
-rw-r--r--src/librustc_parse/parser/ty.rs3
-rw-r--r--src/librustc_passes/ast_validation.rs33
-rw-r--r--src/librustc_passes/check_const.rs4
-rw-r--r--src/librustc_passes/diagnostic_items.rs2
-rw-r--r--src/librustc_passes/entry.rs9
-rw-r--r--src/librustc_passes/intrinsicck.rs1
-rw-r--r--src/librustc_passes/lib.rs2
-rw-r--r--src/librustc_passes/lib_features.rs1
-rw-r--r--src/librustc_passes/loops.rs3
-rw-r--r--src/librustc_passes/region.rs1
-rw-r--r--src/librustc_passes/stability.rs1
-rw-r--r--src/librustc_plugin_impl/Cargo.toml1
-rw-r--r--src/librustc_plugin_impl/load.rs9
-rw-r--r--src/librustc_privacy/Cargo.toml1
-rw-r--r--src/librustc_privacy/lib.rs4
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs25
-rw-r--r--src/librustc_resolve/diagnostics.rs3
-rw-r--r--src/librustc_resolve/imports.rs5
-rw-r--r--src/librustc_resolve/late.rs40
-rw-r--r--src/librustc_resolve/late/diagnostics.rs11
-rw-r--r--src/librustc_resolve/lib.rs4
-rw-r--r--src/librustc_resolve/lifetimes.rs44
-rw-r--r--src/librustc_typeck/astconv.rs25
-rw-r--r--src/librustc_typeck/check/autoderef.rs1
-rw-r--r--src/librustc_typeck/check/callee.rs3
-rw-r--r--src/librustc_typeck/check/cast.rs20
-rw-r--r--src/librustc_typeck/check/coercion.rs2
-rw-r--r--src/librustc_typeck/check/compare_method.rs3
-rw-r--r--src/librustc_typeck/check/dropck.rs2
-rw-r--r--src/librustc_typeck/check/expr.rs13
-rw-r--r--src/librustc_typeck/check/intrinsic.rs16
-rw-r--r--src/librustc_typeck/check/method/probe.rs6
-rw-r--r--src/librustc_typeck/check/method/suggest.rs12
-rw-r--r--src/librustc_typeck/check/mod.rs33
-rw-r--r--src/librustc_typeck/check/op.rs2
-rw-r--r--src/librustc_typeck/check/pat.rs13
-rw-r--r--src/librustc_typeck/check/wfcheck.rs6
-rw-r--r--src/librustc_typeck/coherence/builtin.rs39
-rw-r--r--src/librustc_typeck/coherence/inherent_impls.rs1
-rw-r--r--src/librustc_typeck/coherence/inherent_impls_overlap.rs1
-rw-r--r--src/librustc_typeck/coherence/mod.rs1
-rw-r--r--src/librustc_typeck/coherence/orphan.rs1
-rw-r--r--src/librustc_typeck/coherence/unsafety.rs16
-rw-r--r--src/librustc_typeck/collect.rs48
-rw-r--r--src/librustc_typeck/impl_wf_check.rs1
-rw-r--r--src/librustc_typeck/lib.rs3
-rw-r--r--src/librustc_typeck/outlives/test.rs3
-rw-r--r--src/librustc_typeck/structured_errors.rs6
-rw-r--r--src/librustc_typeck/variance/test.rs3
-rw-r--r--src/libsyntax/attr/builtin.rs73
-rw-r--r--src/libsyntax/diagnostics/macros.rs169
-rw-r--r--src/libsyntax/feature_gate/check.rs28
-rw-r--r--src/libsyntax/lib.rs6
-rw-r--r--src/test/run-make-fulldeps/simd-ffi/simd.rs35
-rw-r--r--src/test/ui/conflicting-repr-hints.rs35
-rw-r--r--src/test/ui/conflicting-repr-hints.stderr35
-rw-r--r--src/test/ui/feature-gates/feature-gate-repr-simd.rs2
-rw-r--r--src/test/ui/feature-gates/feature-gate-repr-simd.stderr4
-rw-r--r--src/test/ui/issues/issue-14221.stderr2
-rw-r--r--src/test/ui/issues/issue-19100.stderr2
-rw-r--r--src/test/ui/issues/issue-30302.stderr2
-rw-r--r--src/test/ui/issues/issue-39720.rs10
-rw-r--r--src/test/ui/issues/issue-39720.stderr16
-rw-r--r--src/test/ui/issues/issue-47094.rs6
-rw-r--r--src/test/ui/issues/issue-47094.stderr15
-rw-r--r--src/test/ui/lint/lint-uppercase-variables.stderr2
-rw-r--r--src/test/ui/pattern/issue-67776-match-same-name-enum-variant-refs.stderr2
109 files changed, 624 insertions, 653 deletions
diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs
index 7395b03c4eb..d525f364593 100644
--- a/src/librustc/hir/check_attr.rs
+++ b/src/librustc/hir/check_attr.rs
@@ -8,6 +8,8 @@ use crate::hir::intravisit::{self, NestedVisitorMap, Visitor};
 use crate::lint::builtin::UNUSED_ATTRIBUTES;
 use crate::ty::query::Providers;
 use crate::ty::TyCtxt;
+
+use errors::struct_span_err;
 use rustc_error_codes::*;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
@@ -430,21 +432,27 @@ impl CheckAttrVisitor<'tcx> {
         // Error on repr(transparent, <anything else>).
         if is_transparent && hints.len() > 1 {
             let hint_spans: Vec<_> = hint_spans.clone().collect();
-            span_err!(
+            struct_span_err!(
                 self.tcx.sess,
                 hint_spans,
                 E0692,
                 "transparent {} cannot have other repr hints",
                 target
-            );
+            )
+            .emit();
         }
         // Warn on repr(u8, u16), repr(C, simd), and c-like-enum-repr(C, u8)
         if (int_reprs > 1)
             || (is_simd && is_c)
             || (int_reprs == 1 && is_c && item.map_or(false, |item| is_c_like_enum(item)))
         {
-            let hint_spans: Vec<_> = hint_spans.collect();
-            span_warn!(self.tcx.sess, hint_spans, E0566, "conflicting representation hints");
+            struct_span_err!(
+                self.tcx.sess,
+                hint_spans.collect::<Vec<Span>>(),
+                E0566,
+                "conflicting representation hints",
+            )
+            .emit();
         }
     }
 
diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs
index f262672fdc8..92292b3d35f 100644
--- a/src/librustc/infer/error_reporting/mod.rs
+++ b/src/librustc/infer/error_reporting/mod.rs
@@ -68,7 +68,7 @@ use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::Node;
 
-use errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString};
+use errors::{struct_span_err, Applicability, DiagnosticBuilder, DiagnosticStyledString};
 use rustc_error_codes::*;
 use rustc_span::{Pos, Span};
 use rustc_target::spec::abi;
diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs
index 091bfba7ca6..4dedf0a23e8 100644
--- a/src/librustc/infer/error_reporting/need_type_info.rs
+++ b/src/librustc/infer/error_reporting/need_type_info.rs
@@ -4,7 +4,7 @@ use crate::infer::type_variable::TypeVariableOriginKind;
 use crate::infer::InferCtxt;
 use crate::ty::print::Print;
 use crate::ty::{self, DefIdTree, Infer, Ty, TyVar};
-use errors::{Applicability, DiagnosticBuilder};
+use errors::{struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Namespace};
 use rustc_hir::{Body, Expr, ExprKind, FunctionRetTy, HirId, Local, Pat};
@@ -151,14 +151,11 @@ pub enum TypeAnnotationNeeded {
 
 impl Into<errors::DiagnosticId> for TypeAnnotationNeeded {
     fn into(self) -> errors::DiagnosticId {
-        syntax::diagnostic_used!(E0282);
-        syntax::diagnostic_used!(E0283);
-        syntax::diagnostic_used!(E0284);
-        errors::DiagnosticId::Error(match self {
-            Self::E0282 => "E0282".to_string(),
-            Self::E0283 => "E0283".to_string(),
-            Self::E0284 => "E0284".to_string(),
-        })
+        match self {
+            Self::E0282 => errors::error_code!(E0282),
+            Self::E0283 => errors::error_code!(E0283),
+            Self::E0284 => errors::error_code!(E0284),
+        }
     }
 }
 
diff --git a/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs b/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs
index cfb6d5bd244..b73fb40f637 100644
--- a/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs
+++ b/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs
@@ -5,6 +5,7 @@ use crate::infer::error_reporting::nice_region_error::util::AnonymousParamInfo;
 use crate::infer::error_reporting::nice_region_error::NiceRegionError;
 use crate::util::common::ErrorReported;
 
+use errors::struct_span_err;
 use rustc_error_codes::*;
 
 impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
diff --git a/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs b/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs
index 0d56fc57230..dacd2025da5 100644
--- a/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs
+++ b/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs
@@ -2,7 +2,7 @@
 //! where one region is named and the other is anonymous.
 use crate::infer::error_reporting::nice_region_error::NiceRegionError;
 use crate::ty;
-use errors::{Applicability, DiagnosticBuilder};
+use errors::{struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir::{FunctionRetTy, TyKind};
 
 use rustc_error_codes::*;
diff --git a/src/librustc/infer/error_reporting/note.rs b/src/librustc/infer/error_reporting/note.rs
index 7919274c373..a3fdcb44f99 100644
--- a/src/librustc/infer/error_reporting/note.rs
+++ b/src/librustc/infer/error_reporting/note.rs
@@ -3,7 +3,7 @@ use crate::infer::{self, InferCtxt, SubregionOrigin};
 use crate::middle::region;
 use crate::ty::error::TypeError;
 use crate::ty::{self, Region};
-use errors::DiagnosticBuilder;
+use errors::{struct_span_err, DiagnosticBuilder};
 
 use rustc_error_codes::*;
 
diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs
index a22ed940961..839e8588ff0 100644
--- a/src/librustc/infer/opaque_types/mod.rs
+++ b/src/librustc/infer/opaque_types/mod.rs
@@ -6,7 +6,7 @@ use crate::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder, TypeVisitor};
 use crate::ty::free_region_map::FreeRegionRelations;
 use crate::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef};
 use crate::ty::{self, GenericParamDefKind, Ty, TyCtxt};
-use errors::DiagnosticBuilder;
+use errors::{struct_span_err, DiagnosticBuilder};
 use rustc::session::config::nightly_options;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::Lrc;
@@ -524,11 +524,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         err.span_label(span, label);
 
         if nightly_options::is_nightly_build() {
-            help!(
-                err,
-                "add #![feature(member_constraints)] to the crate attributes \
-                   to enable"
-            );
+            err.help("add #![feature(member_constraints)] to the crate attributes to enable");
         }
 
         err.emit();
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index 847c61033da..3726e6ace54 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -96,6 +96,12 @@ declare_lint! {
 }
 
 declare_lint! {
+    pub BINDINGS_WITH_VARIANT_NAME,
+    Warn,
+    "detects pattern bindings with the same name as one of the matched variants"
+}
+
+declare_lint! {
     pub UNUSED_MACROS,
     Warn,
     "detects macros that were not used"
@@ -459,6 +465,7 @@ declare_lint_pass! {
         UNREACHABLE_CODE,
         UNREACHABLE_PATTERNS,
         OVERLAPPING_PATTERNS,
+        BINDINGS_WITH_VARIANT_NAME,
         UNUSED_MACROS,
         WARNINGS,
         UNUSED_FEATURES,
diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs
index 0ac682428d6..ea96b15a162 100644
--- a/src/librustc/lint/context.rs
+++ b/src/librustc/lint/context.rs
@@ -25,17 +25,17 @@ use crate::middle::privacy::AccessLevels;
 use crate::session::Session;
 use crate::ty::layout::{LayoutError, LayoutOf, TyLayout};
 use crate::ty::{self, print::Printer, subst::GenericArg, Ty, TyCtxt};
-use errors::DiagnosticBuilder;
+use errors::{struct_span_err, DiagnosticBuilder};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync;
+use rustc_error_codes::*;
 use rustc_hir as hir;
 use rustc_hir::def_id::{CrateNum, DefId};
-use rustc_span::{symbol::Symbol, MultiSpan, Span};
-use std::slice;
+use rustc_span::{symbol::Symbol, MultiSpan, Span, DUMMY_SP};
 use syntax::ast;
 use syntax::util::lev_distance::find_best_match_for_name;
 
-use rustc_error_codes::*;
+use std::slice;
 
 /// Information about the registered lints.
 ///
@@ -290,7 +290,8 @@ impl LintStore {
             CheckLintNameResult::Ok(_) => None,
             CheckLintNameResult::Warning(ref msg, _) => Some(sess.struct_warn(msg)),
             CheckLintNameResult::NoLint(suggestion) => {
-                let mut err = struct_err!(sess, E0602, "unknown lint: `{}`", lint_name);
+                let mut err =
+                    struct_span_err!(sess, DUMMY_SP, E0602, "unknown lint: `{}`", lint_name);
 
                 if let Some(suggestion) = suggestion {
                     err.help(&format!("did you mean: `{}`", suggestion));
diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs
index 78d01ff4fed..abd52a9de50 100644
--- a/src/librustc/lint/levels.rs
+++ b/src/librustc/lint/levels.rs
@@ -5,7 +5,7 @@ use crate::lint::builtin;
 use crate::lint::context::{CheckLintNameResult, LintStore};
 use crate::lint::{self, Level, Lint, LintId, LintSource};
 use crate::session::Session;
-use errors::{Applicability, DiagnosticBuilder};
+use errors::{struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_hir::HirId;
@@ -274,13 +274,14 @@ impl<'a> LintLevelsBuilder<'a> {
                 let tool_name = if meta_item.path.segments.len() > 1 {
                     let tool_ident = meta_item.path.segments[0].ident;
                     if !attr::is_known_lint_tool(tool_ident) {
-                        span_err!(
+                        struct_span_err!(
                             sess,
                             tool_ident.span,
                             E0710,
                             "an unknown tool name found in scoped lint: `{}`",
                             pprust::path_to_string(&meta_item.path),
-                        );
+                        )
+                        .emit();
                         continue;
                     }
 
diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs
index 220560a67e0..6f59df01a52 100644
--- a/src/librustc/middle/lang_items.rs
+++ b/src/librustc/middle/lang_items.rs
@@ -14,6 +14,7 @@ use crate::middle::cstore::ExternCrate;
 use crate::middle::weak_lang_items;
 use crate::ty::{self, TyCtxt};
 
+use errors::struct_span_err;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
@@ -184,7 +185,8 @@ impl LanguageItemCollector<'tcx> {
                         span,
                         E0152,
                         "duplicate lang item found: `{}`.",
-                        name),
+                        name
+                    ),
                     None => {
                         match self.tcx.extern_crate(item_def_id) {
                             Some(ExternCrate {dependency_of, ..}) => {
@@ -204,7 +206,7 @@ impl LanguageItemCollector<'tcx> {
                     },
                 };
                 if let Some(span) = self.tcx.hir().span_if_local(original_def_id) {
-                    span_note!(&mut err, span, "first defined here.");
+                    err.span_note(span, "first defined here.");
                 } else {
                     match self.tcx.extern_crate(original_def_id) {
                         Some(ExternCrate {dependency_of, ..}) => {
diff --git a/src/librustc/middle/weak_lang_items.rs b/src/librustc/middle/weak_lang_items.rs
index 8e6ac165fab..e9e35b7617c 100644
--- a/src/librustc/middle/weak_lang_items.rs
+++ b/src/librustc/middle/weak_lang_items.rs
@@ -6,6 +6,7 @@ use crate::session::config;
 use crate::hir::intravisit;
 use crate::hir::intravisit::{NestedVisitorMap, Visitor};
 use crate::ty::TyCtxt;
+use errors::struct_span_err;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
@@ -124,9 +125,12 @@ impl<'a, 'tcx> Context<'a, 'tcx> {
                 self.items.missing.push(lang_items::$item);
             }
         } else)* {
-            span_err!(self.tcx.sess, span, E0264,
-                      "unknown external lang item: `{}`",
-                      name);
+            struct_span_err!(
+                self.tcx.sess, span, E0264,
+                "unknown external lang item: `{}`",
+                name
+            )
+            .emit();
         }
     }
 }
diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs
index f54b9231d1a..cb11ac49cec 100644
--- a/src/librustc/mir/interpret/error.rs
+++ b/src/librustc/mir/interpret/error.rs
@@ -7,7 +7,7 @@ use crate::ty::query::TyCtxtAt;
 use crate::ty::{self, layout, Ty};
 
 use backtrace::Backtrace;
-use errors::DiagnosticBuilder;
+use errors::{struct_span_err, DiagnosticBuilder};
 use hir::GeneratorKind;
 use rustc_hir as hir;
 use rustc_macros::HashStable;
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index 172330dbc7e..00251d55706 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -20,7 +20,8 @@ use crate::ty::GenericParamDefKind;
 use crate::ty::SubtypePredicate;
 use crate::ty::TypeckTables;
 use crate::ty::{self, AdtKind, DefIdTree, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable};
-use errors::{pluralize, Applicability, DiagnosticBuilder, Style};
+
+use errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, Style};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
diff --git a/src/librustc/traits/on_unimplemented.rs b/src/librustc/traits/on_unimplemented.rs
index 92984b48ae9..f1b830e43fc 100644
--- a/src/librustc/traits/on_unimplemented.rs
+++ b/src/librustc/traits/on_unimplemented.rs
@@ -2,6 +2,8 @@ use fmt_macros::{Parser, Piece, Position};
 
 use crate::ty::{self, GenericParamDefKind, TyCtxt};
 use crate::util::common::ErrorReported;
+
+use errors::struct_span_err;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::def_id::DefId;
 use rustc_span::symbol::{kw, sym, Symbol};
@@ -292,26 +294,28 @@ impl<'tcx> OnUnimplementedFormatString {
                         match generics.params.iter().find(|param| param.name == s) {
                             Some(_) => (),
                             None => {
-                                span_err!(
+                                struct_span_err!(
                                     tcx.sess,
                                     span,
                                     E0230,
                                     "there is no parameter `{}` on trait `{}`",
                                     s,
                                     name
-                                );
+                                )
+                                .emit();
                                 result = Err(ErrorReported);
                             }
                         }
                     }
                     // `{:1}` and `{}` are not to be used
                     Position::ArgumentIs(_) | Position::ArgumentImplicitlyIs(_) => {
-                        span_err!(
+                        struct_span_err!(
                             tcx.sess,
                             span,
                             E0231,
                             "only named substitution parameters are allowed"
-                        );
+                        )
+                        .emit();
                         result = Err(ErrorReported);
                     }
                 },
diff --git a/src/librustc/traits/query/dropck_outlives.rs b/src/librustc/traits/query/dropck_outlives.rs
index 87f7f674dab..370acb53896 100644
--- a/src/librustc/traits/query/dropck_outlives.rs
+++ b/src/librustc/traits/query/dropck_outlives.rs
@@ -76,15 +76,15 @@ pub struct DropckOutlivesResult<'tcx> {
 impl<'tcx> DropckOutlivesResult<'tcx> {
     pub fn report_overflows(&self, tcx: TyCtxt<'tcx>, span: Span, ty: Ty<'tcx>) {
         if let Some(overflow_ty) = self.overflows.iter().next() {
-            let mut err = struct_span_err!(
+            errors::struct_span_err!(
                 tcx.sess,
                 span,
                 E0320,
                 "overflow while adding drop-check rules for {}",
                 ty,
-            );
-            err.note(&format!("overflowed on {}", overflow_ty));
-            err.emit();
+            )
+            .note(&format!("overflowed on {}", overflow_ty))
+            .emit();
         }
     }
 
diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs
index 520cd3e3852..d1897148838 100644
--- a/src/librustc/traits/specialize/mod.rs
+++ b/src/librustc/traits/specialize/mod.rs
@@ -17,6 +17,7 @@ use crate::traits::select::IntercrateAmbiguityCause;
 use crate::traits::{self, coherence, FutureCompatOverlapErrorKind, ObligationCause, TraitEngine};
 use crate::ty::subst::{InternalSubsts, Subst, SubstsRef};
 use crate::ty::{self, TyCtxt, TypeFoldable};
+use errors::struct_span_err;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def_id::DefId;
 use rustc_span::DUMMY_SP;
diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs
index e56955b0e44..35608540383 100644
--- a/src/librustc/ty/query/plumbing.rs
+++ b/src/librustc/ty/query/plumbing.rs
@@ -9,11 +9,7 @@ use crate::ty::query::Query;
 use crate::ty::tls;
 use crate::ty::{self, TyCtxt};
 
-use errors::Diagnostic;
-use errors::DiagnosticBuilder;
-use errors::FatalError;
-use errors::Handler;
-use errors::Level;
+use errors::{struct_span_err, Diagnostic, DiagnosticBuilder, FatalError, Handler, Level};
 #[cfg(not(parallel_compiler))]
 use rustc_data_structures::cold_path;
 use rustc_data_structures::fx::{FxHashMap, FxHasher};
diff --git a/src/librustc_ast_lowering/expr.rs b/src/librustc_ast_lowering/expr.rs
index 6c8b8b05057..ee020c7e589 100644
--- a/src/librustc_ast_lowering/expr.rs
+++ b/src/librustc_ast_lowering/expr.rs
@@ -3,6 +3,7 @@ use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericAr
 use rustc::bug;
 use rustc_data_structures::thin_vec::ThinVec;
 use rustc_error_codes::*;
+use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def::Res;
 use rustc_span::source_map::{respan, DesugaringKind, Span, Spanned};
@@ -10,7 +11,6 @@ use rustc_span::symbol::{sym, Symbol};
 use syntax::ast::*;
 use syntax::attr;
 use syntax::ptr::P as AstP;
-use syntax::{span_err, struct_span_err};
 
 impl<'hir> LoweringContext<'_, 'hir> {
     fn lower_exprs(&mut self, exprs: &[AstP<Expr>]) -> &'hir [hir::Expr<'hir>] {
@@ -685,12 +685,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
         match generator_kind {
             Some(hir::GeneratorKind::Gen) => {
                 if !decl.inputs.is_empty() {
-                    span_err!(
+                    struct_span_err!(
                         self.sess,
                         fn_decl_span,
                         E0628,
                         "generators cannot have explicit parameters"
-                    );
+                    )
+                    .emit();
                 }
                 Some(movability)
             }
@@ -699,7 +700,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
             }
             None => {
                 if movability == Movability::Static {
-                    span_err!(self.sess, fn_decl_span, E0697, "closures cannot be static");
+                    struct_span_err!(self.sess, fn_decl_span, E0697, "closures cannot be static")
+                        .emit();
                 }
                 None
             }
@@ -946,7 +948,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
         match self.generator_kind {
             Some(hir::GeneratorKind::Gen) => {}
             Some(hir::GeneratorKind::Async(_)) => {
-                span_err!(self.sess, span, E0727, "`async` generators are not yet supported",);
+                struct_span_err!(
+                    self.sess,
+                    span,
+                    E0727,
+                    "`async` generators are not yet supported"
+                )
+                .emit();
                 return hir::ExprKind::Err;
             }
             None => self.generator_kind = Some(hir::GeneratorKind::Gen),
diff --git a/src/librustc_ast_lowering/item.rs b/src/librustc_ast_lowering/item.rs
index 2515ca9d946..a5892a22d9d 100644
--- a/src/librustc_ast_lowering/item.rs
+++ b/src/librustc_ast_lowering/item.rs
@@ -4,6 +4,7 @@ use super::{ImplTraitContext, ImplTraitPosition, ImplTraitTypeIdVisitor};
 use rustc::arena::Arena;
 use rustc::bug;
 use rustc_error_codes::*;
+use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
@@ -14,7 +15,6 @@ use rustc_span::Span;
 use rustc_target::spec::abi;
 use syntax::ast::*;
 use syntax::attr;
-use syntax::struct_span_err;
 use syntax::visit::{self, Visitor};
 
 use log::debug;
diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs
index bc3dfecd4a6..8b79d9b4f47 100644
--- a/src/librustc_ast_lowering/lib.rs
+++ b/src/librustc_ast_lowering/lib.rs
@@ -47,7 +47,7 @@ use rustc::{bug, span_bug};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::sync::Lrc;
 use rustc_error_codes::*;
-use rustc_errors::Applicability;
+use rustc_errors::{struct_span_err, Applicability};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Namespace, PartialRes, PerNS, Res};
 use rustc_hir::def_id::{DefId, DefIdMap, DefIndex, CRATE_DEF_INDEX};
@@ -69,7 +69,7 @@ use syntax::sess::ParseSess;
 use syntax::token::{self, Nonterminal, Token};
 use syntax::tokenstream::{TokenStream, TokenTree};
 use syntax::visit::{self, Visitor};
-use syntax::{help, struct_span_err, walk_list};
+use syntax::walk_list;
 
 use log::{debug, trace};
 use smallvec::{smallvec, SmallVec};
@@ -1347,10 +1347,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         );
                         if pos == ImplTraitPosition::Binding && nightly_options::is_nightly_build()
                         {
-                            help!(
-                                err,
+                            err.help(
                                 "add `#![feature(impl_trait_in_bindings)]` to the crate \
-                                   attributes to enable"
+                                   attributes to enable",
                             );
                         }
                         err.emit();
diff --git a/src/librustc_builtin_macros/asm.rs b/src/librustc_builtin_macros/asm.rs
index a136a07a40c..78d2d37ef56 100644
--- a/src/librustc_builtin_macros/asm.rs
+++ b/src/librustc_builtin_macros/asm.rs
@@ -2,7 +2,7 @@
 //
 use State::*;
 
-use errors::{DiagnosticBuilder, PResult};
+use errors::{struct_span_err, DiagnosticBuilder, PResult};
 use rustc_expand::base::*;
 use rustc_parse::parser::Parser;
 use rustc_span::symbol::{kw, sym, Symbol};
@@ -11,7 +11,6 @@ use syntax::ast::{self, AsmDialect};
 use syntax::ptr::P;
 use syntax::token::{self, Token};
 use syntax::tokenstream::{self, TokenStream};
-use syntax::{span_err, struct_span_err};
 
 use rustc_error_codes::*;
 
@@ -173,12 +172,13 @@ fn parse_inline_asm<'a>(
                         Some('=') => None,
                         Some('+') => Some(Symbol::intern(&format!("={}", ch.as_str()))),
                         _ => {
-                            span_err!(
-                                cx,
+                            struct_span_err!(
+                                cx.parse_sess.span_diagnostic,
                                 span,
                                 E0661,
                                 "output operand constraint lacks '=' or '+'"
-                            );
+                            )
+                            .emit();
                             None
                         }
                     };
@@ -202,9 +202,21 @@ fn parse_inline_asm<'a>(
                     let constraint = parse_asm_str(&mut p)?;
 
                     if constraint.as_str().starts_with("=") {
-                        span_err!(cx, p.prev_span, E0662, "input operand constraint contains '='");
+                        struct_span_err!(
+                            cx.parse_sess.span_diagnostic,
+                            p.prev_span,
+                            E0662,
+                            "input operand constraint contains '='"
+                        )
+                        .emit();
                     } else if constraint.as_str().starts_with("+") {
-                        span_err!(cx, p.prev_span, E0663, "input operand constraint contains '+'");
+                        struct_span_err!(
+                            cx.parse_sess.span_diagnostic,
+                            p.prev_span,
+                            E0663,
+                            "input operand constraint contains '+'"
+                        )
+                        .emit();
                     }
 
                     p.expect(&token::OpenDelim(token::Paren))?;
@@ -225,12 +237,13 @@ fn parse_inline_asm<'a>(
                     if OPTIONS.iter().any(|&opt| s == opt) {
                         cx.span_warn(p.prev_span, "expected a clobber, found an option");
                     } else if s.as_str().starts_with("{") || s.as_str().ends_with("}") {
-                        span_err!(
-                            cx,
+                        struct_span_err!(
+                            cx.parse_sess.span_diagnostic,
                             p.prev_span,
                             E0664,
                             "clobber should not be surrounded by braces"
-                        );
+                        )
+                        .emit();
                     }
 
                     clobs.push(s);
diff --git a/src/librustc_builtin_macros/deriving/default.rs b/src/librustc_builtin_macros/deriving/default.rs
index f40d6d7e424..8d3f1951373 100644
--- a/src/librustc_builtin_macros/deriving/default.rs
+++ b/src/librustc_builtin_macros/deriving/default.rs
@@ -2,12 +2,12 @@ use crate::deriving::generic::ty::*;
 use crate::deriving::generic::*;
 use crate::deriving::path_std;
 
+use errors::struct_span_err;
 use rustc_expand::base::{Annotatable, DummyResult, ExtCtxt};
 use rustc_span::symbol::{kw, sym};
 use rustc_span::Span;
 use syntax::ast::{Expr, MetaItem};
 use syntax::ptr::P;
-use syntax::span_err;
 
 use rustc_error_codes::*;
 
@@ -74,7 +74,13 @@ fn default_substructure(
             }
         },
         StaticEnum(..) => {
-            span_err!(cx, trait_span, E0665, "`Default` cannot be derived for enums, only structs");
+            struct_span_err!(
+                cx.parse_sess.span_diagnostic,
+                trait_span,
+                E0665,
+                "`Default` cannot be derived for enums, only structs"
+            )
+            .emit();
             // let compilation continue
             DummyResult::raw_expr(trait_span, true)
         }
diff --git a/src/librustc_codegen_ssa/common.rs b/src/librustc_codegen_ssa/common.rs
index 299a6d95272..e4531a77656 100644
--- a/src/librustc_codegen_ssa/common.rs
+++ b/src/librustc_codegen_ssa/common.rs
@@ -2,6 +2,7 @@
 
 use rustc::session::Session;
 use rustc::ty::{Ty, TyCtxt};
+use rustc_errors::struct_span_err;
 use rustc_span::Span;
 
 use crate::base;
@@ -196,5 +197,5 @@ pub fn shift_mask_val<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
 }
 
 pub fn span_invalid_monomorphization_error(a: &Session, b: Span, c: &str) {
-    span_err!(a, b, E0511, "{}", c);
+    struct_span_err!(a, b, E0511, "{}", c).emit();
 }
diff --git a/src/librustc_codegen_ssa/lib.rs b/src/librustc_codegen_ssa/lib.rs
index b476fd95200..a8d051db8b4 100644
--- a/src/librustc_codegen_ssa/lib.rs
+++ b/src/librustc_codegen_ssa/lib.rs
@@ -21,8 +21,6 @@
 extern crate log;
 #[macro_use]
 extern crate rustc;
-#[macro_use]
-extern crate syntax;
 
 use rustc::dep_graph::WorkProduct;
 use rustc::middle::cstore::{CrateSource, LibSource, NativeLibrary};
diff --git a/src/librustc_codegen_ssa/mir/statement.rs b/src/librustc_codegen_ssa/mir/statement.rs
index 48ba64143a7..574c06d9ceb 100644
--- a/src/librustc_codegen_ssa/mir/statement.rs
+++ b/src/librustc_codegen_ssa/mir/statement.rs
@@ -1,4 +1,5 @@
 use rustc::mir;
+use rustc_errors::struct_span_err;
 
 use super::FunctionCx;
 use super::LocalRef;
@@ -81,12 +82,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         if let OperandValue::Immediate(_) = op.val {
                             acc.push(op.immediate());
                         } else {
-                            span_err!(
+                            struct_span_err!(
                                 bx.sess(),
                                 span.to_owned(),
                                 E0669,
                                 "invalid value for constraint in inline assembly"
-                            );
+                            )
+                            .emit();
                         }
                         acc
                     },
@@ -100,12 +102,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         statement.source_info.span,
                     );
                     if !res {
-                        span_err!(
+                        struct_span_err!(
                             bx.sess(),
                             statement.source_info.span,
                             E0668,
                             "malformed inline assembly"
-                        );
+                        )
+                        .emit();
                     }
                 }
                 bx
diff --git a/src/librustc_error_codes/error_codes/E0566.md b/src/librustc_error_codes/error_codes/E0566.md
index 62fb66f6149..3dcd801a21a 100644
--- a/src/librustc_error_codes/error_codes/E0566.md
+++ b/src/librustc_error_codes/error_codes/E0566.md
@@ -2,8 +2,8 @@ Conflicting representation hints have been used on a same item.
 
 Erroneous code example:
 
-```
-#[repr(u32, u64)] // warning!
+```compile_fail,E0566
+#[repr(u32, u64)]
 enum Repr { A }
 ```
 
diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs
index 79ec9ad7b03..73f66d55037 100644
--- a/src/librustc_errors/diagnostic_builder.rs
+++ b/src/librustc_errors/diagnostic_builder.rs
@@ -385,3 +385,22 @@ impl<'a> Drop for DiagnosticBuilder<'a> {
         }
     }
 }
+
+#[macro_export]
+macro_rules! struct_span_err {
+    ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
+        $session.struct_span_err_with_code(
+            $span,
+            &format!($($message)*),
+            $crate::error_code!($code),
+        )
+    })
+}
+
+#[macro_export]
+macro_rules! error_code {
+    ($code:ident) => {{
+        let _ = $code;
+        $crate::DiagnosticId::Error(stringify!($code).to_owned())
+    }};
+}
diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index cfd7b76a222..b21715fadfe 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -20,6 +20,7 @@ use rustc_target::spec::{PanicStrategy, TargetTriple};
 use std::path::Path;
 use std::{cmp, fs};
 
+use errors::struct_span_err;
 use log::{debug, info, log_enabled};
 use proc_macro::bridge::client::ProcMacro;
 use rustc_expand::base::SyntaxExtension;
@@ -29,7 +30,6 @@ use rustc_span::{Span, DUMMY_SP};
 use syntax::ast;
 use syntax::attr;
 use syntax::expand::allocator::{global_allocator_spans, AllocatorKind};
-use syntax::span_fatal;
 
 use rustc_error_codes::*;
 
@@ -261,7 +261,7 @@ impl<'a> CrateLoader<'a> {
         if self.local_crate_name == root.name()
             && self.sess.local_crate_disambiguator() == root.disambiguator()
         {
-            span_fatal!(
+            struct_span_err!(
                 self.sess,
                 span,
                 E0519,
@@ -271,6 +271,7 @@ impl<'a> CrateLoader<'a> {
                          will result in symbol conflicts between the two.",
                 root.name()
             )
+            .emit()
         }
 
         // Check for conflicts with any crate loaded so far
@@ -280,7 +281,7 @@ impl<'a> CrateLoader<'a> {
                other.hash() != root.hash()
             {
                 // but different SVH
-                span_fatal!(
+                struct_span_err!(
                     self.sess,
                     span,
                     E0523,
@@ -289,6 +290,7 @@ impl<'a> CrateLoader<'a> {
                          will result in symbol conflicts between the two.",
                     root.name()
                 )
+                .emit();
             }
         });
     }
diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs
index 59e769cabb7..9f9a2187ece 100644
--- a/src/librustc_metadata/locator.rs
+++ b/src/librustc_metadata/locator.rs
@@ -215,6 +215,7 @@
 use crate::creader::Library;
 use crate::rmeta::{rustc_version, MetadataBlob, METADATA_HEADER};
 
+use errors::{struct_span_err, DiagnosticBuilder};
 use rustc::middle::cstore::{CrateSource, MetadataLoader};
 use rustc::session::filesearch::{FileDoesntMatch, FileMatches, FileSearch};
 use rustc::session::search_paths::PathKind;
@@ -222,13 +223,9 @@ use rustc::session::{config, CrateDisambiguator, Session};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::MetadataRef;
-
-use errors::DiagnosticBuilder;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
 use rustc_target::spec::{Target, TargetTriple};
-use syntax::struct_span_err;
-use syntax::{span_err, span_fatal};
 
 use std::cmp;
 use std::fmt;
@@ -1038,28 +1035,28 @@ pub fn find_plugin_registrar(
     };
 
     if target_only {
-        // Need to abort before syntax expansion.
         let message = format!(
-            "plugin `{}` is not available for triple `{}` \
-                                (only found {})",
+            "plugin `{}` is not available for triple `{}` (only found {})",
             name,
             config::host_triple(),
             sess.opts.target_triple
         );
-        span_fatal!(sess, span, E0456, "{}", &message);
+        struct_span_err!(sess, span, E0456, "{}", &message).emit();
+        return None;
     }
 
     match library.source.dylib {
         Some(dylib) => Some((dylib.0, library.metadata.get_root().disambiguator())),
         None => {
-            span_err!(
+            struct_span_err!(
                 sess,
                 span,
                 E0457,
                 "plugin `{}` only found in rlib format, but must be available \
                         in dylib format",
                 name
-            );
+            )
+            .emit();
             // No need to abort because the loading code will just ignore this
             // empty dylib.
             None
diff --git a/src/librustc_metadata/native_libs.rs b/src/librustc_metadata/native_libs.rs
index c524d2074f5..c9f47475af8 100644
--- a/src/librustc_metadata/native_libs.rs
+++ b/src/librustc_metadata/native_libs.rs
@@ -1,7 +1,9 @@
+use errors::struct_span_err;
 use rustc::middle::cstore::{self, NativeLibrary};
 use rustc::session::Session;
 use rustc::ty::TyCtxt;
 use rustc_data_structures::fx::FxHashSet;
+use rustc_error_codes::*;
 use rustc_hir as hir;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_span::source_map::Span;
@@ -9,9 +11,6 @@ use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_target::spec::abi::Abi;
 use syntax::attr;
 use syntax::feature_gate::feature_err;
-use syntax::{span_err, struct_span_err};
-
-use rustc_error_codes::*;
 
 crate fn collect(tcx: TyCtxt<'_>) -> Vec<NativeLibrary> {
     let mut collector = Collector { tcx, libs: Vec::new() };
@@ -159,7 +158,7 @@ impl Collector<'tcx> {
         if lib.kind == cstore::NativeFramework && !is_osx {
             let msg = "native frameworks are only available on macOS targets";
             match span {
-                Some(span) => span_err!(self.tcx.sess, span, E0455, "{}", msg),
+                Some(span) => struct_span_err!(self.tcx.sess, span, E0455, "{}", msg).emit(),
                 None => self.tcx.sess.err(msg),
             }
         }
diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs
index a963735905e..b1df198406d 100644
--- a/src/librustc_mir/borrow_check/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/type_check/mod.rs
@@ -28,6 +28,7 @@ use rustc::ty::{
 };
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_error_codes::*;
+use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_index::vec::{Idx, IndexVec};
diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs
index ca7912b447e..07bb87f7b54 100644
--- a/src/librustc_mir/hair/pattern/check_match.rs
+++ b/src/librustc_mir/hair/pattern/check_match.rs
@@ -10,7 +10,7 @@ use rustc::session::Session;
 use rustc::ty::subst::{InternalSubsts, SubstsRef};
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc_error_codes::*;
-use rustc_errors::{Applicability, DiagnosticBuilder};
+use rustc_errors::{error_code, struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::def::*;
 use rustc_hir::def_id::DefId;
@@ -116,7 +116,7 @@ impl PatCtxt<'_, '_> {
     }
 
     fn span_e0158(&self, span: Span, text: &str) {
-        span_err!(self.tcx.sess, span, E0158, "{}", text)
+        struct_span_err!(self.tcx.sess, span, E0158, "{}", text).emit();
     }
 }
 
@@ -291,24 +291,26 @@ fn check_for_bindings_named_same_as_variants(cx: &MatchVisitor<'_, '_>, pat: &Pa
                             variant.ident == ident && variant.ctor_kind == CtorKind::Const
                         })
                     {
-                        // FIXME(Centril): Should be a lint?
                         let ty_path = cx.tcx.def_path_str(edef.did);
-                        let mut err = struct_span_warn!(
-                            cx.tcx.sess,
-                            p.span,
-                            E0170,
-                            "pattern binding `{}` is named the same as one \
-                             of the variants of the type `{}`",
-                            ident,
-                            ty_path
-                        );
-                        err.span_suggestion(
-                            p.span,
-                            "to match on the variant, qualify the path",
-                            format!("{}::{}", ty_path, ident),
-                            Applicability::MachineApplicable,
-                        );
-                        err.emit();
+                        cx.tcx
+                            .struct_span_lint_hir(
+                                lint::builtin::BINDINGS_WITH_VARIANT_NAME,
+                                p.hir_id,
+                                p.span,
+                                &format!(
+                                    "pattern binding `{}` is named the same as one \
+                                    of the variants of the type `{}`",
+                                    ident, ty_path
+                                ),
+                            )
+                            .code(error_code!(E0170))
+                            .span_suggestion(
+                                p.span,
+                                "to match on the variant, qualify the path",
+                                format!("{}::{}", ty_path, ident),
+                                Applicability::MachineApplicable,
+                            )
+                            .emit();
                     }
                 }
             }
diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs
index bac40a06c78..611d3f5b832 100644
--- a/src/librustc_mir/hair/pattern/mod.rs
+++ b/src/librustc_mir/hair/pattern/mod.rs
@@ -16,6 +16,7 @@ use rustc::ty::layout::VariantIdx;
 use rustc::ty::subst::{GenericArg, SubstsRef};
 use rustc::ty::{self, AdtDef, DefIdTree, Region, Ty, TyCtxt, UserType};
 use rustc::ty::{CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations};
+use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
 use rustc_hir::pat_util::EnumerateAndAdjustIterator;
@@ -463,12 +464,13 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
                                 PatKind::Range(PatRange { lo, hi, end })
                             }
                             (RangeEnd::Excluded, _) => {
-                                span_err!(
+                                struct_span_err!(
                                     self.tcx.sess,
                                     lo_expr.span,
                                     E0579,
                                     "lower range bound must be less than upper",
-                                );
+                                )
+                                .emit();
                                 PatKind::Wild
                             }
                             (RangeEnd::Included, Some(Ordering::Equal)) => {
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index 32b35c4139d..9f70f1dd576 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -35,8 +35,6 @@ Rust MIR: a lowered representation of Rust. Also: an experiment!
 extern crate log;
 #[macro_use]
 extern crate rustc;
-#[macro_use]
-extern crate syntax;
 
 mod borrow_check;
 mod build;
diff --git a/src/librustc_mir/transform/check_consts/ops.rs b/src/librustc_mir/transform/check_consts/ops.rs
index 1583647a4d4..abef008a8ec 100644
--- a/src/librustc_mir/transform/check_consts/ops.rs
+++ b/src/librustc_mir/transform/check_consts/ops.rs
@@ -2,6 +2,7 @@
 
 use rustc::session::config::nightly_options;
 use rustc::ty::TyCtxt;
+use rustc_errors::struct_span_err;
 use rustc_hir::def_id::DefId;
 use rustc_span::symbol::sym;
 use rustc_span::{Span, Symbol};
@@ -115,12 +116,7 @@ impl NonConstOp for FnCallUnstable {
             &format!("`{}` is not yet stable as a const fn", item.tcx.def_path_str(def_id)),
         );
         if nightly_options::is_nightly_build() {
-            help!(
-                &mut err,
-                "add `#![feature({})]` to the \
-                   crate attributes to enable",
-                feature
-            );
+            err.help(&format!("add `#![feature({})]` to the crate attributes to enable", feature));
         }
         err.emit();
     }
@@ -197,13 +193,14 @@ impl NonConstOp for Loop {
 pub struct CellBorrow;
 impl NonConstOp for CellBorrow {
     fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
-        span_err!(
+        struct_span_err!(
             item.tcx.sess,
             span,
             E0492,
             "cannot borrow a constant which may contain \
             interior mutability, create a static instead"
-        );
+        )
+        .emit();
     }
 }
 
@@ -375,13 +372,14 @@ impl NonConstOp for ThreadLocalAccess {
     const IS_SUPPORTED_IN_MIRI: bool = false;
 
     fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
-        span_err!(
+        struct_span_err!(
             item.tcx.sess,
             span,
             E0625,
             "thread-local statics cannot be \
             accessed at compile-time"
-        );
+        )
+        .emit();
     }
 }
 
diff --git a/src/librustc_mir/transform/check_consts/validation.rs b/src/librustc_mir/transform/check_consts/validation.rs
index 3c52a2e0dd2..0aa42de538d 100644
--- a/src/librustc_mir/transform/check_consts/validation.rs
+++ b/src/librustc_mir/transform/check_consts/validation.rs
@@ -7,6 +7,7 @@ use rustc::traits::{self, TraitEngine};
 use rustc::ty::cast::CastTy;
 use rustc::ty::{self, TyCtxt};
 use rustc_error_codes::*;
+use rustc_errors::struct_span_err;
 use rustc_hir::{def_id::DefId, HirId};
 use rustc_index::bit_set::BitSet;
 use rustc_span::symbol::sym;
diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs
index b333bc681f6..5cf5c54dd48 100644
--- a/src/librustc_mir/transform/check_unsafety.rs
+++ b/src/librustc_mir/transform/check_unsafety.rs
@@ -6,6 +6,7 @@ use rustc::ty::cast::CastTy;
 use rustc::ty::query::Providers;
 use rustc::ty::{self, TyCtxt};
 use rustc_data_structures::fx::FxHashSet;
+use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::Node;
diff --git a/src/librustc_mir/util/borrowck_errors.rs b/src/librustc_mir/util/borrowck_errors.rs
index 9f67109b34a..c275eecfb33 100644
--- a/src/librustc_mir/util/borrowck_errors.rs
+++ b/src/librustc_mir/util/borrowck_errors.rs
@@ -1,8 +1,7 @@
 use rustc::ty::{self, Ty, TyCtxt};
-use rustc_errors::{DiagnosticBuilder, DiagnosticId};
-use rustc_span::{MultiSpan, Span};
-
 use rustc_error_codes::*;
+use rustc_errors::{struct_span_err, DiagnosticBuilder, DiagnosticId};
+use rustc_span::{MultiSpan, Span};
 
 impl<'cx, 'tcx> crate::borrow_check::MirBorrowckCtxt<'cx, 'tcx> {
     crate fn cannot_move_when_borrowed(&self, span: Span, desc: &str) -> DiagnosticBuilder<'cx> {
diff --git a/src/librustc_parse/parser/diagnostics.rs b/src/librustc_parse/parser/diagnostics.rs
index 94785e9eff3..9abfbc698c5 100644
--- a/src/librustc_parse/parser/diagnostics.rs
+++ b/src/librustc_parse/parser/diagnostics.rs
@@ -2,7 +2,8 @@ use super::{BlockMode, Parser, PathStyle, SemiColonMode, SeqSep, TokenExpectType
 
 use rustc_data_structures::fx::FxHashSet;
 use rustc_error_codes::*;
-use rustc_errors::{self, pluralize, Applicability, DiagnosticBuilder, Handler, PResult};
+use rustc_errors::{pluralize, struct_span_err};
+use rustc_errors::{Applicability, DiagnosticBuilder, Handler, PResult};
 use rustc_span::symbol::kw;
 use rustc_span::{MultiSpan, Span, SpanSnippetError, DUMMY_SP};
 use syntax::ast::{
@@ -11,7 +12,6 @@ use syntax::ast::{
 use syntax::ast::{AttrVec, ItemKind, Mutability, Pat, PatKind, PathSegment, QSelf, Ty, TyKind};
 use syntax::print::pprust;
 use syntax::ptr::P;
-use syntax::struct_span_err;
 use syntax::token::{self, token_can_begin_expr, TokenKind};
 use syntax::util::parser::AssocOp;
 
diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs
index a05bc48981e..918e826fc26 100644
--- a/src/librustc_parse/parser/item.rs
+++ b/src/librustc_parse/parser/item.rs
@@ -4,7 +4,7 @@ use super::{FollowedByType, Parser, PathStyle};
 use crate::maybe_whole;
 
 use rustc_error_codes::*;
-use rustc_errors::{Applicability, DiagnosticBuilder, PResult, StashKey};
+use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, PResult, StashKey};
 use rustc_span::source_map::{self, respan, Span};
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::BytePos;
@@ -16,7 +16,6 @@ use syntax::ast::{EnumDef, Generics, StructField, TraitRef, Ty, TyKind, Variant,
 use syntax::ast::{FnHeader, ForeignItem, ForeignItemKind, Mutability, Visibility, VisibilityKind};
 use syntax::print::pprust;
 use syntax::ptr::P;
-use syntax::struct_span_err;
 use syntax::token;
 use syntax::tokenstream::{DelimSpan, TokenStream, TokenTree};
 
diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs
index a2fa335cf72..8d695eda98d 100644
--- a/src/librustc_parse/parser/mod.rs
+++ b/src/librustc_parse/parser/mod.rs
@@ -15,7 +15,7 @@ use crate::lexer::UnmatchedBrace;
 use crate::{Directory, DirectoryOwnership};
 
 use log::debug;
-use rustc_errors::{Applicability, DiagnosticBuilder, FatalError, PResult};
+use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, FatalError, PResult};
 use rustc_span::source_map::respan;
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::{BytePos, FileName, Span, DUMMY_SP};
@@ -24,7 +24,6 @@ use syntax::ast::{IsAsync, MacArgs, MacDelimiter, Mutability, StrLit, Visibility
 use syntax::print::pprust;
 use syntax::ptr::P;
 use syntax::sess::ParseSess;
-use syntax::struct_span_err;
 use syntax::token::{self, DelimToken, Token, TokenKind};
 use syntax::tokenstream::{self, DelimSpan, TokenStream, TokenTree, TreeAndJoint};
 use syntax::util::comments::{doc_comment_style, strip_doc_comment_decoration};
diff --git a/src/librustc_parse/parser/ty.rs b/src/librustc_parse/parser/ty.rs
index 4122aa17f83..f96c82a1ab3 100644
--- a/src/librustc_parse/parser/ty.rs
+++ b/src/librustc_parse/parser/ty.rs
@@ -4,7 +4,7 @@ use super::{Parser, PathStyle, PrevTokenKind, TokenType};
 use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
 
 use rustc_error_codes::*;
-use rustc_errors::{pluralize, Applicability, PResult};
+use rustc_errors::{pluralize, struct_span_err, Applicability, PResult};
 use rustc_span::source_map::Span;
 use rustc_span::symbol::kw;
 use syntax::ast::{
@@ -15,7 +15,6 @@ use syntax::ast::{
 };
 use syntax::ast::{Mac, Mutability};
 use syntax::ptr::P;
-use syntax::struct_span_err;
 use syntax::token::{self, Token};
 
 /// Returns `true` if `IDENT t` can start a type -- `IDENT::a::b`, `IDENT<u8, u8>`,
diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs
index 038c4284f25..5000cd5f52f 100644
--- a/src/librustc_passes/ast_validation.rs
+++ b/src/librustc_passes/ast_validation.rs
@@ -6,7 +6,7 @@
 // This pass is supposed to perform only simple checks not requiring name resolution
 // or type checking or some other kind of complex analysis.
 
-use errors::{Applicability, FatalError};
+use errors::{struct_span_err, Applicability, FatalError};
 use rustc::lint;
 use rustc::session::Session;
 use rustc_data_structures::fx::FxHashMap;
@@ -20,7 +20,7 @@ use syntax::attr;
 use syntax::expand::is_proc_macro_attr;
 use syntax::print::pprust;
 use syntax::visit::{self, Visitor};
-use syntax::{span_err, struct_span_err, walk_list};
+use syntax::walk_list;
 
 use rustc_error_codes::*;
 
@@ -470,7 +470,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 self.check_fn_decl(fn_decl);
             }
             ExprKind::InlineAsm(..) if !self.session.target.target.options.allow_asm => {
-                span_err!(self.session, expr.span, E0472, "asm! is unsupported on this target");
+                struct_span_err!(
+                    self.session,
+                    expr.span,
+                    E0472,
+                    "asm! is unsupported on this target"
+                )
+                .emit();
             }
             _ => {}
         }
@@ -498,12 +504,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 for bound in bounds {
                     if let GenericBound::Outlives(ref lifetime) = *bound {
                         if any_lifetime_bounds {
-                            span_err!(
+                            struct_span_err!(
                                 self.session,
                                 lifetime.ident.span,
                                 E0226,
                                 "only a single explicit lifetime bound is permitted"
-                            );
+                            )
+                            .emit();
                             break;
                         }
                         any_lifetime_bounds = true;
@@ -575,7 +582,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                         .emit();
                 }
                 if unsafety == Unsafety::Unsafe && polarity == ImplPolarity::Negative {
-                    span_err!(self.session, item.span, E0198, "negative impls cannot be unsafe");
+                    struct_span_err!(
+                        self.session,
+                        item.span,
+                        E0198,
+                        "negative impls cannot be unsafe"
+                    )
+                    .emit();
                 }
                 for impl_item in impl_items {
                     self.invalid_visibility(&impl_item.vis, None);
@@ -591,7 +604,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                     Some("place qualifiers on individual impl items instead"),
                 );
                 if unsafety == Unsafety::Unsafe {
-                    span_err!(self.session, item.span, E0197, "inherent impls cannot be unsafe");
+                    struct_span_err!(
+                        self.session,
+                        item.span,
+                        E0197,
+                        "inherent impls cannot be unsafe"
+                    )
+                    .emit();
                 }
                 if polarity == ImplPolarity::Negative {
                     self.err_handler().span_err(item.span, "inherent impls cannot be negative");
diff --git a/src/librustc_passes/check_const.rs b/src/librustc_passes/check_const.rs
index 30ec0fe7185..f6a9d1cace1 100644
--- a/src/librustc_passes/check_const.rs
+++ b/src/librustc_passes/check_const.rs
@@ -7,6 +7,7 @@
 //! errors. We still look for those primitives in the MIR const-checker to ensure nothing slips
 //! through, but errors for structured control flow in a `const` should be emitted here.
 
+use errors::struct_span_err;
 use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc::hir::map::Map;
 use rustc::session::config::nightly_options;
@@ -18,7 +19,6 @@ use rustc_hir::def_id::DefId;
 use rustc_span::{sym, Span, Symbol};
 use syntax::ast::Mutability;
 use syntax::feature_gate::feature_err;
-use syntax::span_err;
 
 use std::fmt;
 
@@ -154,7 +154,7 @@ impl<'tcx> CheckConstVisitor<'tcx> {
             required_gates.iter().copied().filter(|&g| !features.enabled(g)).collect();
 
         match missing_gates.as_slice() {
-            &[] => span_err!(self.tcx.sess, span, E0744, "{}", msg),
+            &[] => struct_span_err!(self.tcx.sess, span, E0744, "{}", msg).emit(),
 
             // If the user enabled `#![feature(const_loop)]` but not `#![feature(const_if_match)]`,
             // explain why their `while` loop is being rejected.
diff --git a/src/librustc_passes/diagnostic_items.rs b/src/librustc_passes/diagnostic_items.rs
index f84f9984202..c083830b730 100644
--- a/src/librustc_passes/diagnostic_items.rs
+++ b/src/librustc_passes/diagnostic_items.rs
@@ -73,7 +73,7 @@ fn collect_item(
                 )),
             };
             if let Some(span) = tcx.hir().span_if_local(original_def_id) {
-                span_note!(&mut err, span, "first defined here.");
+                err.span_note(span, "first defined here.");
             } else {
                 err.note(&format!(
                     "first defined in crate `{}`.",
diff --git a/src/librustc_passes/entry.rs b/src/librustc_passes/entry.rs
index 91b787b7c99..8273504715d 100644
--- a/src/librustc_passes/entry.rs
+++ b/src/librustc_passes/entry.rs
@@ -1,3 +1,4 @@
+use errors::struct_span_err;
 use rustc::hir::map as hir_map;
 use rustc::session::config::EntryFnType;
 use rustc::session::{config, Session};
@@ -7,7 +8,7 @@ use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::{HirId, ImplItem, Item, ItemKind, TraitItem};
 use rustc_span::symbol::sym;
-use rustc_span::Span;
+use rustc_span::{Span, DUMMY_SP};
 use syntax::attr;
 use syntax::entry::EntryPointType;
 
@@ -108,7 +109,8 @@ fn find_item(item: &Item<'_>, ctxt: &mut EntryContext<'_, '_>, at_root: bool) {
             if ctxt.main_fn.is_none() {
                 ctxt.main_fn = Some((item.hir_id, item.span));
             } else {
-                span_err!(ctxt.session, item.span, E0136, "multiple `main` functions");
+                struct_span_err!(ctxt.session, item.span, E0136, "multiple `main` functions")
+                    .emit();
             }
         }
         EntryPointType::OtherMain => {
@@ -166,8 +168,9 @@ fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) {
     }
 
     // There is no main function.
-    let mut err = struct_err!(
+    let mut err = struct_span_err!(
         tcx.sess,
+        DUMMY_SP,
         E0601,
         "`main` function not found in crate `{}`",
         tcx.crate_name(LOCAL_CRATE)
diff --git a/src/librustc_passes/intrinsicck.rs b/src/librustc_passes/intrinsicck.rs
index cc311916cab..2b9a692117c 100644
--- a/src/librustc_passes/intrinsicck.rs
+++ b/src/librustc_passes/intrinsicck.rs
@@ -1,3 +1,4 @@
+use errors::struct_span_err;
 use rustc::ty::layout::{LayoutError, Pointer, SizeSkeleton, VariantIdx};
 use rustc::ty::query::Providers;
 use rustc::ty::{self, Ty, TyCtxt};
diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs
index a692c45ced4..f128d3891d7 100644
--- a/src/librustc_passes/lib.rs
+++ b/src/librustc_passes/lib.rs
@@ -14,8 +14,6 @@
 extern crate rustc;
 #[macro_use]
 extern crate log;
-#[macro_use]
-extern crate syntax;
 
 use rustc::ty::query::Providers;
 
diff --git a/src/librustc_passes/lib_features.rs b/src/librustc_passes/lib_features.rs
index df3e4ee3af5..df56bcff81f 100644
--- a/src/librustc_passes/lib_features.rs
+++ b/src/librustc_passes/lib_features.rs
@@ -4,6 +4,7 @@
 // and `#[unstable (..)]`), but are not declared in one single location
 // (unlike lang features), which means we need to collect them instead.
 
+use errors::struct_span_err;
 use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc::middle::lib_features::LibFeatures;
 use rustc::ty::query::Providers;
diff --git a/src/librustc_passes/loops.rs b/src/librustc_passes/loops.rs
index ec8c8ee8be9..262f2382da3 100644
--- a/src/librustc_passes/loops.rs
+++ b/src/librustc_passes/loops.rs
@@ -2,7 +2,7 @@ use Context::*;
 
 use rustc::session::Session;
 
-use errors::Applicability;
+use errors::{struct_span_err, Applicability};
 use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc::hir::map::Map;
 use rustc::ty::query::Providers;
@@ -11,7 +11,6 @@ use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::{Destination, Movability, Node};
 use rustc_span::Span;
-use syntax::struct_span_err;
 
 use rustc_error_codes::*;
 
diff --git a/src/librustc_passes/region.rs b/src/librustc_passes/region.rs
index f2aa5aff171..75c74c4f923 100644
--- a/src/librustc_passes/region.rs
+++ b/src/librustc_passes/region.rs
@@ -17,6 +17,7 @@ use rustc_hir::{Arm, Block, Expr, Local, Node, Pat, PatKind, Stmt};
 use rustc_index::vec::Idx;
 use rustc_span::source_map;
 use rustc_span::Span;
+use syntax::walk_list;
 
 use std::mem;
 
diff --git a/src/librustc_passes/stability.rs b/src/librustc_passes/stability.rs
index 68e2bc53261..33c985bd66b 100644
--- a/src/librustc_passes/stability.rs
+++ b/src/librustc_passes/stability.rs
@@ -1,6 +1,7 @@
 //! A pass that annotates every item and method with its stability level,
 //! propagating default levels lexically from parent to children ast nodes.
 
+use errors::struct_span_err;
 use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc::lint;
 use rustc::middle::privacy::AccessLevels;
diff --git a/src/librustc_plugin_impl/Cargo.toml b/src/librustc_plugin_impl/Cargo.toml
index 54cceca7d3a..d0b7accafd6 100644
--- a/src/librustc_plugin_impl/Cargo.toml
+++ b/src/librustc_plugin_impl/Cargo.toml
@@ -12,6 +12,7 @@ doctest = false
 
 [dependencies]
 rustc = { path = "../librustc" }
+rustc_errors = { path = "../librustc_errors" }
 rustc_hir = { path = "../librustc_hir" }
 rustc_metadata = { path = "../librustc_metadata" }
 syntax = { path = "../libsyntax" }
diff --git a/src/librustc_plugin_impl/load.rs b/src/librustc_plugin_impl/load.rs
index 2215e49ec97..65661ec24f0 100644
--- a/src/librustc_plugin_impl/load.rs
+++ b/src/librustc_plugin_impl/load.rs
@@ -3,18 +3,17 @@
 use crate::Registry;
 use rustc::middle::cstore::MetadataLoader;
 use rustc::session::Session;
+use rustc_error_codes::*;
+use rustc_errors::struct_span_err;
 use rustc_metadata::locator;
-
 use rustc_span::symbol::sym;
 use rustc_span::Span;
+use syntax::ast::{Crate, Ident};
+
 use std::borrow::ToOwned;
 use std::env;
 use std::mem;
 use std::path::PathBuf;
-use syntax::ast::{Crate, Ident};
-use syntax::struct_span_err;
-
-use rustc_error_codes::*;
 
 /// Pointer to a registrar function.
 type PluginRegistrarFn = fn(&mut Registry<'_>);
diff --git a/src/librustc_privacy/Cargo.toml b/src/librustc_privacy/Cargo.toml
index 6c9a2d65ef7..795b6c107fe 100644
--- a/src/librustc_privacy/Cargo.toml
+++ b/src/librustc_privacy/Cargo.toml
@@ -10,6 +10,7 @@ path = "lib.rs"
 
 [dependencies]
 rustc = { path = "../librustc" }
+rustc_errors = { path = "../librustc_errors" }
 rustc_hir = { path = "../librustc_hir" }
 rustc_typeck = { path = "../librustc_typeck" }
 syntax = { path = "../libsyntax" }
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index c932e8bb1f4..17e56129247 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -3,9 +3,6 @@
 #![feature(nll)]
 #![recursion_limit = "256"]
 
-#[macro_use]
-extern crate syntax;
-
 use rustc::bug;
 use rustc::hir::intravisit::{self, DeepVisitor, NestedVisitorMap, Visitor};
 use rustc::lint;
@@ -15,6 +12,7 @@ use rustc::ty::query::Providers;
 use rustc::ty::subst::InternalSubsts;
 use rustc::ty::{self, GenericParamDefKind, TraitRef, Ty, TyCtxt, TypeFoldable};
 use rustc_data_structures::fx::FxHashSet;
+use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 46dde451c7f..6472f39e844 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -28,7 +28,7 @@ use rustc_data_structures::sync::Lrc;
 use std::cell::Cell;
 use std::ptr;
 
-use errors::Applicability;
+use errors::{struct_span_err, Applicability};
 
 use rustc_expand::base::SyntaxExtension;
 use rustc_expand::expand::AstFragment;
@@ -40,7 +40,6 @@ use syntax::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind, Nod
 use syntax::ast::{AssocItem, AssocItemKind, MetaItemKind, StmtKind};
 use syntax::ast::{Ident, Name};
 use syntax::attr;
-use syntax::span_err;
 use syntax::token::{self, Token};
 use syntax::visit::{self, Visitor};
 
@@ -954,22 +953,27 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
         for attr in &item.attrs {
             if attr.check_name(sym::macro_use) {
                 if self.parent_scope.module.parent.is_some() {
-                    span_err!(
+                    struct_span_err!(
                         self.r.session,
                         item.span,
                         E0468,
                         "an `extern crate` loading macros must be at the crate root"
-                    );
+                    )
+                    .emit();
                 }
                 if let ItemKind::ExternCrate(Some(orig_name)) = item.kind {
                     if orig_name == kw::SelfLower {
-                        self.r.session.span_err(
-                            attr.span,
-                            "`macro_use` is not supported on `extern crate self`",
-                        );
+                        self.r
+                            .session
+                            .struct_span_err(
+                                attr.span,
+                                "`macro_use` is not supported on `extern crate self`",
+                            )
+                            .emit();
                     }
                 }
-                let ill_formed = |span| span_err!(self.r.session, span, E0466, "bad macro import");
+                let ill_formed =
+                    |span| struct_span_err!(self.r.session, span, E0466, "bad macro import").emit();
                 match attr.meta() {
                     Some(meta) => match meta.kind {
                         MetaItemKind::Word => {
@@ -1042,7 +1046,8 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
                         allow_shadowing,
                     );
                 } else {
-                    span_err!(self.r.session, ident.span, E0469, "imported macro not found");
+                    struct_span_err!(self.r.session, ident.span, E0469, "imported macro not found")
+                        .emit();
                 }
             }
         }
diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs
index ba3d2314569..b81e71f0acf 100644
--- a/src/librustc_resolve/diagnostics.rs
+++ b/src/librustc_resolve/diagnostics.rs
@@ -1,6 +1,6 @@
 use std::cmp::Reverse;
 
-use errors::{Applicability, DiagnosticBuilder};
+use errors::{struct_span_err, Applicability, DiagnosticBuilder};
 use log::debug;
 use rustc::bug;
 use rustc::session::Session;
@@ -16,7 +16,6 @@ use rustc_span::symbol::{kw, Symbol};
 use rustc_span::{BytePos, MultiSpan, Span};
 use syntax::ast::{self, Ident, Path};
 use syntax::print::pprust;
-use syntax::struct_span_err;
 use syntax::util::lev_distance::find_best_match_for_name;
 
 use crate::imports::{ImportDirective, ImportDirectiveSubclass, ImportResolver};
diff --git a/src/librustc_resolve/imports.rs b/src/librustc_resolve/imports.rs
index 5ede0564b1a..72de895f350 100644
--- a/src/librustc_resolve/imports.rs
+++ b/src/librustc_resolve/imports.rs
@@ -11,8 +11,7 @@ use crate::{BindingKey, ModuleKind, ResolutionError, Resolver, Segment};
 use crate::{CrateLint, Module, ModuleOrUniformRoot, ParentScope, PerNS, ScopeSet, Weak};
 use crate::{NameBinding, NameBindingKind, PathResult, PrivacyError, ToNameBinding};
 
-use errors::{pluralize, Applicability};
-
+use errors::{pluralize, struct_span_err, Applicability};
 use rustc::hir::exports::Export;
 use rustc::lint::builtin::BuiltinLintDiagnostics;
 use rustc::lint::builtin::{PUB_USE_OF_PRIVATE_EXTERN_CRATE, UNUSED_IMPORTS};
@@ -27,8 +26,8 @@ use rustc_span::hygiene::ExpnId;
 use rustc_span::symbol::kw;
 use rustc_span::{MultiSpan, Span};
 use syntax::ast::{Ident, Name, NodeId};
+use syntax::unwrap_or;
 use syntax::util::lev_distance::find_best_match_for_name;
-use syntax::{struct_span_err, unwrap_or};
 
 use rustc_error_codes::*;
 
diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs
index fb7aacba2dc..29a1be6bb74 100644
--- a/src/librustc_resolve/late.rs
+++ b/src/librustc_resolve/late.rs
@@ -11,6 +11,7 @@ use crate::{path_names_to_string, BindingError, CrateLint, LexicalScopeBinding};
 use crate::{Module, ModuleOrUniformRoot, NameBindingKind, ParentScope, PathResult};
 use crate::{ResolutionError, Resolver, Segment, UseError};
 
+use errors::DiagnosticId;
 use log::debug;
 use rustc::{bug, lint, span_bug};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -304,32 +305,21 @@ impl<'a> PathSource<'a> {
         }
     }
 
-    fn error_code(self, has_unexpected_resolution: bool) -> &'static str {
-        syntax::diagnostic_used!(E0404);
-        syntax::diagnostic_used!(E0405);
-        syntax::diagnostic_used!(E0412);
-        syntax::diagnostic_used!(E0422);
-        syntax::diagnostic_used!(E0423);
-        syntax::diagnostic_used!(E0425);
-        syntax::diagnostic_used!(E0531);
-        syntax::diagnostic_used!(E0532);
-        syntax::diagnostic_used!(E0573);
-        syntax::diagnostic_used!(E0574);
-        syntax::diagnostic_used!(E0575);
-        syntax::diagnostic_used!(E0576);
+    fn error_code(self, has_unexpected_resolution: bool) -> DiagnosticId {
+        use errors::error_code;
         match (self, has_unexpected_resolution) {
-            (PathSource::Trait(_), true) => "E0404",
-            (PathSource::Trait(_), false) => "E0405",
-            (PathSource::Type, true) => "E0573",
-            (PathSource::Type, false) => "E0412",
-            (PathSource::Struct, true) => "E0574",
-            (PathSource::Struct, false) => "E0422",
-            (PathSource::Expr(..), true) => "E0423",
-            (PathSource::Expr(..), false) => "E0425",
-            (PathSource::Pat, true) | (PathSource::TupleStruct, true) => "E0532",
-            (PathSource::Pat, false) | (PathSource::TupleStruct, false) => "E0531",
-            (PathSource::TraitItem(..), true) => "E0575",
-            (PathSource::TraitItem(..), false) => "E0576",
+            (PathSource::Trait(_), true) => error_code!(E0404),
+            (PathSource::Trait(_), false) => error_code!(E0405),
+            (PathSource::Type, true) => error_code!(E0573),
+            (PathSource::Type, false) => error_code!(E0412),
+            (PathSource::Struct, true) => error_code!(E0574),
+            (PathSource::Struct, false) => error_code!(E0422),
+            (PathSource::Expr(..), true) => error_code!(E0423),
+            (PathSource::Expr(..), false) => error_code!(E0425),
+            (PathSource::Pat, true) | (PathSource::TupleStruct, true) => error_code!(E0532),
+            (PathSource::Pat, false) | (PathSource::TupleStruct, false) => error_code!(E0531),
+            (PathSource::TraitItem(..), true) => error_code!(E0575),
+            (PathSource::TraitItem(..), false) => error_code!(E0576),
         }
     }
 }
diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs
index 5a12a75a855..029f8421475 100644
--- a/src/librustc_resolve/late/diagnostics.rs
+++ b/src/librustc_resolve/late/diagnostics.rs
@@ -4,7 +4,7 @@ use crate::path_names_to_string;
 use crate::{CrateLint, Module, ModuleKind, ModuleOrUniformRoot};
 use crate::{PathResult, PathSource, Segment};
 
-use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
+use errors::{Applicability, DiagnosticBuilder};
 use log::debug;
 use rustc::session::config::nightly_options;
 use rustc_data_structures::fx::FxHashSet;
@@ -73,7 +73,6 @@ impl<'a> LateResolutionVisitor<'a, '_> {
         let expected = source.descr_expected();
         let path_str = Segment::names_to_string(path);
         let item_str = path.last().unwrap().ident;
-        let code = source.error_code(res.is_some());
         let (base_msg, fallback_label, base_span, could_be_expr) = if let Some(res) = res {
             (
                 format!("expected {}, found {} `{}`", expected, res.descr(), path_str),
@@ -123,7 +122,7 @@ impl<'a> LateResolutionVisitor<'a, '_> {
             )
         };
 
-        let code = DiagnosticId::Error(code.into());
+        let code = source.error_code(res.is_some());
         let mut err = self.r.session.struct_span_err_with_code(base_span, &base_msg, code);
 
         // Emit help message for fake-self from other languages (e.g., `this` in Javascript).
@@ -140,8 +139,7 @@ impl<'a> LateResolutionVisitor<'a, '_> {
 
         // Emit special messages for unresolved `Self` and `self`.
         if is_self_type(path, ns) {
-            syntax::diagnostic_used!(E0411);
-            err.code(DiagnosticId::Error("E0411".into()));
+            err.code(errors::error_code!(E0411));
             err.span_label(
                 span,
                 format!("`Self` is only available in impls, traits, and type definitions"),
@@ -151,8 +149,7 @@ impl<'a> LateResolutionVisitor<'a, '_> {
         if is_self_value(path, ns) {
             debug!("smart_resolve_path_fragment: E0424, source={:?}", source);
 
-            syntax::diagnostic_used!(E0424);
-            err.code(DiagnosticId::Error("E0424".into()));
+            err.code(errors::error_code!(E0424));
             err.span_label(span, match source {
                 PathSource::Pat => format!(
                     "`self` value is a keyword and may not be bound to variables or shadowed",
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 199752b93c1..f8e42724df7 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -20,7 +20,7 @@ pub use rustc_hir::def::{Namespace, PerNS};
 
 use Determinacy::*;
 
-use errors::{Applicability, DiagnosticBuilder};
+use errors::{struct_span_err, Applicability, DiagnosticBuilder};
 use rustc::hir::exports::ExportMap;
 use rustc::hir::map::Definitions;
 use rustc::lint;
@@ -49,8 +49,8 @@ use syntax::ast::{Crate, CRATE_NODE_ID};
 use syntax::ast::{ItemKind, Path};
 use syntax::attr;
 use syntax::print::pprust;
+use syntax::unwrap_or;
 use syntax::visit::{self, Visitor};
-use syntax::{struct_span_err, unwrap_or};
 
 use log::debug;
 use std::cell::{Cell, RefCell};
diff --git a/src/librustc_resolve/lifetimes.rs b/src/librustc_resolve/lifetimes.rs
index 4cd3a9e1a80..15858f7d8ab 100644
--- a/src/librustc_resolve/lifetimes.rs
+++ b/src/librustc_resolve/lifetimes.rs
@@ -5,7 +5,7 @@
 //! used between functions, and they operate in a purely top-down
 //! way. Therefore, we break lifetime name resolution into a separate pass.
 
-use errors::{pluralize, Applicability, DiagnosticBuilder};
+use errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
 use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc::hir::map::Map;
 use rustc::lint;
@@ -26,7 +26,7 @@ use std::cell::Cell;
 use std::mem::{replace, take};
 use syntax::ast;
 use syntax::attr;
-use syntax::{help, span_err, struct_span_err, walk_list};
+use syntax::walk_list;
 
 use log::debug;
 
@@ -591,13 +591,14 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                                     || krate.impl_items.contains_key(&parent_impl_id)
                                     || krate.trait_items.contains_key(&parent_trait_id))
                                 {
-                                    span_err!(
+                                    struct_span_err!(
                                         self.tcx.sess,
                                         lifetime.span,
                                         E0657,
                                         "`impl Trait` can only capture lifetimes \
                                          bound at the fn or impl level"
-                                    );
+                                    )
+                                    .emit();
                                     self.uninsert_lifetime_on_error(lifetime, def.unwrap());
                                 }
                             }
@@ -943,12 +944,13 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
             })
         {
             if self.trait_ref_hack {
-                span_err!(
+                struct_span_err!(
                     self.tcx.sess,
                     trait_ref.span,
                     E0316,
                     "nested quantification of lifetimes"
-                );
+                )
+                .emit();
             }
             let next_early_index = self.next_early_index();
             let scope = Scope::Binder {
@@ -2433,36 +2435,32 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
         }
 
         if len == 0 {
-            help!(
-                db,
-                "this function's return type contains a borrowed value, but \
-                 there is no value for it to be borrowed from"
+            db.help(
+                "this function's return type contains a borrowed value, \
+                but there is no value for it to be borrowed from",
             );
             self.suggest_lifetime(db, span, "consider giving it a 'static lifetime")
         } else if elided_len == 0 {
-            help!(
-                db,
+            db.help(
                 "this function's return type contains a borrowed value with \
                  an elided lifetime, but the lifetime cannot be derived from \
-                 the arguments"
+                 the arguments",
             );
             let msg = "consider giving it an explicit bounded or 'static lifetime";
             self.suggest_lifetime(db, span, msg)
         } else if elided_len == 1 {
-            help!(
-                db,
-                "this function's return type contains a borrowed value, but \
-                 the signature does not say which {} it is borrowed from",
+            db.help(&format!(
+                "this function's return type contains a borrowed value, \
+                but the signature does not say which {} it is borrowed from",
                 m
-            );
+            ));
             true
         } else {
-            help!(
-                db,
-                "this function's return type contains a borrowed value, but \
-                 the signature does not say whether it is borrowed from {}",
+            db.help(&format!(
+                "this function's return type contains a borrowed value, \
+                but the signature does not say whether it is borrowed from {}",
                 m
-            );
+            ));
             true
         }
     }
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 5acaede2ee0..4bacf934937 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -9,7 +9,7 @@ use crate::middle::resolve_lifetime as rl;
 use crate::namespace::Namespace;
 use crate::require_c_abi_if_c_variadic;
 use crate::util::common::ErrorReported;
-use errors::{Applicability, DiagnosticId};
+use errors::{struct_span_err, Applicability, DiagnosticId};
 use rustc::hir::intravisit::Visitor;
 use rustc::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS;
 use rustc::traits;
@@ -1119,13 +1119,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 if unbound.is_none() {
                     unbound = Some(&ptr.trait_ref);
                 } else {
-                    span_err!(
+                    struct_span_err!(
                         tcx.sess,
                         span,
                         E0203,
                         "type parameter has more than one relaxed default \
                         bound, only one is supported"
-                    );
+                    )
+                    .emit();
                 }
             }
         }
@@ -1445,7 +1446,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         }
 
         if regular_traits.is_empty() && auto_traits.is_empty() {
-            span_err!(tcx.sess, span, E0224, "at least one trait is required for an object type");
+            struct_span_err!(
+                tcx.sess,
+                span,
+                E0224,
+                "at least one trait is required for an object type"
+            )
+            .emit();
             return tcx.types.err;
         }
 
@@ -1601,13 +1608,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     self.ast_region_to_region(lifetime, None)
                 } else {
                     self.re_infer(None, span).unwrap_or_else(|| {
-                        span_err!(
+                        struct_span_err!(
                             tcx.sess,
                             span,
                             E0228,
                             "the lifetime bound for this object type cannot be deduced \
                              from context; please supply an explicit bound"
-                        );
+                        )
+                        .emit();
                         tcx.lifetimes.re_static
                     })
                 }
@@ -2880,12 +2888,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         // error.
         let r = derived_region_bounds[0];
         if derived_region_bounds[1..].iter().any(|r1| r != *r1) {
-            span_err!(
+            struct_span_err!(
                 tcx.sess,
                 span,
                 E0227,
                 "ambiguous lifetime bound, explicit lifetime bound required"
-            );
+            )
+            .emit();
         }
         return Some(r);
     }
diff --git a/src/librustc_typeck/check/autoderef.rs b/src/librustc_typeck/check/autoderef.rs
index 3b4f408b8aa..3d02889d2dd 100644
--- a/src/librustc_typeck/check/autoderef.rs
+++ b/src/librustc_typeck/check/autoderef.rs
@@ -1,6 +1,7 @@
 use super::method::MethodCallee;
 use super::{FnCtxt, Needs, PlaceOp};
 
+use errors::struct_span_err;
 use rustc::infer::{InferCtxt, InferOk};
 use rustc::session::DiagnosticMessageId;
 use rustc::traits::{self, TraitEngine};
diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs
index 23db0fc463d..a1915bc025f 100644
--- a/src/librustc_typeck/check/callee.rs
+++ b/src/librustc_typeck/check/callee.rs
@@ -1,8 +1,9 @@
 use super::autoderef::Autoderef;
 use super::method::MethodCallee;
 use super::{Expectation, FnCtxt, Needs, TupleArgumentsFlag};
+use crate::type_error_struct;
 
-use errors::{Applicability, DiagnosticBuilder};
+use errors::{struct_span_err, Applicability, DiagnosticBuilder};
 use hir::def::Res;
 use hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs
index 0be21ad58be..9dbf55c4948 100644
--- a/src/librustc_typeck/check/cast.rs
+++ b/src/librustc_typeck/check/cast.rs
@@ -32,8 +32,9 @@ use super::FnCtxt;
 
 use crate::hir::def_id::DefId;
 use crate::lint;
+use crate::type_error_struct;
 use crate::util::common::ErrorReported;
-use errors::{Applicability, DiagnosticBuilder};
+use errors::{struct_span_err, Applicability, DiagnosticBuilder};
 use rustc::middle::lang_items;
 use rustc::session::Session;
 use rustc::traits;
@@ -425,17 +426,16 @@ impl<'a, 'tcx> CastCheck<'tcx> {
                             );
                         }
                         Err(_) => {
-                            span_help!(err, self.cast_span, "did you mean `&{}{}`?", mtstr, tstr)
+                            let msg = &format!("did you mean `&{}{}`?", mtstr, tstr);
+                            err.span_help(self.cast_span, msg);
                         }
                     }
                 } else {
-                    span_help!(
-                        err,
-                        self.span,
+                    let msg = &format!(
                         "consider using an implicit coercion to `&{}{}` instead",
-                        mtstr,
-                        tstr
+                        mtstr, tstr
                     );
+                    err.span_help(self.span, msg);
                 }
             }
             ty::Adt(def, ..) if def.is_box() => {
@@ -448,11 +448,13 @@ impl<'a, 'tcx> CastCheck<'tcx> {
                             Applicability::MachineApplicable,
                         );
                     }
-                    Err(_) => span_help!(err, self.cast_span, "did you mean `Box<{}>`?", tstr),
+                    Err(_) => {
+                        err.span_help(self.cast_span, &format!("did you mean `Box<{}>`?", tstr));
+                    }
                 }
             }
             _ => {
-                span_help!(err, self.expr.span, "consider using a box or reference as appropriate");
+                err.span_help(self.expr.span, "consider using a box or reference as appropriate");
             }
         }
         err.emit();
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index 36ad6ea1bc9..ec298ca6971 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -51,7 +51,7 @@
 //! we may want to adjust precisely when coercions occur.
 
 use crate::check::{FnCtxt, Needs};
-use errors::DiagnosticBuilder;
+use errors::{struct_span_err, DiagnosticBuilder};
 use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc::infer::{Coercion, InferOk, InferResult};
 use rustc::traits::{self, ObligationCause, ObligationCauseCode};
diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs
index 13e37c124e0..e1f2950469b 100644
--- a/src/librustc_typeck/check/compare_method.rs
+++ b/src/librustc_typeck/check/compare_method.rs
@@ -1,4 +1,4 @@
-use errors::{Applicability, DiagnosticId};
+use errors::{pluralize, struct_span_err, Applicability, DiagnosticId};
 use rustc::hir::intravisit;
 use rustc::infer::{self, InferOk};
 use rustc::traits::{self, ObligationCause, ObligationCauseCode, Reveal};
@@ -11,7 +11,6 @@ use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::{GenericParamKind, ImplItemKind, TraitItemKind};
 use rustc_span::Span;
-use syntax::errors::pluralize;
 
 use super::{potentially_plural_count, FnCtxt, Inherited};
 
diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs
index 004fce7e35b..33a07423c25 100644
--- a/src/librustc_typeck/check/dropck.rs
+++ b/src/librustc_typeck/check/dropck.rs
@@ -1,8 +1,8 @@
 use crate::check::regionck::RegionCtxt;
-
 use crate::hir;
 use crate::hir::def_id::DefId;
 use crate::util::common::ErrorReported;
+use errors::struct_span_err;
 use rustc::infer::outlives::env::OutlivesEnvironment;
 use rustc::infer::{InferOk, SuppressRegionErrors};
 use rustc::middle::region;
diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs
index c12d8400f08..01795ef3966 100644
--- a/src/librustc_typeck/check/expr.rs
+++ b/src/librustc_typeck/check/expr.rs
@@ -14,9 +14,10 @@ use crate::check::Expectation::{self, ExpectCastableToType, ExpectHasType, NoExp
 use crate::check::FnCtxt;
 use crate::check::Needs;
 use crate::check::TupleArgumentsFlag::DontTupleArguments;
+use crate::type_error_struct;
 use crate::util::common::ErrorReported;
 
-use errors::{pluralize, Applicability, DiagnosticBuilder, DiagnosticId};
+use errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, DiagnosticId};
 use rustc::infer;
 use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc::middle::lang_items;
@@ -1108,13 +1109,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // Prohibit struct expressions when non-exhaustive flag is set.
         let adt = adt_ty.ty_adt_def().expect("`check_struct_path` returned non-ADT type");
         if !adt.did.is_local() && variant.is_field_list_non_exhaustive() {
-            span_err!(
+            struct_span_err!(
                 self.tcx.sess,
                 expr.span,
                 E0639,
                 "cannot create non-exhaustive {} using struct expression",
                 adt.variant_descr()
-            );
+            )
+            .emit();
         }
 
         let error_happened = self.check_expr_struct_fields(
@@ -1152,12 +1154,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             .insert(expr.hir_id, fru_field_types);
                     }
                     _ => {
-                        span_err!(
+                        struct_span_err!(
                             self.tcx.sess,
                             base_expr.span,
                             E0436,
                             "functional record update syntax requires a struct"
-                        );
+                        )
+                        .emit();
                     }
                 }
             }
diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs
index a267b9786f1..2b731947aa0 100644
--- a/src/librustc_typeck/check/intrinsic.rs
+++ b/src/librustc_typeck/check/intrinsic.rs
@@ -2,17 +2,16 @@
 //! intrinsics that the compiler exposes.
 
 use crate::require_same_types;
+
+use errors::struct_span_err;
 use rustc::traits::{ObligationCause, ObligationCauseCode};
 use rustc::ty::subst::Subst;
 use rustc::ty::{self, Ty, TyCtxt};
-
+use rustc_error_codes::*;
+use rustc_hir as hir;
 use rustc_span::symbol::Symbol;
 use rustc_target::spec::abi::Abi;
 
-use rustc_hir as hir;
-
-use rustc_error_codes::*;
-
 use std::iter;
 
 fn equate_intrinsic_type<'tcx>(
@@ -413,19 +412,20 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>)
                 (2, params, param(1))
             }
             Err(_) => {
-                span_err!(
+                struct_span_err!(
                     tcx.sess,
                     it.span,
                     E0439,
                     "invalid `simd_shuffle`, needs length: `{}`",
                     name
-                );
+                )
+                .emit();
                 return;
             }
         },
         _ => {
             let msg = format!("unrecognized platform-specific intrinsic function: `{}`", name);
-            tcx.sess.span_err(it.span, &msg);
+            tcx.sess.struct_span_err(it.span, &msg).emit();
             return;
         }
     };
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index 50f22eabf62..4f0467b78b2 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -9,6 +9,7 @@ use crate::hir::def::DefKind;
 use crate::hir::def_id::DefId;
 use crate::namespace::Namespace;
 
+use errors::struct_span_err;
 use rustc::infer::canonical::OriginalQueryValues;
 use rustc::infer::canonical::{Canonical, QueryResponse};
 use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
@@ -373,13 +374,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // so we do a future-compat lint here for the 2015 edition
                 // (see https://github.com/rust-lang/rust/issues/46906)
                 if self.tcx.sess.rust_2018() {
-                    span_err!(
+                    struct_span_err!(
                         self.tcx.sess,
                         span,
                         E0699,
                         "the type of this value must be known \
                                to call a method on a raw pointer on it"
-                    );
+                    )
+                    .emit();
                 } else {
                     self.tcx.lint_hir(
                         lint::builtin::TYVAR_BEHIND_RAW_POINTER,
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index 1cc1eb2c7b2..8bf9f488e59 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -4,7 +4,7 @@
 use crate::check::FnCtxt;
 use crate::middle::lang_items::FnOnceTraitLangItem;
 use crate::namespace::Namespace;
-use errors::{pluralize, Applicability, DiagnosticBuilder};
+use errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
 use rustc::hir::intravisit;
 use rustc::hir::map as hir_map;
 use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
@@ -193,21 +193,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         let item_span =
                             self.tcx.sess.source_map().def_span(self.tcx.def_span(item.def_id));
                         let idx = if sources.len() > 1 {
-                            span_note!(
-                                err,
-                                item_span,
+                            let msg = &format!(
                                 "candidate #{} is defined in the trait `{}`",
                                 idx + 1,
                                 self.tcx.def_path_str(trait_did)
                             );
+                            err.span_note(item_span, msg);
                             Some(idx + 1)
                         } else {
-                            span_note!(
-                                err,
-                                item_span,
+                            let msg = &format!(
                                 "the candidate is defined in the trait `{}`",
                                 self.tcx.def_path_str(trait_did)
                             );
+                            err.span_note(item_span, msg);
                             None
                         };
                         let path = self.tcx.def_path_str(trait_did);
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 647c56112b2..e6fbae09ba1 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -90,7 +90,7 @@ pub mod writeback;
 use crate::astconv::{AstConv, PathSeg};
 use crate::middle::lang_items;
 use crate::namespace::Namespace;
-use errors::{pluralize, Applicability, DiagnosticBuilder, DiagnosticId};
+use errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, DiagnosticId};
 use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse};
 use rustc::infer::error_reporting::TypeAnnotationNeeded::E0282;
@@ -157,6 +157,17 @@ use self::method::{MethodCallee, SelfSource};
 pub use self::Expectation::*;
 use self::TupleArgumentsFlag::*;
 
+#[macro_export]
+macro_rules! type_error_struct {
+    ($session:expr, $span:expr, $typ:expr, $code:ident, $($message:tt)*) => ({
+        if $typ.references_error() {
+            $session.diagnostic().struct_dummy()
+        } else {
+            errors::struct_span_err!($session, $span, $code, $($message)*)
+        }
+    })
+}
+
 /// The type of a local binding, including the revealed type for anon types.
 #[derive(Copy, Clone, Debug)]
 pub struct LocalTy<'tcx> {
@@ -2091,7 +2102,7 @@ fn check_impl_items_against_trait<'tcx>(
 
     if !invalidated_items.is_empty() {
         let invalidator = overridden_associated_type.unwrap();
-        span_err!(
+        struct_span_err!(
             tcx.sess,
             invalidator.span,
             E0399,
@@ -2099,6 +2110,7 @@ fn check_impl_items_against_trait<'tcx>(
             invalidator.ident,
             invalidated_items.iter().map(|name| name.to_string()).collect::<Vec<_>>().join("`, `")
         )
+        .emit();
     }
 }
 
@@ -2241,7 +2253,7 @@ pub fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: DefId) {
         if def.is_struct() {
             let fields = &def.non_enum_variant().fields;
             if fields.is_empty() {
-                span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty");
+                struct_span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty").emit();
                 return;
             }
             let e = fields[0].ty(tcx, substs);
@@ -2255,12 +2267,13 @@ pub fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: DefId) {
                 ty::Param(_) => { /* struct<T>(T, T, T, T) is ok */ }
                 _ if e.is_machine() => { /* struct(u8, u8, u8, u8) is ok */ }
                 _ => {
-                    span_err!(
+                    struct_span_err!(
                         tcx.sess,
                         sp,
                         E0077,
                         "SIMD vector element type should be machine type"
-                    );
+                    )
+                    .emit();
                     return;
                 }
             }
@@ -2545,14 +2558,15 @@ pub fn check_enum<'tcx>(
 }
 
 fn report_unexpected_variant_res(tcx: TyCtxt<'_>, res: Res, span: Span, qpath: &QPath<'_>) {
-    span_err!(
+    struct_span_err!(
         tcx.sess,
         span,
         E0533,
         "expected unit struct, unit variant or constant, found {} `{}`",
         res.descr(),
         hir::print::to_string(tcx.hir(), |s| s.print_qpath(qpath, false))
-    );
+    )
+    .emit();
 }
 
 impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
@@ -3762,13 +3776,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     arg_types.iter().map(|k| k.expect_ty()).collect()
                 }
                 _ => {
-                    span_err!(
+                    struct_span_err!(
                         tcx.sess,
                         sp,
                         E0059,
                         "cannot use call notation; the first type parameter \
                          for the function trait is neither a tuple nor unit"
-                    );
+                    )
+                    .emit();
                     expected_arg_tys = vec![];
                     self.err_args(args.len())
                 }
diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs
index 691469e4883..3dd11220859 100644
--- a/src/librustc_typeck/check/op.rs
+++ b/src/librustc_typeck/check/op.rs
@@ -2,7 +2,7 @@
 
 use super::method::MethodCallee;
 use super::{FnCtxt, Needs};
-use errors::{self, Applicability};
+use errors::{self, struct_span_err, Applicability};
 use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
 use rustc::ty::TyKind::{Adt, Array, Char, FnDef, Never, Ref, Str, Tuple, Uint};
diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs
index 051bf61c90a..58c722f1da6 100644
--- a/src/librustc_typeck/check/pat.rs
+++ b/src/librustc_typeck/check/pat.rs
@@ -1,5 +1,5 @@
 use crate::check::FnCtxt;
-use errors::{pluralize, Applicability, DiagnosticBuilder};
+use errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
 use rustc::infer;
 use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc::traits::Pattern;
@@ -983,22 +983,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         // Require `..` if struct has non_exhaustive attribute.
         if variant.is_field_list_non_exhaustive() && !adt.did.is_local() && !etc {
-            span_err!(
+            struct_span_err!(
                 tcx.sess,
                 span,
                 E0638,
                 "`..` required with {} marked as non-exhaustive",
                 kind_name
-            );
+            )
+            .emit();
         }
 
         // Report an error if incorrect number of the fields were specified.
         if kind_name == "union" {
             if fields.len() != 1 {
-                tcx.sess.span_err(span, "union patterns should have exactly one field");
+                tcx.sess
+                    .struct_span_err(span, "union patterns should have exactly one field")
+                    .emit();
             }
             if etc {
-                tcx.sess.span_err(span, "`..` cannot be used in union patterns");
+                tcx.sess.struct_span_err(span, "`..` cannot be used in union patterns").emit();
             }
         } else if !etc && unmentioned_fields.len() > 0 {
             self.error_unmentioned_fields(span, &unmentioned_fields, variant);
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index f3a51fa33fa..c57eb672189 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -1,6 +1,7 @@
 use crate::check::{FnCtxt, Inherited};
 use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter};
 
+use errors::{struct_span_err, DiagnosticBuilder};
 use rustc::infer::opaque_types::may_define_opaque_type;
 use rustc::middle::lang_items;
 use rustc::traits::{self, ObligationCause, ObligationCauseCode};
@@ -9,8 +10,6 @@ use rustc::ty::{self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, Typ
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir::def_id::DefId;
 use rustc_hir::ItemKind;
-
-use errors::DiagnosticBuilder;
 use rustc_span::symbol::sym;
 use rustc_span::Span;
 use syntax::ast;
@@ -113,13 +112,14 @@ pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: DefId) {
                 ty::ImplPolarity::Negative => {
                     // FIXME(#27579): what amount of WF checking do we need for neg impls?
                     if trait_ref.is_some() && !is_auto {
-                        span_err!(
+                        struct_span_err!(
                             tcx.sess,
                             item.span,
                             E0192,
                             "negative impls are only allowed for \
                                    auto traits (e.g., `Send` and `Sync`)"
                         )
+                        .emit()
                     }
                 }
                 ty::ImplPolarity::Reservation => {
diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs
index eb1ea679040..5af5acda143 100644
--- a/src/librustc_typeck/coherence/builtin.rs
+++ b/src/librustc_typeck/coherence/builtin.rs
@@ -1,25 +1,23 @@
 //! Check properties that are required by built-in traits and set
 //! up data structures required by type-checking/codegen.
 
+use errors::struct_span_err;
+use rustc::infer;
 use rustc::infer::outlives::env::OutlivesEnvironment;
 use rustc::infer::SuppressRegionErrors;
 use rustc::middle::lang_items::UnsizeTraitLangItem;
 use rustc::middle::region;
-
-use rustc::infer;
 use rustc::traits::misc::{can_type_implement_copy, CopyImplementationError};
 use rustc::traits::predicate_for_trait_def;
 use rustc::traits::{self, ObligationCause, TraitEngine};
 use rustc::ty::adjustment::CoerceUnsizedInfo;
 use rustc::ty::TypeFoldable;
 use rustc::ty::{self, Ty, TyCtxt};
-
+use rustc_error_codes::*;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::ItemKind;
 
-use rustc_error_codes::*;
-
 pub fn check_trait(tcx: TyCtxt<'_>, trait_def_id: DefId) {
     Checker { tcx, trait_def_id }
         .check(tcx.lang_items().drop_trait(), visit_implementation_of_drop)
@@ -393,7 +391,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn
                 if def_a != def_b {
                     let source_path = tcx.def_path_str(def_a.did);
                     let target_path = tcx.def_path_str(def_b.did);
-                    span_err!(
+                    struct_span_err!(
                         tcx.sess,
                         span,
                         E0377,
@@ -402,7 +400,8 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn
                                definition; expected `{}`, found `{}`",
                         source_path,
                         target_path
-                    );
+                    )
+                    .emit();
                     return err_info;
                 }
 
@@ -479,14 +478,15 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn
                     .collect::<Vec<_>>();
 
                 if diff_fields.is_empty() {
-                    span_err!(
+                    struct_span_err!(
                         tcx.sess,
                         span,
                         E0374,
                         "the trait `CoerceUnsized` may only be implemented \
                                for a coercion between structures with one field \
                                being coerced, none found"
-                    );
+                    )
+                    .emit();
                     return err_info;
                 } else if diff_fields.len() > 1 {
                     let item = tcx.hir().expect_item(impl_hir_id);
@@ -496,19 +496,19 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn
                         tcx.hir().span(impl_hir_id)
                     };
 
-                    let mut err = struct_span_err!(
+                    struct_span_err!(
                         tcx.sess,
                         span,
                         E0375,
                         "implementing the trait \
                                                     `CoerceUnsized` requires multiple \
                                                     coercions"
-                    );
-                    err.note(
+                    )
+                    .note(
                         "`CoerceUnsized` may only be implemented for \
                               a coercion between structures with one field being coerced",
-                    );
-                    err.note(&format!(
+                    )
+                    .note(&format!(
                         "currently, {} fields need coercions: {}",
                         diff_fields.len(),
                         diff_fields
@@ -518,9 +518,9 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn
                             })
                             .collect::<Vec<_>>()
                             .join(", ")
-                    ));
-                    err.span_label(span, "requires multiple coercions");
-                    err.emit();
+                    ))
+                    .span_label(span, "requires multiple coercions")
+                    .emit();
                     return err_info;
                 }
 
@@ -530,13 +530,14 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn
             }
 
             _ => {
-                span_err!(
+                struct_span_err!(
                     tcx.sess,
                     span,
                     E0376,
                     "the trait `CoerceUnsized` may only be implemented \
                            for a coercion between structures"
-                );
+                )
+                .emit();
                 return err_info;
             }
         };
diff --git a/src/librustc_typeck/coherence/inherent_impls.rs b/src/librustc_typeck/coherence/inherent_impls.rs
index 76de177e8e5..73d03f92447 100644
--- a/src/librustc_typeck/coherence/inherent_impls.rs
+++ b/src/librustc_typeck/coherence/inherent_impls.rs
@@ -7,6 +7,7 @@
 //! `tcx.inherent_impls(def_id)`). That value, however,
 //! is computed by selecting an idea from this table.
 
+use errors::struct_span_err;
 use rustc::ty::{self, CrateInherentImpls, TyCtxt};
 use rustc_hir as hir;
 use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
diff --git a/src/librustc_typeck/coherence/inherent_impls_overlap.rs b/src/librustc_typeck/coherence/inherent_impls_overlap.rs
index fed8ed53468..01d2f528d45 100644
--- a/src/librustc_typeck/coherence/inherent_impls_overlap.rs
+++ b/src/librustc_typeck/coherence/inherent_impls_overlap.rs
@@ -1,4 +1,5 @@
 use crate::namespace::Namespace;
+use errors::struct_span_err;
 use rustc::traits::{self, IntercrateMode};
 use rustc::ty::TyCtxt;
 use rustc_hir as hir;
diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs
index 2d19b73eac3..1a008ef23fc 100644
--- a/src/librustc_typeck/coherence/mod.rs
+++ b/src/librustc_typeck/coherence/mod.rs
@@ -7,6 +7,7 @@
 
 use crate::hir::def_id::{DefId, LOCAL_CRATE};
 use crate::hir::HirId;
+use errors::struct_span_err;
 use rustc::traits;
 use rustc::ty::query::Providers;
 use rustc::ty::{self, TyCtxt, TypeFoldable};
diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs
index 8a87bcabeec..cf9935143b2 100644
--- a/src/librustc_typeck/coherence/orphan.rs
+++ b/src/librustc_typeck/coherence/orphan.rs
@@ -1,6 +1,7 @@
 //! Orphan checker: every impl either implements a trait defined in this
 //! crate or pertains to a type defined in this crate.
 
+use errors::struct_span_err;
 use rustc::traits;
 use rustc::ty::{self, TyCtxt};
 use rustc_hir as hir;
diff --git a/src/librustc_typeck/coherence/unsafety.rs b/src/librustc_typeck/coherence/unsafety.rs
index ed0d9ba643a..9257aa759b4 100644
--- a/src/librustc_typeck/coherence/unsafety.rs
+++ b/src/librustc_typeck/coherence/unsafety.rs
@@ -1,6 +1,7 @@
 //! Unsafety checker: every impl either implements a trait defined in this
 //! crate or pertains to a type defined in this crate.
 
+use errors::struct_span_err;
 use rustc::ty::TyCtxt;
 use rustc_hir as hir;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
@@ -33,23 +34,25 @@ impl UnsafetyChecker<'tcx> {
             });
             match (trait_def.unsafety, unsafe_attr, unsafety, polarity) {
                 (Unsafety::Normal, None, Unsafety::Unsafe, hir::ImplPolarity::Positive) => {
-                    span_err!(
+                    struct_span_err!(
                         self.tcx.sess,
                         item.span,
                         E0199,
                         "implementing the trait `{}` is not unsafe",
                         trait_ref.print_only_trait_path()
-                    );
+                    )
+                    .emit();
                 }
 
                 (Unsafety::Unsafe, _, Unsafety::Normal, hir::ImplPolarity::Positive) => {
-                    span_err!(
+                    struct_span_err!(
                         self.tcx.sess,
                         item.span,
                         E0200,
                         "the trait `{}` requires an `unsafe impl` declaration",
                         trait_ref.print_only_trait_path()
-                    );
+                    )
+                    .emit();
                 }
 
                 (
@@ -58,13 +61,14 @@ impl UnsafetyChecker<'tcx> {
                     Unsafety::Normal,
                     hir::ImplPolarity::Positive,
                 ) => {
-                    span_err!(
+                    struct_span_err!(
                         self.tcx.sess,
                         item.span,
                         E0569,
                         "requires an `unsafe impl` declaration due to `#[{}]` attribute",
                         attr_name
-                    );
+                    )
+                    .emit();
                 }
 
                 (_, _, Unsafety::Unsafe, hir::ImplPolarity::Negative) => {
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index fb9e4ba5ce2..35c380612d2 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -20,6 +20,7 @@ use crate::constrained_generic_params as cgp;
 use crate::lint;
 use crate::middle::resolve_lifetime as rl;
 use crate::middle::weak_lang_items;
+use errors::{struct_span_err, Applicability, StashKey};
 use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
 use rustc::mir::mono::Linkage;
@@ -45,8 +46,6 @@ use syntax::ast::{Ident, MetaItemKind};
 use syntax::attr::{list_contains_name, mark_used, InlineAttr, OptimizeAttr};
 use syntax::feature_gate;
 
-use errors::{Applicability, StashKey};
-
 use rustc_error_codes::*;
 
 struct OnlySelfBounds(bool);
@@ -320,13 +319,14 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> {
             self.tcx().mk_projection(item_def_id, item_substs)
         } else {
             // There are no late-bound regions; we can just ignore the binder.
-            span_err!(
+            struct_span_err!(
                 self.tcx().sess,
                 span,
                 E0212,
                 "cannot extract an associated type from a higher-ranked trait bound \
                  in this context"
-            );
+            )
+            .emit();
             self.tcx().types.err
         }
     }
@@ -861,17 +861,14 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::TraitDef {
 
     let paren_sugar = tcx.has_attr(def_id, sym::rustc_paren_sugar);
     if paren_sugar && !tcx.features().unboxed_closures {
-        let mut err = tcx.sess.struct_span_err(
-            item.span,
-            "the `#[rustc_paren_sugar]` attribute is a temporary means of controlling \
+        tcx.sess
+            .struct_span_err(
+                item.span,
+                "the `#[rustc_paren_sugar]` attribute is a temporary means of controlling \
              which traits can use parenthetical notation",
-        );
-        help!(
-            &mut err,
-            "add `#![feature(unboxed_closures)]` to \
-             the crate attributes to use it"
-        );
-        err.emit();
+            )
+            .help("add `#![feature(unboxed_closures)]` to the crate attributes to use it")
+            .emit();
     }
 
     let is_marker = tcx.has_attr(def_id, sym::marker);
@@ -1206,12 +1203,13 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics {
 }
 
 fn report_assoc_ty_on_inherent_impl(tcx: TyCtxt<'_>, span: Span) {
-    span_err!(
+    struct_span_err!(
         tcx.sess,
         span,
         E0202,
         "associated types are not yet supported in inherent impls (see #8995)"
-    );
+    )
+    .emit();
 }
 
 fn infer_placeholder_type(
@@ -2767,14 +2765,26 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
                 mark_used(attr);
                 inline_span = Some(attr.span);
                 if items.len() != 1 {
-                    span_err!(tcx.sess.diagnostic(), attr.span, E0534, "expected one argument");
+                    struct_span_err!(
+                        tcx.sess.diagnostic(),
+                        attr.span,
+                        E0534,
+                        "expected one argument"
+                    )
+                    .emit();
                     InlineAttr::None
                 } else if list_contains_name(&items[..], sym::always) {
                     InlineAttr::Always
                 } else if list_contains_name(&items[..], sym::never) {
                     InlineAttr::Never
                 } else {
-                    span_err!(tcx.sess.diagnostic(), items[0].span(), E0535, "invalid argument");
+                    struct_span_err!(
+                        tcx.sess.diagnostic(),
+                        items[0].span(),
+                        E0535,
+                        "invalid argument"
+                    )
+                    .emit();
 
                     InlineAttr::None
                 }
@@ -2788,7 +2798,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
         if !attr.has_name(sym::optimize) {
             return ia;
         }
-        let err = |sp, s| span_err!(tcx.sess.diagnostic(), sp, E0722, "{}", s);
+        let err = |sp, s| struct_span_err!(tcx.sess.diagnostic(), sp, E0722, "{}", s).emit();
         match attr.meta().map(|i| i.kind) {
             Some(MetaItemKind::Word) => {
                 err(attr.span, "expected one argument");
diff --git a/src/librustc_typeck/impl_wf_check.rs b/src/librustc_typeck/impl_wf_check.rs
index b22d7c68cf9..e3e61ebb936 100644
--- a/src/librustc_typeck/impl_wf_check.rs
+++ b/src/librustc_typeck/impl_wf_check.rs
@@ -9,6 +9,7 @@
 //! fixed, but for the moment it's easier to do these checks early.
 
 use crate::constrained_generic_params as cgp;
+use errors::struct_span_err;
 use rustc::ty::query::Providers;
 use rustc::ty::{self, TyCtxt, TypeFoldable};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index 8fba65db309..bc48e046a0c 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -71,8 +71,6 @@ This API is completely unstable and subject to change.
 
 #[macro_use]
 extern crate log;
-#[macro_use]
-extern crate syntax;
 
 #[macro_use]
 extern crate rustc;
@@ -93,6 +91,7 @@ mod outlives;
 mod structured_errors;
 mod variance;
 
+use errors::struct_span_err;
 use rustc::infer::InferOk;
 use rustc::lint;
 use rustc::middle;
diff --git a/src/librustc_typeck/outlives/test.rs b/src/librustc_typeck/outlives/test.rs
index f8907c85218..b693743e474 100644
--- a/src/librustc_typeck/outlives/test.rs
+++ b/src/librustc_typeck/outlives/test.rs
@@ -1,3 +1,4 @@
+use errors::struct_span_err;
 use rustc::ty::TyCtxt;
 use rustc_hir as hir;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
@@ -21,7 +22,7 @@ impl ItemLikeVisitor<'tcx> for OutlivesTest<'tcx> {
         // attribute and report an error with various results if found.
         if self.tcx.has_attr(item_def_id, sym::rustc_outlives) {
             let inferred_outlives_of = self.tcx.inferred_outlives_of(item_def_id);
-            span_err!(self.tcx.sess, item.span, E0640, "{:?}", inferred_outlives_of);
+            struct_span_err!(self.tcx.sess, item.span, E0640, "{:?}", inferred_outlives_of).emit();
         }
     }
 
diff --git a/src/librustc_typeck/structured_errors.rs b/src/librustc_typeck/structured_errors.rs
index 251732b6f12..dc6c45b4184 100644
--- a/src/librustc_typeck/structured_errors.rs
+++ b/src/librustc_typeck/structured_errors.rs
@@ -50,8 +50,7 @@ impl<'tcx> StructuredDiagnostic<'tcx> for VariadicError<'tcx> {
     }
 
     fn code(&self) -> DiagnosticId {
-        syntax::diagnostic_used!(E0617);
-        DiagnosticId::Error("E0617".to_owned())
+        errors::error_code!(E0617)
     }
 
     fn common(&self) -> DiagnosticBuilder<'tcx> {
@@ -112,8 +111,7 @@ impl<'tcx> StructuredDiagnostic<'tcx> for SizedUnsizedCastError<'tcx> {
     }
 
     fn code(&self) -> DiagnosticId {
-        syntax::diagnostic_used!(E0607);
-        DiagnosticId::Error("E0607".to_owned())
+        errors::error_code!(E0607)
     }
 
     fn common(&self) -> DiagnosticBuilder<'tcx> {
diff --git a/src/librustc_typeck/variance/test.rs b/src/librustc_typeck/variance/test.rs
index a8003a588ba..860bfe79395 100644
--- a/src/librustc_typeck/variance/test.rs
+++ b/src/librustc_typeck/variance/test.rs
@@ -1,3 +1,4 @@
+use errors::struct_span_err;
 use rustc::ty::TyCtxt;
 use rustc_hir as hir;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
@@ -21,7 +22,7 @@ impl ItemLikeVisitor<'tcx> for VarianceTest<'tcx> {
         // attribute and report an error with various results if found.
         if self.tcx.has_attr(item_def_id, sym::rustc_variance) {
             let variances_of = self.tcx.variances_of(item_def_id);
-            span_err!(self.tcx.sess, item.span, E0208, "{:?}", variances_of);
+            struct_span_err!(self.tcx.sess, item.span, E0208, "{:?}", variances_of).emit();
         }
     }
 
diff --git a/src/libsyntax/attr/builtin.rs b/src/libsyntax/attr/builtin.rs
index 04c28dd5c5b..b308d479545 100644
--- a/src/libsyntax/attr/builtin.rs
+++ b/src/libsyntax/attr/builtin.rs
@@ -6,7 +6,7 @@ use crate::feature_gate::feature_err;
 use crate::print::pprust;
 use crate::sess::ParseSess;
 
-use errors::{Applicability, Handler};
+use errors::{struct_span_err, Applicability, Handler};
 use rustc_feature::{find_gated_cfg, is_builtin_attr_name, Features, GatedCfg};
 use rustc_macros::HashStable_Generic;
 use rustc_span::hygiene::Transparency;
@@ -31,17 +31,21 @@ enum AttrError {
 fn handle_errors(sess: &ParseSess, span: Span, error: AttrError) {
     let diag = &sess.span_diagnostic;
     match error {
-        AttrError::MultipleItem(item) => span_err!(diag, span, E0538, "multiple '{}' items", item),
+        AttrError::MultipleItem(item) => {
+            struct_span_err!(diag, span, E0538, "multiple '{}' items", item).emit();
+        }
         AttrError::UnknownMetaItem(item, expected) => {
             let expected = expected.iter().map(|name| format!("`{}`", name)).collect::<Vec<_>>();
             struct_span_err!(diag, span, E0541, "unknown meta item '{}'", item)
                 .span_label(span, format!("expected one of {}", expected.join(", ")))
                 .emit();
         }
-        AttrError::MissingSince => span_err!(diag, span, E0542, "missing 'since'"),
-        AttrError::MissingFeature => span_err!(diag, span, E0546, "missing 'feature'"),
+        AttrError::MissingSince => struct_span_err!(diag, span, E0542, "missing 'since'").emit(),
+        AttrError::MissingFeature => {
+            struct_span_err!(diag, span, E0546, "missing 'feature'").emit();
+        }
         AttrError::MultipleStabilityLevels => {
-            span_err!(diag, span, E0544, "multiple stability levels")
+            struct_span_err!(diag, span, E0544, "multiple stability levels").emit();
         }
         AttrError::UnsupportedLiteral(msg, is_bytestr) => {
             let mut err = struct_span_err!(diag, span, E0565, "{}", msg);
@@ -283,7 +287,7 @@ where
                     *item = Some(v);
                     true
                 } else {
-                    span_err!(diagnostic, meta.span, E0539, "incorrect meta item");
+                    struct_span_err!(diagnostic, meta.span, E0539, "incorrect meta item").emit();
                     false
                 }
             };
@@ -331,12 +335,13 @@ where
             match meta_name {
                 sym::rustc_deprecated => {
                     if rustc_depr.is_some() {
-                        span_err!(
+                        struct_span_err!(
                             diagnostic,
                             item_sp,
                             E0540,
                             "multiple rustc_deprecated attributes"
-                        );
+                        )
+                        .emit();
                         continue 'outer;
                     }
 
@@ -351,7 +356,8 @@ where
                             continue;
                         }
                         _ => {
-                            span_err!(diagnostic, attr.span, E0543, "missing 'reason'");
+                            struct_span_err!(diagnostic, attr.span, E0543, "missing 'reason'")
+                                .emit();
                             continue;
                         }
                     }
@@ -426,12 +432,13 @@ where
                                         // Disallowing this requires updates to some submodules
                                         NonZeroU32::new(num)
                                     } else {
-                                        span_err!(
+                                        struct_span_err!(
                                             diagnostic,
                                             attr.span,
                                             E0545,
                                             "incorrect 'issue'"
-                                        );
+                                        )
+                                        .emit();
                                         continue;
                                     }
                                 }
@@ -453,7 +460,8 @@ where
                             continue;
                         }
                         _ => {
-                            span_err!(diagnostic, attr.span, E0547, "missing 'issue'");
+                            struct_span_err!(diagnostic, attr.span, E0547, "missing 'issue'")
+                                .emit();
                             continue;
                         }
                     }
@@ -539,13 +547,14 @@ where
         if let Some(ref mut stab) = stab {
             stab.rustc_depr = Some(rustc_depr);
         } else {
-            span_err!(
+            struct_span_err!(
                 diagnostic,
                 item_sp,
                 E0549,
                 "rustc_deprecated attribute must be paired with \
                        either stable or unstable attribute"
-            );
+            )
+            .emit();
         }
     }
 
@@ -555,14 +564,15 @@ where
             stab.promotable = promotable;
             stab.allow_const_fn_ptr = allow_const_fn_ptr;
         } else {
-            span_err!(
+            struct_span_err!(
                 diagnostic,
                 item_sp,
                 E0717,
                 "rustc_promotable and rustc_allow_const_fn_ptr attributes \
                       must be paired with either a rustc_const_unstable or a rustc_const_stable \
                       attribute"
-            );
+            )
+            .emit();
         }
     }
 
@@ -649,20 +659,27 @@ pub fn eval_condition(
                 }
                 sym::not => {
                     if mis.len() != 1 {
-                        span_err!(sess.span_diagnostic, cfg.span, E0536, "expected 1 cfg-pattern");
+                        struct_span_err!(
+                            sess.span_diagnostic,
+                            cfg.span,
+                            E0536,
+                            "expected 1 cfg-pattern"
+                        )
+                        .emit();
                         return false;
                     }
 
                     !eval_condition(mis[0].meta_item().unwrap(), sess, eval)
                 }
                 _ => {
-                    span_err!(
+                    struct_span_err!(
                         sess.span_diagnostic,
                         cfg.span,
                         E0537,
                         "invalid predicate `{}`",
                         pprust::path_to_string(&cfg.path)
-                    );
+                    )
+                    .emit();
                     false
                 }
             }
@@ -703,7 +720,7 @@ where
         }
 
         if depr.is_some() {
-            span_err!(diagnostic, item_sp, E0550, "multiple deprecated attributes");
+            struct_span_err!(diagnostic, item_sp, E0550, "multiple deprecated attributes").emit();
             break;
         }
 
@@ -741,7 +758,8 @@ where
                                 ),
                             );
                         } else {
-                            span_err!(diagnostic, meta.span, E0551, "incorrect meta item");
+                            struct_span_err!(diagnostic, meta.span, E0551, "incorrect meta item")
+                                .emit();
                         }
 
                         false
@@ -900,13 +918,14 @@ pub fn find_repr_attrs(sess: &ParseSess, attr: &Attribute) -> Vec<ReprAttr> {
                         };
                     }
                     if let Some(literal_error) = literal_error {
-                        span_err!(
+                        struct_span_err!(
                             diagnostic,
                             item.span(),
                             E0589,
                             "invalid `repr(align)` attribute: {}",
                             literal_error
-                        );
+                        )
+                        .emit();
                     }
                 } else {
                     if let Some(meta_item) = item.meta_item() {
@@ -945,7 +964,13 @@ pub fn find_repr_attrs(sess: &ParseSess, attr: &Attribute) -> Vec<ReprAttr> {
                 }
                 if !recognised {
                     // Not a word we recognize
-                    span_err!(diagnostic, item.span(), E0552, "unrecognized representation hint");
+                    struct_span_err!(
+                        diagnostic,
+                        item.span(),
+                        E0552,
+                        "unrecognized representation hint"
+                    )
+                    .emit();
                 }
             }
         }
diff --git a/src/libsyntax/diagnostics/macros.rs b/src/libsyntax/diagnostics/macros.rs
deleted file mode 100644
index 4ed17418c30..00000000000
--- a/src/libsyntax/diagnostics/macros.rs
+++ /dev/null
@@ -1,169 +0,0 @@
-#[macro_export]
-macro_rules! diagnostic_used {
-    ($code:ident) => {
-        let _ = $code;
-    };
-}
-
-#[macro_export]
-macro_rules! span_fatal {
-    ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
-        $crate::diagnostic_used!($code);
-        $session.span_fatal_with_code(
-            $span,
-            &format!($($message)*),
-            $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
-        )
-    })
-}
-
-#[macro_export]
-macro_rules! span_err {
-    ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
-        $crate::diagnostic_used!($code);
-        $session.span_err_with_code(
-            $span,
-            &format!($($message)*),
-            $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
-        )
-    })
-}
-
-#[macro_export]
-macro_rules! span_warn {
-    ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
-        $crate::diagnostic_used!($code);
-        $session.span_warn_with_code(
-            $span,
-            &format!($($message)*),
-            $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
-        )
-    })
-}
-
-#[macro_export]
-macro_rules! struct_err {
-    ($session:expr, $code:ident, $($message:tt)*) => ({
-        $crate::diagnostic_used!($code);
-        $session.struct_err_with_code(
-            &format!($($message)*),
-            $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
-        )
-    })
-}
-
-#[macro_export]
-macro_rules! span_err_or_warn {
-    ($is_warning:expr, $session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
-        $crate::diagnostic_used!($code);
-        if $is_warning {
-            $session.span_warn_with_code(
-                $span,
-                &format!($($message)*),
-                $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
-            )
-        } else {
-            $session.span_err_with_code(
-                $span,
-                &format!($($message)*),
-                $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
-            )
-        }
-    })
-}
-
-#[macro_export]
-macro_rules! struct_span_fatal {
-    ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
-        $crate::diagnostic_used!($code);
-        $session.struct_span_fatal_with_code(
-            $span,
-            &format!($($message)*),
-            $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
-        )
-    })
-}
-
-#[macro_export]
-macro_rules! struct_span_err {
-    ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
-        $crate::diagnostic_used!($code);
-        $session.struct_span_err_with_code(
-            $span,
-            &format!($($message)*),
-            $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
-        )
-    })
-}
-
-#[macro_export]
-macro_rules! stringify_error_code {
-    ($code:ident) => {{
-        $crate::diagnostic_used!($code);
-        $crate::errors::DiagnosticId::Error(stringify!($code).to_owned())
-    }};
-}
-
-#[macro_export]
-macro_rules! type_error_struct {
-    ($session:expr, $span:expr, $typ:expr, $code:ident, $($message:tt)*) => ({
-        if $typ.references_error() {
-            $session.diagnostic().struct_dummy()
-        } else {
-            struct_span_err!($session, $span, $code, $($message)*)
-        }
-    })
-}
-
-#[macro_export]
-macro_rules! struct_span_warn {
-    ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
-        $crate::diagnostic_used!($code);
-        $session.struct_span_warn_with_code(
-            $span,
-            &format!($($message)*),
-            $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
-        )
-    })
-}
-
-#[macro_export]
-macro_rules! struct_span_err_or_warn {
-    ($is_warning:expr, $session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
-        $crate::diagnostic_used!($code);
-        if $is_warning {
-            $session.struct_span_warn_with_code(
-                $span,
-                &format!($($message)*),
-                $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
-            )
-        } else {
-            $session.struct_span_err_with_code(
-                $span,
-                &format!($($message)*),
-                $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
-            )
-        }
-    })
-}
-
-#[macro_export]
-macro_rules! span_note {
-    ($err:expr, $span:expr, $($message:tt)*) => ({
-        ($err).span_note($span, &format!($($message)*));
-    })
-}
-
-#[macro_export]
-macro_rules! span_help {
-    ($err:expr, $span:expr, $($message:tt)*) => ({
-        ($err).span_help($span, &format!($($message)*));
-    })
-}
-
-#[macro_export]
-macro_rules! help {
-    ($err:expr, $($message:tt)*) => ({
-        ($err).help(&format!($($message)*));
-    })
-}
diff --git a/src/libsyntax/feature_gate/check.rs b/src/libsyntax/feature_gate/check.rs
index 0e94a722777..26545bfa61b 100644
--- a/src/libsyntax/feature_gate/check.rs
+++ b/src/libsyntax/feature_gate/check.rs
@@ -4,7 +4,7 @@ use crate::attr;
 use crate::sess::ParseSess;
 use crate::visit::{self, FnKind, Visitor};
 
-use errors::{Applicability, DiagnosticBuilder, Handler};
+use errors::{error_code, struct_span_err, Applicability, DiagnosticBuilder, Handler};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_error_codes::*;
 use rustc_feature::{find_feature_issue, GateIssue};
@@ -91,9 +91,7 @@ fn leveled_feature_err<'a>(
     let diag = &sess.span_diagnostic;
 
     let mut err = match level {
-        GateStrength::Hard => {
-            diag.struct_span_err_with_code(span, explain, stringify_error_code!(E0658))
-        }
+        GateStrength::Hard => diag.struct_span_err_with_code(span, explain, error_code!(E0658)),
         GateStrength::Soft => diag.struct_span_warn(span, explain),
     };
 
@@ -827,15 +825,9 @@ pub fn get_features(
             };
 
             if let Some(edition) = edition_enabled_features.get(&name) {
-                struct_span_warn!(
-                    span_handler,
-                    mi.span(),
-                    E0705,
-                    "the feature `{}` is included in the Rust {} edition",
-                    name,
-                    edition,
-                )
-                .emit();
+                let msg =
+                    &format!("the feature `{}` is included in the Rust {} edition", name, edition);
+                span_handler.struct_span_warn_with_code(mi.span(), msg, error_code!(E0705)).emit();
                 continue;
             }
 
@@ -863,13 +855,14 @@ pub fn get_features(
 
             if let Some(allowed) = allow_features.as_ref() {
                 if allowed.iter().find(|&f| name.as_str() == *f).is_none() {
-                    span_err!(
+                    struct_span_err!(
                         span_handler,
                         mi.span(),
                         E0725,
                         "the feature `{}` is not in the list of allowed features",
                         name
-                    );
+                    )
+                    .emit();
                     continue;
                 }
             }
@@ -953,13 +946,14 @@ pub fn check_crate(
 fn maybe_stage_features(span_handler: &Handler, krate: &ast::Crate, unstable: UnstableFeatures) {
     if !unstable.is_nightly_build() {
         for attr in krate.attrs.iter().filter(|attr| attr.check_name(sym::feature)) {
-            span_err!(
+            struct_span_err!(
                 span_handler,
                 attr.span,
                 E0554,
                 "`#![feature]` may not be used on the {} release channel",
                 option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)")
-            );
+            )
+            .emit();
         }
     }
 }
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index 72beddf7bb5..b197eab7394 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -62,12 +62,6 @@ pub fn with_default_globals<R>(f: impl FnOnce() -> R) -> R {
 
 scoped_tls::scoped_thread_local!(pub static GLOBALS: Globals);
 
-#[macro_use]
-pub mod diagnostics {
-    #[macro_use]
-    pub mod macros;
-}
-
 pub mod util {
     pub mod classify;
     pub mod comments;
diff --git a/src/test/run-make-fulldeps/simd-ffi/simd.rs b/src/test/run-make-fulldeps/simd-ffi/simd.rs
index 75d95a4eaf1..c63fe4ddce2 100644
--- a/src/test/run-make-fulldeps/simd-ffi/simd.rs
+++ b/src/test/run-make-fulldeps/simd-ffi/simd.rs
@@ -4,35 +4,28 @@
 // cross-compiled standard libraries.
 #![feature(no_core, optin_builtin_traits)]
 #![no_core]
-
 #![feature(repr_simd, simd_ffi, link_llvm_intrinsics, lang_items, rustc_attrs)]
 
-
-#[repr(C)]
 #[derive(Copy)]
 #[repr(simd)]
 pub struct f32x4(f32, f32, f32, f32);
 
-
-extern {
+extern "C" {
     #[link_name = "llvm.sqrt.v4f32"]
     fn vsqrt(x: f32x4) -> f32x4;
 }
 
 pub fn foo(x: f32x4) -> f32x4 {
-    unsafe {vsqrt(x)}
+    unsafe { vsqrt(x) }
 }
 
-#[repr(C)]
 #[derive(Copy)]
 #[repr(simd)]
 pub struct i32x4(i32, i32, i32, i32);
 
-
-extern {
+extern "C" {
     // _mm_sll_epi32
-    #[cfg(any(target_arch = "x86",
-              target_arch = "x86-64"))]
+    #[cfg(any(target_arch = "x86", target_arch = "x86-64"))]
     #[link_name = "llvm.x86.sse2.psll.d"]
     fn integer(a: i32x4, b: i32x4) -> i32x4;
 
@@ -48,22 +41,24 @@ extern {
     // just some substitute foreign symbol, not an LLVM intrinsic; so
     // we still get type checking, but not as detailed as (ab)using
     // LLVM.
-    #[cfg(not(any(target_arch = "x86",
-                  target_arch = "x86-64",
-                  target_arch = "arm",
-                  target_arch = "aarch64")))]
+    #[cfg(not(any(
+        target_arch = "x86",
+        target_arch = "x86-64",
+        target_arch = "arm",
+        target_arch = "aarch64"
+    )))]
     fn integer(a: i32x4, b: i32x4) -> i32x4;
 }
 
 pub fn bar(a: i32x4, b: i32x4) -> i32x4 {
-    unsafe {integer(a, b)}
+    unsafe { integer(a, b) }
 }
 
 #[lang = "sized"]
-pub trait Sized { }
+pub trait Sized {}
 
 #[lang = "copy"]
-pub trait Copy { }
+pub trait Copy {}
 
 impl Copy for f32 {}
 impl Copy for i32 {}
@@ -77,4 +72,6 @@ auto trait Freeze {}
 
 #[macro_export]
 #[rustc_builtin_macro]
-macro_rules! Copy { () => () }
+macro_rules! Copy {
+    () => {};
+}
diff --git a/src/test/ui/conflicting-repr-hints.rs b/src/test/ui/conflicting-repr-hints.rs
index cc986b25219..8e9c11690a8 100644
--- a/src/test/ui/conflicting-repr-hints.rs
+++ b/src/test/ui/conflicting-repr-hints.rs
@@ -1,16 +1,24 @@
 #![allow(dead_code)]
 
 #[repr(C)]
-enum A { A }
+enum A {
+    A,
+}
 
 #[repr(u64)]
-enum B { B }
+enum B {
+    B,
+}
 
-#[repr(C, u64)] //~ WARNING conflicting representation hints
-enum C { C }
+#[repr(C, u64)] //~ ERROR conflicting representation hints
+enum C {
+    C,
+}
 
-#[repr(u32, u64)] //~ WARNING conflicting representation hints
-enum D { D }
+#[repr(u32, u64)] //~ ERROR conflicting representation hints
+enum D {
+    D,
+}
 
 #[repr(C, packed)]
 struct E(i32);
@@ -37,20 +45,23 @@ struct J(i32); //~ ERROR type has conflicting packed representation hints
 struct K(i32);
 
 #[repr(packed, align(8))]
-union X { //~ ERROR type has conflicting packed and align representation hints
-    i: i32
+union X {
+    //~^ ERROR type has conflicting packed and align representation hints
+    i: i32,
 }
 
 #[repr(packed)]
 #[repr(align(8))]
-union Y { //~ ERROR type has conflicting packed and align representation hints
-    i: i32
+union Y {
+    //~^ ERROR type has conflicting packed and align representation hints
+    i: i32,
 }
 
 #[repr(align(8))]
 #[repr(packed)]
-union Z { //~ ERROR type has conflicting packed and align representation hints
-    i: i32
+union Z {
+    //~^ ERROR type has conflicting packed and align representation hints
+    i: i32,
 }
 
 fn main() {}
diff --git a/src/test/ui/conflicting-repr-hints.stderr b/src/test/ui/conflicting-repr-hints.stderr
index 414c15f93bc..0dfe360dbb3 100644
--- a/src/test/ui/conflicting-repr-hints.stderr
+++ b/src/test/ui/conflicting-repr-hints.stderr
@@ -1,70 +1,73 @@
-warning[E0566]: conflicting representation hints
-  --> $DIR/conflicting-repr-hints.rs:9:8
+error[E0566]: conflicting representation hints
+  --> $DIR/conflicting-repr-hints.rs:13:8
    |
 LL | #[repr(C, u64)]
    |        ^  ^^^
 
-warning[E0566]: conflicting representation hints
-  --> $DIR/conflicting-repr-hints.rs:12:8
+error[E0566]: conflicting representation hints
+  --> $DIR/conflicting-repr-hints.rs:18:8
    |
 LL | #[repr(u32, u64)]
    |        ^^^  ^^^
 
 error[E0587]: type has conflicting packed and align representation hints
-  --> $DIR/conflicting-repr-hints.rs:19:1
+  --> $DIR/conflicting-repr-hints.rs:27:1
    |
 LL | struct F(i32);
    | ^^^^^^^^^^^^^^
 
 error[E0587]: type has conflicting packed and align representation hints
-  --> $DIR/conflicting-repr-hints.rs:23:1
+  --> $DIR/conflicting-repr-hints.rs:31:1
    |
 LL | struct G(i32);
    | ^^^^^^^^^^^^^^
 
 error[E0587]: type has conflicting packed and align representation hints
-  --> $DIR/conflicting-repr-hints.rs:27:1
+  --> $DIR/conflicting-repr-hints.rs:35:1
    |
 LL | struct H(i32);
    | ^^^^^^^^^^^^^^
 
 error[E0634]: type has conflicting packed representation hints
-  --> $DIR/conflicting-repr-hints.rs:30:1
+  --> $DIR/conflicting-repr-hints.rs:38:1
    |
 LL | struct I(i32);
    | ^^^^^^^^^^^^^^
 
 error[E0634]: type has conflicting packed representation hints
-  --> $DIR/conflicting-repr-hints.rs:34:1
+  --> $DIR/conflicting-repr-hints.rs:42:1
    |
 LL | struct J(i32);
    | ^^^^^^^^^^^^^^
 
 error[E0587]: type has conflicting packed and align representation hints
-  --> $DIR/conflicting-repr-hints.rs:40:1
+  --> $DIR/conflicting-repr-hints.rs:48:1
    |
 LL | / union X {
-LL | |     i: i32
+LL | |
+LL | |     i: i32,
 LL | | }
    | |_^
 
 error[E0587]: type has conflicting packed and align representation hints
-  --> $DIR/conflicting-repr-hints.rs:46:1
+  --> $DIR/conflicting-repr-hints.rs:55:1
    |
 LL | / union Y {
-LL | |     i: i32
+LL | |
+LL | |     i: i32,
 LL | | }
    | |_^
 
 error[E0587]: type has conflicting packed and align representation hints
-  --> $DIR/conflicting-repr-hints.rs:52:1
+  --> $DIR/conflicting-repr-hints.rs:62:1
    |
 LL | / union Z {
-LL | |     i: i32
+LL | |
+LL | |     i: i32,
 LL | | }
    | |_^
 
-error: aborting due to 8 previous errors
+error: aborting due to 10 previous errors
 
 Some errors have detailed explanations: E0566, E0587.
 For more information about an error, try `rustc --explain E0566`.
diff --git a/src/test/ui/feature-gates/feature-gate-repr-simd.rs b/src/test/ui/feature-gates/feature-gate-repr-simd.rs
index 9d28f437415..1e4a404fa25 100644
--- a/src/test/ui/feature-gates/feature-gate-repr-simd.rs
+++ b/src/test/ui/feature-gates/feature-gate-repr-simd.rs
@@ -1,7 +1,7 @@
 #[repr(simd)] //~ error: SIMD types are experimental
 struct Foo(u64, u64);
 
-#[repr(C)] //~ warn: conflicting representation hints
+#[repr(C)] //~ ERROR conflicting representation hints
 #[repr(simd)] //~ error: SIMD types are experimental
 struct Bar(u64, u64);
 
diff --git a/src/test/ui/feature-gates/feature-gate-repr-simd.stderr b/src/test/ui/feature-gates/feature-gate-repr-simd.stderr
index 02c8400e03e..37a7bd0b129 100644
--- a/src/test/ui/feature-gates/feature-gate-repr-simd.stderr
+++ b/src/test/ui/feature-gates/feature-gate-repr-simd.stderr
@@ -16,7 +16,7 @@ LL | #[repr(simd)]
    = note: for more information, see https://github.com/rust-lang/rust/issues/27731
    = help: add `#![feature(repr_simd)]` to the crate attributes to enable
 
-warning[E0566]: conflicting representation hints
+error[E0566]: conflicting representation hints
   --> $DIR/feature-gate-repr-simd.rs:4:8
    |
 LL | #[repr(C)]
@@ -24,7 +24,7 @@ LL | #[repr(C)]
 LL | #[repr(simd)]
    |        ^^^^
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0566, E0658.
 For more information about an error, try `rustc --explain E0566`.
diff --git a/src/test/ui/issues/issue-14221.stderr b/src/test/ui/issues/issue-14221.stderr
index 3e5e25a9f6d..9864c0840d8 100644
--- a/src/test/ui/issues/issue-14221.stderr
+++ b/src/test/ui/issues/issue-14221.stderr
@@ -3,6 +3,8 @@ warning[E0170]: pattern binding `A` is named the same as one of the variants of
    |
 LL |             A => "A",
    |             ^ help: to match on the variant, qualify the path: `E::A`
+   |
+   = note: `#[warn(bindings_with_variant_name)]` on by default
 
 warning[E0170]: pattern binding `B` is named the same as one of the variants of the type `E`
   --> $DIR/issue-14221.rs:15:13
diff --git a/src/test/ui/issues/issue-19100.stderr b/src/test/ui/issues/issue-19100.stderr
index 1ab13477e37..01e5313fcc1 100644
--- a/src/test/ui/issues/issue-19100.stderr
+++ b/src/test/ui/issues/issue-19100.stderr
@@ -3,6 +3,8 @@ warning[E0170]: pattern binding `Bar` is named the same as one of the variants o
    |
 LL | Bar if true
    | ^^^ help: to match on the variant, qualify the path: `Foo::Bar`
+   |
+   = note: `#[warn(bindings_with_variant_name)]` on by default
 
 warning[E0170]: pattern binding `Baz` is named the same as one of the variants of the type `Foo`
   --> $DIR/issue-19100.rs:22:1
diff --git a/src/test/ui/issues/issue-30302.stderr b/src/test/ui/issues/issue-30302.stderr
index d762d6f2b3d..ac1b5235f44 100644
--- a/src/test/ui/issues/issue-30302.stderr
+++ b/src/test/ui/issues/issue-30302.stderr
@@ -3,6 +3,8 @@ warning[E0170]: pattern binding `Nil` is named the same as one of the variants o
    |
 LL |         Nil => true,
    |         ^^^ help: to match on the variant, qualify the path: `Stack::Nil`
+   |
+   = note: `#[warn(bindings_with_variant_name)]` on by default
 
 error: unreachable pattern
   --> $DIR/issue-30302.rs:15:9
diff --git a/src/test/ui/issues/issue-39720.rs b/src/test/ui/issues/issue-39720.rs
index 1a4775fc960..8cf841f9371 100644
--- a/src/test/ui/issues/issue-39720.rs
+++ b/src/test/ui/issues/issue-39720.rs
@@ -1,26 +1,22 @@
 // run-pass
-#![allow(non_snake_case)]
-
 // ignore-emscripten FIXME(#45351)
 
 #![feature(repr_simd, platform_intrinsics)]
 
-#[repr(C)] //~ WARNING conflicting representation hints
 #[repr(simd)]
 #[derive(Copy, Clone, Debug)]
-pub struct char3(pub i8, pub i8, pub i8);
+pub struct Char3(pub i8, pub i8, pub i8);
 
-#[repr(C)]  //~ WARNING conflicting representation hints
 #[repr(simd)]
 #[derive(Copy, Clone, Debug)]
-pub struct short3(pub i16, pub i16, pub i16);
+pub struct Short3(pub i16, pub i16, pub i16);
 
 extern "platform-intrinsic" {
     fn simd_cast<T, U>(x: T) -> U;
 }
 
 fn main() {
-    let cast: short3 = unsafe { simd_cast(char3(10, -3, -9)) };
+    let cast: Short3 = unsafe { simd_cast(Char3(10, -3, -9)) };
 
     println!("{:?}", cast);
 }
diff --git a/src/test/ui/issues/issue-39720.stderr b/src/test/ui/issues/issue-39720.stderr
deleted file mode 100644
index 8121ed28940..00000000000
--- a/src/test/ui/issues/issue-39720.stderr
+++ /dev/null
@@ -1,16 +0,0 @@
-warning[E0566]: conflicting representation hints
-  --> $DIR/issue-39720.rs:8:8
-   |
-LL | #[repr(C)]
-   |        ^
-LL | #[repr(simd)]
-   |        ^^^^
-
-warning[E0566]: conflicting representation hints
-  --> $DIR/issue-39720.rs:13:8
-   |
-LL | #[repr(C)]
-   |        ^
-LL | #[repr(simd)]
-   |        ^^^^
-
diff --git a/src/test/ui/issues/issue-47094.rs b/src/test/ui/issues/issue-47094.rs
index 97da984d4af..3258ee92a74 100644
--- a/src/test/ui/issues/issue-47094.rs
+++ b/src/test/ui/issues/issue-47094.rs
@@ -1,12 +1,10 @@
-// check-pass
-
-#[repr(C,u8)] //~ WARNING conflicting representation hints
+#[repr(C, u8)] //~ ERROR conflicting representation hints
 enum Foo {
     A,
     B,
 }
 
-#[repr(C)] //~ WARNING conflicting representation hints
+#[repr(C)] //~ ERROR conflicting representation hints
 #[repr(u8)]
 enum Bar {
     A,
diff --git a/src/test/ui/issues/issue-47094.stderr b/src/test/ui/issues/issue-47094.stderr
index 16bcec0c7bb..c807f644fd3 100644
--- a/src/test/ui/issues/issue-47094.stderr
+++ b/src/test/ui/issues/issue-47094.stderr
@@ -1,14 +1,17 @@
-warning[E0566]: conflicting representation hints
-  --> $DIR/issue-47094.rs:3:8
+error[E0566]: conflicting representation hints
+  --> $DIR/issue-47094.rs:1:8
    |
-LL | #[repr(C,u8)]
-   |        ^ ^^
+LL | #[repr(C, u8)]
+   |        ^  ^^
 
-warning[E0566]: conflicting representation hints
-  --> $DIR/issue-47094.rs:9:8
+error[E0566]: conflicting representation hints
+  --> $DIR/issue-47094.rs:7:8
    |
 LL | #[repr(C)]
    |        ^
 LL | #[repr(u8)]
    |        ^^
 
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0566`.
diff --git a/src/test/ui/lint/lint-uppercase-variables.stderr b/src/test/ui/lint/lint-uppercase-variables.stderr
index f614d5d71f8..b937832ac62 100644
--- a/src/test/ui/lint/lint-uppercase-variables.stderr
+++ b/src/test/ui/lint/lint-uppercase-variables.stderr
@@ -3,6 +3,8 @@ warning[E0170]: pattern binding `Foo` is named the same as one of the variants o
    |
 LL |         Foo => {}
    |         ^^^ help: to match on the variant, qualify the path: `foo::Foo::Foo`
+   |
+   = note: `#[warn(bindings_with_variant_name)]` on by default
 
 warning: unused variable: `Foo`
   --> $DIR/lint-uppercase-variables.rs:22:9
diff --git a/src/test/ui/pattern/issue-67776-match-same-name-enum-variant-refs.stderr b/src/test/ui/pattern/issue-67776-match-same-name-enum-variant-refs.stderr
index abb8d6907e7..21218d9a173 100644
--- a/src/test/ui/pattern/issue-67776-match-same-name-enum-variant-refs.stderr
+++ b/src/test/ui/pattern/issue-67776-match-same-name-enum-variant-refs.stderr
@@ -3,6 +3,8 @@ warning[E0170]: pattern binding `Bar` is named the same as one of the variants o
    |
 LL |         Bar => {},
    |         ^^^ help: to match on the variant, qualify the path: `Foo::Bar`
+   |
+   = note: `#[warn(bindings_with_variant_name)]` on by default
 
 warning[E0170]: pattern binding `Baz` is named the same as one of the variants of the type `Foo`
   --> $DIR/issue-67776-match-same-name-enum-variant-refs.rs:19:9