about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-02-23 19:26:35 +0000
committerbors <bors@rust-lang.org>2020-02-23 19:26:35 +0000
commit6d0e58bff88f620c1a4f641a627f046bf4cde4ad (patch)
tree1d68f7c1f1aadd1ce180daf6b6dd3b5d09d02972 /src
parentb1f395de642e8be7bcbbd2bd8aaadab715851f49 (diff)
parentd6414f5f8c30593cd250fddf315e6f0098c3239a (diff)
Auto merge of #69393 - Dylan-DPC:rollup-rxbd1zg, r=Dylan-DPC
Rollup of 5 pull requests

Successful merges:

 - #69336 (Do not ping the infrastructure team on toolstate changes)
 - #69351 (Improve external MinGW detection)
 - #69361 (parse: allow `type Foo: Ord` syntactically)
 - #69375 (Rename CodeMap to SourceMap follow up)
 - #69376 (parser: Cleanup `Parser::bump_with` and its uses)

Failed merges:

r? @ghost
Diffstat (limited to 'src')
-rw-r--r--src/librustc/ich/hcx.rs2
-rw-r--r--src/librustc/middle/stability.rs4
-rw-r--r--src/librustc_ast_lowering/item.rs18
-rw-r--r--src/librustc_ast_lowering/lib.rs2
-rw-r--r--src/librustc_ast_passes/ast_validation.rs7
-rw-r--r--src/librustc_ast_passes/feature_gate.rs2
-rw-r--r--src/librustc_ast_pretty/pprust.rs36
-rw-r--r--src/librustc_driver/pretty.rs4
-rw-r--r--src/librustc_errors/json.rs8
-rw-r--r--src/librustc_errors/lib.rs32
-rw-r--r--src/librustc_hir/print.rs8
-rw-r--r--src/librustc_infer/infer/error_reporting/mod.rs8
-rw-r--r--src/librustc_parse/parser/expr.rs4
-rw-r--r--src/librustc_parse/parser/item.rs32
-rw-r--r--src/librustc_parse/parser/mod.rs178
-rw-r--r--src/librustc_passes/liveness.rs8
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs4
-rw-r--r--src/librustc_resolve/diagnostics.rs14
-rw-r--r--src/librustc_resolve/late.rs2
-rw-r--r--src/librustc_resolve/late/diagnostics.rs22
-rw-r--r--src/librustc_save_analysis/dump_visitor.rs13
-rw-r--r--src/librustc_save_analysis/lib.rs10
-rw-r--r--src/librustc_save_analysis/sig.rs7
-rw-r--r--src/librustc_session/parse.rs10
-rw-r--r--src/librustc_span/caching_source_map_view.rs8
-rw-r--r--src/librustc_typeck/check/demand.rs24
-rw-r--r--src/librustc_typeck/coherence/orphan.rs4
-rw-r--r--src/librustdoc/clean/mod.rs14
-rw-r--r--src/librustdoc/core.rs2
-rw-r--r--src/librustdoc/html/highlight.rs4
-rw-r--r--src/librustdoc/passes/check_code_block_syntax.rs4
-rw-r--r--src/librustdoc/test.rs4
-rw-r--r--src/libsyntax/ast.rs4
-rw-r--r--src/libsyntax/mut_visit.rs5
-rw-r--r--src/libsyntax/token.rs33
-rw-r--r--src/libsyntax/util/comments.rs4
-rw-r--r--src/libsyntax/visit.rs7
-rw-r--r--src/test/ui/parser/bounds-lifetime-where.rs2
-rw-r--r--src/test/ui/parser/bounds-lifetime-where.stderr4
-rw-r--r--src/test/ui/parser/item-free-type-bounds-semantic-fail.rs20
-rw-r--r--src/test/ui/parser/item-free-type-bounds-semantic-fail.stderr67
-rw-r--r--src/test/ui/parser/item-free-type-bounds-syntactic-pass.rs13
42 files changed, 357 insertions, 301 deletions
diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs
index 9e2db35dc6d..1a9c5d1f13f 100644
--- a/src/librustc/ich/hcx.rs
+++ b/src/librustc/ich/hcx.rs
@@ -149,7 +149,7 @@ impl<'a> StableHashingContext<'a> {
     #[inline]
     pub fn source_map(&mut self) -> &mut CachingSourceMapView<'a> {
         match self.caching_source_map {
-            Some(ref mut cm) => cm,
+            Some(ref mut sm) => sm,
             ref mut none => {
                 *none = Some(CachingSourceMapView::new(self.raw_source_map));
                 none.as_mut().unwrap()
diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs
index dd30fb23c2e..7b5faa2423a 100644
--- a/src/librustc/middle/stability.rs
+++ b/src/librustc/middle/stability.rs
@@ -106,10 +106,10 @@ pub fn report_unstable(
     };
 
     let msp: MultiSpan = span.into();
-    let cm = &sess.parse_sess.source_map();
+    let sm = &sess.parse_sess.source_map();
     let span_key = msp.primary_span().and_then(|sp: Span| {
         if !sp.is_dummy() {
-            let file = cm.lookup_char_pos(sp.lo()).file;
+            let file = sm.lookup_char_pos(sp.lo()).file;
             if file.name.is_macros() { None } else { Some(span) }
         } else {
             None
diff --git a/src/librustc_ast_lowering/item.rs b/src/librustc_ast_lowering/item.rs
index ad7221b16b2..1a19fab0265 100644
--- a/src/librustc_ast_lowering/item.rs
+++ b/src/librustc_ast_lowering/item.rs
@@ -297,28 +297,28 @@ impl<'hir> LoweringContext<'_, 'hir> {
             ItemKind::Mod(ref m) => hir::ItemKind::Mod(self.lower_mod(m)),
             ItemKind::ForeignMod(ref nm) => hir::ItemKind::ForeignMod(self.lower_foreign_mod(nm)),
             ItemKind::GlobalAsm(ref ga) => hir::ItemKind::GlobalAsm(self.lower_global_asm(ga)),
-            ItemKind::TyAlias(ref ty, ref generics) => match ty.kind.opaque_top_hack() {
+            ItemKind::TyAlias(ref generics, _, Some(ref ty)) => match ty.kind.opaque_top_hack() {
                 None => {
                     let ty = self.lower_ty(ty, ImplTraitContext::disallowed());
                     let generics = self.lower_generics(generics, ImplTraitContext::disallowed());
                     hir::ItemKind::TyAlias(ty, generics)
                 }
                 Some(bounds) => {
+                    let ctx = || ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Misc);
                     let ty = hir::OpaqueTy {
-                        generics: self.lower_generics(
-                            generics,
-                            ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Misc),
-                        ),
-                        bounds: self.lower_param_bounds(
-                            bounds,
-                            ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Misc),
-                        ),
+                        generics: self.lower_generics(generics, ctx()),
+                        bounds: self.lower_param_bounds(bounds, ctx()),
                         impl_trait_fn: None,
                         origin: hir::OpaqueTyOrigin::TypeAlias,
                     };
                     hir::ItemKind::OpaqueTy(ty)
                 }
             },
+            ItemKind::TyAlias(ref generics, _, None) => {
+                let ty = self.arena.alloc(self.ty(span, hir::TyKind::Err));
+                let generics = self.lower_generics(generics, ImplTraitContext::disallowed());
+                hir::ItemKind::TyAlias(ty, generics)
+            }
             ItemKind::Enum(ref enum_definition, ref generics) => hir::ItemKind::Enum(
                 hir::EnumDef {
                     variants: self.arena.alloc_from_iter(
diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs
index ac4ca30382f..9bb46009fe6 100644
--- a/src/librustc_ast_lowering/lib.rs
+++ b/src/librustc_ast_lowering/lib.rs
@@ -462,7 +462,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     ItemKind::Struct(_, ref generics)
                     | ItemKind::Union(_, ref generics)
                     | ItemKind::Enum(_, ref generics)
-                    | ItemKind::TyAlias(_, ref generics)
+                    | ItemKind::TyAlias(ref generics, ..)
                     | ItemKind::Trait(_, _, ref generics, ..) => {
                         let def_id = self.lctx.resolver.definitions().local_def_id(item.id);
                         let count = generics
diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs
index 1194269e0ee..a9844a7059e 100644
--- a/src/librustc_ast_passes/ast_validation.rs
+++ b/src/librustc_ast_passes/ast_validation.rs
@@ -969,6 +969,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 let msg = "free static item without body";
                 self.error_item_without_body(item.span, "static", msg, " = <expr>;");
             }
+            ItemKind::TyAlias(_, ref bounds, ref body) => {
+                if body.is_none() {
+                    let msg = "free type alias without body";
+                    self.error_item_without_body(item.span, "type", msg, " = <type>;");
+                }
+                self.check_type_no_bounds(bounds, "this context");
+            }
             _ => {}
         }
 
diff --git a/src/librustc_ast_passes/feature_gate.rs b/src/librustc_ast_passes/feature_gate.rs
index 3c924847a73..5bddae0d49e 100644
--- a/src/librustc_ast_passes/feature_gate.rs
+++ b/src/librustc_ast_passes/feature_gate.rs
@@ -372,7 +372,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
                 gate_feature_post!(&self, decl_macro, i.span, msg);
             }
 
-            ast::ItemKind::TyAlias(ref ty, ..) => self.check_impl_trait(&ty),
+            ast::ItemKind::TyAlias(_, _, Some(ref ty)) => self.check_impl_trait(&ty),
 
             _ => {}
         }
diff --git a/src/librustc_ast_pretty/pprust.rs b/src/librustc_ast_pretty/pprust.rs
index 27cef8502a1..548ae6e7e63 100644
--- a/src/librustc_ast_pretty/pprust.rs
+++ b/src/librustc_ast_pretty/pprust.rs
@@ -47,15 +47,15 @@ pub struct NoAnn;
 impl PpAnn for NoAnn {}
 
 pub struct Comments<'a> {
-    cm: &'a SourceMap,
+    sm: &'a SourceMap,
     comments: Vec<comments::Comment>,
     current: usize,
 }
 
 impl<'a> Comments<'a> {
-    pub fn new(cm: &'a SourceMap, filename: FileName, input: String) -> Comments<'a> {
-        let comments = comments::gather_comments(cm, filename, input);
-        Comments { cm, comments, current: 0 }
+    pub fn new(sm: &'a SourceMap, filename: FileName, input: String) -> Comments<'a> {
+        let comments = comments::gather_comments(sm, filename, input);
+        Comments { sm, comments, current: 0 }
     }
 
     pub fn next(&self) -> Option<comments::Comment> {
@@ -71,8 +71,8 @@ impl<'a> Comments<'a> {
             if cmnt.style != comments::Trailing {
                 return None;
             }
-            let span_line = self.cm.lookup_char_pos(span.hi());
-            let comment_line = self.cm.lookup_char_pos(cmnt.pos);
+            let span_line = self.sm.lookup_char_pos(span.hi());
+            let comment_line = self.sm.lookup_char_pos(cmnt.pos);
             let next = next_pos.unwrap_or_else(|| cmnt.pos + BytePos(1));
             if span.hi() < cmnt.pos && cmnt.pos < next && span_line.line == comment_line.line {
                 return Some(cmnt);
@@ -95,7 +95,7 @@ crate const INDENT_UNIT: usize = 4;
 /// Requires you to pass an input filename and reader so that
 /// it can scan the input text for comments to copy forward.
 pub fn print_crate<'a>(
-    cm: &'a SourceMap,
+    sm: &'a SourceMap,
     krate: &ast::Crate,
     filename: FileName,
     input: String,
@@ -106,7 +106,7 @@ pub fn print_crate<'a>(
 ) -> String {
     let mut s = State {
         s: pp::mk_printer(),
-        comments: Some(Comments::new(cm, filename, input)),
+        comments: Some(Comments::new(sm, filename, input)),
         ann,
         is_expanded,
     };
@@ -522,8 +522,8 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
                 self.hardbreak();
             }
         }
-        if let Some(cm) = self.comments() {
-            cm.current += 1;
+        if let Some(cmnts) = self.comments() {
+            cmnts.current += 1;
         }
     }
 
@@ -1185,18 +1185,10 @@ impl<'a> State<'a> {
                 self.s.word(ga.asm.to_string());
                 self.end();
             }
-            ast::ItemKind::TyAlias(ref ty, ref generics) => {
-                self.head(visibility_qualified(&item.vis, "type"));
-                self.print_ident(item.ident);
-                self.print_generic_params(&generics.params);
-                self.end(); // end the inner ibox
-
-                self.print_where_clause(&generics.where_clause);
-                self.s.space();
-                self.word_space("=");
-                self.print_type(ty);
-                self.s.word(";");
-                self.end(); // end the outer ibox
+            ast::ItemKind::TyAlias(ref generics, ref bounds, ref ty) => {
+                let def = ast::Defaultness::Final;
+                let ty = ty.as_deref();
+                self.print_associated_type(item.ident, generics, bounds, ty, &item.vis, def);
             }
             ast::ItemKind::Enum(ref enum_definition, ref params) => {
                 self.print_enum_def(enum_definition, params, item.ident, item.span, &item.vis);
diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs
index d4f01490499..236a7243998 100644
--- a/src/librustc_driver/pretty.rs
+++ b/src/librustc_driver/pretty.rs
@@ -452,8 +452,8 @@ pub fn print_after_hir_lowering<'tcx>(
             call_with_pp_support_hir(&s, tcx, move |annotation, krate| {
                 debug!("pretty printing source code {:?}", s);
                 let sess = annotation.sess();
-                let cm = sess.source_map();
-                *out = pprust_hir::print_crate(cm, krate, src_name, src, annotation.pp_ann())
+                let sm = sess.source_map();
+                *out = pprust_hir::print_crate(sm, krate, src_name, src, annotation.pp_ann())
             })
         }
 
diff --git a/src/librustc_errors/json.rs b/src/librustc_errors/json.rs
index ffdff6acec5..1f6e268b506 100644
--- a/src/librustc_errors/json.rs
+++ b/src/librustc_errors/json.rs
@@ -373,13 +373,13 @@ impl DiagnosticSpan {
 
 impl DiagnosticSpanLine {
     fn line_from_source_file(
-        fm: &rustc_span::SourceFile,
+        sf: &rustc_span::SourceFile,
         index: usize,
         h_start: usize,
         h_end: usize,
     ) -> DiagnosticSpanLine {
         DiagnosticSpanLine {
-            text: fm.get_line(index).map_or(String::new(), |l| l.into_owned()),
+            text: sf.get_line(index).map_or(String::new(), |l| l.into_owned()),
             highlight_start: h_start,
             highlight_end: h_end,
         }
@@ -392,13 +392,13 @@ impl DiagnosticSpanLine {
         je.sm
             .span_to_lines(span)
             .map(|lines| {
-                let fm = &*lines.file;
+                let sf = &*lines.file;
                 lines
                     .lines
                     .iter()
                     .map(|line| {
                         DiagnosticSpanLine::line_from_source_file(
-                            fm,
+                            sf,
                             line.line_index,
                             line.start_col.0 + 1,
                             line.end_col.0 + 1,
diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs
index 594e813def8..1a0fe343521 100644
--- a/src/librustc_errors/lib.rs
+++ b/src/librustc_errors/lib.rs
@@ -144,7 +144,7 @@ pub struct SubstitutionPart {
 impl CodeSuggestion {
     /// Returns the assembled code suggestions, whether they should be shown with an underline
     /// and whether the substitution only differs in capitalization.
-    pub fn splice_lines(&self, cm: &SourceMap) -> Vec<(String, Vec<SubstitutionPart>, bool)> {
+    pub fn splice_lines(&self, sm: &SourceMap) -> Vec<(String, Vec<SubstitutionPart>, bool)> {
         use rustc_span::{CharPos, Pos};
 
         fn push_trailing(
@@ -176,7 +176,7 @@ impl CodeSuggestion {
             .filter(|subst| {
                 // Suggestions coming from macros can have malformed spans. This is a heavy
                 // handed approach to avoid ICEs by ignoring the suggestion outright.
-                let invalid = subst.parts.iter().any(|item| cm.is_valid_span(item.span).is_err());
+                let invalid = subst.parts.iter().any(|item| sm.is_valid_span(item.span).is_err());
                 if invalid {
                     debug!("splice_lines: suggestion contains an invalid span: {:?}", subst);
                 }
@@ -193,7 +193,7 @@ impl CodeSuggestion {
                 let hi = substitution.parts.iter().map(|part| part.span.hi()).max()?;
                 let bounding_span = Span::with_root_ctxt(lo, hi);
                 // The different spans might belong to different contexts, if so ignore suggestion.
-                let lines = cm.span_to_lines(bounding_span).ok()?;
+                let lines = sm.span_to_lines(bounding_span).ok()?;
                 assert!(!lines.lines.is_empty());
 
                 // To build up the result, we do this for each span:
@@ -205,36 +205,36 @@ impl CodeSuggestion {
                 // - splice in the span substitution
                 //
                 // Finally push the trailing line segment of the last span
-                let fm = &lines.file;
-                let mut prev_hi = cm.lookup_char_pos(bounding_span.lo());
+                let sf = &lines.file;
+                let mut prev_hi = sm.lookup_char_pos(bounding_span.lo());
                 prev_hi.col = CharPos::from_usize(0);
 
-                let mut prev_line = fm.get_line(lines.lines[0].line_index);
+                let mut prev_line = sf.get_line(lines.lines[0].line_index);
                 let mut buf = String::new();
 
                 for part in &substitution.parts {
-                    let cur_lo = cm.lookup_char_pos(part.span.lo());
+                    let cur_lo = sm.lookup_char_pos(part.span.lo());
                     if prev_hi.line == cur_lo.line {
                         push_trailing(&mut buf, prev_line.as_ref(), &prev_hi, Some(&cur_lo));
                     } else {
                         push_trailing(&mut buf, prev_line.as_ref(), &prev_hi, None);
                         // push lines between the previous and current span (if any)
                         for idx in prev_hi.line..(cur_lo.line - 1) {
-                            if let Some(line) = fm.get_line(idx) {
+                            if let Some(line) = sf.get_line(idx) {
                                 buf.push_str(line.as_ref());
                                 buf.push('\n');
                             }
                         }
-                        if let Some(cur_line) = fm.get_line(cur_lo.line - 1) {
+                        if let Some(cur_line) = sf.get_line(cur_lo.line - 1) {
                             let end = std::cmp::min(cur_line.len(), cur_lo.col.to_usize());
                             buf.push_str(&cur_line[..end]);
                         }
                     }
                     buf.push_str(&part.snippet);
-                    prev_hi = cm.lookup_char_pos(part.span.hi());
-                    prev_line = fm.get_line(prev_hi.line - 1);
+                    prev_hi = sm.lookup_char_pos(part.span.hi());
+                    prev_line = sf.get_line(prev_hi.line - 1);
                 }
-                let only_capitalization = is_case_difference(cm, &buf, bounding_span);
+                let only_capitalization = is_case_difference(sm, &buf, bounding_span);
                 // if the replacement already ends with a newline, don't print the next line
                 if !buf.ends_with('\n') {
                     push_trailing(&mut buf, prev_line.as_ref(), &prev_hi, None);
@@ -363,23 +363,23 @@ impl Handler {
         color_config: ColorConfig,
         can_emit_warnings: bool,
         treat_err_as_bug: Option<usize>,
-        cm: Option<Lrc<SourceMap>>,
+        sm: Option<Lrc<SourceMap>>,
     ) -> Self {
         Self::with_tty_emitter_and_flags(
             color_config,
-            cm,
+            sm,
             HandlerFlags { can_emit_warnings, treat_err_as_bug, ..Default::default() },
         )
     }
 
     pub fn with_tty_emitter_and_flags(
         color_config: ColorConfig,
-        cm: Option<Lrc<SourceMap>>,
+        sm: Option<Lrc<SourceMap>>,
         flags: HandlerFlags,
     ) -> Self {
         let emitter = Box::new(EmitterWriter::stderr(
             color_config,
-            cm,
+            sm,
             false,
             false,
             None,
diff --git a/src/librustc_hir/print.rs b/src/librustc_hir/print.rs
index e49f99fb717..c9faa299d37 100644
--- a/src/librustc_hir/print.rs
+++ b/src/librustc_hir/print.rs
@@ -140,13 +140,13 @@ pub const INDENT_UNIT: usize = 4;
 /// Requires you to pass an input filename and reader so that
 /// it can scan the input text for comments to copy forward.
 pub fn print_crate<'a>(
-    cm: &'a SourceMap,
+    sm: &'a SourceMap,
     krate: &hir::Crate<'_>,
     filename: FileName,
     input: String,
     ann: &'a dyn PpAnn,
 ) -> String {
-    let mut s = State::new_from_input(cm, filename, input, ann);
+    let mut s = State::new_from_input(sm, filename, input, ann);
 
     // When printing the AST, we sometimes need to inject `#[no_std]` here.
     // Since you can't compile the HIR, it's not necessary.
@@ -158,12 +158,12 @@ pub fn print_crate<'a>(
 
 impl<'a> State<'a> {
     pub fn new_from_input(
-        cm: &'a SourceMap,
+        sm: &'a SourceMap,
         filename: FileName,
         input: String,
         ann: &'a dyn PpAnn,
     ) -> State<'a> {
-        State { s: pp::mk_printer(), comments: Some(Comments::new(cm, filename, input)), ann }
+        State { s: pp::mk_printer(), comments: Some(Comments::new(sm, filename, input)), ann }
     }
 }
 
diff --git a/src/librustc_infer/infer/error_reporting/mod.rs b/src/librustc_infer/infer/error_reporting/mod.rs
index 359b417b3bf..008658dff42 100644
--- a/src/librustc_infer/infer/error_reporting/mod.rs
+++ b/src/librustc_infer/infer/error_reporting/mod.rs
@@ -194,7 +194,7 @@ fn msg_span_from_early_bound_and_free_regions(
     tcx: TyCtxt<'tcx>,
     region: ty::Region<'tcx>,
 ) -> (String, Option<Span>) {
-    let cm = tcx.sess.source_map();
+    let sm = tcx.sess.source_map();
 
     let scope = region.free_region_binding_scope(tcx);
     let node = tcx.hir().as_local_hir_id(scope).unwrap_or(hir::DUMMY_HIR_ID);
@@ -207,7 +207,7 @@ fn msg_span_from_early_bound_and_free_regions(
     };
     let (prefix, span) = match *region {
         ty::ReEarlyBound(ref br) => {
-            let mut sp = cm.def_span(tcx.hir().span(node));
+            let mut sp = sm.def_span(tcx.hir().span(node));
             if let Some(param) =
                 tcx.hir().get_generics(scope).and_then(|generics| generics.get_named(br.name))
             {
@@ -216,7 +216,7 @@ fn msg_span_from_early_bound_and_free_regions(
             (format!("the lifetime `{}` as defined on", br.name), sp)
         }
         ty::ReFree(ty::FreeRegion { bound_region: ty::BoundRegion::BrNamed(_, name), .. }) => {
-            let mut sp = cm.def_span(tcx.hir().span(node));
+            let mut sp = sm.def_span(tcx.hir().span(node));
             if let Some(param) =
                 tcx.hir().get_generics(scope).and_then(|generics| generics.get_named(name))
             {
@@ -230,7 +230,7 @@ fn msg_span_from_early_bound_and_free_regions(
             }
             _ => (
                 format!("the lifetime `{}` as defined on", region),
-                cm.def_span(tcx.hir().span(node)),
+                sm.def_span(tcx.hir().span(node)),
             ),
         },
         _ => bug!(),
diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs
index 97daa91eed1..3ae97ed5f88 100644
--- a/src/librustc_parse/parser/expr.rs
+++ b/src/librustc_parse/parser/expr.rs
@@ -1625,10 +1625,10 @@ impl<'a> Parser<'a> {
         let hi = self.token.span;
 
         if require_comma {
-            let cm = self.sess.source_map();
+            let sm = self.sess.source_map();
             self.expect_one_of(&[token::Comma], &[token::CloseDelim(token::Brace)]).map_err(
                 |mut err| {
-                    match (cm.span_to_lines(expr.span), cm.span_to_lines(arm_start_span)) {
+                    match (sm.span_to_lines(expr.span), sm.span_to_lines(arm_start_span)) {
                         (Ok(ref expr_lines), Ok(ref arm_start_lines))
                             if arm_start_lines.lines[0].end_col == expr_lines.lines[0].end_col
                                 && expr_lines.lines.len() == 2
diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs
index 4dcde2f92db..328cf11c532 100644
--- a/src/librustc_parse/parser/item.rs
+++ b/src/librustc_parse/parser/item.rs
@@ -156,8 +156,7 @@ impl<'a> Parser<'a> {
             self.parse_item_mod(attrs)?
         } else if self.eat_keyword(kw::Type) {
             // TYPE ITEM
-            let (ident, ty, generics) = self.parse_type_alias()?;
-            (ident, ItemKind::TyAlias(ty, generics))
+            self.parse_type_alias()?
         } else if self.eat_keyword(kw::Enum) {
             // ENUM ITEM
             self.parse_item_enum()?
@@ -676,7 +675,10 @@ impl<'a> Parser<'a> {
         vis: &Visibility,
     ) -> PResult<'a, (Ident, AssocItemKind)> {
         if self.eat_keyword(kw::Type) {
-            self.parse_assoc_ty()
+            match self.parse_type_alias()? {
+                (ident, ItemKind::TyAlias(a, b, c)) => Ok((ident, AssocItemKind::TyAlias(a, b, c))),
+                _ => unreachable!(),
+            }
         } else if self.check_fn_front_matter() {
             let (ident, sig, generics, body) = self.parse_fn(at_end, attrs, req_name)?;
             Ok((ident, AssocItemKind::Fn(sig, generics, body)))
@@ -700,10 +702,12 @@ impl<'a> Parser<'a> {
         }
     }
 
-    /// Parses the following grammar:
-    ///
-    ///     AssocTy = Ident ["<"...">"] [":" [GenericBounds]] ["where" ...] ["=" Ty]
-    fn parse_assoc_ty(&mut self) -> PResult<'a, (Ident, AssocItemKind)> {
+    /// Parses a `type` alias with the following grammar:
+    /// ```
+    /// TypeAlias = "type" Ident Generics {":" GenericBounds}? {"=" Ty}? ";" ;
+    /// ```
+    /// The `"type"` has already been eaten.
+    fn parse_type_alias(&mut self) -> PResult<'a, (Ident, ItemKind)> {
         let ident = self.parse_ident()?;
         let mut generics = self.parse_generics()?;
 
@@ -715,7 +719,7 @@ impl<'a> Parser<'a> {
         let default = if self.eat(&token::Eq) { Some(self.parse_ty()?) } else { None };
         self.expect_semi()?;
 
-        Ok((ident, AssocItemKind::TyAlias(generics, bounds, default)))
+        Ok((ident, ItemKind::TyAlias(generics, bounds, default)))
     }
 
     /// Parses a `UseTree`.
@@ -989,18 +993,6 @@ impl<'a> Parser<'a> {
         P(Ty { kind: TyKind::Infer, span: id.span, id: ast::DUMMY_NODE_ID })
     }
 
-    /// Parses the grammar:
-    ///     Ident ["<"...">"] ["where" ...] ("=" | ":") Ty ";"
-    fn parse_type_alias(&mut self) -> PResult<'a, (Ident, P<Ty>, Generics)> {
-        let ident = self.parse_ident()?;
-        let mut tps = self.parse_generics()?;
-        tps.where_clause = self.parse_where_clause()?;
-        self.expect(&token::Eq)?;
-        let ty = self.parse_ty()?;
-        self.expect_semi()?;
-        Ok((ident, ty, tps))
-    }
-
     /// Parses an enum declaration.
     fn parse_item_enum(&mut self) -> PResult<'a, ItemInfo> {
         let id = self.parse_ident()?;
diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs
index 937e5e3cd69..75d4b3750f1 100644
--- a/src/librustc_parse/parser/mod.rs
+++ b/src/librustc_parse/parser/mod.rs
@@ -601,141 +601,76 @@ impl<'a> Parser<'a> {
         )
     }
 
-    /// Expects and consumes a `+`. if `+=` is seen, replaces it with a `=`
-    /// and continues. If a `+` is not seen, returns `false`.
-    ///
-    /// This is used when token-splitting `+=` into `+`.
-    /// See issue #47856 for an example of when this may occur.
-    fn eat_plus(&mut self) -> bool {
-        self.expected_tokens.push(TokenType::Token(token::BinOp(token::Plus)));
-        match self.token.kind {
-            token::BinOp(token::Plus) => {
-                self.bump();
+    /// Eats the expected token if it's present possibly breaking
+    /// compound tokens like multi-character operators in process.
+    /// Returns `true` if the token was eaten.
+    fn break_and_eat(&mut self, expected: TokenKind) -> bool {
+        if self.token.kind == expected {
+            self.bump();
+            return true;
+        }
+        match self.token.kind.break_two_token_op() {
+            Some((first, second)) if first == expected => {
+                let first_span = self.sess.source_map().start_point(self.token.span);
+                let second_span = self.token.span.with_lo(first_span.hi());
+                self.set_token(Token::new(first, first_span));
+                self.bump_with(Token::new(second, second_span));
                 true
             }
-            token::BinOpEq(token::Plus) => {
-                let start_point = self.sess.source_map().start_point(self.token.span);
-                self.bump_with(token::Eq, self.token.span.with_lo(start_point.hi()));
-                true
+            _ => {
+                self.expected_tokens.push(TokenType::Token(expected));
+                false
             }
-            _ => false,
         }
     }
 
-    /// Expects and consumes an `&`. If `&&` is seen, replaces it with a single
-    /// `&` and continues. If an `&` is not seen, signals an error.
+    /// Eats `+` possibly breaking tokens like `+=` in process.
+    fn eat_plus(&mut self) -> bool {
+        self.break_and_eat(token::BinOp(token::Plus))
+    }
+
+    /// Eats `&` possibly breaking tokens like `&&` in process.
+    /// Signals an error if `&` is not eaten.
     fn expect_and(&mut self) -> PResult<'a, ()> {
-        self.expected_tokens.push(TokenType::Token(token::BinOp(token::And)));
-        match self.token.kind {
-            token::BinOp(token::And) => {
-                self.bump();
-                Ok(())
-            }
-            token::AndAnd => {
-                let start_point = self.sess.source_map().start_point(self.token.span);
-                Ok(self
-                    .bump_with(token::BinOp(token::And), self.token.span.with_lo(start_point.hi())))
-            }
-            _ => self.unexpected(),
-        }
+        if self.break_and_eat(token::BinOp(token::And)) { Ok(()) } else { self.unexpected() }
     }
 
-    /// Expects and consumes an `|`. If `||` is seen, replaces it with a single
-    /// `|` and continues. If an `|` is not seen, signals an error.
+    /// Eats `|` possibly breaking tokens like `||` in process.
+    /// Signals an error if `|` was not eaten.
     fn expect_or(&mut self) -> PResult<'a, ()> {
-        self.expected_tokens.push(TokenType::Token(token::BinOp(token::Or)));
-        match self.token.kind {
-            token::BinOp(token::Or) => {
-                self.bump();
-                Ok(())
-            }
-            token::OrOr => {
-                let start_point = self.sess.source_map().start_point(self.token.span);
-                Ok(self
-                    .bump_with(token::BinOp(token::Or), self.token.span.with_lo(start_point.hi())))
-            }
-            _ => self.unexpected(),
-        }
+        if self.break_and_eat(token::BinOp(token::Or)) { Ok(()) } else { self.unexpected() }
     }
 
-    /// Attempts to consume a `<`. If `<<` is seen, replaces it with a single
-    /// `<` and continue. If `<-` is seen, replaces it with a single `<`
-    /// and continue. If a `<` is not seen, returns false.
-    ///
-    /// This is meant to be used when parsing generics on a path to get the
-    /// starting token.
+    /// Eats `<` possibly breaking tokens like `<<` in process.
     fn eat_lt(&mut self) -> bool {
-        self.expected_tokens.push(TokenType::Token(token::Lt));
-        let ate = match self.token.kind {
-            token::Lt => {
-                self.bump();
-                true
-            }
-            token::BinOp(token::Shl) => {
-                let start_point = self.sess.source_map().start_point(self.token.span);
-                self.bump_with(token::Lt, self.token.span.with_lo(start_point.hi()));
-                true
-            }
-            token::LArrow => {
-                let start_point = self.sess.source_map().start_point(self.token.span);
-                self.bump_with(
-                    token::BinOp(token::Minus),
-                    self.token.span.with_lo(start_point.hi()),
-                );
-                true
-            }
-            _ => false,
-        };
-
+        let ate = self.break_and_eat(token::Lt);
         if ate {
             // See doc comment for `unmatched_angle_bracket_count`.
             self.unmatched_angle_bracket_count += 1;
             self.max_angle_bracket_count += 1;
             debug!("eat_lt: (increment) count={:?}", self.unmatched_angle_bracket_count);
         }
-
         ate
     }
 
+    /// Eats `<` possibly breaking tokens like `<<` in process.
+    /// Signals an error if `<` was not eaten.
     fn expect_lt(&mut self) -> PResult<'a, ()> {
-        if !self.eat_lt() { self.unexpected() } else { Ok(()) }
+        if self.eat_lt() { Ok(()) } else { self.unexpected() }
     }
 
-    /// Expects and consumes a single `>` token. if a `>>` is seen, replaces it
-    /// with a single `>` and continues. If a `>` is not seen, signals an error.
+    /// Eats `>` possibly breaking tokens like `>>` in process.
+    /// Signals an error if `>` was not eaten.
     fn expect_gt(&mut self) -> PResult<'a, ()> {
-        self.expected_tokens.push(TokenType::Token(token::Gt));
-        let ate = match self.token.kind {
-            token::Gt => {
-                self.bump();
-                Some(())
-            }
-            token::BinOp(token::Shr) => {
-                let start_point = self.sess.source_map().start_point(self.token.span);
-                Some(self.bump_with(token::Gt, self.token.span.with_lo(start_point.hi())))
-            }
-            token::BinOpEq(token::Shr) => {
-                let start_point = self.sess.source_map().start_point(self.token.span);
-                Some(self.bump_with(token::Ge, self.token.span.with_lo(start_point.hi())))
-            }
-            token::Ge => {
-                let start_point = self.sess.source_map().start_point(self.token.span);
-                Some(self.bump_with(token::Eq, self.token.span.with_lo(start_point.hi())))
-            }
-            _ => None,
-        };
-
-        match ate {
-            Some(_) => {
-                // See doc comment for `unmatched_angle_bracket_count`.
-                if self.unmatched_angle_bracket_count > 0 {
-                    self.unmatched_angle_bracket_count -= 1;
-                    debug!("expect_gt: (decrement) count={:?}", self.unmatched_angle_bracket_count);
-                }
-
-                Ok(())
+        if self.break_and_eat(token::Gt) {
+            // See doc comment for `unmatched_angle_bracket_count`.
+            if self.unmatched_angle_bracket_count > 0 {
+                self.unmatched_angle_bracket_count -= 1;
+                debug!("expect_gt: (decrement) count={:?}", self.unmatched_angle_bracket_count);
             }
-            None => self.unexpected(),
+            Ok(())
+        } else {
+            self.unexpected()
         }
     }
 
@@ -903,10 +838,10 @@ impl<'a> Parser<'a> {
         }
     }
 
-    /// Advance the parser by one token.
-    pub fn bump(&mut self) {
+    /// Advance the parser by one token using provided token as the next one.
+    fn bump_with(&mut self, next_token: Token) {
+        // Bumping after EOF is a bad sign, usually an infinite loop.
         if self.prev_token.kind == TokenKind::Eof {
-            // Bumping after EOF is a bad sign, usually an infinite loop.
             let msg = "attempted to bump the parser past EOF (may be stuck in a loop)";
             self.span_bug(self.token.span, msg);
         }
@@ -914,30 +849,19 @@ impl<'a> Parser<'a> {
         // Update the current and previous tokens.
         self.prev_token = self.token.take();
         self.unnormalized_prev_token = self.unnormalized_token.take();
-        let next_token = self.next_tok(self.unnormalized_prev_token.span);
         self.set_token(next_token);
 
         // Update fields derived from the previous token.
         self.prev_span = self.unnormalized_prev_token.span;
 
+        // Diagnostics.
         self.expected_tokens.clear();
     }
 
-    /// Advances the parser using provided token as a next one. Use this when
-    /// consuming a part of a token. For example a single `<` from `<<`.
-    /// FIXME: this function sets the previous token data to some semi-nonsensical values
-    /// which kind of work because they are currently used in very limited ways in practice.
-    /// Correct token kinds and spans need to be calculated instead.
-    fn bump_with(&mut self, next: TokenKind, span: Span) {
-        // Update the current and previous tokens.
-        self.prev_token = self.token.take();
-        self.unnormalized_prev_token = self.unnormalized_token.take();
-        self.set_token(Token::new(next, span));
-
-        // Update fields derived from the previous token.
-        self.prev_span = self.unnormalized_prev_token.span.with_hi(span.lo());
-
-        self.expected_tokens.clear();
+    /// Advance the parser by one token.
+    pub fn bump(&mut self) {
+        let next_token = self.next_tok(self.unnormalized_token.span);
+        self.bump_with(next_token);
     }
 
     /// Look-ahead `dist` tokens of `self.token` and get access to that token there.
diff --git a/src/librustc_passes/liveness.rs b/src/librustc_passes/liveness.rs
index 709068d2189..f0bb3cd08ad 100644
--- a/src/librustc_passes/liveness.rs
+++ b/src/librustc_passes/liveness.rs
@@ -144,11 +144,11 @@ enum LiveNodeKind {
 }
 
 fn live_node_kind_to_string(lnk: LiveNodeKind, tcx: TyCtxt<'_>) -> String {
-    let cm = tcx.sess.source_map();
+    let sm = tcx.sess.source_map();
     match lnk {
-        UpvarNode(s) => format!("Upvar node [{}]", cm.span_to_string(s)),
-        ExprNode(s) => format!("Expr node [{}]", cm.span_to_string(s)),
-        VarDefNode(s) => format!("Var def node [{}]", cm.span_to_string(s)),
+        UpvarNode(s) => format!("Upvar node [{}]", sm.span_to_string(s)),
+        ExprNode(s) => format!("Expr node [{}]", sm.span_to_string(s)),
+        VarDefNode(s) => format!("Var def node [{}]", sm.span_to_string(s)),
         ExitNode => "Exit node".to_owned(),
     }
 }
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 1f622b80e8e..383bfe18fd0 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -718,8 +718,8 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
             }
 
             // These items live in the type namespace.
-            ItemKind::TyAlias(ref ty, _) => {
-                let def_kind = match ty.kind.opaque_top_hack() {
+            ItemKind::TyAlias(_, _, ref ty) => {
+                let def_kind = match ty.as_deref().and_then(|ty| ty.kind.opaque_top_hack()) {
                     None => DefKind::TyAlias,
                     Some(_) => DefKind::OpaqueTy,
                 };
diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs
index 075dca8f01d..7c48ccfaddd 100644
--- a/src/librustc_resolve/diagnostics.rs
+++ b/src/librustc_resolve/diagnostics.rs
@@ -90,9 +90,9 @@ impl<'tcx> Into<MissingLifetimeSpot<'tcx>> for &'tcx hir::Generics<'tcx> {
 /// *Attention*: the method used is very fragile since it essentially duplicates the work of the
 /// parser. If you need to use this function or something similar, please consider updating the
 /// `source_map` functions and this function to something more robust.
-fn reduce_impl_span_to_impl_keyword(cm: &SourceMap, impl_span: Span) -> Span {
-    let impl_span = cm.span_until_char(impl_span, '<');
-    let impl_span = cm.span_until_whitespace(impl_span);
+fn reduce_impl_span_to_impl_keyword(sm: &SourceMap, impl_span: Span) -> Span {
+    let impl_span = sm.span_until_char(impl_span, '<');
+    let impl_span = sm.span_until_whitespace(impl_span);
     impl_span
 }
 
@@ -136,14 +136,14 @@ impl<'a> Resolver<'a> {
                 );
                 err.span_label(span, format!("use of generic parameter from outer function"));
 
-                let cm = self.session.source_map();
+                let sm = self.session.source_map();
                 match outer_res {
                     Res::SelfTy(maybe_trait_defid, maybe_impl_defid) => {
                         if let Some(impl_span) =
                             maybe_impl_defid.and_then(|def_id| self.definitions.opt_span(def_id))
                         {
                             err.span_label(
-                                reduce_impl_span_to_impl_keyword(cm, impl_span),
+                                reduce_impl_span_to_impl_keyword(sm, impl_span),
                                 "`Self` type implicitly declared here, by this `impl`",
                             );
                         }
@@ -180,7 +180,7 @@ impl<'a> Resolver<'a> {
                     // Try to retrieve the span of the function signature and generate a new
                     // message with a local type or const parameter.
                     let sugg_msg = &format!("try using a local generic parameter instead");
-                    if let Some((sugg_span, snippet)) = cm.generate_local_type_param_snippet(span) {
+                    if let Some((sugg_span, snippet)) = sm.generate_local_type_param_snippet(span) {
                         // Suggest the modification to the user
                         err.span_suggestion(
                             sugg_span,
@@ -188,7 +188,7 @@ impl<'a> Resolver<'a> {
                             snippet,
                             Applicability::MachineApplicable,
                         );
-                    } else if let Some(sp) = cm.generate_fn_name_span(span) {
+                    } else if let Some(sp) = sm.generate_fn_name_span(span) {
                         err.span_label(
                             sp,
                             format!("try adding a local generic parameter in this method instead"),
diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs
index 73601cd2ee7..74628e6e5a0 100644
--- a/src/librustc_resolve/late.rs
+++ b/src/librustc_resolve/late.rs
@@ -797,7 +797,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
         debug!("(resolving item) resolving {} ({:?})", name, item.kind);
 
         match item.kind {
-            ItemKind::TyAlias(_, ref generics) | ItemKind::Fn(_, ref generics, _) => {
+            ItemKind::TyAlias(ref generics, _, _) | ItemKind::Fn(_, ref generics, _) => {
                 self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| {
                     visit::walk_item(this, item)
                 });
diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs
index 6ec4a13500e..6a6fba8270b 100644
--- a/src/librustc_resolve/late/diagnostics.rs
+++ b/src/librustc_resolve/late/diagnostics.rs
@@ -725,21 +725,21 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
 
     /// Only used in a specific case of type ascription suggestions
     fn get_colon_suggestion_span(&self, start: Span) -> Span {
-        let cm = self.r.session.source_map();
-        start.to(cm.next_point(start))
+        let sm = self.r.session.source_map();
+        start.to(sm.next_point(start))
     }
 
     fn type_ascription_suggestion(&self, err: &mut DiagnosticBuilder<'_>, base_span: Span) {
-        let cm = self.r.session.source_map();
-        let base_snippet = cm.span_to_snippet(base_span);
+        let sm = self.r.session.source_map();
+        let base_snippet = sm.span_to_snippet(base_span);
         if let Some(sp) = self.diagnostic_metadata.current_type_ascription.last() {
             let mut sp = *sp;
             loop {
                 // Try to find the `:`; bail on first non-':' / non-whitespace.
-                sp = cm.next_point(sp);
-                if let Ok(snippet) = cm.span_to_snippet(sp.to(cm.next_point(sp))) {
-                    let line_sp = cm.lookup_char_pos(sp.hi()).line;
-                    let line_base_sp = cm.lookup_char_pos(base_span.lo()).line;
+                sp = sm.next_point(sp);
+                if let Ok(snippet) = sm.span_to_snippet(sp.to(sm.next_point(sp))) {
+                    let line_sp = sm.lookup_char_pos(sp.hi()).line;
+                    let line_base_sp = sm.lookup_char_pos(base_span.lo()).line;
                     if snippet == ":" {
                         let mut show_label = true;
                         if line_sp != line_base_sp {
@@ -753,7 +753,7 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
                             let colon_sp = self.get_colon_suggestion_span(sp);
                             let after_colon_sp =
                                 self.get_colon_suggestion_span(colon_sp.shrink_to_hi());
-                            if !cm
+                            if !sm
                                 .span_to_snippet(after_colon_sp)
                                 .map(|s| s == " ")
                                 .unwrap_or(false)
@@ -770,8 +770,8 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
                                 let mut sp = after_colon_sp;
                                 for _ in 0..100 {
                                     // Try to find an assignment
-                                    sp = cm.next_point(sp);
-                                    let snippet = cm.span_to_snippet(sp.to(cm.next_point(sp)));
+                                    sp = sm.next_point(sp);
+                                    let snippet = sm.span_to_snippet(sp.to(sm.next_point(sp)));
                                     match snippet {
                                         Ok(ref x) if x.as_str() == "=" => {
                                             err.span_suggestion(
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index db7733e7241..442f3b695a2 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -1233,8 +1233,8 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> {
         let qualname =
             format!("::{}", self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(id)));
 
-        let cm = self.tcx.sess.source_map();
-        let filename = cm.span_to_filename(span);
+        let sm = self.tcx.sess.source_map();
+        let filename = sm.span_to_filename(span);
         let data_id = id_from_node_id(id, &self.save_ctxt);
         let children = m.items.iter().map(|i| id_from_node_id(i.id, &self.save_ctxt)).collect();
         let span = self.span_from_span(span);
@@ -1311,12 +1311,15 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> {
                 self.process_mod(item);
                 visit::walk_mod(self, m);
             }
-            TyAlias(ref ty, ref ty_params) => {
+            TyAlias(ref ty_params, _, ref ty) => {
                 let qualname = format!(
                     "::{}",
                     self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(item.id))
                 );
-                let value = ty_to_string(&ty);
+                let value = match ty {
+                    Some(ty) => ty_to_string(&ty),
+                    None => "_".to_string(),
+                };
                 if !self.span.filter_generated(item.ident.span) {
                     let span = self.span_from_span(item.ident.span);
                     let id = id_from_node_id(item.id, &self.save_ctxt);
@@ -1341,7 +1344,7 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> {
                     );
                 }
 
-                self.visit_ty(&ty);
+                walk_list!(self, visit_ty, ty);
                 self.process_generic_params(ty_params, &qualname, item.id);
             }
             Mac(_) => (),
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index 6e7ecf92441..43a0cfecd3e 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -66,9 +66,9 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
     fn span_from_span(&self, span: Span) -> SpanData {
         use rls_span::{Column, Row};
 
-        let cm = self.tcx.sess.source_map();
-        let start = cm.lookup_char_pos(span.lo());
-        let end = cm.lookup_char_pos(span.hi());
+        let sm = self.tcx.sess.source_map();
+        let start = sm.lookup_char_pos(span.lo());
+        let end = sm.lookup_char_pos(span.hi());
 
         SpanData {
             file_name: start.file.name.to_string().into(),
@@ -258,8 +258,8 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
                     self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(item.id))
                 );
 
-                let cm = self.tcx.sess.source_map();
-                let filename = cm.span_to_filename(m.inner);
+                let sm = self.tcx.sess.source_map();
+                let filename = sm.span_to_filename(m.inner);
 
                 filter!(self.span_utils, item.ident.span);
 
diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs
index a2c61db4b7c..2c07ed0571b 100644
--- a/src/librustc_save_analysis/sig.rs
+++ b/src/librustc_save_analysis/sig.rs
@@ -423,12 +423,15 @@ impl Sig for ast::Item {
 
                 Ok(Signature { text, defs, refs: vec![] })
             }
-            ast::ItemKind::TyAlias(ref ty, ref generics) => {
+            ast::ItemKind::TyAlias(ref generics, _, ref ty) => {
                 let text = "type ".to_owned();
                 let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?;
 
                 sig.text.push_str(" = ");
-                let ty = ty.make(offset + sig.text.len(), id, scx)?;
+                let ty = match ty {
+                    Some(ty) => ty.make(offset + sig.text.len(), id, scx)?,
+                    None => Err("Ty")?,
+                };
                 sig.text.push_str(&ty.text);
                 sig.text.push(';');
 
diff --git a/src/librustc_session/parse.rs b/src/librustc_session/parse.rs
index 30888e343ed..6d4f4be03ec 100644
--- a/src/librustc_session/parse.rs
+++ b/src/librustc_session/parse.rs
@@ -124,9 +124,9 @@ pub struct ParseSess {
 
 impl ParseSess {
     pub fn new(file_path_mapping: FilePathMapping) -> Self {
-        let cm = Lrc::new(SourceMap::new(file_path_mapping));
-        let handler = Handler::with_tty_emitter(ColorConfig::Auto, true, None, Some(cm.clone()));
-        ParseSess::with_span_handler(handler, cm)
+        let sm = Lrc::new(SourceMap::new(file_path_mapping));
+        let handler = Handler::with_tty_emitter(ColorConfig::Auto, true, None, Some(sm.clone()));
+        ParseSess::with_span_handler(handler, sm)
     }
 
     pub fn with_span_handler(handler: Handler, source_map: Lrc<SourceMap>) -> Self {
@@ -148,9 +148,9 @@ impl ParseSess {
     }
 
     pub fn with_silent_emitter() -> Self {
-        let cm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
+        let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
         let handler = Handler::with_emitter(false, None, Box::new(SilentEmitter));
-        ParseSess::with_span_handler(handler, cm)
+        ParseSess::with_span_handler(handler, sm)
     }
 
     #[inline]
diff --git a/src/librustc_span/caching_source_map_view.rs b/src/librustc_span/caching_source_map_view.rs
index c329f2225b0..d6725160a5d 100644
--- a/src/librustc_span/caching_source_map_view.rs
+++ b/src/librustc_span/caching_source_map_view.rs
@@ -13,14 +13,14 @@ struct CacheEntry {
 }
 
 #[derive(Clone)]
-pub struct CachingSourceMapView<'cm> {
-    source_map: &'cm SourceMap,
+pub struct CachingSourceMapView<'sm> {
+    source_map: &'sm SourceMap,
     line_cache: [CacheEntry; 3],
     time_stamp: usize,
 }
 
-impl<'cm> CachingSourceMapView<'cm> {
-    pub fn new(source_map: &'cm SourceMap) -> CachingSourceMapView<'cm> {
+impl<'sm> CachingSourceMapView<'sm> {
+    pub fn new(source_map: &'sm SourceMap) -> CachingSourceMapView<'sm> {
         let files = source_map.files();
         let first_file = files[0].clone();
         let entry = CacheEntry {
diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs
index 63ebf612964..c289176c303 100644
--- a/src/librustc_typeck/check/demand.rs
+++ b/src/librustc_typeck/check/demand.rs
@@ -324,13 +324,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         hir_id: hir::HirId,
         sp: Span,
     ) -> bool {
-        let cm = self.sess().source_map();
+        let sm = self.sess().source_map();
         let parent_id = self.tcx.hir().get_parent_node(hir_id);
         if let Some(parent) = self.tcx.hir().find(parent_id) {
             // Account for fields
             if let Node::Expr(hir::Expr { kind: hir::ExprKind::Struct(_, fields, ..), .. }) = parent
             {
-                if let Ok(src) = cm.span_to_snippet(sp) {
+                if let Ok(src) = sm.span_to_snippet(sp) {
                     for field in *fields {
                         if field.ident.as_str() == src && field.is_shorthand {
                             return true;
@@ -364,9 +364,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         checked_ty: Ty<'tcx>,
         expected: Ty<'tcx>,
     ) -> Option<(Span, &'static str, String)> {
-        let cm = self.sess().source_map();
+        let sm = self.sess().source_map();
         let sp = expr.span;
-        if !cm.span_to_filename(sp).is_real() {
+        if !sm.span_to_filename(sp).is_real() {
             // Ignore if span is from within a macro #41858, #58298. We previously used the macro
             // call span, but that breaks down when the type error comes from multiple calls down.
             return None;
@@ -388,7 +388,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     if arr == self.tcx.types.u8 =>
                 {
                     if let hir::ExprKind::Lit(_) = expr.kind {
-                        if let Ok(src) = cm.span_to_snippet(sp) {
+                        if let Ok(src) = sm.span_to_snippet(sp) {
                             if src.starts_with("b\"") {
                                 return Some((
                                     sp,
@@ -403,7 +403,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     if arr == self.tcx.types.u8 =>
                 {
                     if let hir::ExprKind::Lit(_) = expr.kind {
-                        if let Ok(src) = cm.span_to_snippet(sp) {
+                        if let Ok(src) = sm.span_to_snippet(sp) {
                             if src.starts_with("\"") {
                                 return Some((
                                     sp,
@@ -450,7 +450,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             sugg_sp = arg.span;
                         }
                     }
-                    if let Ok(src) = cm.span_to_snippet(sugg_sp) {
+                    if let Ok(src) = sm.span_to_snippet(sugg_sp) {
                         let needs_parens = match expr.kind {
                             // parenthesize if needed (Issue #46756)
                             hir::ExprKind::Cast(_, _) | hir::ExprKind::Binary(_, _, _) => true,
@@ -480,7 +480,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                 //                                   |     |
                                 //    consider dereferencing here: `*opt`  |
                                 // expected mutable reference, found enum `Option`
-                                if let Ok(src) = cm.span_to_snippet(left_expr.span) {
+                                if let Ok(src) = sm.span_to_snippet(left_expr.span) {
                                     return Some((
                                         left_expr.span,
                                         "consider dereferencing here to assign to the mutable \
@@ -516,8 +516,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             {
                 // We have `&T`, check if what was expected was `T`. If so,
                 // we may want to suggest removing a `&`.
-                if !cm.span_to_filename(expr.span).is_real() {
-                    if let Ok(code) = cm.span_to_snippet(sp) {
+                if !sm.span_to_filename(expr.span).is_real() {
+                    if let Ok(code) = sm.span_to_snippet(sp) {
                         if code.chars().next() == Some('&') {
                             return Some((
                                 sp,
@@ -528,7 +528,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     }
                     return None;
                 }
-                if let Ok(code) = cm.span_to_snippet(expr.span) {
+                if let Ok(code) = sm.span_to_snippet(expr.span) {
                     return Some((sp, "consider removing the borrow", code));
                 }
             }
@@ -562,7 +562,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 let is_copy = self.infcx.type_is_copy_modulo_regions(self.param_env, expected, sp);
 
                 if is_copy && impls_deref {
-                    if let Ok(code) = cm.span_to_snippet(sp) {
+                    if let Ok(code) = sm.span_to_snippet(sp) {
                         let message = if checked_ty.is_region_ptr() {
                             "consider dereferencing the borrow"
                         } else {
diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs
index 6ce0da666a7..a8e5a0ddf26 100644
--- a/src/librustc_typeck/coherence/orphan.rs
+++ b/src/librustc_typeck/coherence/orphan.rs
@@ -33,8 +33,8 @@ impl ItemLikeVisitor<'v> for OrphanChecker<'tcx> {
             );
             let trait_ref = self.tcx.impl_trait_ref(def_id).unwrap();
             let trait_def_id = trait_ref.def_id;
-            let cm = self.tcx.sess.source_map();
-            let sp = cm.def_span(item.span);
+            let sm = self.tcx.sess.source_map();
+            let sp = sm.def_span(item.span);
             match traits::orphan_check(self.tcx, def_id) {
                 Ok(()) => {}
                 Err(traits::OrphanCheckErr::NonLocalInputType(tys)) => {
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index af81087b53e..50c780e9ecb 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -263,9 +263,9 @@ impl Clean<Item> for doctree::Module<'_> {
         // determine if we should display the inner contents or
         // the outer `mod` item for the source code.
         let whence = {
-            let cm = cx.sess().source_map();
-            let outer = cm.lookup_char_pos(self.where_outer.lo());
-            let inner = cm.lookup_char_pos(self.where_inner.lo());
+            let sm = cx.sess().source_map();
+            let outer = sm.lookup_char_pos(self.where_outer.lo());
+            let inner = sm.lookup_char_pos(self.where_inner.lo());
             if outer.file.start_pos == inner.file.start_pos {
                 // mod foo { ... }
                 self.where_outer
@@ -1917,10 +1917,10 @@ impl Clean<Span> for rustc_span::Span {
             return Span::empty();
         }
 
-        let cm = cx.sess().source_map();
-        let filename = cm.span_to_filename(*self);
-        let lo = cm.lookup_char_pos(self.lo());
-        let hi = cm.lookup_char_pos(self.hi());
+        let sm = cx.sess().source_map();
+        let filename = sm.span_to_filename(*self);
+        let lo = sm.lookup_char_pos(self.lo());
+        let hi = sm.lookup_char_pos(self.hi());
         Span {
             filename,
             loline: lo.line,
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index c3c07e2e02c..8c4e65765d3 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -177,7 +177,7 @@ pub fn new_handler(
             Box::new(
                 EmitterWriter::stderr(
                     color_config,
-                    source_map.map(|cm| cm as _),
+                    source_map.map(|sm| sm as _),
                     short,
                     debugging_opts.teach,
                     debugging_opts.terminal_width,
diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs
index 1ea053605ec..849c5c3e072 100644
--- a/src/librustdoc/html/highlight.rs
+++ b/src/librustdoc/html/highlight.rs
@@ -38,11 +38,11 @@ pub fn render_with_highlighting(
     }
 
     let sess = ParseSess::with_silent_emitter();
-    let fm = sess
+    let sf = sess
         .source_map()
         .new_source_file(FileName::Custom(String::from("rustdoc-highlighting")), src.to_owned());
     let highlight_result = rustc_driver::catch_fatal_errors(|| {
-        let lexer = lexer::StringReader::new(&sess, fm, None);
+        let lexer = lexer::StringReader::new(&sess, sf, None);
         let mut classifier = Classifier::new(lexer, sess.source_map());
 
         let mut highlighted_source = vec![];
diff --git a/src/librustdoc/passes/check_code_block_syntax.rs b/src/librustdoc/passes/check_code_block_syntax.rs
index 3b7c0db05a5..a6dad3c3920 100644
--- a/src/librustdoc/passes/check_code_block_syntax.rs
+++ b/src/librustdoc/passes/check_code_block_syntax.rs
@@ -32,9 +32,9 @@ impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> {
 
         let emitter = BufferEmitter { messages: Lrc::clone(&buffered_messages) };
 
-        let cm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
+        let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
         let handler = Handler::with_emitter(false, None, Box::new(emitter));
-        let sess = ParseSess::with_span_handler(handler, cm);
+        let sess = ParseSess::with_span_handler(handler, sm);
         let source_file = sess.source_map().new_source_file(
             FileName::Custom(String::from("doctest")),
             dox[code_block.code].to_owned(),
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index 0c7dfa1417a..5dd7bd82755 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -402,12 +402,12 @@ pub fn make_test(
 
             // Any errors in parsing should also appear when the doctest is compiled for real, so just
             // send all the errors that libsyntax emits directly into a `Sink` instead of stderr.
-            let cm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
+            let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
             let emitter =
                 EmitterWriter::new(box io::sink(), None, false, false, false, None, false);
             // FIXME(misdreavus): pass `-Z treat-err-as-bug` to the doctest parser
             let handler = Handler::with_emitter(false, None, box emitter);
-            let sess = ParseSess::with_span_handler(handler, cm);
+            let sess = ParseSess::with_span_handler(handler, sm);
 
             let mut found_main = false;
             let mut found_extern_crate = cratename.is_none();
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 9ae3010a0f6..849950e939a 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -2524,7 +2524,7 @@ pub enum ItemKind {
     /// A type alias (`type`).
     ///
     /// E.g., `type Foo = Bar<u8>;`.
-    TyAlias(P<Ty>, Generics),
+    TyAlias(Generics, GenericBounds, Option<P<Ty>>),
     /// An enum definition (`enum`).
     ///
     /// E.g., `enum Foo<A, B> { C<A>, D<B> }`.
@@ -2594,7 +2594,7 @@ impl ItemKind {
     pub fn generics(&self) -> Option<&Generics> {
         match self {
             Self::Fn(_, generics, _)
-            | Self::TyAlias(_, generics)
+            | Self::TyAlias(generics, ..)
             | Self::Enum(_, generics)
             | Self::Struct(_, generics)
             | Self::Union(_, generics)
diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs
index 92f20b719f8..02f790dfbb4 100644
--- a/src/libsyntax/mut_visit.rs
+++ b/src/libsyntax/mut_visit.rs
@@ -902,9 +902,10 @@ pub fn noop_visit_item_kind<T: MutVisitor>(kind: &mut ItemKind, vis: &mut T) {
         ItemKind::Mod(m) => vis.visit_mod(m),
         ItemKind::ForeignMod(nm) => vis.visit_foreign_mod(nm),
         ItemKind::GlobalAsm(_ga) => {}
-        ItemKind::TyAlias(ty, generics) => {
-            vis.visit_ty(ty);
+        ItemKind::TyAlias(generics, bounds, ty) => {
             vis.visit_generics(generics);
+            visit_bounds(bounds, vis);
+            visit_opt(ty, |ty| vis.visit_ty(ty));
         }
         ItemKind::Enum(EnumDef { variants }, generics) => {
             variants.flat_map_in_place(|variant| vis.flat_map_variant(variant));
diff --git a/src/libsyntax/token.rs b/src/libsyntax/token.rs
index 862934300e0..6eeee498815 100644
--- a/src/libsyntax/token.rs
+++ b/src/libsyntax/token.rs
@@ -270,6 +270,39 @@ impl TokenKind {
         Literal(Lit::new(kind, symbol, suffix))
     }
 
+    // An approximation to proc-macro-style single-character operators used by rustc parser.
+    // If the operator token can be broken into two tokens, the first of which is single-character,
+    // then this function performs that operation, otherwise it returns `None`.
+    pub fn break_two_token_op(&self) -> Option<(TokenKind, TokenKind)> {
+        Some(match *self {
+            Le => (Lt, Eq),
+            EqEq => (Eq, Eq),
+            Ne => (Not, Eq),
+            Ge => (Gt, Eq),
+            AndAnd => (BinOp(And), BinOp(And)),
+            OrOr => (BinOp(Or), BinOp(Or)),
+            BinOp(Shl) => (Lt, Lt),
+            BinOp(Shr) => (Gt, Gt),
+            BinOpEq(Plus) => (BinOp(Plus), Eq),
+            BinOpEq(Minus) => (BinOp(Minus), Eq),
+            BinOpEq(Star) => (BinOp(Star), Eq),
+            BinOpEq(Slash) => (BinOp(Slash), Eq),
+            BinOpEq(Percent) => (BinOp(Percent), Eq),
+            BinOpEq(Caret) => (BinOp(Caret), Eq),
+            BinOpEq(And) => (BinOp(And), Eq),
+            BinOpEq(Or) => (BinOp(Or), Eq),
+            BinOpEq(Shl) => (Lt, Le),
+            BinOpEq(Shr) => (Gt, Ge),
+            DotDot => (Dot, Dot),
+            DotDotDot => (Dot, DotDot),
+            ModSep => (Colon, Colon),
+            RArrow => (BinOp(Minus), Gt),
+            LArrow => (Lt, BinOp(Minus)),
+            FatArrow => (Eq, Gt),
+            _ => return None,
+        })
+    }
+
     /// Returns tokens that are likely to be typed accidentally instead of the current token.
     /// Enables better error recovery when the wrong token is found.
     pub fn similar_tokens(&self) -> Option<Vec<TokenKind>> {
diff --git a/src/libsyntax/util/comments.rs b/src/libsyntax/util/comments.rs
index 5a67531624d..0e42ae11fa2 100644
--- a/src/libsyntax/util/comments.rs
+++ b/src/libsyntax/util/comments.rs
@@ -189,8 +189,8 @@ fn split_block_comment_into_lines(text: &str, col: CharPos) -> Vec<String> {
 // it appears this function is called only from pprust... that's
 // probably not a good thing.
 pub fn gather_comments(sm: &SourceMap, path: FileName, src: String) -> Vec<Comment> {
-    let cm = SourceMap::new(sm.path_mapping().clone());
-    let source_file = cm.new_source_file(path, src);
+    let sm = SourceMap::new(sm.path_mapping().clone());
+    let source_file = sm.new_source_file(path, src);
     let text = (*source_file.src.as_ref().unwrap()).clone();
 
     let text: &str = text.as_str();
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index dedd42fe0f6..bd35918dba7 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -312,9 +312,10 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
             walk_list!(visitor, visit_foreign_item, &foreign_module.items);
         }
         ItemKind::GlobalAsm(ref ga) => visitor.visit_global_asm(ga),
-        ItemKind::TyAlias(ref typ, ref generics) => {
-            visitor.visit_ty(typ);
-            visitor.visit_generics(generics)
+        ItemKind::TyAlias(ref generics, ref bounds, ref ty) => {
+            visitor.visit_generics(generics);
+            walk_list!(visitor, visit_param_bound, bounds);
+            walk_list!(visitor, visit_ty, ty);
         }
         ItemKind::Enum(ref enum_definition, ref generics) => {
             visitor.visit_generics(generics);
diff --git a/src/test/ui/parser/bounds-lifetime-where.rs b/src/test/ui/parser/bounds-lifetime-where.rs
index acb04e7859b..e60cc153e67 100644
--- a/src/test/ui/parser/bounds-lifetime-where.rs
+++ b/src/test/ui/parser/bounds-lifetime-where.rs
@@ -5,6 +5,6 @@ type A where 'a:, = u8; // OK
 type A where 'a: 'b + 'c = u8; // OK
 type A where = u8; // OK
 type A where 'a: 'b + = u8; // OK
-type A where , = u8; //~ ERROR expected one of `=`, lifetime, or type, found `,`
+type A where , = u8; //~ ERROR expected one of `;`, `=`, lifetime, or type, found `,`
 
 fn main() {}
diff --git a/src/test/ui/parser/bounds-lifetime-where.stderr b/src/test/ui/parser/bounds-lifetime-where.stderr
index 05cebd6d351..950fa46c66b 100644
--- a/src/test/ui/parser/bounds-lifetime-where.stderr
+++ b/src/test/ui/parser/bounds-lifetime-where.stderr
@@ -1,8 +1,8 @@
-error: expected one of `=`, lifetime, or type, found `,`
+error: expected one of `;`, `=`, lifetime, or type, found `,`
   --> $DIR/bounds-lifetime-where.rs:8:14
    |
 LL | type A where , = u8;
-   |              ^ expected one of `=`, lifetime, or type
+   |              ^ expected one of `;`, `=`, lifetime, or type
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/item-free-type-bounds-semantic-fail.rs b/src/test/ui/parser/item-free-type-bounds-semantic-fail.rs
new file mode 100644
index 00000000000..9db4111fbab
--- /dev/null
+++ b/src/test/ui/parser/item-free-type-bounds-semantic-fail.rs
@@ -0,0 +1,20 @@
+fn main() {}
+
+fn semantics() {
+    type A: Ord;
+    //~^ ERROR bounds on `type`s in this context have no effect
+    //~| ERROR free type alias without body
+    type B: Ord = u8;
+    //~^ ERROR bounds on `type`s in this context have no effect
+    type C: Ord where 'static: 'static = u8;
+    //~^ ERROR bounds on `type`s in this context have no effect
+    type D<_T>: Ord;
+    //~^ ERROR bounds on `type`s in this context have no effect
+    //~| ERROR free type alias without body
+    type E<_T>: Ord = u8;
+    //~^ ERROR bounds on `type`s in this context have no effect
+    //~| ERROR type parameter `_T` is unused
+    type F<_T>: Ord where 'static: 'static = u8;
+    //~^ ERROR bounds on `type`s in this context have no effect
+    //~| ERROR type parameter `_T` is unused
+}
diff --git a/src/test/ui/parser/item-free-type-bounds-semantic-fail.stderr b/src/test/ui/parser/item-free-type-bounds-semantic-fail.stderr
new file mode 100644
index 00000000000..1b086512891
--- /dev/null
+++ b/src/test/ui/parser/item-free-type-bounds-semantic-fail.stderr
@@ -0,0 +1,67 @@
+error: free type alias without body
+  --> $DIR/item-free-type-bounds-semantic-fail.rs:4:5
+   |
+LL |     type A: Ord;
+   |     ^^^^^^^^^^^-
+   |                |
+   |                help: provide a definition for the type: `= <type>;`
+
+error: bounds on `type`s in this context have no effect
+  --> $DIR/item-free-type-bounds-semantic-fail.rs:4:13
+   |
+LL |     type A: Ord;
+   |             ^^^
+
+error: bounds on `type`s in this context have no effect
+  --> $DIR/item-free-type-bounds-semantic-fail.rs:7:13
+   |
+LL |     type B: Ord = u8;
+   |             ^^^
+
+error: bounds on `type`s in this context have no effect
+  --> $DIR/item-free-type-bounds-semantic-fail.rs:9:13
+   |
+LL |     type C: Ord where 'static: 'static = u8;
+   |             ^^^
+
+error: free type alias without body
+  --> $DIR/item-free-type-bounds-semantic-fail.rs:11:5
+   |
+LL |     type D<_T>: Ord;
+   |     ^^^^^^^^^^^^^^^-
+   |                    |
+   |                    help: provide a definition for the type: `= <type>;`
+
+error: bounds on `type`s in this context have no effect
+  --> $DIR/item-free-type-bounds-semantic-fail.rs:11:17
+   |
+LL |     type D<_T>: Ord;
+   |                 ^^^
+
+error: bounds on `type`s in this context have no effect
+  --> $DIR/item-free-type-bounds-semantic-fail.rs:14:17
+   |
+LL |     type E<_T>: Ord = u8;
+   |                 ^^^
+
+error: bounds on `type`s in this context have no effect
+  --> $DIR/item-free-type-bounds-semantic-fail.rs:17:17
+   |
+LL |     type F<_T>: Ord where 'static: 'static = u8;
+   |                 ^^^
+
+error[E0091]: type parameter `_T` is unused
+  --> $DIR/item-free-type-bounds-semantic-fail.rs:14:12
+   |
+LL |     type E<_T>: Ord = u8;
+   |            ^^ unused type parameter
+
+error[E0091]: type parameter `_T` is unused
+  --> $DIR/item-free-type-bounds-semantic-fail.rs:17:12
+   |
+LL |     type F<_T>: Ord where 'static: 'static = u8;
+   |            ^^ unused type parameter
+
+error: aborting due to 10 previous errors
+
+For more information about this error, try `rustc --explain E0091`.
diff --git a/src/test/ui/parser/item-free-type-bounds-syntactic-pass.rs b/src/test/ui/parser/item-free-type-bounds-syntactic-pass.rs
new file mode 100644
index 00000000000..58fc926d08f
--- /dev/null
+++ b/src/test/ui/parser/item-free-type-bounds-syntactic-pass.rs
@@ -0,0 +1,13 @@
+// check-pass
+
+fn main() {}
+
+#[cfg(FALSE)]
+fn syntax() {
+    type A: Ord;
+    type B: Ord = u8;
+    type C: Ord where 'static: 'static = u8;
+    type D<_T>: Ord;
+    type E<_T>: Ord = u8;
+    type F<_T>: Ord where 'static: 'static = u8;
+}