From 751dcdf606d4ff3b27b1c820535304bfb022170c Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Tue, 5 Feb 2019 16:48:45 +0100
Subject: [PATCH 01/28] Add Const kind to AST

Co-Authored-By: Gabriel Smith <yodaldevoid@users.noreply.github.com>
---
 src/libsyntax/ast.rs | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 2cfe2cc896cb..57a3bf86b0e5 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -167,6 +167,17 @@ impl GenericArgs {
 pub enum GenericArg {
     Lifetime(Lifetime),
     Type(P<Ty>),
+    Const(AnonConst),
+}
+
+impl GenericArg {
+    pub fn span(&self) -> Span {
+        match self {
+            GenericArg::Lifetime(lt) => lt.ident.span,
+            GenericArg::Type(ty) => ty.span,
+            GenericArg::Const(ct) => ct.value.span,
+        }
+    }
 }
 
 /// A path like `Foo<'a, T>`
@@ -300,9 +311,8 @@ pub type GenericBounds = Vec<GenericBound>;
 pub enum GenericParamKind {
     /// A lifetime definition (e.g., `'a: 'b + 'c + 'd`).
     Lifetime,
-    Type {
-        default: Option<P<Ty>>,
-    },
+    Type { default: Option<P<Ty>> },
+    Const { ty: P<Ty> },
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]

From 8d83521f0b1c842e42f87dd59dbca9c98b456cbd Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Tue, 5 Feb 2019 16:49:10 +0100
Subject: [PATCH 02/28] Add const_generics feature flag

Co-Authored-By: Gabriel Smith <yodaldevoid@users.noreply.github.com>
---
 src/libsyntax/feature_gate.rs | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index e7b9a884b5e0..0853b4399d2c 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -15,7 +15,7 @@
 use AttributeType::*;
 use AttributeGate::*;
 
-use crate::ast::{self, NodeId, PatKind, RangeEnd};
+use crate::ast::{self, NodeId, GenericParam, GenericParamKind, PatKind, RangeEnd};
 use crate::attr;
 use crate::early_buffered_lints::BufferedEarlyLintId;
 use crate::source_map::Spanned;
@@ -462,6 +462,9 @@ declare_features! (
     // Re-Rebalance coherence
     (active, re_rebalance_coherence, "1.32.0", Some(55437), None),
 
+    // Const generic types.
+    (active, const_generics, "1.34.0", Some(44580), None),
+
     // #[optimize(X)]
     (active, optimize_attribute, "1.34.0", Some(54882), None),
 
@@ -1899,6 +1902,14 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
         visit::walk_fn(self, fn_kind, fn_decl, span);
     }
 
+    fn visit_generic_param(&mut self, param: &'a GenericParam) {
+        if let GenericParamKind::Const { .. } = param.kind {
+            gate_feature_post!(&self, const_generics, param.ident.span,
+                "const generics are unstable");
+        }
+        visit::walk_generic_param(self, param);
+    }
+
     fn visit_trait_item(&mut self, ti: &'a ast::TraitItem) {
         match ti.node {
             ast::TraitItemKind::Method(ref sig, ref block) => {
@@ -1984,7 +1995,7 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute],
     // Some features are known to be incomplete and using them is likely to have
     // unanticipated results, such as compiler crashes. We warn the user about these
     // to alert them.
-    let incomplete_features = ["generic_associated_types"];
+    let incomplete_features = ["generic_associated_types", "const_generics"];
 
     let mut features = Features::new();
     let mut edition_enabled_features = FxHashMap::default();

From 0a8d98a270da057975d3cc552a4bb5f0bda5a3af Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Tue, 5 Feb 2019 16:49:38 +0100
Subject: [PATCH 03/28] Parse const generics

Co-Authored-By: Gabriel Smith <yodaldevoid@users.noreply.github.com>
---
 src/libsyntax/parse/parser.rs | 276 ++++++++++++----------------------
 src/libsyntax/parse/token.rs  |  14 ++
 2 files changed, 112 insertions(+), 178 deletions(-)

diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index cacdab980fac..2ff450af4238 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -397,6 +397,7 @@ crate enum TokenType {
     Ident,
     Path,
     Type,
+    Const,
 }
 
 impl TokenType {
@@ -409,6 +410,7 @@ impl TokenType {
             TokenType::Ident => "identifier".to_string(),
             TokenType::Path => "path".to_string(),
             TokenType::Type => "type".to_string(),
+            TokenType::Const => "const".to_string(),
         }
     }
 }
@@ -946,6 +948,19 @@ impl<'a> Parser<'a> {
         }
     }
 
+    fn check_const_param(&mut self) -> bool {
+        self.check_keyword(keywords::Const)
+    }
+
+    fn check_const_arg(&mut self) -> bool {
+        if self.token.can_begin_const_arg() {
+            true
+        } else {
+            self.expected_tokens.push(TokenType::Const);
+            false
+        }
+    }
+
     /// Expect and consume a `+`. if `+=` is seen, replace it with a `=`
     /// and continue. If a `+` is not seen, return false.
     ///
@@ -5482,15 +5497,28 @@ impl<'a> Parser<'a> {
         Ok((ident, TraitItemKind::Type(bounds, default), generics))
     }
 
+    fn parse_const_param(&mut self, preceding_attrs: Vec<Attribute>) -> PResult<'a, GenericParam> {
+        self.expect_keyword(keywords::Const)?;
+        let ident = self.parse_ident()?;
+        self.expect(&token::Colon)?;
+        let ty = self.parse_ty()?;
+
+        Ok(GenericParam {
+            ident,
+            id: ast::DUMMY_NODE_ID,
+            attrs: preceding_attrs.into(),
+            bounds: Vec::new(),
+            kind: GenericParamKind::Const {
+                ty,
+            }
+        })
+    }
+
     /// Parses (possibly empty) list of lifetime and type parameters, possibly including
     /// trailing comma and erroneous trailing attributes.
     crate fn parse_generic_params(&mut self) -> PResult<'a, Vec<ast::GenericParam>> {
-        let mut lifetimes = Vec::new();
         let mut params = Vec::new();
-        let mut seen_ty_param: Option<Span> = None;
-        let mut last_comma_span = None;
-        let mut bad_lifetime_pos = vec![];
-        let mut suggestions = vec![];
+        let mut prev_param: Option<ParamKindOrd> = None;
         loop {
             let attrs = self.parse_outer_attributes()?;
             if self.check_lifetime() {
@@ -5501,39 +5529,36 @@ impl<'a> Parser<'a> {
                 } else {
                     Vec::new()
                 };
-                lifetimes.push(ast::GenericParam {
+                params.push(ast::GenericParam {
                     ident: lifetime.ident,
                     id: lifetime.id,
                     attrs: attrs.into(),
                     bounds,
                     kind: ast::GenericParamKind::Lifetime,
                 });
-                if let Some(sp) = seen_ty_param {
-                    let remove_sp = last_comma_span.unwrap_or(self.prev_span).to(self.prev_span);
-                    bad_lifetime_pos.push(self.prev_span);
-                    if let Ok(snippet) = self.sess.source_map().span_to_snippet(self.prev_span) {
-                        suggestions.push((remove_sp, String::new()));
-                        suggestions.push((
-                            sp.shrink_to_lo(),
-                            format!("{}, ", snippet)));
-                    }
-                }
+                prev_param = Some(ParamKindOrd::Lifetime);
+            } else if self.check_const_param() {
+                // Parse const parameter.
+                params.push(self.parse_const_param(attrs)?);
+                prev_param = Some(ParamKindOrd::Const);
             } else if self.check_ident() {
                 // Parse type parameter.
                 params.push(self.parse_ty_param(attrs)?);
-                if seen_ty_param.is_none() {
-                    seen_ty_param = Some(self.prev_span);
-                }
+                prev_param = Some(ParamKindOrd::Type);
             } else {
                 // Check for trailing attributes and stop parsing.
                 if !attrs.is_empty() {
-                    let param_kind = if seen_ty_param.is_some() { "type" } else { "lifetime" };
-                    self.struct_span_err(
-                        attrs[0].span,
-                        &format!("trailing attribute after {} parameters", param_kind),
-                    )
-                    .span_label(attrs[0].span, "attributes must go before parameters")
-                    .emit();
+                    if let Some(prev_param) = prev_param {
+                        self.struct_span_err(
+                            attrs[0].span,
+                            &format!(
+                                "trailing attribute after {} parameter",
+                                prev_param,
+                            ),
+                        )
+                        .span_label(attrs[0].span, "attributes must go before parameters")
+                        .emit();
+                    }
                 }
                 break
             }
@@ -5541,24 +5566,8 @@ impl<'a> Parser<'a> {
             if !self.eat(&token::Comma) {
                 break
             }
-            last_comma_span = Some(self.prev_span);
-        }
-        if !bad_lifetime_pos.is_empty() {
-            let mut err = self.struct_span_err(
-                bad_lifetime_pos,
-                "lifetime parameters must be declared prior to type parameters",
-            );
-            if !suggestions.is_empty() {
-                err.multipart_suggestion(
-                    "move the lifetime parameter prior to the first type parameter",
-                    suggestions,
-                    Applicability::MachineApplicable,
-                );
-            }
-            err.emit();
         }
-        lifetimes.extend(params);  // ensure the correct order of lifetimes and type params
-        Ok(lifetimes)
+        Ok(params)
     }
 
     /// Parse a set of optional generic type parameter declarations. Where
@@ -5740,35 +5749,16 @@ impl<'a> Parser<'a> {
     fn parse_generic_args(&mut self) -> PResult<'a, (Vec<GenericArg>, Vec<TypeBinding>)> {
         let mut args = Vec::new();
         let mut bindings = Vec::new();
+        let mut misplaced_assoc_ty_bindings: Vec<Span> = Vec::new();
+        let mut assoc_ty_bindings: Vec<Span> = Vec::new();
 
-        let mut seen_type = false;
-        let mut seen_binding = false;
+        let args_lo = self.span;
 
-        let mut last_comma_span = None;
-        let mut first_type_or_binding_span: Option<Span> = None;
-        let mut first_binding_span: Option<Span> = None;
-
-        let mut bad_lifetime_pos = vec![];
-        let mut bad_type_pos = vec![];
-
-        let mut lifetime_suggestions = vec![];
-        let mut type_suggestions = vec![];
         loop {
             if self.check_lifetime() && self.look_ahead(1, |t| !t.is_like_plus()) {
                 // Parse lifetime argument.
                 args.push(GenericArg::Lifetime(self.expect_lifetime()));
-
-                if seen_type || seen_binding {
-                    let remove_sp = last_comma_span.unwrap_or(self.prev_span).to(self.prev_span);
-                    bad_lifetime_pos.push(self.prev_span);
-
-                    if let Ok(snippet) = self.sess.source_map().span_to_snippet(self.prev_span) {
-                        lifetime_suggestions.push((remove_sp, String::new()));
-                        lifetime_suggestions.push((
-                            first_type_or_binding_span.unwrap().shrink_to_lo(),
-                            format!("{}, ", snippet)));
-                    }
-                }
+                misplaced_assoc_ty_bindings.append(&mut assoc_ty_bindings);
             } else if self.check_ident() && self.look_ahead(1, |t| t == &token::Eq) {
                 // Parse associated type binding.
                 let lo = self.span;
@@ -5782,131 +5772,59 @@ impl<'a> Parser<'a> {
                     ty,
                     span,
                 });
-
-                seen_binding = true;
-                if first_type_or_binding_span.is_none() {
-                    first_type_or_binding_span = Some(span);
-                }
-                if first_binding_span.is_none() {
-                    first_binding_span = Some(span);
-                }
+                assoc_ty_bindings.push(span);
+            } else if self.check_const_arg() {
+                // Parse const argument.
+                let expr = if let token::OpenDelim(token::Brace) = self.token {
+                    self.parse_block_expr(None, self.span, BlockCheckMode::Default, ThinVec::new())?
+                } else if self.token.can_begin_literal_or_bool() {
+                    let lit = self.parse_lit()?;
+                    self.mk_expr(lit.span, ExprKind::Lit(lit), ThinVec::new())
+                } else {
+                    // FIXME(const_generics): to distinguish between idents for types and consts,
+                    // we should introduce a GenericArg::Ident in the AST and distinguish when
+                    // lowering to the HIR. For now, idents for const args are not permitted.
+                    return Err(
+                        self.fatal("identifiers may currently not be used for const generics")
+                    );
+                };
+                let value = AnonConst {
+                    id: ast::DUMMY_NODE_ID,
+                    value: expr,
+                };
+                args.push(GenericArg::Const(value));
+                misplaced_assoc_ty_bindings.append(&mut assoc_ty_bindings);
             } else if self.check_type() {
                 // Parse type argument.
-                let ty_param = self.parse_ty()?;
-                if seen_binding {
-                    let remove_sp = last_comma_span.unwrap_or(self.prev_span).to(self.prev_span);
-                    bad_type_pos.push(self.prev_span);
-
-                    if let Ok(snippet) = self.sess.source_map().span_to_snippet(self.prev_span) {
-                        type_suggestions.push((remove_sp, String::new()));
-                        type_suggestions.push((
-                            first_binding_span.unwrap().shrink_to_lo(),
-                            format!("{}, ", snippet)));
-                    }
-                }
-
-                if first_type_or_binding_span.is_none() {
-                    first_type_or_binding_span = Some(ty_param.span);
-                }
-                args.push(GenericArg::Type(ty_param));
-                seen_type = true;
+                args.push(GenericArg::Type(self.parse_ty()?));
+                misplaced_assoc_ty_bindings.append(&mut assoc_ty_bindings);
             } else {
                 break
             }
 
             if !self.eat(&token::Comma) {
                 break
-            } else {
-                last_comma_span = Some(self.prev_span);
-            }
-        }
-
-        self.maybe_report_incorrect_generic_argument_order(
-            bad_lifetime_pos, bad_type_pos, lifetime_suggestions, type_suggestions
-        );
-
-        Ok((args, bindings))
-    }
-
-    /// Maybe report an error about incorrect generic argument order - "lifetime parameters
-    /// must be declared before type parameters", "type parameters must be declared before
-    /// associated type bindings" or both.
-    fn maybe_report_incorrect_generic_argument_order(
-        &self,
-        bad_lifetime_pos: Vec<Span>,
-        bad_type_pos: Vec<Span>,
-        lifetime_suggestions: Vec<(Span, String)>,
-        type_suggestions: Vec<(Span, String)>,
-    ) {
-        let mut err = if !bad_lifetime_pos.is_empty() && !bad_type_pos.is_empty() {
-            let mut positions = bad_lifetime_pos.clone();
-            positions.extend_from_slice(&bad_type_pos);
-
-            self.struct_span_err(
-                positions,
-                "generic arguments must declare lifetimes, types and associated type bindings in \
-                 that order",
-            )
-        } else if !bad_lifetime_pos.is_empty() {
-            self.struct_span_err(
-                bad_lifetime_pos.clone(),
-                "lifetime parameters must be declared prior to type parameters"
-            )
-        } else if !bad_type_pos.is_empty() {
-            self.struct_span_err(
-                bad_type_pos.clone(),
-                "type parameters must be declared prior to associated type bindings"
-            )
-        } else {
-            return;
-        };
-
-        if !bad_lifetime_pos.is_empty() {
-            for sp in &bad_lifetime_pos {
-                err.span_label(*sp, "must be declared prior to type parameters");
-            }
-        }
-
-        if !bad_type_pos.is_empty() {
-            for sp in &bad_type_pos {
-                err.span_label(*sp, "must be declared prior to associated type bindings");
             }
         }
 
-        if !lifetime_suggestions.is_empty() && !type_suggestions.is_empty() {
-            let mut suggestions = lifetime_suggestions;
-            suggestions.extend_from_slice(&type_suggestions);
-
-            let plural = bad_lifetime_pos.len() + bad_type_pos.len() > 1;
-            err.multipart_suggestion(
-                &format!(
-                    "move the parameter{}",
-                    if plural { "s" } else { "" },
-                ),
-                suggestions,
-                Applicability::MachineApplicable,
-            );
-        } else if !lifetime_suggestions.is_empty() {
-            err.multipart_suggestion(
-                &format!(
-                    "move the lifetime parameter{} prior to the first type parameter",
-                    if bad_lifetime_pos.len() > 1 { "s" } else { "" },
-                ),
-                lifetime_suggestions,
-                Applicability::MachineApplicable,
-            );
-        } else if !type_suggestions.is_empty() {
-            err.multipart_suggestion(
-                &format!(
-                    "move the type parameter{} prior to the first associated type binding",
-                    if bad_type_pos.len() > 1 { "s" } else { "" },
-                ),
-                type_suggestions,
-                Applicability::MachineApplicable,
+        // FIXME: we would like to report this in ast_validation instead, but we currently do not
+        // preserve ordering of generic parameters with respect to associated type binding, so we
+        // lose that information after parsing.
+        if misplaced_assoc_ty_bindings.len() > 0 {
+            let mut err = self.struct_span_err(
+                args_lo.to(self.prev_span),
+                "associated type bindings must be declared after generic parameters",
             );
+            for span in misplaced_assoc_ty_bindings {
+                err.span_label(
+                    span,
+                    "this associated type binding should be moved after the generic parameters",
+                );
+            }
+            err.emit();
         }
 
-        err.emit();
+        Ok((args, bindings))
     }
 
     /// Parses an optional `where` clause and places it in `generics`.
@@ -6526,6 +6444,7 @@ impl<'a> Parser<'a> {
         //     `<` (LIFETIME|IDENT) `,` - first generic parameter in a list
         //     `<` (LIFETIME|IDENT) `:` - generic parameter with bounds
         //     `<` (LIFETIME|IDENT) `=` - generic parameter with a default
+        //     `<` const IDENT          - generic const parameter
         // The only truly ambiguous case is
         //     `<` IDENT `>` `::` IDENT ...
         // we disambiguate it in favor of generics (`impl<T> ::absolute::Path<T> { ... }`)
@@ -6535,7 +6454,8 @@ impl<'a> Parser<'a> {
             (self.look_ahead(1, |t| t == &token::Pound || t == &token::Gt) ||
              self.look_ahead(1, |t| t.is_lifetime() || t.is_ident()) &&
                 self.look_ahead(2, |t| t == &token::Gt || t == &token::Comma ||
-                                       t == &token::Colon || t == &token::Eq))
+                                       t == &token::Colon || t == &token::Eq) ||
+             self.look_ahead(1, |t| t.is_keyword(keywords::Const)))
     }
 
     fn parse_impl_body(&mut self) -> PResult<'a, (Vec<ImplItem>, Vec<Attribute>)> {
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index 3b1fa5ea01f5..dad320727396 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -279,6 +279,20 @@ impl Token {
         }
     }
 
+    /// Returns `true` if the token can appear at the start of a const param.
+    pub fn can_begin_const_arg(&self) -> bool {
+        match self {
+            OpenDelim(Brace) => true,
+            Interpolated(ref nt) => match nt.0 {
+                NtExpr(..) => true,
+                NtBlock(..) => true,
+                NtLiteral(..) => true,
+                _ => false,
+            }
+            _ => self.can_begin_literal_or_bool(),
+        }
+    }
+
     /// Returns `true` if the token can appear at the start of a generic bound.
     crate fn can_begin_bound(&self) -> bool {
         self.is_path_start() || self.is_lifetime() || self.is_keyword(keywords::For) ||

From d7695abb7667d2e8b7a010282ad5f44abbc58a58 Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Tue, 5 Feb 2019 16:50:00 +0100
Subject: [PATCH 04/28] Support const generics in derive

Co-Authored-By: Gabriel Smith <yodaldevoid@users.noreply.github.com>
---
 src/libsyntax/ext/build.rs                | 20 +++++++++++++++++++-
 src/libsyntax_ext/deriving/generic/mod.rs |  4 ++++
 src/libsyntax_ext/deriving/generic/ty.rs  | 12 +++++++++++-
 3 files changed, 34 insertions(+), 2 deletions(-)

diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 1e83f6c03ec3..6708e3c12a00 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -38,12 +38,14 @@ pub trait AstBuilder {
                 bindings: Vec<ast::TypeBinding>)
                 -> (ast::QSelf, ast::Path);
 
-    // types
+    // types and consts
     fn ty_mt(&self, ty: P<ast::Ty>, mutbl: ast::Mutability) -> ast::MutTy;
 
     fn ty(&self, span: Span, ty: ast::TyKind) -> P<ast::Ty>;
     fn ty_path(&self, path: ast::Path) -> P<ast::Ty>;
     fn ty_ident(&self, span: Span, idents: ast::Ident) -> P<ast::Ty>;
+    fn anon_const(&self, span: Span, expr: ast::ExprKind) -> ast::AnonConst;
+    fn const_ident(&self, span: Span, idents: ast::Ident) -> ast::AnonConst;
 
     fn ty_rptr(&self, span: Span,
                ty: P<ast::Ty>,
@@ -394,6 +396,22 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
         self.ty_path(self.path_ident(span, ident))
     }
 
+    fn anon_const(&self, span: Span, expr: ast::ExprKind) -> ast::AnonConst {
+        ast::AnonConst {
+            id: ast::DUMMY_NODE_ID,
+            value: P(ast::Expr {
+                id: ast::DUMMY_NODE_ID,
+                node: expr,
+                span,
+                attrs: ThinVec::new(),
+            })
+        }
+    }
+
+    fn const_ident(&self, span: Span, ident: ast::Ident) -> ast::AnonConst {
+        self.anon_const(span, ast::ExprKind::Path(None, self.path_ident(span, ident)))
+    }
+
     fn ty_rptr(&self,
                span: Span,
                ty: P<ast::Ty>,
diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs
index e6fe125da9f9..4678c7520455 100644
--- a/src/libsyntax_ext/deriving/generic/mod.rs
+++ b/src/libsyntax_ext/deriving/generic/mod.rs
@@ -560,6 +560,7 @@ impl<'a> TraitDef<'a> {
 
                 cx.typaram(self.span, param.ident, vec![], bounds, None)
             }
+            GenericParamKind::Const { .. } => param.clone(),
         }));
 
         // and similarly for where clauses
@@ -657,6 +658,9 @@ impl<'a> TraitDef<'a> {
             GenericParamKind::Type { .. } => {
                 GenericArg::Type(cx.ty_ident(self.span, param.ident))
             }
+            GenericParamKind::Const { .. } => {
+                GenericArg::Const(cx.const_ident(self.span, param.ident))
+            }
         }).collect();
 
         // Create the type of `self`.
diff --git a/src/libsyntax_ext/deriving/generic/ty.rs b/src/libsyntax_ext/deriving/generic/ty.rs
index ea6e07922b2b..100ec0057ee0 100644
--- a/src/libsyntax_ext/deriving/generic/ty.rs
+++ b/src/libsyntax_ext/deriving/generic/ty.rs
@@ -94,7 +94,7 @@ impl<'a> Path<'a> {
     }
 }
 
-/// A type. Supports pointers, Self, and literals
+/// A type. Supports pointers, Self, and literals.
 #[derive(Clone)]
 pub enum Ty<'a> {
     Self_,
@@ -107,6 +107,13 @@ pub enum Ty<'a> {
     Tuple(Vec<Ty<'a>>),
 }
 
+/// A const expression. Supports literals and blocks.
+#[derive(Clone, Eq, PartialEq)]
+pub enum Const {
+    Literal,
+    Block,
+}
+
 pub fn borrowed_ptrty<'r>() -> PtrTy<'r> {
     Borrowed(None, ast::Mutability::Immutable)
 }
@@ -180,6 +187,9 @@ impl<'a> Ty<'a> {
                     GenericParamKind::Type { .. } => {
                         GenericArg::Type(cx.ty_ident(span, param.ident))
                     }
+                    GenericParamKind::Const { .. } => {
+                        GenericArg::Const(cx.const_ident(span, param.ident))
+                    }
                 }).collect();
 
                 cx.path_all(span, false, vec![self_ty], params, vec![])

From b4ef753e8f45a67f6756ad4c9103e0e327a1e078 Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Tue, 5 Feb 2019 16:50:16 +0100
Subject: [PATCH 05/28] Add pretty-printing for const generics

Co-Authored-By: Gabriel Smith <yodaldevoid@users.noreply.github.com>
---
 src/librustc_save_analysis/sig.rs |  5 +++++
 src/libsyntax/print/pprust.rs     | 12 +++++++++++-
 2 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs
index 7d4c0d0f9f56..e7ea90d921e3 100644
--- a/src/librustc_save_analysis/sig.rs
+++ b/src/librustc_save_analysis/sig.rs
@@ -646,6 +646,11 @@ impl Sig for ast::Generics {
                         param_text.push_str(&pprust::bounds_to_string(&param.bounds));
                         // FIXME descend properly into bounds.
                     }
+                    ast::GenericParamKind::Const { ref ty } => {
+                        param_text.push_str(&pprust::bounds_to_string(&param.bounds));
+                        param_text.push_str("= ");
+                        param_text.push_str(&pprust::ty_to_string(&ty));
+                    }
                 }
             }
             text.push_str(&param_text);
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index c7c4c4f16205..c670f47b597d 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -1025,6 +1025,7 @@ impl<'a> State<'a> {
         match generic_arg {
             GenericArg::Lifetime(lt) => self.print_lifetime(*lt),
             GenericArg::Type(ty) => self.print_type(ty),
+            GenericArg::Const(ct) => self.print_expr(&ct.value),
         }
     }
 
@@ -2929,7 +2930,7 @@ impl<'a> State<'a> {
                     s.print_outer_attributes_inline(&param.attrs)?;
                     let lt = ast::Lifetime { id: param.id, ident: param.ident };
                     s.print_lifetime_bounds(lt, &param.bounds)
-                },
+                }
                 ast::GenericParamKind::Type { ref default } => {
                     s.print_outer_attributes_inline(&param.attrs)?;
                     s.print_ident(param.ident)?;
@@ -2943,6 +2944,15 @@ impl<'a> State<'a> {
                         _ => Ok(())
                     }
                 }
+                ast::GenericParamKind::Const { ref ty } => {
+                    s.print_outer_attributes_inline(&param.attrs)?;
+                    s.word_space("const")?;
+                    s.print_ident(param.ident)?;
+                    s.s.space()?;
+                    s.word_space(":")?;
+                    s.print_type(ty)?;
+                    s.print_type_bounds(":", &param.bounds)
+                }
             }
         })?;
 

From ea0d99829da705377b7b690062401f772f0babe8 Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Tue, 5 Feb 2019 16:50:55 +0100
Subject: [PATCH 06/28] Add resolution errors for const generics

Co-Authored-By: Gabriel Smith <yodaldevoid@users.noreply.github.com>
---
 src/librustc_resolve/lib.rs | 158 ++++++++++++++++++++++++++++--------
 src/libsyntax/ast.rs        |  20 +++++
 2 files changed, 146 insertions(+), 32 deletions(-)

diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index b166b1be02f4..934bb0f03c4f 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -51,6 +51,7 @@ use syntax::ast::{FnDecl, ForeignItem, ForeignItemKind, GenericParamKind, Generi
 use syntax::ast::{Item, ItemKind, ImplItem, ImplItemKind};
 use syntax::ast::{Label, Local, Mutability, Pat, PatKind, Path};
 use syntax::ast::{QSelf, TraitItemKind, TraitRef, Ty, TyKind};
+use syntax::ast::ParamKindOrd;
 use syntax::ptr::P;
 use syntax::{span_err, struct_span_err, unwrap_or, walk_list};
 
@@ -142,10 +143,11 @@ impl Ord for BindingError {
 }
 
 enum ResolutionError<'a> {
-    /// error E0401: can't use type parameters from outer function
-    TypeParametersFromOuterFunction(Def),
-    /// error E0403: the name is already used for a type parameter in this type parameter list
-    NameAlreadyUsedInTypeParameterList(Name, &'a Span),
+    /// error E0401: can't use type or const parameters from outer function
+    ParametersFromOuterFunction(Def, ParamKindOrd),
+    /// error E0403: the name is already used for a type/const parameter in this list of
+    /// generic parameters
+    NameAlreadyUsedInParameterList(Name, &'a Span),
     /// error E0407: method is not a member of trait
     MethodNotMemberOfTrait(Name, &'a str),
     /// error E0437: type is not a member of trait
@@ -177,7 +179,9 @@ enum ResolutionError<'a> {
     /// error E0530: X bindings cannot shadow Ys
     BindingShadowsSomethingUnacceptable(&'a str, Name, &'a NameBinding<'a>),
     /// error E0128: type parameters with a default cannot use forward declared identifiers
-    ForwardDeclaredTyParam,
+    ForwardDeclaredTyParam, // FIXME(const_generics:defaults)
+    /// error E0670: const parameter cannot depend on type parameter
+    ConstParamDependentOnTypeParam,
 }
 
 /// Combines an error with provided span and emits it
@@ -195,12 +199,14 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver<'_>,
                                    resolution_error: ResolutionError<'a>)
                                    -> DiagnosticBuilder<'sess> {
     match resolution_error {
-        ResolutionError::TypeParametersFromOuterFunction(outer_def) => {
+        ResolutionError::ParametersFromOuterFunction(outer_def, kind) => {
             let mut err = struct_span_err!(resolver.session,
-                                           span,
-                                           E0401,
-                                           "can't use type parameters from outer function");
-            err.span_label(span, "use of type variable from outer function");
+                span,
+                E0401,
+                "can't use {} parameters from outer function",
+                kind,
+            );
+            err.span_label(span, format!("use of {} variable from outer function", kind));
 
             let cm = resolver.session.source_map();
             match outer_def {
@@ -224,20 +230,25 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver<'_>,
                     }
                     return err;
                 },
-                Def::TyParam(typaram_defid) => {
-                    if let Some(typaram_span) = resolver.definitions.opt_span(typaram_defid) {
-                        err.span_label(typaram_span, "type variable from outer function");
+                Def::TyParam(def_id) => {
+                    if let Some(span) = resolver.definitions.opt_span(def_id) {
+                        err.span_label(span, "type variable from outer function");
                     }
-                },
+                }
+                Def::ConstParam(def_id) => {
+                    if let Some(span) = resolver.definitions.opt_span(def_id) {
+                        err.span_label(span, "const variable from outer function");
+                    }
+                }
                 _ => {
-                    bug!("TypeParametersFromOuterFunction should only be used with Def::SelfTy or \
-                         Def::TyParam")
+                    bug!("TypeParametersFromOuterFunction should only be used with Def::SelfTy, \
+                         Def::TyParam or Def::ConstParam");
                 }
             }
 
             // Try to retrieve the span of the function signature and generate a new message with
-            // a local type parameter
-            let sugg_msg = "try using a local type parameter instead";
+            // a local type or const parameter.
+            let sugg_msg = &format!("try using a local {} parameter instead", kind);
             if let Some((sugg_span, new_snippet)) = cm.generate_local_type_param_snippet(span) {
                 // Suggest the modification to the user
                 err.span_suggestion(
@@ -247,19 +258,20 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver<'_>,
                     Applicability::MachineApplicable,
                 );
             } else if let Some(sp) = cm.generate_fn_name_span(span) {
-                err.span_label(sp, "try adding a local type parameter in this method instead");
+                err.span_label(sp,
+                    format!("try adding a local {} parameter in this method instead", kind));
             } else {
-                err.help("try using a local type parameter instead");
+                err.help(&format!("try using a local {} parameter instead", kind));
             }
 
             err
         }
-        ResolutionError::NameAlreadyUsedInTypeParameterList(name, first_use_span) => {
+        ResolutionError::NameAlreadyUsedInParameterList(name, first_use_span) => {
              let mut err = struct_span_err!(resolver.session,
                                             span,
                                             E0403,
-                                            "the name `{}` is already used for a type parameter \
-                                            in this type parameter list",
+                                            "the name `{}` is already used for a generic \
+                                            parameter in this list of generic parameters",
                                             name);
              err.span_label(span, "already used");
              err.span_label(first_use_span.clone(), format!("first use of `{}`", name));
@@ -416,6 +428,12 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver<'_>,
                 span, "defaulted type parameters cannot be forward declared".to_string());
             err
         }
+        ResolutionError::ConstParamDependentOnTypeParam => {
+            let mut err = struct_span_err!(resolver.session, span, E0670,
+                                           "const parameters cannot depend on type parameters");
+            err.span_label(span, format!("const parameter depends on type parameter"));
+            err
+        }
     }
 }
 
@@ -546,7 +564,7 @@ impl<'a> PathSource<'a> {
                 Def::Struct(..) | Def::Union(..) | Def::Enum(..) |
                 Def::Trait(..) | Def::TraitAlias(..) | Def::TyAlias(..) |
                 Def::AssociatedTy(..) | Def::PrimTy(..) | Def::TyParam(..) |
-                Def::SelfTy(..) | Def::Existential(..) |
+                Def::SelfTy(..) | Def::Existential(..) | Def::ConstParam(..) |
                 Def::ForeignTy(..) => true,
                 _ => false,
             },
@@ -564,7 +582,7 @@ impl<'a> PathSource<'a> {
                 Def::VariantCtor(_, CtorKind::Const) | Def::VariantCtor(_, CtorKind::Fn) |
                 Def::Const(..) | Def::Static(..) | Def::Local(..) | Def::Upvar(..) |
                 Def::Fn(..) | Def::Method(..) | Def::AssociatedConst(..) |
-                Def::SelfCtor(..) => true,
+                Def::SelfCtor(..) | Def::ConstParam(..) => true,
                 _ => false,
             },
             PathSource::Pat => match def {
@@ -855,6 +873,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
         self.label_ribs.pop();
         self.ribs[ValueNS].pop();
     }
+
     fn visit_generics(&mut self, generics: &'tcx Generics) {
         // For type parameter defaults, we have to ban access
         // to following type parameters, as the Substs can only
@@ -865,6 +884,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
         let mut found_default = false;
         default_ban_rib.bindings.extend(generics.params.iter()
             .filter_map(|param| match param.kind {
+                GenericParamKind::Const { .. } |
                 GenericParamKind::Lifetime { .. } => None,
                 GenericParamKind::Type { ref default, .. } => {
                     found_default |= default.is_some();
@@ -876,6 +896,16 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
                 }
             }));
 
+        // We also ban access to type parameters for use as the types of const parameters.
+        let mut const_ty_param_ban_rib = Rib::new(TyParamAsConstParamTy);
+        const_ty_param_ban_rib.bindings.extend(generics.params.iter()
+            .filter(|param| if let GenericParamKind::Type { .. } = param.kind {
+                true
+            } else {
+                false
+            })
+            .map(|param| (Ident::with_empty_ctxt(param.ident.name), Def::Err)));
+
         for param in &generics.params {
             match param.kind {
                 GenericParamKind::Lifetime { .. } => self.visit_generic_param(param),
@@ -893,6 +923,17 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
                     // Allow all following defaults to refer to this type parameter.
                     default_ban_rib.bindings.remove(&Ident::with_empty_ctxt(param.ident.name));
                 }
+                GenericParamKind::Const { ref ty } => {
+                    self.ribs[TypeNS].push(const_ty_param_ban_rib);
+
+                    for bound in &param.bounds {
+                        self.visit_param_bound(bound);
+                    }
+
+                    self.visit_ty(ty);
+
+                    const_ty_param_ban_rib = self.ribs[TypeNS].pop().unwrap();
+                }
             }
         }
         for p in &generics.where_clause.predicates {
@@ -944,6 +985,9 @@ enum RibKind<'a> {
     /// from the default of a type parameter because they're not declared
     /// before said type parameter. Also see the `visit_generics` override.
     ForwardTyParamBanRibKind,
+
+    /// We forbid the use of type parameters as the types of const parameters.
+    TyParamAsConstParamTy,
 }
 
 /// One local scope.
@@ -2535,7 +2579,7 @@ impl<'a> Resolver<'a> {
 
                             if seen_bindings.contains_key(&ident) {
                                 let span = seen_bindings.get(&ident).unwrap();
-                                let err = ResolutionError::NameAlreadyUsedInTypeParameterList(
+                                let err = ResolutionError::NameAlreadyUsedInParameterList(
                                     ident.name,
                                     span,
                                 );
@@ -2548,6 +2592,24 @@ impl<'a> Resolver<'a> {
                             function_type_rib.bindings.insert(ident, def);
                             self.record_def(param.id, PathResolution::new(def));
                         }
+                        GenericParamKind::Const { .. } => {
+                            let ident = param.ident.modern();
+                            debug!("with_type_parameter_rib: {}", param.id);
+
+                            if seen_bindings.contains_key(&ident) {
+                                let span = seen_bindings.get(&ident).unwrap();
+                                let err = ResolutionError::NameAlreadyUsedInParameterList(
+                                    ident.name,
+                                    span,
+                                );
+                                resolve_error(self, param.ident.span, err);
+                            }
+                            seen_bindings.entry(ident).or_insert(param.ident.span);
+
+                            let def = Def::ConstParam(self.definitions.local_def_id(param.id));
+                            function_type_rib.bindings.insert(ident, def);
+                            self.record_def(param.id, PathResolution::new(def));
+                        }
                     }
                 }
                 self.ribs[TypeNS].push(function_type_rib);
@@ -4106,6 +4168,15 @@ impl<'a> Resolver<'a> {
             return Def::Err;
         }
 
+        // An invalid use of a type parameter as the type of a const parameter.
+        if let TyParamAsConstParamTy = self.ribs[ns][rib_index].kind {
+            if record_used {
+                resolve_error(self, span, ResolutionError::ConstParamDependentOnTypeParam);
+            }
+            assert_eq!(def, Def::Err);
+            return Def::Err;
+        }
+
         match def {
             Def::Upvar(..) => {
                 span_bug!(span, "unexpected {:?} in bindings", def)
@@ -4114,7 +4185,7 @@ impl<'a> Resolver<'a> {
                 for rib in ribs {
                     match rib.kind {
                         NormalRibKind | ModuleRibKind(..) | MacroDefinition(..) |
-                        ForwardTyParamBanRibKind => {
+                        ForwardTyParamBanRibKind | TyParamAsConstParamTy => {
                             // Nothing to do. Continue.
                         }
                         ClosureRibKind(function_id) => {
@@ -4167,21 +4238,44 @@ impl<'a> Resolver<'a> {
                     match rib.kind {
                         NormalRibKind | TraitOrImplItemRibKind | ClosureRibKind(..) |
                         ModuleRibKind(..) | MacroDefinition(..) | ForwardTyParamBanRibKind |
-                        ConstantItemRibKind => {
+                        ConstantItemRibKind | TyParamAsConstParamTy => {
                             // Nothing to do. Continue.
                         }
                         ItemRibKind => {
-                            // This was an attempt to use a type parameter outside
-                            // its scope.
+                            // This was an attempt to use a type parameter outside its scope.
                             if record_used {
-                                resolve_error(self, span,
-                                    ResolutionError::TypeParametersFromOuterFunction(def));
+                                resolve_error(
+                                    self,
+                                    span,
+                                    ResolutionError::ParametersFromOuterFunction(
+                                        def,
+                                        ParamKindOrd::Type,
+                                    ),
+                                );
                             }
                             return Def::Err;
                         }
                     }
                 }
             }
+            Def::ConstParam(..) => {
+                for rib in ribs {
+                    if let ItemRibKind = rib.kind {
+                        // This was an attempt to use a const parameter outside its scope.
+                        if record_used {
+                            resolve_error(
+                                self,
+                                span,
+                                ResolutionError::ParametersFromOuterFunction(
+                                    def,
+                                    ParamKindOrd::Const,
+                                ),
+                            );
+                        }
+                        return Def::Err;
+                    }
+                }
+            }
             _ => {}
         }
         def
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 57a3bf86b0e5..ab3883d2b9b9 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -307,6 +307,26 @@ impl GenericBound {
 
 pub type GenericBounds = Vec<GenericBound>;
 
+/// Specifies the enforced ordering for generic parameters. In the future,
+/// if we wanted to relax this order, we could override `PartialEq` and
+/// `PartialOrd`, to allow the kinds to be unordered.
+#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
+pub enum ParamKindOrd {
+    Lifetime,
+    Type,
+    Const,
+}
+
+impl fmt::Display for ParamKindOrd {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match self {
+            ParamKindOrd::Lifetime => "lifetime".fmt(f),
+            ParamKindOrd::Type => "type".fmt(f),
+            ParamKindOrd::Const => "const".fmt(f),
+        }
+    }
+}
+
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub enum GenericParamKind {
     /// A lifetime definition (e.g., `'a: 'b + 'c + 'd`).

From 29f72063667187f2d281e940209a924730e165b2 Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Tue, 5 Feb 2019 16:51:49 +0100
Subject: [PATCH 07/28] Add const params to Def

Co-Authored-By: Gabriel Smith <yodaldevoid@users.noreply.github.com>
---
 src/librustc/hir/def.rs               | 5 ++++-
 src/librustc/hir/map/def_collector.rs | 1 +
 src/librustc/hir/map/definitions.rs   | 8 ++++++--
 src/librustc/ich/impls_hir.rs         | 1 +
 src/librustc/ty/item_path.rs          | 1 +
 src/librustc/util/ppaux.rs            | 1 +
 src/librustc_save_analysis/lib.rs     | 7 +++++++
 7 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs
index 6566c6041b6e..15efa7650293 100644
--- a/src/librustc/hir/def.rs
+++ b/src/librustc/hir/def.rs
@@ -52,6 +52,7 @@ pub enum Def {
     AssociatedExistential(DefId),
     PrimTy(hir::PrimTy),
     TyParam(DefId),
+    ConstParam(DefId),
     SelfTy(Option<DefId> /* trait */, Option<DefId> /* impl */),
     ToolMod, // e.g., `rustfmt` in `#[rustfmt::skip]`
 
@@ -265,7 +266,8 @@ impl Def {
             Def::Fn(id) | Def::Mod(id) | Def::Static(id, _) |
             Def::Variant(id) | Def::VariantCtor(id, ..) | Def::Enum(id) |
             Def::TyAlias(id) | Def::TraitAlias(id) |
-            Def::AssociatedTy(id) | Def::TyParam(id) | Def::Struct(id) | Def::StructCtor(id, ..) |
+            Def::AssociatedTy(id) | Def::TyParam(id) | Def::ConstParam(id) | Def::Struct(id) |
+            Def::StructCtor(id, ..) |
             Def::Union(id) | Def::Trait(id) | Def::Method(id) | Def::Const(id) |
             Def::AssociatedConst(id) | Def::Macro(id, ..) |
             Def::Existential(id) | Def::AssociatedExistential(id) | Def::ForeignTy(id) => {
@@ -322,6 +324,7 @@ impl Def {
             Def::Const(..) => "constant",
             Def::AssociatedConst(..) => "associated constant",
             Def::TyParam(..) => "type parameter",
+            Def::ConstParam(..) => "const parameter",
             Def::PrimTy(..) => "builtin type",
             Def::Local(..) => "local variable",
             Def::Upvar(..) => "closure capture",
diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs
index 710170674f76..02fb503e752b 100644
--- a/src/librustc/hir/map/def_collector.rs
+++ b/src/librustc/hir/map/def_collector.rs
@@ -218,6 +218,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
         let def_path_data = match param.kind {
             GenericParamKind::Lifetime { .. } => DefPathData::LifetimeParam(name),
             GenericParamKind::Type { .. } => DefPathData::TypeParam(name),
+            GenericParamKind::Const { .. } => DefPathData::ConstParam(name),
         };
         self.create_def(param.id, def_path_data, REGULAR_SPACE, param.ident.span);
 
diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs
index a8193e1d3483..84e9cde6df16 100644
--- a/src/librustc/hir/map/definitions.rs
+++ b/src/librustc/hir/map/definitions.rs
@@ -356,10 +356,12 @@ pub enum DefPathData {
     /// A closure expression
     ClosureExpr,
     // Subportions of items
-    /// A type parameter (generic parameter)
+    /// A type (generic) parameter
     TypeParam(InternedString),
-    /// A lifetime definition
+    /// A lifetime (generic) parameter
     LifetimeParam(InternedString),
+    /// A const (generic) parameter
+    ConstParam(InternedString),
     /// A variant of a enum
     EnumVariant(InternedString),
     /// A struct field
@@ -641,6 +643,7 @@ impl DefPathData {
             MacroDef(name) |
             TypeParam(name) |
             LifetimeParam(name) |
+            ConstParam(name) |
             EnumVariant(name) |
             Field(name) |
             GlobalMetaData(name) => Some(name),
@@ -669,6 +672,7 @@ impl DefPathData {
             MacroDef(name) |
             TypeParam(name) |
             LifetimeParam(name) |
+            ConstParam(name) |
             EnumVariant(name) |
             Field(name) |
             GlobalMetaData(name) => {
diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs
index 2b359428b1fa..712fd360fbb6 100644
--- a/src/librustc/ich/impls_hir.rs
+++ b/src/librustc/ich/impls_hir.rs
@@ -1046,6 +1046,7 @@ impl_stable_hash_for!(enum hir::def::Def {
     AssociatedExistential(def_id),
     PrimTy(prim_ty),
     TyParam(def_id),
+    ConstParam(def_id),
     SelfTy(trait_def_id, impl_def_id),
     ForeignTy(def_id),
     Fn(def_id),
diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs
index f89e50d69694..8214c8bacc70 100644
--- a/src/librustc/ty/item_path.rs
+++ b/src/librustc/ty/item_path.rs
@@ -325,6 +325,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             data @ DefPathData::Module(..) |
             data @ DefPathData::TypeParam(..) |
             data @ DefPathData::LifetimeParam(..) |
+            data @ DefPathData::ConstParam(..) |
             data @ DefPathData::EnumVariant(..) |
             data @ DefPathData::Field(..) |
             data @ DefPathData::AnonConst |
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index 2cd82d44af3a..a12ec3471a91 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -426,6 +426,7 @@ impl PrintContext {
                     DefPathData::ClosureExpr |
                     DefPathData::TypeParam(_) |
                     DefPathData::LifetimeParam(_) |
+                    DefPathData::ConstParam(_) |
                     DefPathData::Field(_) |
                     DefPathData::StructCtor |
                     DefPathData::AnonConst |
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index 73eb5de5c76f..4969d521b803 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -762,6 +762,13 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
                     ref_id: id_from_def_id(def_id),
                 })
             }
+            HirDef::ConstParam(def_id) => {
+                Some(Ref {
+                    kind: RefKind::Variable,
+                    span,
+                    ref_id: id_from_def_id(def_id),
+                })
+            }
             HirDef::StructCtor(def_id, _) => {
                 // This is a reference to a tuple struct where the def_id points
                 // to an invisible constructor function. That is not a very useful

From 2fec52bf58d66b6efc7a2d87c9296072b727fc83 Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Tue, 5 Feb 2019 16:52:02 +0100
Subject: [PATCH 08/28] Add lowering errors for const generics

Co-Authored-By: Gabriel Smith <yodaldevoid@users.noreply.github.com>
---
 src/librustc/hir/lowering.rs | 79 +++++++++++++++++++++---------------
 src/libsyntax/mut_visit.rs   |  4 ++
 src/libsyntax/visit.rs       |  2 +
 3 files changed, 53 insertions(+), 32 deletions(-)

diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index d0fd5bd6844b..3de41b1665d6 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -1157,6 +1157,15 @@ impl<'a> LoweringContext<'a> {
         match arg {
             ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(&lt)),
             ast::GenericArg::Type(ty) => GenericArg::Type(self.lower_ty_direct(&ty, itctx)),
+            ast::GenericArg::Const(ct) => {
+                // FIXME(const_generics): const generics are not yet defined in the HIR.
+                self.sess.struct_span_err(
+                    ct.value.span,
+                    "const generics in any position are currently unsupported",
+                ).emit();
+                self.sess.abort_if_errors();
+                bug!();
+            }
         }
     }
 
@@ -2441,7 +2450,7 @@ impl<'a> LoweringContext<'a> {
             |this| this.lower_param_bounds(&param.bounds, itctx.reborrow()),
         );
 
-        match param.kind {
+        let (name, kind) = match param.kind {
             GenericParamKind::Lifetime => {
                 let was_collecting_in_band = self.is_collecting_in_band_lifetimes;
                 self.is_collecting_in_band_lifetimes = false;
@@ -2457,22 +2466,14 @@ impl<'a> LoweringContext<'a> {
                         | hir::LifetimeName::Static => hir::ParamName::Plain(lt.name.ident()),
                     hir::LifetimeName::Error => ParamName::Error,
                 };
-                let param = hir::GenericParam {
-                    id: lt.id,
-                    hir_id: lt.hir_id,
-                    name: param_name,
-                    span: lt.span,
-                    pure_wrt_drop: attr::contains_name(&param.attrs, "may_dangle"),
-                    attrs: self.lower_attrs(&param.attrs),
-                    bounds,
-                    kind: hir::GenericParamKind::Lifetime {
-                        kind: hir::LifetimeParamKind::Explicit,
-                    }
+
+                let kind = hir::GenericParamKind::Lifetime {
+                    kind: hir::LifetimeParamKind::Explicit
                 };
 
                 self.is_collecting_in_band_lifetimes = was_collecting_in_band;
 
-                param
+                (param_name, kind)
             }
             GenericParamKind::Type { ref default, .. } => {
                 // Don't expose `Self` (recovered "keyword used as ident" parse error).
@@ -2491,27 +2492,41 @@ impl<'a> LoweringContext<'a> {
                                    .chain(params)
                                    .collect();
                 }
-                let LoweredNodeId { node_id, hir_id } = self.lower_node_id(param.id);
 
-                hir::GenericParam {
-                    id: node_id,
-                    hir_id,
-                    name: hir::ParamName::Plain(ident),
-                    pure_wrt_drop: attr::contains_name(&param.attrs, "may_dangle"),
-                    attrs: self.lower_attrs(&param.attrs),
-                    bounds,
-                    span: ident.span,
-                    kind: hir::GenericParamKind::Type {
-                        default: default.as_ref().map(|x| {
-                            self.lower_ty(x, ImplTraitContext::disallowed())
-                        }),
-                        synthetic: param.attrs.iter()
-                                              .filter(|attr| attr.check_name("rustc_synthetic"))
-                                              .map(|_| hir::SyntheticTyParamKind::ImplTrait)
-                                              .next(),
-                    }
-                }
+                let kind = hir::GenericParamKind::Type {
+                    default: default.as_ref().map(|x| {
+                        self.lower_ty(x, ImplTraitContext::disallowed())
+                    }),
+                    synthetic: param.attrs.iter()
+                                          .filter(|attr| attr.check_name("rustc_synthetic"))
+                                          .map(|_| hir::SyntheticTyParamKind::ImplTrait)
+                                          .next(),
+                };
+
+                (hir::ParamName::Plain(ident), kind)
             }
+            GenericParamKind::Const { .. } => {
+                // FIXME(const_generics): const generics are not yet defined in the HIR.
+                self.sess.struct_span_err(
+                    param.ident.span,
+                    "const generics in any position are currently unsupported",
+                ).emit();
+                self.sess.abort_if_errors();
+                bug!();
+            }
+        };
+
+        let LoweredNodeId { node_id, hir_id } = self.lower_node_id(param.id);
+
+        hir::GenericParam {
+            id: node_id,
+            hir_id,
+            name,
+            span: param.ident.span,
+            pure_wrt_drop: attr::contains_name(&param.attrs, "may_dangle"),
+            attrs: self.lower_attrs(&param.attrs),
+            bounds,
+            kind,
         }
     }
 
diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs
index 0fd8bbf100fa..1e5eb0992bd1 100644
--- a/src/libsyntax/mut_visit.rs
+++ b/src/libsyntax/mut_visit.rs
@@ -480,6 +480,7 @@ pub fn noop_visit_generic_arg<T: MutVisitor>(arg: &mut GenericArg, vis: &mut T)
     match arg {
         GenericArg::Lifetime(lt) => vis.visit_lifetime(lt),
         GenericArg::Type(ty) => vis.visit_ty(ty),
+        GenericArg::Const(ct) => vis.visit_anon_const(ct),
     }
 }
 
@@ -698,6 +699,9 @@ pub fn noop_visit_generic_param<T: MutVisitor>(param: &mut GenericParam, vis: &m
         GenericParamKind::Type { default } => {
             visit_opt(default, |default| vis.visit_ty(default));
         }
+        GenericParamKind::Const { ty } => {
+            vis.visit_ty(ty);
+        }
     }
 }
 
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index acbb58a66b6b..bb3b0ea7359a 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -126,6 +126,7 @@ pub trait Visitor<'ast>: Sized {
         match generic_arg {
             GenericArg::Lifetime(lt) => self.visit_lifetime(lt),
             GenericArg::Type(ty) => self.visit_ty(ty),
+            GenericArg::Const(ct) => self.visit_anon_const(ct),
         }
     }
     fn visit_assoc_type_binding(&mut self, type_binding: &'ast TypeBinding) {
@@ -486,6 +487,7 @@ pub fn walk_generic_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a Generi
     match param.kind {
         GenericParamKind::Lifetime => {}
         GenericParamKind::Type { ref default } => walk_list!(visitor, visit_ty, default),
+        GenericParamKind::Const { ref ty, .. } => visitor.visit_ty(ty),
     }
 }
 

From 11874a0c14a1637a310f0088a2c91ceb2810f6dd Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Tue, 5 Feb 2019 16:52:17 +0100
Subject: [PATCH 09/28] Validate generic parameter and argument order in
 ast_validation

Co-Authored-By: Gabriel Smith <yodaldevoid@users.noreply.github.com>
---
 src/librustc_passes/ast_validation.rs | 128 ++++++++++++++++++++++----
 1 file changed, 112 insertions(+), 16 deletions(-)

diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs
index 3deb2ff8d8a0..502799900642 100644
--- a/src/librustc_passes/ast_validation.rs
+++ b/src/librustc_passes/ast_validation.rs
@@ -9,6 +9,7 @@
 use std::mem;
 use rustc::lint;
 use rustc::session::Session;
+use rustc_data_structures::fx::FxHashMap;
 use syntax::ast::*;
 use syntax::attr;
 use syntax::source_map::Spanned;
@@ -271,7 +272,74 @@ impl<'a> AstValidator<'a> {
             _ => None,
         }
     }
+}
 
+enum GenericPosition {
+    Param,
+    Arg,
+}
+
+fn validate_generics_order<'a>(
+    handler: &errors::Handler,
+    generics: impl Iterator<Item = (ParamKindOrd, Span, Option<Ident>)>,
+    pos: GenericPosition,
+    span: Span,
+) {
+    let mut max_param: Option<ParamKindOrd> = None;
+    let mut out_of_order = FxHashMap::default();
+    let mut param_idents = vec![];
+
+    for (kind, span, ident) in generics {
+        if let Some(ident) = ident {
+            param_idents.push((kind, param_idents.len(), ident));
+        }
+        let max_param = &mut max_param;
+        match max_param {
+            Some(max_param) if *max_param > kind => {
+                let entry = out_of_order.entry(kind).or_insert((*max_param, vec![]));
+                entry.1.push(span);
+            }
+            Some(_) | None => *max_param = Some(kind),
+        };
+    }
+
+    let mut ordered_params = "<".to_string();
+    if !out_of_order.is_empty() {
+        param_idents.sort_by_key(|&(po, i, _)| (po, i));
+        let mut first = true;
+        for (_, _, ident) in param_idents {
+            if !first {
+                ordered_params += ", ";
+            }
+            ordered_params += &ident.as_str();
+            first = false;
+        }
+    }
+    ordered_params += ">";
+
+    let pos_str = match pos {
+        GenericPosition::Param => "parameter",
+        GenericPosition::Arg => "argument",
+    };
+
+    for (param_ord, (max_param, spans)) in out_of_order {
+        let mut err = handler.struct_span_err(spans,
+            &format!(
+                "{} {pos}s must be declared prior to {} {pos}s",
+                param_ord,
+                max_param,
+                pos = pos_str,
+            ));
+        if let GenericPosition::Param = pos {
+            err.span_suggestion(
+                span,
+                &format!("reorder the {}s: lifetimes, then types, then consts", pos_str),
+                ordered_params.clone(),
+                Applicability::MachineApplicable,
+            );
+        }
+        err.emit();
+    }
 }
 
 impl<'a> Visitor<'a> for AstValidator<'a> {
@@ -412,6 +480,26 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                         .note("only trait implementations may be annotated with default").emit();
                 }
             }
+            ItemKind::Fn(_, header, ref generics, _) => {
+                // We currently do not permit const generics in `const fn`, as
+                // this is tantamount to allowing compile-time dependent typing.
+                if header.constness.node == Constness::Const {
+                    // Look for const generics and error if we find any.
+                    for param in &generics.params {
+                        match param.kind {
+                            GenericParamKind::Const { .. } => {
+                                self.err_handler()
+                                    .struct_span_err(
+                                        item.span,
+                                        "const parameters are not permitted in `const fn`",
+                                    )
+                                    .emit();
+                            }
+                            _ => {}
+                        }
+                    }
+                }
+            }
             ItemKind::ForeignMod(..) => {
                 self.invalid_visibility(
                     &item.vis,
@@ -508,6 +596,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
         match *generic_args {
             GenericArgs::AngleBracketed(ref data) => {
                 walk_list!(self, visit_generic_arg, &data.args);
+                validate_generics_order(self.err_handler(), data.args.iter().map(|arg| {
+                    (match arg {
+                        GenericArg::Lifetime(..) => ParamKindOrd::Lifetime,
+                        GenericArg::Type(..) => ParamKindOrd::Type,
+                        GenericArg::Const(..) => ParamKindOrd::Const,
+                    }, arg.span(), None)
+                }), GenericPosition::Arg, generic_args.span());
                 // Type bindings such as `Item=impl Debug` in `Iterator<Item=Debug>`
                 // are allowed to contain nested `impl Trait`.
                 self.with_impl_trait(None, |this| {
@@ -526,27 +621,27 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
     }
 
     fn visit_generics(&mut self, generics: &'a Generics) {
-        let mut seen_non_lifetime_param = false;
-        let mut seen_default = None;
+        let mut prev_ty_default = None;
         for param in &generics.params {
-            match (&param.kind, seen_non_lifetime_param) {
-                (GenericParamKind::Lifetime { .. }, true) => {
+            if let GenericParamKind::Type { ref default, .. } = param.kind {
+                if default.is_some() {
+                    prev_ty_default = Some(param.ident.span);
+                } else if let Some(span) = prev_ty_default {
                     self.err_handler()
-                        .span_err(param.ident.span, "lifetime parameters must be leading");
-                },
-                (GenericParamKind::Lifetime { .. }, false) => {}
-                (GenericParamKind::Type { ref default, .. }, _) => {
-                    seen_non_lifetime_param = true;
-                    if default.is_some() {
-                        seen_default = Some(param.ident.span);
-                    } else if let Some(span) = seen_default {
-                        self.err_handler()
-                            .span_err(span, "type parameters with a default must be trailing");
-                        break;
-                    }
+                        .span_err(span, "type parameters with a default must be trailing");
+                    break;
                 }
             }
         }
+
+        validate_generics_order(self.err_handler(), generics.params.iter().map(|param| {
+            (match param.kind {
+                GenericParamKind::Lifetime { .. } => ParamKindOrd::Lifetime,
+                GenericParamKind::Type { .. } => ParamKindOrd::Type,
+                GenericParamKind::Const { .. } => ParamKindOrd::Const,
+            }, param.ident.span, Some(param.ident))
+        }), GenericPosition::Param, generics.span);
+
         for predicate in &generics.where_clause.predicates {
             if let WherePredicate::EqPredicate(ref predicate) = *predicate {
                 self.err_handler()
@@ -554,6 +649,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                                                supported in where clauses (see #20041)");
             }
         }
+
         visit::walk_generics(self, generics)
     }
 

From 06abaee21ba25b4d5ebaf014928269734ad9ee15 Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Tue, 5 Feb 2019 16:52:31 +0100
Subject: [PATCH 10/28] Add error for const parameters depending on type
 parameters

Co-Authored-By: Gabriel Smith <yodaldevoid@users.noreply.github.com>
---
 src/librustc_resolve/diagnostics.rs | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs
index 0db8689c0c17..a5f9124674a5 100644
--- a/src/librustc_resolve/diagnostics.rs
+++ b/src/librustc_resolve/diagnostics.rs
@@ -414,8 +414,8 @@ https://doc.rust-lang.org/reference.html#use-declarations
 "##,
 
 E0401: r##"
-Inner items do not inherit type parameters from the functions they are embedded
-in.
+Inner items do not inherit type or const parameters from the functions
+they are embedded in.
 
 Erroneous code example:
 
@@ -1642,6 +1642,17 @@ fn main() {
 ```
 "##,
 
+E0670: r##"
+Const parameters cannot depend on type parameters.
+The following is therefore invalid:
+
+```
+fn const_id<T, const N: T>() -> T {
+    N
+}
+```
+"##,
+
 }
 
 register_diagnostics! {

From 3991ba76ee25785b84d3cb3f345780bd48783529 Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Tue, 5 Feb 2019 16:53:26 +0100
Subject: [PATCH 11/28] Support const generics in save analysis

Co-Authored-By: Gabriel Smith <yodaldevoid@users.noreply.github.com>
---
 src/librustc_save_analysis/dump_visitor.rs | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index 995df3802aab..91e9c7745d28 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -364,6 +364,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
                         );
                     }
                 }
+                ast::GenericParamKind::Const { .. } => {}
             }
         }
         self.visit_generics(generics);
@@ -1447,9 +1448,16 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc
 
     fn visit_generics(&mut self, generics: &'l ast::Generics) {
         for param in &generics.params {
-            if let ast::GenericParamKind::Type { ref default, .. } = param.kind {
-                self.process_bounds(&param.bounds);
-                if let Some(ref ty) = default {
+            match param.kind {
+                ast::GenericParamKind::Lifetime { .. } => {}
+                ast::GenericParamKind::Type { ref default, .. } => {
+                    self.process_bounds(&param.bounds);
+                    if let Some(ref ty) = default {
+                        self.visit_ty(&ty);
+                    }
+                }
+                ast::GenericParamKind::Const { ref ty } => {
+                    self.process_bounds(&param.bounds);
                     self.visit_ty(&ty);
                 }
             }

From 8fd597900629b215e858eebcfb24ab542364cc0e Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Tue, 5 Feb 2019 16:58:53 +0100
Subject: [PATCH 12/28] Add const generics feature gate test

Co-Authored-By: Gabriel Smith <yodaldevoid@users.noreply.github.com>
---
 .../feature-gate-const_generics.rs            |  6 +++++
 .../feature-gate-const_generics.stderr        | 25 +++++++++++++++++++
 2 files changed, 31 insertions(+)
 create mode 100644 src/test/ui/feature-gates/feature-gate-const_generics.rs
 create mode 100644 src/test/ui/feature-gates/feature-gate-const_generics.stderr

diff --git a/src/test/ui/feature-gates/feature-gate-const_generics.rs b/src/test/ui/feature-gates/feature-gate-const_generics.rs
new file mode 100644
index 000000000000..a8a4ed577229
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-const_generics.rs
@@ -0,0 +1,6 @@
+fn foo<const X: ()>() {} //~ ERROR const generics are unstable
+//~^ const generics in any position are currently unsupported
+
+struct Foo<const X: usize>([(); X]); //~ ERROR const generics are unstable
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-const_generics.stderr b/src/test/ui/feature-gates/feature-gate-const_generics.stderr
new file mode 100644
index 000000000000..905cc07b6a17
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-const_generics.stderr
@@ -0,0 +1,25 @@
+error[E0658]: const generics are unstable (see issue #44580)
+  --> $DIR/feature-gate-const_generics.rs:1:14
+   |
+LL | fn foo<const X: ()>() {} //~ ERROR const generics are unstable
+   |              ^
+   |
+   = help: add #![feature(const_generics)] to the crate attributes to enable
+
+error[E0658]: const generics are unstable (see issue #44580)
+  --> $DIR/feature-gate-const_generics.rs:4:18
+   |
+LL | struct Foo<const X: usize>([(); X]); //~ ERROR const generics are unstable
+   |                  ^
+   |
+   = help: add #![feature(const_generics)] to the crate attributes to enable
+
+error: const generics in any position are currently unsupported
+  --> $DIR/feature-gate-const_generics.rs:1:14
+   |
+LL | fn foo<const X: ()>() {} //~ ERROR const generics are unstable
+   |              ^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0658`.

From 455d659e91c6e7b0b9eee15066e85180b9ade584 Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Tue, 5 Feb 2019 17:00:19 +0100
Subject: [PATCH 13/28] Update tests

Co-Authored-By: Gabriel Smith <yodaldevoid@users.noreply.github.com>
---
 .../attrs-with-no-formal-in-generics-1.rs     |   2 +-
 .../attrs-with-no-formal-in-generics-1.stderr |   2 +-
 .../attrs-with-no-formal-in-generics-2.rs     |   2 +-
 .../attrs-with-no-formal-in-generics-2.stderr |   2 +-
 .../attrs-with-no-formal-in-generics-3.rs     |   2 +-
 .../attrs-with-no-formal-in-generics-3.stderr |   2 +-
 .../duplicate/duplicate-type-parameter.stderr |  14 +-
 src/test/ui/error-codes/E0403.stderr          |   2 +-
 src/test/ui/issues/issue-20616-3.rs           |   6 +-
 src/test/ui/issues/issue-20616-3.stderr       |   6 +-
 src/test/ui/issues/issue-20616-4.rs           |   4 +-
 src/test/ui/issues/issue-20616-4.stderr       |   6 +-
 src/test/ui/issues/issue-20616-5.rs           |   4 +-
 src/test/ui/issues/issue-20616-5.stderr       |   6 +-
 src/test/ui/issues/issue-20616-6.rs           |   4 +-
 src/test/ui/issues/issue-20616-6.stderr       |   6 +-
 src/test/ui/issues/issue-20616-7.rs           |   6 +-
 src/test/ui/issues/issue-20616-7.stderr       |   6 +-
 src/test/ui/issues/issue-20616-8.rs           |   6 +-
 src/test/ui/issues/issue-20616-8.stderr       |   6 +-
 src/test/ui/issues/issue-20616-9.rs           |   6 +-
 src/test/ui/issues/issue-20616-9.stderr       |   6 +-
 .../ui/lifetime-before-type-params.stderr     |  24 +--
 src/test/ui/parser/bounds-lifetime.rs         |   2 +-
 src/test/ui/parser/bounds-lifetime.stderr     |   6 +-
 src/test/ui/parser/issue-14303-enum.stderr    |   6 +-
 src/test/ui/parser/issue-14303-fn-def.stderr  |   6 +-
 src/test/ui/parser/issue-14303-fncall.rs      |   2 +-
 src/test/ui/parser/issue-14303-fncall.stderr  |   8 +-
 src/test/ui/parser/issue-14303-impl.stderr    |   6 +-
 src/test/ui/parser/issue-14303-path.rs        |   2 +-
 src/test/ui/parser/issue-14303-path.stderr    |  10 +-
 src/test/ui/parser/issue-14303-struct.stderr  |   6 +-
 src/test/ui/parser/issue-14303-trait.stderr   |   6 +-
 src/test/ui/parser/issue-32214.rs             |   2 +-
 src/test/ui/parser/issue-32214.stderr         |  12 +-
 .../ui/parser/removed-syntax-uniq-mut-ty.rs   |   2 +-
 .../parser/removed-syntax-uniq-mut-ty.stderr  |   6 +-
 .../empty_generics.rs                         |   2 +-
 .../empty_generics.stderr                     |   4 +-
 .../suggestions/suggest-move-lifetimes.stderr |  24 +--
 src/test/ui/suggestions/suggest-move-types.rs |  20 ++-
 .../ui/suggestions/suggest-move-types.stderr  | 167 +++++++++---------
 .../ui/traits/trait-object-vs-lifetime.rs     |   2 +-
 .../ui/traits/trait-object-vs-lifetime.stderr |   8 +-
 45 files changed, 182 insertions(+), 257 deletions(-)

diff --git a/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-1.rs b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-1.rs
index d7feb0385307..2ef5f13f3d46 100644
--- a/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-1.rs
+++ b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-1.rs
@@ -7,7 +7,7 @@
 struct RefIntPair<'a, 'b>(&'a u32, &'b u32);
 
 impl<#[rustc_1] 'a, 'b, #[oops]> RefIntPair<'a, 'b> {
-    //~^ ERROR trailing attribute after lifetime parameters
+    //~^ ERROR trailing attribute after lifetime parameter
 }
 
 fn main() {
diff --git a/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-1.stderr b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-1.stderr
index c4c0cee5ccc3..97c0a19a3da3 100644
--- a/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-1.stderr
+++ b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-1.stderr
@@ -1,4 +1,4 @@
-error: trailing attribute after lifetime parameters
+error: trailing attribute after lifetime parameter
   --> $DIR/attrs-with-no-formal-in-generics-1.rs:9:25
    |
 LL | impl<#[rustc_1] 'a, 'b, #[oops]> RefIntPair<'a, 'b> {
diff --git a/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-2.rs b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-2.rs
index f9db6a5f72af..f58ddd5fbda0 100644
--- a/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-2.rs
+++ b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-2.rs
@@ -7,6 +7,6 @@
 struct RefAny<'a, T>(&'a T);
 
 impl<#[rustc_1] 'a, #[rustc_2] T, #[oops]> RefAny<'a, T> {}
-//~^ ERROR trailing attribute after type parameters
+//~^ ERROR trailing attribute after type parameter
 
 fn main() {}
diff --git a/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-2.stderr b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-2.stderr
index 9099d74ce1be..ff7ced77f25b 100644
--- a/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-2.stderr
+++ b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-2.stderr
@@ -1,4 +1,4 @@
-error: trailing attribute after type parameters
+error: trailing attribute after type parameter
   --> $DIR/attrs-with-no-formal-in-generics-2.rs:9:35
    |
 LL | impl<#[rustc_1] 'a, #[rustc_2] T, #[oops]> RefAny<'a, T> {}
diff --git a/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-3.rs b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-3.rs
index e9f908d479f6..44a7c9d7c8b6 100644
--- a/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-3.rs
+++ b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-3.rs
@@ -6,7 +6,7 @@ struct RefIntPair<'a, 'b>(&'a u32, &'b u32);
 
 fn hof_lt<Q>(_: Q)
     where Q: for <#[allow(unused)] 'a, 'b, #[oops]> Fn(RefIntPair<'a,'b>) -> &'b u32
-    //~^ ERROR trailing attribute after lifetime parameters
+    //~^ ERROR trailing attribute after lifetime parameter
 {}
 
 fn main() {}
diff --git a/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-3.stderr b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-3.stderr
index 452f0ea5e175..b383e21e1612 100644
--- a/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-3.stderr
+++ b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-3.stderr
@@ -1,4 +1,4 @@
-error: trailing attribute after lifetime parameters
+error: trailing attribute after lifetime parameter
   --> $DIR/attrs-with-no-formal-in-generics-3.rs:8:44
    |
 LL |     where Q: for <#[allow(unused)] 'a, 'b, #[oops]> Fn(RefIntPair<'a,'b>) -> &'b u32
diff --git a/src/test/ui/duplicate/duplicate-type-parameter.stderr b/src/test/ui/duplicate/duplicate-type-parameter.stderr
index 41750d4bb362..17d48edc35c9 100644
--- a/src/test/ui/duplicate/duplicate-type-parameter.stderr
+++ b/src/test/ui/duplicate/duplicate-type-parameter.stderr
@@ -1,4 +1,4 @@
-error[E0403]: the name `T` is already used for a type parameter in this type parameter list
+error[E0403]: the name `T` is already used for a generic parameter in this list of generic parameters
   --> $DIR/duplicate-type-parameter.rs:1:12
    |
 LL | type Foo<T,T> = Option<T>;
@@ -6,7 +6,7 @@ LL | type Foo<T,T> = Option<T>;
    |          |
    |          first use of `T`
 
-error[E0403]: the name `T` is already used for a type parameter in this type parameter list
+error[E0403]: the name `T` is already used for a generic parameter in this list of generic parameters
   --> $DIR/duplicate-type-parameter.rs:4:14
    |
 LL | struct Bar<T,T>(T);
@@ -14,7 +14,7 @@ LL | struct Bar<T,T>(T);
    |            |
    |            first use of `T`
 
-error[E0403]: the name `T` is already used for a type parameter in this type parameter list
+error[E0403]: the name `T` is already used for a generic parameter in this list of generic parameters
   --> $DIR/duplicate-type-parameter.rs:7:14
    |
 LL | struct Baz<T,T> {
@@ -22,7 +22,7 @@ LL | struct Baz<T,T> {
    |            |
    |            first use of `T`
 
-error[E0403]: the name `T` is already used for a type parameter in this type parameter list
+error[E0403]: the name `T` is already used for a generic parameter in this list of generic parameters
   --> $DIR/duplicate-type-parameter.rs:12:12
    |
 LL | enum Boo<T,T> {
@@ -30,7 +30,7 @@ LL | enum Boo<T,T> {
    |          |
    |          first use of `T`
 
-error[E0403]: the name `T` is already used for a type parameter in this type parameter list
+error[E0403]: the name `T` is already used for a generic parameter in this list of generic parameters
   --> $DIR/duplicate-type-parameter.rs:18:11
    |
 LL | fn quux<T,T>(x: T) {}
@@ -38,7 +38,7 @@ LL | fn quux<T,T>(x: T) {}
    |         |
    |         first use of `T`
 
-error[E0403]: the name `T` is already used for a type parameter in this type parameter list
+error[E0403]: the name `T` is already used for a generic parameter in this list of generic parameters
   --> $DIR/duplicate-type-parameter.rs:21:13
    |
 LL | trait Qux<T,T> {}
@@ -46,7 +46,7 @@ LL | trait Qux<T,T> {}
    |           |
    |           first use of `T`
 
-error[E0403]: the name `T` is already used for a type parameter in this type parameter list
+error[E0403]: the name `T` is already used for a generic parameter in this list of generic parameters
   --> $DIR/duplicate-type-parameter.rs:24:8
    |
 LL | impl<T,T> Qux<T,T> for Option<T> {}
diff --git a/src/test/ui/error-codes/E0403.stderr b/src/test/ui/error-codes/E0403.stderr
index 919a82dbe1a7..b92464750296 100644
--- a/src/test/ui/error-codes/E0403.stderr
+++ b/src/test/ui/error-codes/E0403.stderr
@@ -1,4 +1,4 @@
-error[E0403]: the name `T` is already used for a type parameter in this type parameter list
+error[E0403]: the name `T` is already used for a generic parameter in this list of generic parameters
   --> $DIR/E0403.rs:1:11
    |
 LL | fn foo<T, T>(s: T, u: T) {} //~ ERROR E0403
diff --git a/src/test/ui/issues/issue-20616-3.rs b/src/test/ui/issues/issue-20616-3.rs
index e84506ee249d..9f983f74f5b1 100644
--- a/src/test/ui/issues/issue-20616-3.rs
+++ b/src/test/ui/issues/issue-20616-3.rs
@@ -1,8 +1,8 @@
+// ignore-tidy-linelength
+
 // We need all these 9 issue-20616-N.rs files
 // because we can only catch one parsing error at a time
 
-
-
 type Type_1_<'a, T> = &'a T;
 
 
@@ -12,7 +12,7 @@ type Type_1_<'a, T> = &'a T;
 //type Type_2 = Type_1_<'static ()>; // error: expected `,` or `>` after lifetime name, found `(`
 
 
-type Type_3<T> = Box<T,,>; //~ error: expected one of `>`, identifier, lifetime, or type, found `,`
+type Type_3<T> = Box<T,,>; //~ error: expected one of `>`, const, identifier, lifetime, or type, found `,`
 
 
 //type Type_4<T> = Type_1_<'static,, T>; // error: expected type, found `,`
diff --git a/src/test/ui/issues/issue-20616-3.stderr b/src/test/ui/issues/issue-20616-3.stderr
index 5247298b7cc2..e8edb5ba70f5 100644
--- a/src/test/ui/issues/issue-20616-3.stderr
+++ b/src/test/ui/issues/issue-20616-3.stderr
@@ -1,8 +1,8 @@
-error: expected one of `>`, identifier, lifetime, or type, found `,`
+error: expected one of `>`, const, identifier, lifetime, or type, found `,`
   --> $DIR/issue-20616-3.rs:15:24
    |
-LL | type Type_3<T> = Box<T,,>; //~ error: expected one of `>`, identifier, lifetime, or type, found `,`
-   |                        ^ expected one of `>`, identifier, lifetime, or type here
+LL | type Type_3<T> = Box<T,,>; //~ error: expected one of `>`, const, identifier, lifetime, or type, found `,`
+   |                        ^ expected one of `>`, const, identifier, lifetime, or type here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-20616-4.rs b/src/test/ui/issues/issue-20616-4.rs
index 785a6fa7d9a2..e9a34a04667b 100644
--- a/src/test/ui/issues/issue-20616-4.rs
+++ b/src/test/ui/issues/issue-20616-4.rs
@@ -1,8 +1,6 @@
 // We need all these 9 issue-20616-N.rs files
 // because we can only catch one parsing error at a time
 
-
-
 type Type_1_<'a, T> = &'a T;
 
 
@@ -16,7 +14,7 @@ type Type_1_<'a, T> = &'a T;
 
 
 type Type_4<T> = Type_1_<'static,, T>;
-//~^ error: expected one of `>`, identifier, lifetime, or type, found `,`
+//~^ error: expected one of `>`, const, identifier, lifetime, or type, found `,`
 
 
 type Type_5_<'a> = Type_1_<'a, ()>;
diff --git a/src/test/ui/issues/issue-20616-4.stderr b/src/test/ui/issues/issue-20616-4.stderr
index 74c38d9e97d6..22a655465e83 100644
--- a/src/test/ui/issues/issue-20616-4.stderr
+++ b/src/test/ui/issues/issue-20616-4.stderr
@@ -1,8 +1,8 @@
-error: expected one of `>`, identifier, lifetime, or type, found `,`
-  --> $DIR/issue-20616-4.rs:18:34
+error: expected one of `>`, const, identifier, lifetime, or type, found `,`
+  --> $DIR/issue-20616-4.rs:16:34
    |
 LL | type Type_4<T> = Type_1_<'static,, T>;
-   |                                  ^ expected one of `>`, identifier, lifetime, or type here
+   |                                  ^ expected one of `>`, const, identifier, lifetime, or type here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-20616-5.rs b/src/test/ui/issues/issue-20616-5.rs
index 71dcc1f3a024..23862516d2cb 100644
--- a/src/test/ui/issues/issue-20616-5.rs
+++ b/src/test/ui/issues/issue-20616-5.rs
@@ -1,8 +1,6 @@
 // We need all these 9 issue-20616-N.rs files
 // because we can only catch one parsing error at a time
 
-
-
 type Type_1_<'a, T> = &'a T;
 
 
@@ -22,7 +20,7 @@ type Type_5_<'a> = Type_1_<'a, ()>;
 
 
 type Type_5<'a> = Type_1_<'a, (),,>;
-//~^ error: expected one of `>`, identifier, lifetime, or type, found `,`
+//~^ error: expected one of `>`, const, identifier, lifetime, or type, found `,`
 
 
 //type Type_6 = Type_5_<'a,,>; // error: expected type, found `,`
diff --git a/src/test/ui/issues/issue-20616-5.stderr b/src/test/ui/issues/issue-20616-5.stderr
index 38457beadc44..d83fc41f43ec 100644
--- a/src/test/ui/issues/issue-20616-5.stderr
+++ b/src/test/ui/issues/issue-20616-5.stderr
@@ -1,8 +1,8 @@
-error: expected one of `>`, identifier, lifetime, or type, found `,`
-  --> $DIR/issue-20616-5.rs:24:34
+error: expected one of `>`, const, identifier, lifetime, or type, found `,`
+  --> $DIR/issue-20616-5.rs:22:34
    |
 LL | type Type_5<'a> = Type_1_<'a, (),,>;
-   |                                  ^ expected one of `>`, identifier, lifetime, or type here
+   |                                  ^ expected one of `>`, const, identifier, lifetime, or type here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-20616-6.rs b/src/test/ui/issues/issue-20616-6.rs
index da32da488524..dc327f3f7882 100644
--- a/src/test/ui/issues/issue-20616-6.rs
+++ b/src/test/ui/issues/issue-20616-6.rs
@@ -1,8 +1,6 @@
 // We need all these 9 issue-20616-N.rs files
 // because we can only catch one parsing error at a time
 
-
-
 type Type_1_<'a, T> = &'a T;
 
 
@@ -25,7 +23,7 @@ type Type_5_<'a> = Type_1_<'a, ()>;
 
 
 type Type_6 = Type_5_<'a,,>;
-//~^ error: expected one of `>`, identifier, lifetime, or type, found `,`
+//~^ error: expected one of `>`, const, identifier, lifetime, or type, found `,`
 
 
 //type Type_7 = Box<(),,>; // error: expected type, found `,`
diff --git a/src/test/ui/issues/issue-20616-6.stderr b/src/test/ui/issues/issue-20616-6.stderr
index 55b1d031a391..0740df595234 100644
--- a/src/test/ui/issues/issue-20616-6.stderr
+++ b/src/test/ui/issues/issue-20616-6.stderr
@@ -1,8 +1,8 @@
-error: expected one of `>`, identifier, lifetime, or type, found `,`
-  --> $DIR/issue-20616-6.rs:27:26
+error: expected one of `>`, const, identifier, lifetime, or type, found `,`
+  --> $DIR/issue-20616-6.rs:25:26
    |
 LL | type Type_6 = Type_5_<'a,,>;
-   |                          ^ expected one of `>`, identifier, lifetime, or type here
+   |                          ^ expected one of `>`, const, identifier, lifetime, or type here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-20616-7.rs b/src/test/ui/issues/issue-20616-7.rs
index feaaff2c8902..277b45245063 100644
--- a/src/test/ui/issues/issue-20616-7.rs
+++ b/src/test/ui/issues/issue-20616-7.rs
@@ -1,8 +1,8 @@
+// ignore-tidy-linelength
+
 // We need all these 9 issue-20616-N.rs files
 // because we can only catch one parsing error at a time
 
-
-
 type Type_1_<'a, T> = &'a T;
 
 
@@ -27,7 +27,7 @@ type Type_5_<'a> = Type_1_<'a, ()>;
 //type Type_6 = Type_5_<'a,,>; // error: expected type, found `,`
 
 
-type Type_7 = Box<(),,>; //~ error: expected one of `>`, identifier, lifetime, or type, found `,`
+type Type_7 = Box<(),,>; //~ error: expected one of `>`, const, identifier, lifetime, or type, found `,`
 
 
 //type Type_8<'a,,> = &'a (); // error: expected ident, found `,`
diff --git a/src/test/ui/issues/issue-20616-7.stderr b/src/test/ui/issues/issue-20616-7.stderr
index 8b5f67c703f6..c1422d849fc7 100644
--- a/src/test/ui/issues/issue-20616-7.stderr
+++ b/src/test/ui/issues/issue-20616-7.stderr
@@ -1,8 +1,8 @@
-error: expected one of `>`, identifier, lifetime, or type, found `,`
+error: expected one of `>`, const, identifier, lifetime, or type, found `,`
   --> $DIR/issue-20616-7.rs:30:22
    |
-LL | type Type_7 = Box<(),,>; //~ error: expected one of `>`, identifier, lifetime, or type, found `,`
-   |                      ^ expected one of `>`, identifier, lifetime, or type here
+LL | type Type_7 = Box<(),,>; //~ error: expected one of `>`, const, identifier, lifetime, or type, found `,`
+   |                      ^ expected one of `>`, const, identifier, lifetime, or type here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-20616-8.rs b/src/test/ui/issues/issue-20616-8.rs
index 2fc7243559a3..756119e01271 100644
--- a/src/test/ui/issues/issue-20616-8.rs
+++ b/src/test/ui/issues/issue-20616-8.rs
@@ -1,8 +1,8 @@
+// ignore-tidy-linelength
+
 // We need all these 9 issue-20616-N.rs files
 // because we can only catch one parsing error at a time
 
-
-
 type Type_1_<'a, T> = &'a T;
 
 
@@ -30,7 +30,7 @@ type Type_5_<'a> = Type_1_<'a, ()>;
 //type Type_7 = Box<(),,>; // error: expected type, found `,`
 
 
-type Type_8<'a,,> = &'a (); //~ error: expected one of `>`, identifier, or lifetime, found `,`
+type Type_8<'a,,> = &'a (); //~ error: expected one of `>`, `const`, identifier, or lifetime, found `,`
 
 
 //type Type_9<T,,> = Box<T>; // error: expected identifier, found `,`
diff --git a/src/test/ui/issues/issue-20616-8.stderr b/src/test/ui/issues/issue-20616-8.stderr
index cdeb544f07c4..cfe3ec57712d 100644
--- a/src/test/ui/issues/issue-20616-8.stderr
+++ b/src/test/ui/issues/issue-20616-8.stderr
@@ -1,8 +1,8 @@
-error: expected one of `>`, identifier, or lifetime, found `,`
+error: expected one of `>`, `const`, identifier, or lifetime, found `,`
   --> $DIR/issue-20616-8.rs:33:16
    |
-LL | type Type_8<'a,,> = &'a (); //~ error: expected one of `>`, identifier, or lifetime, found `,`
-   |                ^ expected one of `>`, identifier, or lifetime here
+LL | type Type_8<'a,,> = &'a (); //~ error: expected one of `>`, `const`, identifier, or lifetime, found `,`
+   |                ^ expected one of `>`, `const`, identifier, or lifetime here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-20616-9.rs b/src/test/ui/issues/issue-20616-9.rs
index b14a5b0ff36d..6074fbb2204c 100644
--- a/src/test/ui/issues/issue-20616-9.rs
+++ b/src/test/ui/issues/issue-20616-9.rs
@@ -1,8 +1,8 @@
+// ignore-tidy-linelength
+
 // We need all these 9 issue-20616-N.rs files
 // because we can only catch one parsing error at a time
 
-
-
 type Type_1_<'a, T> = &'a T;
 
 
@@ -33,4 +33,4 @@ type Type_5_<'a> = Type_1_<'a, ()>;
 //type Type_8<'a,,> = &'a (); // error: expected identifier, found `,`
 
 
-type Type_9<T,,> = Box<T>; //~ error: expected one of `>`, identifier, or lifetime, found `,`
+type Type_9<T,,> = Box<T>; //~ error: expected one of `>`, `const`, identifier, or lifetime, found `,`
diff --git a/src/test/ui/issues/issue-20616-9.stderr b/src/test/ui/issues/issue-20616-9.stderr
index dfe705c6f12e..960e8c8c0865 100644
--- a/src/test/ui/issues/issue-20616-9.stderr
+++ b/src/test/ui/issues/issue-20616-9.stderr
@@ -1,8 +1,8 @@
-error: expected one of `>`, identifier, or lifetime, found `,`
+error: expected one of `>`, `const`, identifier, or lifetime, found `,`
   --> $DIR/issue-20616-9.rs:36:15
    |
-LL | type Type_9<T,,> = Box<T>; //~ error: expected one of `>`, identifier, or lifetime, found `,`
-   |               ^ expected one of `>`, identifier, or lifetime here
+LL | type Type_9<T,,> = Box<T>; //~ error: expected one of `>`, `const`, identifier, or lifetime, found `,`
+   |               ^ expected one of `>`, `const`, identifier, or lifetime here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lifetime-before-type-params.stderr b/src/test/ui/lifetime-before-type-params.stderr
index 7ac8dffdfbe0..3cef5db66c66 100644
--- a/src/test/ui/lifetime-before-type-params.stderr
+++ b/src/test/ui/lifetime-before-type-params.stderr
@@ -2,41 +2,25 @@ error: lifetime parameters must be declared prior to type parameters
   --> $DIR/lifetime-before-type-params.rs:2:13
    |
 LL | fn first<T, 'a, 'b>() {}
-   |             ^^  ^^
-help: move the lifetime parameter prior to the first type parameter
-   |
-LL | fn first<'a, 'b, T>() {}
-   |          ^^^ ^^^ --
+   |         ----^^--^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, 'b, T>`
 
 error: lifetime parameters must be declared prior to type parameters
   --> $DIR/lifetime-before-type-params.rs:4:18
    |
 LL | fn second<'a, T, 'b>() {}
-   |                  ^^
-help: move the lifetime parameter prior to the first type parameter
-   |
-LL | fn second<'a, 'b, T>() {}
-   |               ^^^ --
+   |          --------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, 'b, T>`
 
 error: lifetime parameters must be declared prior to type parameters
   --> $DIR/lifetime-before-type-params.rs:6:16
    |
 LL | fn third<T, U, 'a>() {}
-   |                ^^
-help: move the lifetime parameter prior to the first type parameter
-   |
-LL | fn third<'a, T, U>() {}
-   |          ^^^    --
+   |         -------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T, U>`
 
 error: lifetime parameters must be declared prior to type parameters
   --> $DIR/lifetime-before-type-params.rs:8:18
    |
 LL | fn fourth<'a, T, 'b, U, 'c, V>() {}
-   |                  ^^     ^^
-help: move the lifetime parameter prior to the first type parameter
-   |
-LL | fn fourth<'a, 'b, 'c, T, U, V>() {}
-   |               ^^^ ^^^ -- --
+   |          --------^^-----^^---- help: reorder the parameters: lifetimes, then types, then consts: `<'a, 'b, 'c, T, U, V>`
 
 error[E0601]: `main` function not found in crate `lifetime_before_type_params`
    |
diff --git a/src/test/ui/parser/bounds-lifetime.rs b/src/test/ui/parser/bounds-lifetime.rs
index 89a969bb2e2a..9225cfce94eb 100644
--- a/src/test/ui/parser/bounds-lifetime.rs
+++ b/src/test/ui/parser/bounds-lifetime.rs
@@ -6,6 +6,6 @@ type A = for<'a: 'b + 'c> fn(); // OK (rejected later by ast_validation)
 type A = for<'a: 'b,> fn(); // OK(rejected later by ast_validation)
 type A = for<'a: 'b +> fn(); // OK (rejected later by ast_validation)
 type A = for<'a, T> fn(); // OK (rejected later by ast_validation)
-type A = for<,> fn(); //~ ERROR expected one of `>`, identifier, or lifetime, found `,`
+type A = for<,> fn(); //~ ERROR expected one of `>`, `const`, identifier, or lifetime, found `,`
 
 fn main() {}
diff --git a/src/test/ui/parser/bounds-lifetime.stderr b/src/test/ui/parser/bounds-lifetime.stderr
index f39e5beb6ac9..191ea3ebd070 100644
--- a/src/test/ui/parser/bounds-lifetime.stderr
+++ b/src/test/ui/parser/bounds-lifetime.stderr
@@ -1,8 +1,8 @@
-error: expected one of `>`, identifier, or lifetime, found `,`
+error: expected one of `>`, `const`, identifier, or lifetime, found `,`
   --> $DIR/bounds-lifetime.rs:9:14
    |
-LL | type A = for<,> fn(); //~ ERROR expected one of `>`, identifier, or lifetime, found `,`
-   |              ^ expected one of `>`, identifier, or lifetime here
+LL | type A = for<,> fn(); //~ ERROR expected one of `>`, `const`, identifier, or lifetime, found `,`
+   |              ^ expected one of `>`, `const`, identifier, or lifetime here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/issue-14303-enum.stderr b/src/test/ui/parser/issue-14303-enum.stderr
index a31429e7228c..bcecd75b1abb 100644
--- a/src/test/ui/parser/issue-14303-enum.stderr
+++ b/src/test/ui/parser/issue-14303-enum.stderr
@@ -2,11 +2,7 @@ error: lifetime parameters must be declared prior to type parameters
   --> $DIR/issue-14303-enum.rs:1:15
    |
 LL | enum X<'a, T, 'b> {
-   |               ^^
-help: move the lifetime parameter prior to the first type parameter
-   |
-LL | enum X<'a, 'b, T> {
-   |            ^^^ --
+   |       --------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, 'b, T>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/issue-14303-fn-def.stderr b/src/test/ui/parser/issue-14303-fn-def.stderr
index 4582aeef428d..082c37e0be79 100644
--- a/src/test/ui/parser/issue-14303-fn-def.stderr
+++ b/src/test/ui/parser/issue-14303-fn-def.stderr
@@ -2,11 +2,7 @@ error: lifetime parameters must be declared prior to type parameters
   --> $DIR/issue-14303-fn-def.rs:1:15
    |
 LL | fn foo<'a, T, 'b>(x: &'a T) {}
-   |               ^^
-help: move the lifetime parameter prior to the first type parameter
-   |
-LL | fn foo<'a, 'b, T>(x: &'a T) {}
-   |            ^^^ --
+   |       --------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, 'b, T>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/issue-14303-fncall.rs b/src/test/ui/parser/issue-14303-fncall.rs
index 17b9b766b218..39694198cdb4 100644
--- a/src/test/ui/parser/issue-14303-fncall.rs
+++ b/src/test/ui/parser/issue-14303-fncall.rs
@@ -11,7 +11,7 @@ fn foo<'a, 'b>(start: &'a usize, end: &'a usize) {
     let _x = (*start..*end)
         .map(|x| S { a: start, b: end })
         .collect::<Vec<S<_, 'a>>>();
-        //~^ ERROR lifetime parameters must be declared prior to type parameters
+        //~^ ERROR lifetime arguments must be declared prior to type arguments
 }
 
 fn main() {}
diff --git a/src/test/ui/parser/issue-14303-fncall.stderr b/src/test/ui/parser/issue-14303-fncall.stderr
index 2a7364915949..8ef9f1a1a6c7 100644
--- a/src/test/ui/parser/issue-14303-fncall.stderr
+++ b/src/test/ui/parser/issue-14303-fncall.stderr
@@ -1,12 +1,8 @@
-error: lifetime parameters must be declared prior to type parameters
+error: lifetime arguments must be declared prior to type arguments
   --> $DIR/issue-14303-fncall.rs:13:29
    |
 LL |         .collect::<Vec<S<_, 'a>>>();
-   |                             ^^ must be declared prior to type parameters
-help: move the lifetime parameter prior to the first type parameter
-   |
-LL |         .collect::<Vec<S<'a, _>>>();
-   |                          ^^^ --
+   |                             ^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/issue-14303-impl.stderr b/src/test/ui/parser/issue-14303-impl.stderr
index a1953396153e..3b5615d2a9ec 100644
--- a/src/test/ui/parser/issue-14303-impl.stderr
+++ b/src/test/ui/parser/issue-14303-impl.stderr
@@ -2,11 +2,7 @@ error: lifetime parameters must be declared prior to type parameters
   --> $DIR/issue-14303-impl.rs:3:13
    |
 LL | impl<'a, T, 'b> X<T> {}
-   |             ^^
-help: move the lifetime parameter prior to the first type parameter
-   |
-LL | impl<'a, 'b, T> X<T> {}
-   |          ^^^ --
+   |     --------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, 'b, T>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/issue-14303-path.rs b/src/test/ui/parser/issue-14303-path.rs
index a08c89f3437b..386d19859e4a 100644
--- a/src/test/ui/parser/issue-14303-path.rs
+++ b/src/test/ui/parser/issue-14303-path.rs
@@ -8,6 +8,6 @@ mod foo {
 }
 
 fn bar<'a, 'b, 'c, T>(x: foo::X<'a, T, 'b, 'c>) {}
-//~^ ERROR lifetime parameters must be declared prior to type parameters
+//~^ ERROR lifetime arguments must be declared prior to type arguments
 
 fn main() {}
diff --git a/src/test/ui/parser/issue-14303-path.stderr b/src/test/ui/parser/issue-14303-path.stderr
index fb4fb32e11e5..19f2995ebee5 100644
--- a/src/test/ui/parser/issue-14303-path.stderr
+++ b/src/test/ui/parser/issue-14303-path.stderr
@@ -1,14 +1,8 @@
-error: lifetime parameters must be declared prior to type parameters
+error: lifetime arguments must be declared prior to type arguments
   --> $DIR/issue-14303-path.rs:10:40
    |
 LL | fn bar<'a, 'b, 'c, T>(x: foo::X<'a, T, 'b, 'c>) {}
-   |                                        ^^  ^^ must be declared prior to type parameters
-   |                                        |
-   |                                        must be declared prior to type parameters
-help: move the lifetime parameters prior to the first type parameter
-   |
-LL | fn bar<'a, 'b, 'c, T>(x: foo::X<'a, 'b, 'c, T>) {}
-   |                                     ^^^ ^^^ --
+   |                                        ^^  ^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/issue-14303-struct.stderr b/src/test/ui/parser/issue-14303-struct.stderr
index 668b8d1de689..dbd0b987dd19 100644
--- a/src/test/ui/parser/issue-14303-struct.stderr
+++ b/src/test/ui/parser/issue-14303-struct.stderr
@@ -2,11 +2,7 @@ error: lifetime parameters must be declared prior to type parameters
   --> $DIR/issue-14303-struct.rs:1:17
    |
 LL | struct X<'a, T, 'b> {
-   |                 ^^
-help: move the lifetime parameter prior to the first type parameter
-   |
-LL | struct X<'a, 'b, T> {
-   |              ^^^ --
+   |         --------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, 'b, T>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/issue-14303-trait.stderr b/src/test/ui/parser/issue-14303-trait.stderr
index 11ce0c44351a..7dfa62d823fd 100644
--- a/src/test/ui/parser/issue-14303-trait.stderr
+++ b/src/test/ui/parser/issue-14303-trait.stderr
@@ -2,11 +2,7 @@ error: lifetime parameters must be declared prior to type parameters
   --> $DIR/issue-14303-trait.rs:1:18
    |
 LL | trait Foo<'a, T, 'b> {}
-   |                  ^^
-help: move the lifetime parameter prior to the first type parameter
-   |
-LL | trait Foo<'a, 'b, T> {}
-   |               ^^^ --
+   |          --------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, 'b, T>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/issue-32214.rs b/src/test/ui/parser/issue-32214.rs
index 7e55bc038e76..7191a3234c08 100644
--- a/src/test/ui/parser/issue-32214.rs
+++ b/src/test/ui/parser/issue-32214.rs
@@ -3,6 +3,6 @@
 trait Trait<T> { type Item; }
 
 pub fn test<W, I: Trait<Item=(), W> >() {}
-//~^ ERROR type parameters must be declared prior to associated type bindings
+//~^ ERROR associated type bindings must be declared after generic parameters
 
 fn main() { }
diff --git a/src/test/ui/parser/issue-32214.stderr b/src/test/ui/parser/issue-32214.stderr
index 660e517c85a1..7022019a22f2 100644
--- a/src/test/ui/parser/issue-32214.stderr
+++ b/src/test/ui/parser/issue-32214.stderr
@@ -1,12 +1,10 @@
-error: type parameters must be declared prior to associated type bindings
-  --> $DIR/issue-32214.rs:5:34
+error: associated type bindings must be declared after generic parameters
+  --> $DIR/issue-32214.rs:5:25
    |
 LL | pub fn test<W, I: Trait<Item=(), W> >() {}
-   |                                  ^ must be declared prior to associated type bindings
-help: move the type parameter prior to the first associated type binding
-   |
-LL | pub fn test<W, I: Trait<W, Item=()> >() {}
-   |                         ^^       --
+   |                         -------^^^
+   |                         |
+   |                         this associated type binding should be moved after the generic parameters
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/removed-syntax-uniq-mut-ty.rs b/src/test/ui/parser/removed-syntax-uniq-mut-ty.rs
index 12de76d9d6d9..79d51f5595d2 100644
--- a/src/test/ui/parser/removed-syntax-uniq-mut-ty.rs
+++ b/src/test/ui/parser/removed-syntax-uniq-mut-ty.rs
@@ -1 +1 @@
-type mut_box = Box<mut isize>; //~ ERROR expected one of `>`, lifetime, or type, found `mut`
+type mut_box = Box<mut isize>; //~ ERROR expected one of `>`, const, lifetime, or type, found `mut`
diff --git a/src/test/ui/parser/removed-syntax-uniq-mut-ty.stderr b/src/test/ui/parser/removed-syntax-uniq-mut-ty.stderr
index 0177b19d74e7..b2759778d031 100644
--- a/src/test/ui/parser/removed-syntax-uniq-mut-ty.stderr
+++ b/src/test/ui/parser/removed-syntax-uniq-mut-ty.stderr
@@ -1,8 +1,8 @@
-error: expected one of `>`, lifetime, or type, found `mut`
+error: expected one of `>`, const, lifetime, or type, found `mut`
   --> $DIR/removed-syntax-uniq-mut-ty.rs:1:20
    |
-LL | type mut_box = Box<mut isize>; //~ ERROR expected one of `>`, lifetime, or type, found `mut`
-   |                    ^^^ expected one of `>`, lifetime, or type here
+LL | type mut_box = Box<mut isize>; //~ ERROR expected one of `>`, const, lifetime, or type, found `mut`
+   |                    ^^^ expected one of `>`, const, lifetime, or type here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/rfc1598-generic-associated-types/empty_generics.rs b/src/test/ui/rfc1598-generic-associated-types/empty_generics.rs
index 158ebc7d3888..afc27701920d 100644
--- a/src/test/ui/rfc1598-generic-associated-types/empty_generics.rs
+++ b/src/test/ui/rfc1598-generic-associated-types/empty_generics.rs
@@ -3,7 +3,7 @@
 
 trait Foo {
     type Bar<,>;
-    //~^ ERROR expected one of `>`, identifier, or lifetime, found `,`
+    //~^ ERROR expected one of `>`, `const`, identifier, or lifetime, found `,`
 }
 
 fn main() {}
diff --git a/src/test/ui/rfc1598-generic-associated-types/empty_generics.stderr b/src/test/ui/rfc1598-generic-associated-types/empty_generics.stderr
index 2a01b2a3f0fa..5b98302924e3 100644
--- a/src/test/ui/rfc1598-generic-associated-types/empty_generics.stderr
+++ b/src/test/ui/rfc1598-generic-associated-types/empty_generics.stderr
@@ -1,8 +1,8 @@
-error: expected one of `>`, identifier, or lifetime, found `,`
+error: expected one of `>`, `const`, identifier, or lifetime, found `,`
   --> $DIR/empty_generics.rs:5:14
    |
 LL |     type Bar<,>;
-   |              ^ expected one of `>`, identifier, or lifetime here
+   |              ^ expected one of `>`, `const`, identifier, or lifetime here
 
 warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash
   --> $DIR/empty_generics.rs:1:12
diff --git a/src/test/ui/suggestions/suggest-move-lifetimes.stderr b/src/test/ui/suggestions/suggest-move-lifetimes.stderr
index b36e927b5c0c..2d6dee062166 100644
--- a/src/test/ui/suggestions/suggest-move-lifetimes.stderr
+++ b/src/test/ui/suggestions/suggest-move-lifetimes.stderr
@@ -2,41 +2,25 @@ error: lifetime parameters must be declared prior to type parameters
   --> $DIR/suggest-move-lifetimes.rs:1:13
    |
 LL | struct A<T, 'a> { //~ ERROR lifetime parameters must be declared
-   |             ^^
-help: move the lifetime parameter prior to the first type parameter
-   |
-LL | struct A<'a, T> { //~ ERROR lifetime parameters must be declared
-   |          ^^^ --
+   |         ----^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T>`
 
 error: lifetime parameters must be declared prior to type parameters
   --> $DIR/suggest-move-lifetimes.rs:5:13
    |
 LL | struct B<T, 'a, U> { //~ ERROR lifetime parameters must be declared
-   |             ^^
-help: move the lifetime parameter prior to the first type parameter
-   |
-LL | struct B<'a, T, U> { //~ ERROR lifetime parameters must be declared
-   |          ^^^ --
+   |         ----^^---- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T, U>`
 
 error: lifetime parameters must be declared prior to type parameters
   --> $DIR/suggest-move-lifetimes.rs:10:16
    |
 LL | struct C<T, U, 'a> { //~ ERROR lifetime parameters must be declared
-   |                ^^
-help: move the lifetime parameter prior to the first type parameter
-   |
-LL | struct C<'a, T, U> { //~ ERROR lifetime parameters must be declared
-   |          ^^^    --
+   |         -------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T, U>`
 
 error: lifetime parameters must be declared prior to type parameters
   --> $DIR/suggest-move-lifetimes.rs:15:16
    |
 LL | struct D<T, U, 'a, 'b, V, 'c> { //~ ERROR lifetime parameters must be declared
-   |                ^^  ^^     ^^
-help: move the lifetime parameter prior to the first type parameter
-   |
-LL | struct D<'a, 'b, 'c, T, U, V> { //~ ERROR lifetime parameters must be declared
-   |          ^^^ ^^^ ^^^    -- --
+   |         -------^^--^^-----^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, 'b, 'c, T, U, V>`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/suggestions/suggest-move-types.rs b/src/test/ui/suggestions/suggest-move-types.rs
index fd10ba4350c4..890950ea08c5 100644
--- a/src/test/ui/suggestions/suggest-move-types.rs
+++ b/src/test/ui/suggestions/suggest-move-types.rs
@@ -25,19 +25,20 @@ trait ThreeWithLifetime<'a, 'b, 'c, T, U, V> {
   type C;
 }
 
-struct A<T, M: One<A=(), T>> { //~ ERROR type parameters must be declared
+struct A<T, M: One<A=(), T>> { //~ ERROR associated type bindings must be declared after generic parameters
     m: M,
     t: T,
 }
 
 
 struct Al<'a, T, M: OneWithLifetime<A=(), T, 'a>> {
-//~^ ERROR generic arguments must declare lifetimes, types and associated type bindings in that order
+//~^ ERROR associated type bindings must be declared after generic parameters
+//~^^ ERROR lifetime arguments must be declared prior to type arguments
     m: M,
     t: &'a T,
 }
 
-struct B<T, U, V, M: Three<A=(), B=(), C=(), T, U, V>> { //~ ERROR type parameters must be declared
+struct B<T, U, V, M: Three<A=(), B=(), C=(), T, U, V>> { //~ ERROR associated type bindings must be declared after generic parameters
     m: M,
     t: T,
     u: U,
@@ -45,14 +46,15 @@ struct B<T, U, V, M: Three<A=(), B=(), C=(), T, U, V>> { //~ ERROR type paramete
 }
 
 struct Bl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<A=(), B=(), C=(), T, U, V, 'a, 'b, 'c>> {
-//~^ ERROR generic arguments must declare lifetimes, types and associated type bindings in that order
+//~^ ERROR associated type bindings must be declared after generic parameters
+//~^^ ERROR lifetime arguments must be declared prior to type arguments
     m: M,
     t: &'a T,
     u: &'b U,
     v: &'c V,
 }
 
-struct C<T, U, V, M: Three<T, A=(), B=(), C=(), U, V>> { //~ ERROR type parameters must be declared
+struct C<T, U, V, M: Three<T, A=(), B=(), C=(), U, V>> { //~ ERROR associated type bindings must be declared after generic parameters
     m: M,
     t: T,
     u: U,
@@ -60,14 +62,15 @@ struct C<T, U, V, M: Three<T, A=(), B=(), C=(), U, V>> { //~ ERROR type paramete
 }
 
 struct Cl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<T, 'a, A=(), B=(), C=(), U, 'b, V, 'c>> {
-//~^ ERROR generic arguments must declare lifetimes, types and associated type bindings in that order
+//~^ ERROR associated type bindings must be declared after generic parameters
+//~^^ ERROR lifetime arguments must be declared prior to type arguments
     m: M,
     t: &'a T,
     u: &'b U,
     v: &'c V,
 }
 
-struct D<T, U, V, M: Three<T, A=(), B=(), U, C=(), V>> { //~ ERROR type parameters must be declared
+struct D<T, U, V, M: Three<T, A=(), B=(), U, C=(), V>> { //~ ERROR associated type bindings must be declared after generic parameters
     m: M,
     t: T,
     u: U,
@@ -75,7 +78,8 @@ struct D<T, U, V, M: Three<T, A=(), B=(), U, C=(), V>> { //~ ERROR type paramete
 }
 
 struct Dl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<T, 'a, A=(), B=(), U, 'b, C=(), V, 'c>> {
-//~^ ERROR generic arguments must declare lifetimes, types and associated type bindings in that order
+//~^ ERROR associated type bindings must be declared after generic parameters
+//~^^ ERROR lifetime arguments must be declared prior to type arguments
     m: M,
     t: &'a T,
     u: &'b U,
diff --git a/src/test/ui/suggestions/suggest-move-types.stderr b/src/test/ui/suggestions/suggest-move-types.stderr
index 3643d9a91245..0901b71911d4 100644
--- a/src/test/ui/suggestions/suggest-move-types.stderr
+++ b/src/test/ui/suggestions/suggest-move-types.stderr
@@ -1,107 +1,102 @@
-error: type parameters must be declared prior to associated type bindings
-  --> $DIR/suggest-move-types.rs:28:26
+error: associated type bindings must be declared after generic parameters
+  --> $DIR/suggest-move-types.rs:28:20
    |
-LL | struct A<T, M: One<A=(), T>> { //~ ERROR type parameters must be declared
-   |                          ^ must be declared prior to associated type bindings
-help: move the type parameter prior to the first associated type binding
-   |
-LL | struct A<T, M: One<T, A=()>> { //~ ERROR type parameters must be declared
-   |                    ^^    --
+LL | struct A<T, M: One<A=(), T>> { //~ ERROR associated type bindings must be declared after generic parameters
+   |                    ----^^^
+   |                    |
+   |                    this associated type binding should be moved after the generic parameters
 
-error: generic arguments must declare lifetimes, types and associated type bindings in that order
-  --> $DIR/suggest-move-types.rs:34:46
+error: associated type bindings must be declared after generic parameters
+  --> $DIR/suggest-move-types.rs:34:37
    |
 LL | struct Al<'a, T, M: OneWithLifetime<A=(), T, 'a>> {
-   |                                           ^  ^^ must be declared prior to type parameters
-   |                                           |
-   |                                           must be declared prior to associated type bindings
-help: move the parameters
-   |
-LL | struct Al<'a, T, M: OneWithLifetime<'a, T, A=()>> {
-   |                                     ^^^ ^^    --
+   |                                     ----^^^^^^^
+   |                                     |
+   |                                     this associated type binding should be moved after the generic parameters
 
-error: type parameters must be declared prior to associated type bindings
-  --> $DIR/suggest-move-types.rs:40:46
-   |
-LL | struct B<T, U, V, M: Three<A=(), B=(), C=(), T, U, V>> { //~ ERROR type parameters must be declared
-   |                                              ^  ^  ^ must be declared prior to associated type bindings
-   |                                              |  |
-   |                                              |  must be declared prior to associated type bindings
-   |                                              must be declared prior to associated type bindings
-help: move the type parameters prior to the first associated type binding
-   |
-LL | struct B<T, U, V, M: Three<T, U, V, A=(), B=(), C=()>> { //~ ERROR type parameters must be declared
-   |                            ^^ ^^ ^^                --
+error: associated type bindings must be declared after generic parameters
+  --> $DIR/suggest-move-types.rs:41:28
+   |
+LL | struct B<T, U, V, M: Three<A=(), B=(), C=(), T, U, V>> { //~ ERROR associated type bindings must be declared after generic parameters
+   |                            ----^^----^^----^^^^^^^^^
+   |                            |     |     |
+   |                            |     |     this associated type binding should be moved after the generic parameters
+   |                            |     this associated type binding should be moved after the generic parameters
+   |                            this associated type binding should be moved after the generic parameters
 
-error: generic arguments must declare lifetimes, types and associated type bindings in that order
-  --> $DIR/suggest-move-types.rs:47:80
+error: associated type bindings must be declared after generic parameters
+  --> $DIR/suggest-move-types.rs:48:53
    |
 LL | struct Bl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<A=(), B=(), C=(), T, U, V, 'a, 'b, 'c>> {
-   |                                                                       ^  ^  ^  ^^  ^^  ^^ must be declared prior to type parameters
-   |                                                                       |  |  |  |   |
-   |                                                                       |  |  |  |   must be declared prior to type parameters
-   |                                                                       |  |  |  must be declared prior to type parameters
-   |                                                                       |  |  must be declared prior to associated type bindings
-   |                                                                       |  must be declared prior to associated type bindings
-   |                                                                       must be declared prior to associated type bindings
-help: move the parameters
-   |
-LL | struct Bl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<'a, 'b, 'c, T, U, V, A=(), B=(), C=()>> {
-   |                                                     ^^^ ^^^ ^^^ ^^ ^^ ^^                --
+   |                                                     ----^^----^^----^^^^^^^^^^^^^^^^^^^^^
+   |                                                     |     |     |
+   |                                                     |     |     this associated type binding should be moved after the generic parameters
+   |                                                     |     this associated type binding should be moved after the generic parameters
+   |                                                     this associated type binding should be moved after the generic parameters
 
-error: type parameters must be declared prior to associated type bindings
-  --> $DIR/suggest-move-types.rs:55:49
-   |
-LL | struct C<T, U, V, M: Three<T, A=(), B=(), C=(), U, V>> { //~ ERROR type parameters must be declared
-   |                                                 ^  ^ must be declared prior to associated type bindings
-   |                                                 |
-   |                                                 must be declared prior to associated type bindings
-help: move the type parameters prior to the first associated type binding
-   |
-LL | struct C<T, U, V, M: Three<T, U, V, A=(), B=(), C=()>> { //~ ERROR type parameters must be declared
-   |                               ^^ ^^                --
+error: associated type bindings must be declared after generic parameters
+  --> $DIR/suggest-move-types.rs:57:28
+   |
+LL | struct C<T, U, V, M: Three<T, A=(), B=(), C=(), U, V>> { //~ ERROR associated type bindings must be declared after generic parameters
+   |                            ^^^----^^----^^----^^^^^^
+   |                               |     |     |
+   |                               |     |     this associated type binding should be moved after the generic parameters
+   |                               |     this associated type binding should be moved after the generic parameters
+   |                               this associated type binding should be moved after the generic parameters
 
-error: generic arguments must declare lifetimes, types and associated type bindings in that order
-  --> $DIR/suggest-move-types.rs:62:56
+error: associated type bindings must be declared after generic parameters
+  --> $DIR/suggest-move-types.rs:64:53
    |
 LL | struct Cl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<T, 'a, A=(), B=(), C=(), U, 'b, V, 'c>> {
-   |                                                        ^^                    ^  ^^  ^  ^^ must be declared prior to type parameters
-   |                                                        |                     |  |   |
-   |                                                        |                     |  |   must be declared prior to associated type bindings
-   |                                                        |                     |  must be declared prior to type parameters
-   |                                                        |                     must be declared prior to associated type bindings
-   |                                                        must be declared prior to type parameters
-help: move the parameters
+   |                                                     ^^^^^^^----^^----^^----^^^^^^^^^^^^^^
+   |                                                            |     |     |
+   |                                                            |     |     this associated type binding should be moved after the generic parameters
+   |                                                            |     this associated type binding should be moved after the generic parameters
+   |                                                            this associated type binding should be moved after the generic parameters
+
+error: associated type bindings must be declared after generic parameters
+  --> $DIR/suggest-move-types.rs:73:28
+   |
+LL | struct D<T, U, V, M: Three<T, A=(), B=(), U, C=(), V>> { //~ ERROR associated type bindings must be declared after generic parameters
+   |                            ^^^----^^----^^^^^----^^^
+   |                               |     |        |
+   |                               |     |        this associated type binding should be moved after the generic parameters
+   |                               |     this associated type binding should be moved after the generic parameters
+   |                               this associated type binding should be moved after the generic parameters
+
+error: associated type bindings must be declared after generic parameters
+  --> $DIR/suggest-move-types.rs:80:53
    |
-LL | struct Cl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<'a, 'b, 'c, T, U, V, A=(), B=(), C=()>> {
-   |                                                     ^^^ ^^^ ^^^ -- ^^ ^^                --
+LL | struct Dl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<T, 'a, A=(), B=(), U, 'b, C=(), V, 'c>> {
+   |                                                     ^^^^^^^----^^----^^^^^^^^^----^^^^^^^
+   |                                                            |     |            |
+   |                                                            |     |            this associated type binding should be moved after the generic parameters
+   |                                                            |     this associated type binding should be moved after the generic parameters
+   |                                                            this associated type binding should be moved after the generic parameters
 
-error: type parameters must be declared prior to associated type bindings
-  --> $DIR/suggest-move-types.rs:70:43
+error: lifetime arguments must be declared prior to type arguments
+  --> $DIR/suggest-move-types.rs:34:46
    |
-LL | struct D<T, U, V, M: Three<T, A=(), B=(), U, C=(), V>> { //~ ERROR type parameters must be declared
-   |                                           ^        ^ must be declared prior to associated type bindings
-   |                                           |
-   |                                           must be declared prior to associated type bindings
-help: move the type parameters prior to the first associated type binding
+LL | struct Al<'a, T, M: OneWithLifetime<A=(), T, 'a>> {
+   |                                              ^^
+
+error: lifetime arguments must be declared prior to type arguments
+  --> $DIR/suggest-move-types.rs:48:80
    |
-LL | struct D<T, U, V, M: Three<T, U, V, A=(), B=(), C=()>> { //~ ERROR type parameters must be declared
-   |                               ^^ ^^          --    --
+LL | struct Bl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<A=(), B=(), C=(), T, U, V, 'a, 'b, 'c>> {
+   |                                                                                ^^  ^^  ^^
 
-error: generic arguments must declare lifetimes, types and associated type bindings in that order
-  --> $DIR/suggest-move-types.rs:77:56
+error: lifetime arguments must be declared prior to type arguments
+  --> $DIR/suggest-move-types.rs:64:56
    |
-LL | struct Dl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<T, 'a, A=(), B=(), U, 'b, C=(), V, 'c>> {
-   |                                                        ^^              ^  ^^        ^  ^^ must be declared prior to type parameters
-   |                                                        |               |  |         |
-   |                                                        |               |  |         must be declared prior to associated type bindings
-   |                                                        |               |  must be declared prior to type parameters
-   |                                                        |               must be declared prior to associated type bindings
-   |                                                        must be declared prior to type parameters
-help: move the parameters
+LL | struct Cl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<T, 'a, A=(), B=(), C=(), U, 'b, V, 'c>> {
+   |                                                        ^^                       ^^     ^^
+
+error: lifetime arguments must be declared prior to type arguments
+  --> $DIR/suggest-move-types.rs:80:56
    |
-LL | struct Dl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<'a, 'b, 'c, T, U, V, A=(), B=(), C=()>> {
-   |                                                     ^^^ ^^^ ^^^ -- ^^ ^^          --    --
+LL | struct Dl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<T, 'a, A=(), B=(), U, 'b, C=(), V, 'c>> {
+   |                                                        ^^                 ^^           ^^
 
-error: aborting due to 8 previous errors
+error: aborting due to 12 previous errors
 
diff --git a/src/test/ui/traits/trait-object-vs-lifetime.rs b/src/test/ui/traits/trait-object-vs-lifetime.rs
index a12429c868ed..36dec21be052 100644
--- a/src/test/ui/traits/trait-object-vs-lifetime.rs
+++ b/src/test/ui/traits/trait-object-vs-lifetime.rs
@@ -12,6 +12,6 @@ fn main() {
     //~^ ERROR wrong number of lifetime arguments: expected 1, found 2
     //~| ERROR wrong number of type arguments: expected 1, found 0
     let _: S<'static +, 'static>;
-    //~^ ERROR lifetime parameters must be declared prior to type parameters
+    //~^ ERROR lifetime arguments must be declared prior to type arguments
     //~| ERROR at least one non-builtin trait is required for an object type
 }
diff --git a/src/test/ui/traits/trait-object-vs-lifetime.stderr b/src/test/ui/traits/trait-object-vs-lifetime.stderr
index 4cc96bae5cd1..e0c52a72a093 100644
--- a/src/test/ui/traits/trait-object-vs-lifetime.stderr
+++ b/src/test/ui/traits/trait-object-vs-lifetime.stderr
@@ -1,12 +1,8 @@
-error: lifetime parameters must be declared prior to type parameters
+error: lifetime arguments must be declared prior to type arguments
   --> $DIR/trait-object-vs-lifetime.rs:14:25
    |
 LL |     let _: S<'static +, 'static>;
-   |                         ^^^^^^^ must be declared prior to type parameters
-help: move the lifetime parameter prior to the first type parameter
-   |
-LL |     let _: S<'static, 'static +>;
-   |              ^^^^^^^^         --
+   |                         ^^^^^^^
 
 error[E0224]: at least one non-builtin trait is required for an object type
   --> $DIR/trait-object-vs-lifetime.rs:9:23

From 2f73245ca460e1658b988092f5050afcbbf04501 Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Tue, 5 Feb 2019 17:54:23 +0100
Subject: [PATCH 14/28] Add test forbidding const parameters in const fn

---
 .../const-fn-with-const-param.rs              | 12 ++++++++++
 .../const-fn-with-const-param.stderr          | 24 +++++++++++++++++++
 2 files changed, 36 insertions(+)
 create mode 100644 src/test/ui/const-generics/const-fn-with-const-param.rs
 create mode 100644 src/test/ui/const-generics/const-fn-with-const-param.stderr

diff --git a/src/test/ui/const-generics/const-fn-with-const-param.rs b/src/test/ui/const-generics/const-fn-with-const-param.rs
new file mode 100644
index 000000000000..052d723d96ed
--- /dev/null
+++ b/src/test/ui/const-generics/const-fn-with-const-param.rs
@@ -0,0 +1,12 @@
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+const fn const_u32_identity<const X: u32>() -> u32 {
+    //~^ ERROR const parameters are not permitted in `const fn`
+    //~^^ ERROR const generics in any position are currently unsupported
+    X
+}
+
+fn main() {
+    println!("{:?}", const_u32_identity::<18>());
+}
diff --git a/src/test/ui/const-generics/const-fn-with-const-param.stderr b/src/test/ui/const-generics/const-fn-with-const-param.stderr
new file mode 100644
index 000000000000..a08ebfb0d976
--- /dev/null
+++ b/src/test/ui/const-generics/const-fn-with-const-param.stderr
@@ -0,0 +1,24 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/const-fn-with-const-param.rs:1:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+
+error: const parameters are not permitted in `const fn`
+  --> $DIR/const-fn-with-const-param.rs:4:1
+   |
+LL | / const fn const_u32_identity<const X: u32>() -> u32 {
+LL | |     //~^ ERROR const parameters are not permitted in `const fn`
+LL | |     //~^^ ERROR const generics in any position are currently unsupported
+LL | |     X
+LL | | }
+   | |_^
+
+error: const generics in any position are currently unsupported
+  --> $DIR/const-fn-with-const-param.rs:4:35
+   |
+LL | const fn const_u32_identity<const X: u32>() -> u32 {
+   |                                   ^
+
+error: aborting due to 2 previous errors
+

From ed51b6148f4bb74fb38881b6f527f5367b5ae06f Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Tue, 5 Feb 2019 17:55:12 +0100
Subject: [PATCH 15/28] Add test for const parameter depending on type
 parameter

---
 .../const-param-type-depends-on-type-param.rs |  7 +++++++
 ...st-param-type-depends-on-type-param.stderr | 21 +++++++++++++++++++
 2 files changed, 28 insertions(+)
 create mode 100644 src/test/ui/const-generics/const-param-type-depends-on-type-param.rs
 create mode 100644 src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr

diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param.rs b/src/test/ui/const-generics/const-param-type-depends-on-type-param.rs
new file mode 100644
index 000000000000..06ee523be485
--- /dev/null
+++ b/src/test/ui/const-generics/const-param-type-depends-on-type-param.rs
@@ -0,0 +1,7 @@
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+pub struct Dependent<T, const X: T>([(); X]); //~ ERROR const parameters
+//~^ ERROR const generics in any position are currently unsupported
+
+fn main() {}
diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr b/src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr
new file mode 100644
index 000000000000..375c9fa53219
--- /dev/null
+++ b/src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr
@@ -0,0 +1,21 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/const-param-type-depends-on-type-param.rs:1:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+
+error[E0670]: const parameters cannot depend on type parameters
+  --> $DIR/const-param-type-depends-on-type-param.rs:4:34
+   |
+LL | pub struct Dependent<T, const X: T>([(); X]); //~ ERROR const parameters
+   |                                  ^ const parameter depends on type parameter
+
+error: const generics in any position are currently unsupported
+  --> $DIR/const-param-type-depends-on-type-param.rs:4:31
+   |
+LL | pub struct Dependent<T, const X: T>([(); X]); //~ ERROR const parameters
+   |                               ^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0670`.

From bf2f62cb98de0b255db318a3d580ce0c2e1a976d Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Tue, 5 Feb 2019 17:55:25 +0100
Subject: [PATCH 16/28] Add test for const parameter before other generic
 parameters

---
 .../const-param-before-other-params.rs        | 13 ++++++++++
 .../const-param-before-other-params.stderr    | 26 +++++++++++++++++++
 2 files changed, 39 insertions(+)
 create mode 100644 src/test/ui/const-generics/const-param-before-other-params.rs
 create mode 100644 src/test/ui/const-generics/const-param-before-other-params.stderr

diff --git a/src/test/ui/const-generics/const-param-before-other-params.rs b/src/test/ui/const-generics/const-param-before-other-params.rs
new file mode 100644
index 000000000000..3f120cbc4d33
--- /dev/null
+++ b/src/test/ui/const-generics/const-param-before-other-params.rs
@@ -0,0 +1,13 @@
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+fn foo<const X: (), T>(_: T) {
+    //~^ ERROR type parameters must be declared prior to const parameters
+    //~^^ ERROR const generics in any position are currently unsupported
+}
+
+fn bar<const X: (), 'a>(_: &'a ()) {
+    //~^ ERROR lifetime parameters must be declared prior to const parameters
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/const-param-before-other-params.stderr b/src/test/ui/const-generics/const-param-before-other-params.stderr
new file mode 100644
index 000000000000..303ea16ca837
--- /dev/null
+++ b/src/test/ui/const-generics/const-param-before-other-params.stderr
@@ -0,0 +1,26 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/const-param-before-other-params.rs:1:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+
+error: type parameters must be declared prior to const parameters
+  --> $DIR/const-param-before-other-params.rs:4:21
+   |
+LL | fn foo<const X: (), T>(_: T) {
+   |       --------------^- help: reorder the parameters: lifetimes, then types, then consts: `<T, X>`
+
+error: lifetime parameters must be declared prior to const parameters
+  --> $DIR/const-param-before-other-params.rs:9:21
+   |
+LL | fn bar<const X: (), 'a>(_: &'a ()) {
+   |       --------------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, X>`
+
+error: const generics in any position are currently unsupported
+  --> $DIR/const-param-before-other-params.rs:4:14
+   |
+LL | fn foo<const X: (), T>(_: T) {
+   |              ^
+
+error: aborting due to 3 previous errors
+

From 1805546084b2ad5e7a694b8b6974594ee2c4d849 Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Tue, 5 Feb 2019 18:59:53 +0100
Subject: [PATCH 17/28] Fix const generic parameter save analysis

---
 src/librustc_save_analysis/sig.rs | 18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs
index e7ea90d921e3..72615fc8a65a 100644
--- a/src/librustc_save_analysis/sig.rs
+++ b/src/librustc_save_analysis/sig.rs
@@ -622,12 +622,20 @@ impl Sig for ast::Generics {
 
         let mut defs = Vec::with_capacity(self.params.len());
         for param in &self.params {
-            let mut param_text = param.ident.to_string();
+            let mut param_text = String::new();
+            if let ast::GenericParamKind::Const { .. } = param.kind {
+                param_text.push_str("const ");
+            }
+            param_text.push_str(&param.ident.as_str());
             defs.push(SigElement {
                 id: id_from_node_id(param.id, scx),
                 start: offset + text.len(),
-                end: offset + text.len() + param_text.len(),
+                end: offset + text.len() + param_text.as_str().len(),
             });
+            if let ast::GenericParamKind::Const { ref ty } = param.kind {
+                param_text.push_str(": ");
+                param_text.push_str(&pprust::ty_to_string(&ty));
+            }
             if !param.bounds.is_empty() {
                 param_text.push_str(": ");
                 match param.kind {
@@ -646,10 +654,8 @@ impl Sig for ast::Generics {
                         param_text.push_str(&pprust::bounds_to_string(&param.bounds));
                         // FIXME descend properly into bounds.
                     }
-                    ast::GenericParamKind::Const { ref ty } => {
-                        param_text.push_str(&pprust::bounds_to_string(&param.bounds));
-                        param_text.push_str("= ");
-                        param_text.push_str(&pprust::ty_to_string(&ty));
+                    ast::GenericParamKind::Const { .. } => {
+                        // Const generics cannot contain bounds.
                     }
                 }
             }

From 7461a5e655825294682b1d7d9a96aa2524dc7077 Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Tue, 5 Feb 2019 19:00:07 +0100
Subject: [PATCH 18/28] Fix ast_validation printing of const generics

---
 src/librustc_passes/ast_validation.rs         | 20 ++++++++++++-------
 .../const-param-before-other-params.stderr    |  4 ++--
 2 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs
index 502799900642..a1c9d3ece2c0 100644
--- a/src/librustc_passes/ast_validation.rs
+++ b/src/librustc_passes/ast_validation.rs
@@ -7,6 +7,7 @@
 // or type checking or some other kind of complex analysis.
 
 use std::mem;
+use syntax::print::pprust;
 use rustc::lint;
 use rustc::session::Session;
 use rustc_data_structures::fx::FxHashMap;
@@ -281,7 +282,7 @@ enum GenericPosition {
 
 fn validate_generics_order<'a>(
     handler: &errors::Handler,
-    generics: impl Iterator<Item = (ParamKindOrd, Span, Option<Ident>)>,
+    generics: impl Iterator<Item = (ParamKindOrd, Span, Option<String>)>,
     pos: GenericPosition,
     span: Span,
 ) {
@@ -311,7 +312,7 @@ fn validate_generics_order<'a>(
             if !first {
                 ordered_params += ", ";
             }
-            ordered_params += &ident.as_str();
+            ordered_params += &ident;
             first = false;
         }
     }
@@ -635,11 +636,16 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
         }
 
         validate_generics_order(self.err_handler(), generics.params.iter().map(|param| {
-            (match param.kind {
-                GenericParamKind::Lifetime { .. } => ParamKindOrd::Lifetime,
-                GenericParamKind::Type { .. } => ParamKindOrd::Type,
-                GenericParamKind::Const { .. } => ParamKindOrd::Const,
-            }, param.ident.span, Some(param.ident))
+            let span = param.ident.span;
+            let ident = Some(param.ident.to_string());
+            match &param.kind {
+                GenericParamKind::Lifetime { .. } => (ParamKindOrd::Lifetime, span, ident),
+                GenericParamKind::Type { .. } => (ParamKindOrd::Type, span, ident),
+                GenericParamKind::Const { ref ty } => {
+                    let ty = pprust::ty_to_string(ty);
+                    (ParamKindOrd::Const, span, Some(format!("const {}: {}", param.ident, ty)))
+                }
+            }
         }), GenericPosition::Param, generics.span);
 
         for predicate in &generics.where_clause.predicates {
diff --git a/src/test/ui/const-generics/const-param-before-other-params.stderr b/src/test/ui/const-generics/const-param-before-other-params.stderr
index 303ea16ca837..aedcaf52e268 100644
--- a/src/test/ui/const-generics/const-param-before-other-params.stderr
+++ b/src/test/ui/const-generics/const-param-before-other-params.stderr
@@ -8,13 +8,13 @@ error: type parameters must be declared prior to const parameters
   --> $DIR/const-param-before-other-params.rs:4:21
    |
 LL | fn foo<const X: (), T>(_: T) {
-   |       --------------^- help: reorder the parameters: lifetimes, then types, then consts: `<T, X>`
+   |       --------------^- help: reorder the parameters: lifetimes, then types, then consts: `<T, const X: ()>`
 
 error: lifetime parameters must be declared prior to const parameters
   --> $DIR/const-param-before-other-params.rs:9:21
    |
 LL | fn bar<const X: (), 'a>(_: &'a ()) {
-   |       --------------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, X>`
+   |       --------------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, const X: ()>`
 
 error: const generics in any position are currently unsupported
   --> $DIR/const-param-before-other-params.rs:4:14

From 899d013fefba27b66c655af4199ccecf8fb9fdae Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Tue, 5 Feb 2019 21:40:18 +0100
Subject: [PATCH 19/28] Fix E0670 doc error

---
 src/librustc_resolve/diagnostics.rs | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs
index a5f9124674a5..9965225fe0d2 100644
--- a/src/librustc_resolve/diagnostics.rs
+++ b/src/librustc_resolve/diagnostics.rs
@@ -1646,8 +1646,11 @@ E0670: r##"
 Const parameters cannot depend on type parameters.
 The following is therefore invalid:
 
-```
+```compile_fail,E0670
+#![feature(const_generics)]
+
 fn const_id<T, const N: T>() -> T {
+    // ERROR: const parameters cannot depend on type parameters
     N
 }
 ```

From bbdcc4e7ce697bbd6ad398987c5e4ec4928f5da4 Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Thu, 7 Feb 2019 10:10:11 +0100
Subject: [PATCH 20/28] Adjust parser generic parameter errors

---
 src/libsyntax/parse/parser.rs                 | 53 +++++++++----------
 src/libsyntax/parse/token.rs                  |  1 -
 .../attrs-with-no-formal-in-generics-1.rs     |  2 +-
 .../attrs-with-no-formal-in-generics-1.stderr |  2 +-
 .../attrs-with-no-formal-in-generics-2.rs     |  2 +-
 .../attrs-with-no-formal-in-generics-2.stderr |  2 +-
 .../attrs-with-no-formal-in-generics-3.rs     |  2 +-
 .../attrs-with-no-formal-in-generics-3.stderr |  2 +-
 .../const-expression-parameter.rs             | 19 +++++++
 .../const-expression-parameter.stderr         | 26 +++++++++
 src/test/ui/issues/issue-20616-3.rs           |  5 +-
 src/test/ui/issues/issue-20616-3.stderr       |  4 +-
 src/test/ui/issues/issue-20616-7.rs           |  5 +-
 src/test/ui/issues/issue-20616-7.stderr       |  4 +-
 src/test/ui/issues/issue-20616-8.rs           |  5 +-
 src/test/ui/issues/issue-20616-8.stderr       |  4 +-
 src/test/ui/issues/issue-20616-9.rs           |  5 +-
 src/test/ui/issues/issue-20616-9.stderr       |  4 +-
 18 files changed, 93 insertions(+), 54 deletions(-)
 create mode 100644 src/test/ui/const-generics/const-expression-parameter.rs
 create mode 100644 src/test/ui/const-generics/const-expression-parameter.stderr

diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 2ff450af4238..7640f0bdf064 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -948,10 +948,6 @@ impl<'a> Parser<'a> {
         }
     }
 
-    fn check_const_param(&mut self) -> bool {
-        self.check_keyword(keywords::Const)
-    }
-
     fn check_const_arg(&mut self) -> bool {
         if self.token.can_begin_const_arg() {
             true
@@ -1046,7 +1042,8 @@ impl<'a> Parser<'a> {
     }
 
     /// Attempt to consume a `<`. If `<<` is seen, replace it with a single
-    /// `<` and continue. If a `<` is not seen, return false.
+    /// `<` and continue. If `<-` is seen, replace it with a single `<`
+    /// and continue. If a `<` is not seen, return false.
     ///
     /// This is meant to be used when parsing generics on a path to get the
     /// starting token.
@@ -1062,6 +1059,11 @@ impl<'a> Parser<'a> {
                 self.bump_with(token::Lt, span);
                 true
             }
+            token::LArrow => {
+                let span = self.span.with_lo(self.span.lo() + BytePos(1));
+                self.bump_with(token::BinOp(token::Minus), span);
+                true
+            }
             _ => false,
         };
 
@@ -5518,7 +5520,6 @@ impl<'a> Parser<'a> {
     /// trailing comma and erroneous trailing attributes.
     crate fn parse_generic_params(&mut self) -> PResult<'a, Vec<ast::GenericParam>> {
         let mut params = Vec::new();
-        let mut prev_param: Option<ParamKindOrd> = None;
         loop {
             let attrs = self.parse_outer_attributes()?;
             if self.check_lifetime() {
@@ -5536,29 +5537,21 @@ impl<'a> Parser<'a> {
                     bounds,
                     kind: ast::GenericParamKind::Lifetime,
                 });
-                prev_param = Some(ParamKindOrd::Lifetime);
-            } else if self.check_const_param() {
+            } else if self.check_keyword(keywords::Const) {
                 // Parse const parameter.
                 params.push(self.parse_const_param(attrs)?);
-                prev_param = Some(ParamKindOrd::Const);
             } else if self.check_ident() {
                 // Parse type parameter.
                 params.push(self.parse_ty_param(attrs)?);
-                prev_param = Some(ParamKindOrd::Type);
             } else {
                 // Check for trailing attributes and stop parsing.
-                if !attrs.is_empty() {
-                    if let Some(prev_param) = prev_param {
-                        self.struct_span_err(
-                            attrs[0].span,
-                            &format!(
-                                "trailing attribute after {} parameter",
-                                prev_param,
-                            ),
-                        )
-                        .span_label(attrs[0].span, "attributes must go before parameters")
-                        .emit();
-                    }
+                if !attrs.is_empty() && !params.is_empty() {
+                    self.struct_span_err(
+                        attrs[0].span,
+                        &format!("trailing attribute after generic parameter"),
+                    )
+                    .span_label(attrs[0].span, "attributes must go before parameters")
+                    .emit();
                 }
                 break
             }
@@ -5774,19 +5767,25 @@ impl<'a> Parser<'a> {
                 });
                 assoc_ty_bindings.push(span);
             } else if self.check_const_arg() {
+                // FIXME(const_generics): to distinguish between idents for types and consts,
+                // we should introduce a GenericArg::Ident in the AST and distinguish when
+                // lowering to the HIR. For now, idents for const args are not permitted.
+
                 // Parse const argument.
                 let expr = if let token::OpenDelim(token::Brace) = self.token {
                     self.parse_block_expr(None, self.span, BlockCheckMode::Default, ThinVec::new())?
-                } else if self.token.can_begin_literal_or_bool() {
-                    let lit = self.parse_lit()?;
-                    self.mk_expr(lit.span, ExprKind::Lit(lit), ThinVec::new())
-                } else {
+                } else if self.token.is_ident() {
                     // FIXME(const_generics): to distinguish between idents for types and consts,
                     // we should introduce a GenericArg::Ident in the AST and distinguish when
                     // lowering to the HIR. For now, idents for const args are not permitted.
                     return Err(
                         self.fatal("identifiers may currently not be used for const generics")
                     );
+                } else {
+                    // FIXME(const_generics): this currently conflicts with emplacement syntax
+                    // with negative integer literals.
+                    let lit = self.parse_lit()?;
+                    self.mk_expr(lit.span, ExprKind::Lit(lit), ThinVec::new())
                 };
                 let value = AnonConst {
                     id: ast::DUMMY_NODE_ID,
@@ -6444,7 +6443,7 @@ impl<'a> Parser<'a> {
         //     `<` (LIFETIME|IDENT) `,` - first generic parameter in a list
         //     `<` (LIFETIME|IDENT) `:` - generic parameter with bounds
         //     `<` (LIFETIME|IDENT) `=` - generic parameter with a default
-        //     `<` const IDENT          - generic const parameter
+        //     `<` const                - generic const parameter
         // The only truly ambiguous case is
         //     `<` IDENT `>` `::` IDENT ...
         // we disambiguate it in favor of generics (`impl<T> ::absolute::Path<T> { ... }`)
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index dad320727396..c3885f0d04d1 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -284,7 +284,6 @@ impl Token {
         match self {
             OpenDelim(Brace) => true,
             Interpolated(ref nt) => match nt.0 {
-                NtExpr(..) => true,
                 NtBlock(..) => true,
                 NtLiteral(..) => true,
                 _ => false,
diff --git a/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-1.rs b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-1.rs
index 2ef5f13f3d46..ca5fdd9da859 100644
--- a/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-1.rs
+++ b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-1.rs
@@ -7,7 +7,7 @@
 struct RefIntPair<'a, 'b>(&'a u32, &'b u32);
 
 impl<#[rustc_1] 'a, 'b, #[oops]> RefIntPair<'a, 'b> {
-    //~^ ERROR trailing attribute after lifetime parameter
+    //~^ ERROR trailing attribute after generic parameter
 }
 
 fn main() {
diff --git a/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-1.stderr b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-1.stderr
index 97c0a19a3da3..55e7a9877846 100644
--- a/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-1.stderr
+++ b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-1.stderr
@@ -1,4 +1,4 @@
-error: trailing attribute after lifetime parameter
+error: trailing attribute after generic parameter
   --> $DIR/attrs-with-no-formal-in-generics-1.rs:9:25
    |
 LL | impl<#[rustc_1] 'a, 'b, #[oops]> RefIntPair<'a, 'b> {
diff --git a/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-2.rs b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-2.rs
index f58ddd5fbda0..c795612acf08 100644
--- a/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-2.rs
+++ b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-2.rs
@@ -7,6 +7,6 @@
 struct RefAny<'a, T>(&'a T);
 
 impl<#[rustc_1] 'a, #[rustc_2] T, #[oops]> RefAny<'a, T> {}
-//~^ ERROR trailing attribute after type parameter
+//~^ ERROR trailing attribute after generic parameter
 
 fn main() {}
diff --git a/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-2.stderr b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-2.stderr
index ff7ced77f25b..acd0ae3678a7 100644
--- a/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-2.stderr
+++ b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-2.stderr
@@ -1,4 +1,4 @@
-error: trailing attribute after type parameter
+error: trailing attribute after generic parameter
   --> $DIR/attrs-with-no-formal-in-generics-2.rs:9:35
    |
 LL | impl<#[rustc_1] 'a, #[rustc_2] T, #[oops]> RefAny<'a, T> {}
diff --git a/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-3.rs b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-3.rs
index 44a7c9d7c8b6..3cfc70b41850 100644
--- a/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-3.rs
+++ b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-3.rs
@@ -6,7 +6,7 @@ struct RefIntPair<'a, 'b>(&'a u32, &'b u32);
 
 fn hof_lt<Q>(_: Q)
     where Q: for <#[allow(unused)] 'a, 'b, #[oops]> Fn(RefIntPair<'a,'b>) -> &'b u32
-    //~^ ERROR trailing attribute after lifetime parameter
+    //~^ ERROR trailing attribute after generic parameter
 {}
 
 fn main() {}
diff --git a/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-3.stderr b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-3.stderr
index b383e21e1612..b9ca00974677 100644
--- a/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-3.stderr
+++ b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-3.stderr
@@ -1,4 +1,4 @@
-error: trailing attribute after lifetime parameter
+error: trailing attribute after generic parameter
   --> $DIR/attrs-with-no-formal-in-generics-3.rs:8:44
    |
 LL |     where Q: for <#[allow(unused)] 'a, 'b, #[oops]> Fn(RefIntPair<'a,'b>) -> &'b u32
diff --git a/src/test/ui/const-generics/const-expression-parameter.rs b/src/test/ui/const-generics/const-expression-parameter.rs
new file mode 100644
index 000000000000..c582c596bfcc
--- /dev/null
+++ b/src/test/ui/const-generics/const-expression-parameter.rs
@@ -0,0 +1,19 @@
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+fn u32_identity<const X: u32>() -> u32 {
+    //~^ ERROR const generics in any position are currently unsupported
+    5
+}
+
+fn foo_a() {
+    u32_identity::<-1>(); //~ ERROR expected identifier, found `<-`
+}
+
+fn foo_b() {
+    u32_identity::<1 + 2>(); //~ ERROR expected one of `,` or `>`, found `+`
+}
+
+fn main() {
+    u32_identity::<5>(); // ok
+}
diff --git a/src/test/ui/const-generics/const-expression-parameter.stderr b/src/test/ui/const-generics/const-expression-parameter.stderr
new file mode 100644
index 000000000000..1dd3a960316d
--- /dev/null
+++ b/src/test/ui/const-generics/const-expression-parameter.stderr
@@ -0,0 +1,26 @@
+error: expected identifier, found `<-`
+  --> $DIR/const-expression-parameter.rs:10:19
+   |
+LL |     u32_identity::<-1>(); //~ ERROR expected identifier, found `<-`
+   |                   ^^ expected identifier
+
+error: expected one of `,` or `>`, found `+`
+  --> $DIR/const-expression-parameter.rs:14:22
+   |
+LL |     u32_identity::<1 + 2>(); //~ ERROR expected one of `,` or `>`, found `+`
+   |                      ^ expected one of `,` or `>` here
+
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/const-expression-parameter.rs:1:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+
+error: const generics in any position are currently unsupported
+  --> $DIR/const-expression-parameter.rs:4:23
+   |
+LL | fn u32_identity<const X: u32>() -> u32 {
+   |                       ^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/issues/issue-20616-3.rs b/src/test/ui/issues/issue-20616-3.rs
index 9f983f74f5b1..9bfd5bf23130 100644
--- a/src/test/ui/issues/issue-20616-3.rs
+++ b/src/test/ui/issues/issue-20616-3.rs
@@ -1,5 +1,3 @@
-// ignore-tidy-linelength
-
 // We need all these 9 issue-20616-N.rs files
 // because we can only catch one parsing error at a time
 
@@ -12,7 +10,8 @@ type Type_1_<'a, T> = &'a T;
 //type Type_2 = Type_1_<'static ()>; // error: expected `,` or `>` after lifetime name, found `(`
 
 
-type Type_3<T> = Box<T,,>; //~ error: expected one of `>`, const, identifier, lifetime, or type, found `,`
+type Type_3<T> = Box<T,,>;
+//~^ error: expected one of `>`, const, identifier, lifetime, or type, found `,`
 
 
 //type Type_4<T> = Type_1_<'static,, T>; // error: expected type, found `,`
diff --git a/src/test/ui/issues/issue-20616-3.stderr b/src/test/ui/issues/issue-20616-3.stderr
index e8edb5ba70f5..f51fb949c740 100644
--- a/src/test/ui/issues/issue-20616-3.stderr
+++ b/src/test/ui/issues/issue-20616-3.stderr
@@ -1,7 +1,7 @@
 error: expected one of `>`, const, identifier, lifetime, or type, found `,`
-  --> $DIR/issue-20616-3.rs:15:24
+  --> $DIR/issue-20616-3.rs:13:24
    |
-LL | type Type_3<T> = Box<T,,>; //~ error: expected one of `>`, const, identifier, lifetime, or type, found `,`
+LL | type Type_3<T> = Box<T,,>;
    |                        ^ expected one of `>`, const, identifier, lifetime, or type here
 
 error: aborting due to previous error
diff --git a/src/test/ui/issues/issue-20616-7.rs b/src/test/ui/issues/issue-20616-7.rs
index 277b45245063..ffd1620c1d30 100644
--- a/src/test/ui/issues/issue-20616-7.rs
+++ b/src/test/ui/issues/issue-20616-7.rs
@@ -1,5 +1,3 @@
-// ignore-tidy-linelength
-
 // We need all these 9 issue-20616-N.rs files
 // because we can only catch one parsing error at a time
 
@@ -27,7 +25,8 @@ type Type_5_<'a> = Type_1_<'a, ()>;
 //type Type_6 = Type_5_<'a,,>; // error: expected type, found `,`
 
 
-type Type_7 = Box<(),,>; //~ error: expected one of `>`, const, identifier, lifetime, or type, found `,`
+type Type_7 = Box<(),,>;
+//~^ error: expected one of `>`, const, identifier, lifetime, or type, found `,`
 
 
 //type Type_8<'a,,> = &'a (); // error: expected ident, found `,`
diff --git a/src/test/ui/issues/issue-20616-7.stderr b/src/test/ui/issues/issue-20616-7.stderr
index c1422d849fc7..c0e108375be2 100644
--- a/src/test/ui/issues/issue-20616-7.stderr
+++ b/src/test/ui/issues/issue-20616-7.stderr
@@ -1,7 +1,7 @@
 error: expected one of `>`, const, identifier, lifetime, or type, found `,`
-  --> $DIR/issue-20616-7.rs:30:22
+  --> $DIR/issue-20616-7.rs:28:22
    |
-LL | type Type_7 = Box<(),,>; //~ error: expected one of `>`, const, identifier, lifetime, or type, found `,`
+LL | type Type_7 = Box<(),,>;
    |                      ^ expected one of `>`, const, identifier, lifetime, or type here
 
 error: aborting due to previous error
diff --git a/src/test/ui/issues/issue-20616-8.rs b/src/test/ui/issues/issue-20616-8.rs
index 756119e01271..c9e8b61e50b5 100644
--- a/src/test/ui/issues/issue-20616-8.rs
+++ b/src/test/ui/issues/issue-20616-8.rs
@@ -1,5 +1,3 @@
-// ignore-tidy-linelength
-
 // We need all these 9 issue-20616-N.rs files
 // because we can only catch one parsing error at a time
 
@@ -30,7 +28,8 @@ type Type_5_<'a> = Type_1_<'a, ()>;
 //type Type_7 = Box<(),,>; // error: expected type, found `,`
 
 
-type Type_8<'a,,> = &'a (); //~ error: expected one of `>`, `const`, identifier, or lifetime, found `,`
+type Type_8<'a,,> = &'a ();
+//~^ error: expected one of `>`, `const`, identifier, or lifetime, found `,`
 
 
 //type Type_9<T,,> = Box<T>; // error: expected identifier, found `,`
diff --git a/src/test/ui/issues/issue-20616-8.stderr b/src/test/ui/issues/issue-20616-8.stderr
index cfe3ec57712d..0ef9192f1e73 100644
--- a/src/test/ui/issues/issue-20616-8.stderr
+++ b/src/test/ui/issues/issue-20616-8.stderr
@@ -1,7 +1,7 @@
 error: expected one of `>`, `const`, identifier, or lifetime, found `,`
-  --> $DIR/issue-20616-8.rs:33:16
+  --> $DIR/issue-20616-8.rs:31:16
    |
-LL | type Type_8<'a,,> = &'a (); //~ error: expected one of `>`, `const`, identifier, or lifetime, found `,`
+LL | type Type_8<'a,,> = &'a ();
    |                ^ expected one of `>`, `const`, identifier, or lifetime here
 
 error: aborting due to previous error
diff --git a/src/test/ui/issues/issue-20616-9.rs b/src/test/ui/issues/issue-20616-9.rs
index 6074fbb2204c..1c509f26fd63 100644
--- a/src/test/ui/issues/issue-20616-9.rs
+++ b/src/test/ui/issues/issue-20616-9.rs
@@ -1,5 +1,3 @@
-// ignore-tidy-linelength
-
 // We need all these 9 issue-20616-N.rs files
 // because we can only catch one parsing error at a time
 
@@ -33,4 +31,5 @@ type Type_5_<'a> = Type_1_<'a, ()>;
 //type Type_8<'a,,> = &'a (); // error: expected identifier, found `,`
 
 
-type Type_9<T,,> = Box<T>; //~ error: expected one of `>`, `const`, identifier, or lifetime, found `,`
+type Type_9<T,,> = Box<T>;
+//~^ error: expected one of `>`, `const`, identifier, or lifetime, found `,`
diff --git a/src/test/ui/issues/issue-20616-9.stderr b/src/test/ui/issues/issue-20616-9.stderr
index 960e8c8c0865..5fd1400a2e8c 100644
--- a/src/test/ui/issues/issue-20616-9.stderr
+++ b/src/test/ui/issues/issue-20616-9.stderr
@@ -1,7 +1,7 @@
 error: expected one of `>`, `const`, identifier, or lifetime, found `,`
-  --> $DIR/issue-20616-9.rs:36:15
+  --> $DIR/issue-20616-9.rs:34:15
    |
-LL | type Type_9<T,,> = Box<T>; //~ error: expected one of `>`, `const`, identifier, or lifetime, found `,`
+LL | type Type_9<T,,> = Box<T>;
    |               ^ expected one of `>`, `const`, identifier, or lifetime here
 
 error: aborting due to previous error

From 61f35f0641efe60c4e804be046922aa232666797 Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Thu, 7 Feb 2019 10:10:51 +0100
Subject: [PATCH 21/28] Adjust generic const param resolution

---
 src/librustc_resolve/diagnostics.rs           |  14 --
 src/librustc_resolve/lib.rs                   | 175 +++++++-----------
 .../const-param-type-depends-on-type-param.rs |   7 -
 ...st-param-type-depends-on-type-param.stderr |  21 ---
 4 files changed, 65 insertions(+), 152 deletions(-)
 delete mode 100644 src/test/ui/const-generics/const-param-type-depends-on-type-param.rs
 delete mode 100644 src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr

diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs
index 9965225fe0d2..5c095994a1bb 100644
--- a/src/librustc_resolve/diagnostics.rs
+++ b/src/librustc_resolve/diagnostics.rs
@@ -1642,20 +1642,6 @@ fn main() {
 ```
 "##,
 
-E0670: r##"
-Const parameters cannot depend on type parameters.
-The following is therefore invalid:
-
-```compile_fail,E0670
-#![feature(const_generics)]
-
-fn const_id<T, const N: T>() -> T {
-    // ERROR: const parameters cannot depend on type parameters
-    N
-}
-```
-"##,
-
 }
 
 register_diagnostics! {
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 934bb0f03c4f..ebd6b0eb5dab 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -15,7 +15,7 @@ use rustc_errors as errors;
 
 pub use rustc::hir::def::{Namespace, PerNS};
 
-use TypeParameters::*;
+use GenericParameters::*;
 use RibKind::*;
 
 use rustc::hir::map::{Definitions, DefCollector};
@@ -51,7 +51,6 @@ use syntax::ast::{FnDecl, ForeignItem, ForeignItemKind, GenericParamKind, Generi
 use syntax::ast::{Item, ItemKind, ImplItem, ImplItemKind};
 use syntax::ast::{Label, Local, Mutability, Pat, PatKind, Path};
 use syntax::ast::{QSelf, TraitItemKind, TraitRef, Ty, TyKind};
-use syntax::ast::ParamKindOrd;
 use syntax::ptr::P;
 use syntax::{span_err, struct_span_err, unwrap_or, walk_list};
 
@@ -143,8 +142,8 @@ impl Ord for BindingError {
 }
 
 enum ResolutionError<'a> {
-    /// error E0401: can't use type or const parameters from outer function
-    ParametersFromOuterFunction(Def, ParamKindOrd),
+    /// error E0401: can't use type parameters from outer function
+    TypeParametersFromOuterFunction(Def),
     /// error E0403: the name is already used for a type/const parameter in this list of
     /// generic parameters
     NameAlreadyUsedInParameterList(Name, &'a Span),
@@ -180,8 +179,6 @@ enum ResolutionError<'a> {
     BindingShadowsSomethingUnacceptable(&'a str, Name, &'a NameBinding<'a>),
     /// error E0128: type parameters with a default cannot use forward declared identifiers
     ForwardDeclaredTyParam, // FIXME(const_generics:defaults)
-    /// error E0670: const parameter cannot depend on type parameter
-    ConstParamDependentOnTypeParam,
 }
 
 /// Combines an error with provided span and emits it
@@ -199,14 +196,13 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver<'_>,
                                    resolution_error: ResolutionError<'a>)
                                    -> DiagnosticBuilder<'sess> {
     match resolution_error {
-        ResolutionError::ParametersFromOuterFunction(outer_def, kind) => {
+        ResolutionError::TypeParametersFromOuterFunction(outer_def) => {
             let mut err = struct_span_err!(resolver.session,
                 span,
                 E0401,
-                "can't use {} parameters from outer function",
-                kind,
+                "can't use type parameters from outer function",
             );
-            err.span_label(span, format!("use of {} variable from outer function", kind));
+            err.span_label(span, format!("use of type variable from outer function"));
 
             let cm = resolver.session.source_map();
             match outer_def {
@@ -235,20 +231,15 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver<'_>,
                         err.span_label(span, "type variable from outer function");
                     }
                 }
-                Def::ConstParam(def_id) => {
-                    if let Some(span) = resolver.definitions.opt_span(def_id) {
-                        err.span_label(span, "const variable from outer function");
-                    }
-                }
                 _ => {
                     bug!("TypeParametersFromOuterFunction should only be used with Def::SelfTy, \
-                         Def::TyParam or Def::ConstParam");
+                         Def::TyParam");
                 }
             }
 
             // 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 {} parameter instead", kind);
+            let sugg_msg = &format!("try using a local type parameter instead");
             if let Some((sugg_span, new_snippet)) = cm.generate_local_type_param_snippet(span) {
                 // Suggest the modification to the user
                 err.span_suggestion(
@@ -259,9 +250,9 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver<'_>,
                 );
             } else if let Some(sp) = cm.generate_fn_name_span(span) {
                 err.span_label(sp,
-                    format!("try adding a local {} parameter in this method instead", kind));
+                    format!("try adding a local type parameter in this method instead"));
             } else {
-                err.help(&format!("try using a local {} parameter instead", kind));
+                err.help(&format!("try using a local type parameter instead"));
             }
 
             err
@@ -428,12 +419,6 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver<'_>,
                 span, "defaulted type parameters cannot be forward declared".to_string());
             err
         }
-        ResolutionError::ConstParamDependentOnTypeParam => {
-            let mut err = struct_span_err!(resolver.session, span, E0670,
-                                           "const parameters cannot depend on type parameters");
-            err.span_label(span, format!("const parameter depends on type parameter"));
-            err
-        }
     }
 }
 
@@ -766,6 +751,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
         self.resolve_block(block);
     }
     fn visit_anon_const(&mut self, constant: &'tcx ast::AnonConst) {
+        debug!("visit_anon_const {:?}", constant);
         self.with_constant_rib(|this| {
             visit::walk_anon_const(this, constant);
         });
@@ -799,15 +785,15 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
         visit::walk_poly_trait_ref(self, tref, m);
     }
     fn visit_foreign_item(&mut self, foreign_item: &'tcx ForeignItem) {
-        let type_parameters = match foreign_item.node {
+        let generic_params = match foreign_item.node {
             ForeignItemKind::Fn(_, ref generics) => {
-                HasTypeParameters(generics, ItemRibKind)
+                HasGenericParams(generics, ItemRibKind)
             }
-            ForeignItemKind::Static(..) => NoTypeParameters,
-            ForeignItemKind::Ty => NoTypeParameters,
-            ForeignItemKind::Macro(..) => NoTypeParameters,
+            ForeignItemKind::Static(..) => NoGenericParams,
+            ForeignItemKind::Ty => NoGenericParams,
+            ForeignItemKind::Macro(..) => NoGenericParams,
         };
-        self.with_type_parameter_rib(type_parameters, |this| {
+        self.with_generic_param_rib(generic_params, |this| {
             visit::walk_foreign_item(this, foreign_item);
         });
     }
@@ -896,16 +882,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
                 }
             }));
 
-        // We also ban access to type parameters for use as the types of const parameters.
-        let mut const_ty_param_ban_rib = Rib::new(TyParamAsConstParamTy);
-        const_ty_param_ban_rib.bindings.extend(generics.params.iter()
-            .filter(|param| if let GenericParamKind::Type { .. } = param.kind {
-                true
-            } else {
-                false
-            })
-            .map(|param| (Ident::with_empty_ctxt(param.ident.name), Def::Err)));
-
         for param in &generics.params {
             match param.kind {
                 GenericParamKind::Lifetime { .. } => self.visit_generic_param(param),
@@ -924,15 +900,11 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
                     default_ban_rib.bindings.remove(&Ident::with_empty_ctxt(param.ident.name));
                 }
                 GenericParamKind::Const { ref ty } => {
-                    self.ribs[TypeNS].push(const_ty_param_ban_rib);
-
                     for bound in &param.bounds {
                         self.visit_param_bound(bound);
                     }
 
                     self.visit_ty(ty);
-
-                    const_ty_param_ban_rib = self.ribs[TypeNS].pop().unwrap();
                 }
             }
         }
@@ -943,9 +915,9 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
 }
 
 #[derive(Copy, Clone)]
-enum TypeParameters<'a, 'b> {
-    NoTypeParameters,
-    HasTypeParameters(// Type parameters.
+enum GenericParameters<'a, 'b> {
+    NoGenericParams,
+    HasGenericParams(// Type parameters.
                       &'b Generics,
 
                       // The kind of the rib used for type parameters.
@@ -985,9 +957,6 @@ enum RibKind<'a> {
     /// from the default of a type parameter because they're not declared
     /// before said type parameter. Also see the `visit_generics` override.
     ForwardTyParamBanRibKind,
-
-    /// We forbid the use of type parameters as the types of const parameters.
-    TyParamAsConstParamTy,
 }
 
 /// One local scope.
@@ -2405,8 +2374,9 @@ impl<'a> Resolver<'a> {
     }
 
     fn resolve_adt(&mut self, item: &Item, generics: &Generics) {
+        debug!("resolve_adt");
         self.with_current_self_item(item, |this| {
-            this.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), |this| {
+            this.with_generic_param_rib(HasGenericParams(generics, ItemRibKind), |this| {
                 let item_def_id = this.definitions.local_def_id(item.id);
                 this.with_self_rib(Def::SelfTy(None, Some(item_def_id)), |this| {
                     visit::walk_item(this, item);
@@ -2459,13 +2429,13 @@ impl<'a> Resolver<'a> {
 
     fn resolve_item(&mut self, item: &Item) {
         let name = item.ident.name;
-        debug!("(resolving item) resolving {}", name);
+        debug!("(resolving item) resolving {} ({:?})", name, item.node);
 
         match item.node {
             ItemKind::Ty(_, ref generics) |
             ItemKind::Fn(_, _, ref generics, _) |
             ItemKind::Existential(_, ref generics) => {
-                self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind),
+                self.with_generic_param_rib(HasGenericParams(generics, ItemRibKind),
                                              |this| visit::walk_item(this, item));
             }
 
@@ -2484,16 +2454,16 @@ impl<'a> Resolver<'a> {
 
             ItemKind::Trait(.., ref generics, ref bounds, ref trait_items) => {
                 // Create a new rib for the trait-wide type parameters.
-                self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), |this| {
+                self.with_generic_param_rib(HasGenericParams(generics, ItemRibKind), |this| {
                     let local_def_id = this.definitions.local_def_id(item.id);
                     this.with_self_rib(Def::SelfTy(Some(local_def_id), None), |this| {
                         this.visit_generics(generics);
                         walk_list!(this, visit_param_bound, bounds);
 
                         for trait_item in trait_items {
-                            let type_parameters = HasTypeParameters(&trait_item.generics,
+                            let generic_params = HasGenericParams(&trait_item.generics,
                                                                     TraitOrImplItemRibKind);
-                            this.with_type_parameter_rib(type_parameters, |this| {
+                            this.with_generic_param_rib(generic_params, |this| {
                                 match trait_item.node {
                                     TraitItemKind::Const(ref ty, ref default) => {
                                         this.visit_ty(ty);
@@ -2525,7 +2495,7 @@ impl<'a> Resolver<'a> {
 
             ItemKind::TraitAlias(ref generics, ref bounds) => {
                 // Create a new rib for the trait-wide type parameters.
-                self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), |this| {
+                self.with_generic_param_rib(HasGenericParams(generics, ItemRibKind), |this| {
                     let local_def_id = this.definitions.local_def_id(item.id);
                     this.with_self_rib(Def::SelfTy(Some(local_def_id), None), |this| {
                         this.visit_generics(generics);
@@ -2542,6 +2512,7 @@ impl<'a> Resolver<'a> {
 
             ItemKind::Static(ref ty, _, ref expr) |
             ItemKind::Const(ref ty, ref expr) => {
+                debug!("resolve_item ItemKind::Const");
                 self.with_item_rib(|this| {
                     this.visit_ty(ty);
                     this.with_constant_rib(|this| {
@@ -2563,19 +2534,21 @@ impl<'a> Resolver<'a> {
         }
     }
 
-    fn with_type_parameter_rib<'b, F>(&'b mut self, type_parameters: TypeParameters<'a, 'b>, f: F)
+    fn with_generic_param_rib<'b, F>(&'b mut self, generic_params: GenericParameters<'a, 'b>, f: F)
         where F: FnOnce(&mut Resolver<'_>)
     {
-        match type_parameters {
-            HasTypeParameters(generics, rib_kind) => {
+        debug!("with_generic_param_rib");
+        match generic_params {
+            HasGenericParams(generics, rib_kind) => {
                 let mut function_type_rib = Rib::new(rib_kind);
+                let mut function_value_rib = Rib::new(rib_kind);
                 let mut seen_bindings = FxHashMap::default();
                 for param in &generics.params {
                     match param.kind {
                         GenericParamKind::Lifetime { .. } => {}
                         GenericParamKind::Type { .. } => {
                             let ident = param.ident.modern();
-                            debug!("with_type_parameter_rib: {}", param.id);
+                            debug!("with_generic_param_rib: {}", param.id);
 
                             if seen_bindings.contains_key(&ident) {
                                 let span = seen_bindings.get(&ident).unwrap();
@@ -2594,7 +2567,7 @@ impl<'a> Resolver<'a> {
                         }
                         GenericParamKind::Const { .. } => {
                             let ident = param.ident.modern();
-                            debug!("with_type_parameter_rib: {}", param.id);
+                            debug!("with_generic_param_rib: {}", param.id);
 
                             if seen_bindings.contains_key(&ident) {
                                 let span = seen_bindings.get(&ident).unwrap();
@@ -2607,23 +2580,25 @@ impl<'a> Resolver<'a> {
                             seen_bindings.entry(ident).or_insert(param.ident.span);
 
                             let def = Def::ConstParam(self.definitions.local_def_id(param.id));
-                            function_type_rib.bindings.insert(ident, def);
+                            function_value_rib.bindings.insert(ident, def);
                             self.record_def(param.id, PathResolution::new(def));
                         }
                     }
                 }
+                self.ribs[ValueNS].push(function_value_rib);
                 self.ribs[TypeNS].push(function_type_rib);
             }
 
-            NoTypeParameters => {
+            NoGenericParams => {
                 // Nothing to do.
             }
         }
 
         f(self);
 
-        if let HasTypeParameters(..) = type_parameters {
+        if let HasGenericParams(..) = generic_params {
             self.ribs[TypeNS].pop();
+            self.ribs[ValueNS].pop();
         }
     }
 
@@ -2648,6 +2623,7 @@ impl<'a> Resolver<'a> {
     fn with_constant_rib<F>(&mut self, f: F)
         where F: FnOnce(&mut Resolver<'_>)
     {
+        debug!("with_constant_rib");
         self.ribs[ValueNS].push(Rib::new(ConstantItemRibKind));
         self.label_ribs.push(Rib::new(ConstantItemRibKind));
         f(self);
@@ -2741,8 +2717,9 @@ impl<'a> Resolver<'a> {
                               self_type: &Ty,
                               item_id: NodeId,
                               impl_items: &[ImplItem]) {
+        debug!("resolve_implementation");
         // If applicable, create a rib for the type parameters.
-        self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), |this| {
+        self.with_generic_param_rib(HasGenericParams(generics, ItemRibKind), |this| {
             // Dummy self type for better errors if `Self` is used in the trait path.
             this.with_self_rib(Def::SelfTy(None, None), |this| {
                 // Resolve the trait reference, if necessary.
@@ -2755,30 +2732,37 @@ impl<'a> Resolver<'a> {
                         }
                         // Resolve the self type.
                         this.visit_ty(self_type);
-                        // Resolve the type parameters.
+                        // Resolve the generic parameters.
                         this.visit_generics(generics);
                         // Resolve the items within the impl.
                         this.with_current_self_type(self_type, |this| {
                             this.with_self_struct_ctor_rib(item_def_id, |this| {
+                                debug!("resolve_implementation with_self_struct_ctor_rib");
                                 for impl_item in impl_items {
                                     this.resolve_visibility(&impl_item.vis);
 
                                     // We also need a new scope for the impl item type parameters.
-                                    let type_parameters = HasTypeParameters(&impl_item.generics,
-                                                                            TraitOrImplItemRibKind);
-                                    this.with_type_parameter_rib(type_parameters, |this| {
+                                    let generic_params = HasGenericParams(&impl_item.generics,
+                                                                          TraitOrImplItemRibKind);
+                                    this.with_generic_param_rib(generic_params, |this| {
                                         use self::ResolutionError::*;
                                         match impl_item.node {
                                             ImplItemKind::Const(..) => {
+                                                debug!(
+                                                    "resolve_implementation ImplItemKind::Const",
+                                                );
                                                 // If this is a trait impl, ensure the const
                                                 // exists in trait
-                                                this.check_trait_item(impl_item.ident,
-                                                                      ValueNS,
-                                                                      impl_item.span,
-                                                    |n, s| ConstNotMemberOfTrait(n, s));
-                                                this.with_constant_rib(|this|
-                                                    visit::walk_impl_item(this, impl_item)
+                                                this.check_trait_item(
+                                                    impl_item.ident,
+                                                    ValueNS,
+                                                    impl_item.span,
+                                                    |n, s| ConstNotMemberOfTrait(n, s),
                                                 );
+
+                                                this.with_constant_rib(|this| {
+                                                    visit::walk_impl_item(this, impl_item)
+                                                });
                                             }
                                             ImplItemKind::Method(..) => {
                                                 // If this is a trait impl, ensure the method
@@ -4157,6 +4141,7 @@ impl<'a> Resolver<'a> {
                         mut def: Def,
                         record_used: bool,
                         span: Span) -> Def {
+        debug!("adjust_local_def");
         let ribs = &self.ribs[ns][rib_index + 1..];
 
         // An invalid forward use of a type parameter from a previous default.
@@ -4168,15 +4153,6 @@ impl<'a> Resolver<'a> {
             return Def::Err;
         }
 
-        // An invalid use of a type parameter as the type of a const parameter.
-        if let TyParamAsConstParamTy = self.ribs[ns][rib_index].kind {
-            if record_used {
-                resolve_error(self, span, ResolutionError::ConstParamDependentOnTypeParam);
-            }
-            assert_eq!(def, Def::Err);
-            return Def::Err;
-        }
-
         match def {
             Def::Upvar(..) => {
                 span_bug!(span, "unexpected {:?} in bindings", def)
@@ -4185,7 +4161,7 @@ impl<'a> Resolver<'a> {
                 for rib in ribs {
                     match rib.kind {
                         NormalRibKind | ModuleRibKind(..) | MacroDefinition(..) |
-                        ForwardTyParamBanRibKind | TyParamAsConstParamTy => {
+                        ForwardTyParamBanRibKind => {
                             // Nothing to do. Continue.
                         }
                         ClosureRibKind(function_id) => {
@@ -4238,7 +4214,7 @@ impl<'a> Resolver<'a> {
                     match rib.kind {
                         NormalRibKind | TraitOrImplItemRibKind | ClosureRibKind(..) |
                         ModuleRibKind(..) | MacroDefinition(..) | ForwardTyParamBanRibKind |
-                        ConstantItemRibKind | TyParamAsConstParamTy => {
+                        ConstantItemRibKind => {
                             // Nothing to do. Continue.
                         }
                         ItemRibKind => {
@@ -4247,10 +4223,7 @@ impl<'a> Resolver<'a> {
                                 resolve_error(
                                     self,
                                     span,
-                                    ResolutionError::ParametersFromOuterFunction(
-                                        def,
-                                        ParamKindOrd::Type,
-                                    ),
+                                    ResolutionError::TypeParametersFromOuterFunction(def),
                                 );
                             }
                             return Def::Err;
@@ -4258,24 +4231,6 @@ impl<'a> Resolver<'a> {
                     }
                 }
             }
-            Def::ConstParam(..) => {
-                for rib in ribs {
-                    if let ItemRibKind = rib.kind {
-                        // This was an attempt to use a const parameter outside its scope.
-                        if record_used {
-                            resolve_error(
-                                self,
-                                span,
-                                ResolutionError::ParametersFromOuterFunction(
-                                    def,
-                                    ParamKindOrd::Const,
-                                ),
-                            );
-                        }
-                        return Def::Err;
-                    }
-                }
-            }
             _ => {}
         }
         def
diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param.rs b/src/test/ui/const-generics/const-param-type-depends-on-type-param.rs
deleted file mode 100644
index 06ee523be485..000000000000
--- a/src/test/ui/const-generics/const-param-type-depends-on-type-param.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
-
-pub struct Dependent<T, const X: T>([(); X]); //~ ERROR const parameters
-//~^ ERROR const generics in any position are currently unsupported
-
-fn main() {}
diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr b/src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr
deleted file mode 100644
index 375c9fa53219..000000000000
--- a/src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr
+++ /dev/null
@@ -1,21 +0,0 @@
-warning: the feature `const_generics` is incomplete and may cause the compiler to crash
-  --> $DIR/const-param-type-depends-on-type-param.rs:1:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-
-error[E0670]: const parameters cannot depend on type parameters
-  --> $DIR/const-param-type-depends-on-type-param.rs:4:34
-   |
-LL | pub struct Dependent<T, const X: T>([(); X]); //~ ERROR const parameters
-   |                                  ^ const parameter depends on type parameter
-
-error: const generics in any position are currently unsupported
-  --> $DIR/const-param-type-depends-on-type-param.rs:4:31
-   |
-LL | pub struct Dependent<T, const X: T>([(); X]); //~ ERROR const parameters
-   |                               ^
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0670`.

From b3015abfa0f47261c5db37d48ac135709dbd741a Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Thu, 7 Feb 2019 10:27:56 +0100
Subject: [PATCH 22/28] Fix update to 2018 edition

---
 src/libsyntax/ast.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index ab3883d2b9b9..681d8eeaa0d7 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -318,7 +318,7 @@ pub enum ParamKindOrd {
 }
 
 impl fmt::Display for ParamKindOrd {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self {
             ParamKindOrd::Lifetime => "lifetime".fmt(f),
             ParamKindOrd::Type => "type".fmt(f),

From dbc7924b3fbd9b9a0a206b16b4f00049948676c3 Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Thu, 7 Feb 2019 10:58:08 +0100
Subject: [PATCH 23/28] Add test for generic parameter list solely containing
 an attribute

---
 src/test/ui/attribute-with-no-generics-in-parameter-list.rs | 5 +++++
 1 file changed, 5 insertions(+)
 create mode 100644 src/test/ui/attribute-with-no-generics-in-parameter-list.rs

diff --git a/src/test/ui/attribute-with-no-generics-in-parameter-list.rs b/src/test/ui/attribute-with-no-generics-in-parameter-list.rs
new file mode 100644
index 000000000000..3342f749dee9
--- /dev/null
+++ b/src/test/ui/attribute-with-no-generics-in-parameter-list.rs
@@ -0,0 +1,5 @@
+// run-pass
+
+fn foo<#[attr]>() {} // ok
+
+fn main() {}

From 9ad04b9960ed125d450fbf49f3c4c21702ab36ae Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Thu, 7 Feb 2019 14:58:31 +0100
Subject: [PATCH 24/28] Add warning for a parameter list with an attribute but
 no parameters

---
 src/libsyntax/parse/parser.rs                 | 26 ++++++++++++++-----
 ...bute-with-no-generics-in-parameter-list.rs |  4 +--
 ...-with-no-generics-in-parameter-list.stderr |  8 ++++++
 3 files changed, 28 insertions(+), 10 deletions(-)
 create mode 100644 src/test/ui/attribute-with-no-generics-in-parameter-list.stderr

diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 7640f0bdf064..d9195ebe3122 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -5545,13 +5545,25 @@ impl<'a> Parser<'a> {
                 params.push(self.parse_ty_param(attrs)?);
             } else {
                 // Check for trailing attributes and stop parsing.
-                if !attrs.is_empty() && !params.is_empty() {
-                    self.struct_span_err(
-                        attrs[0].span,
-                        &format!("trailing attribute after generic parameter"),
-                    )
-                    .span_label(attrs[0].span, "attributes must go before parameters")
-                    .emit();
+                if !attrs.is_empty() {
+                    if !params.is_empty() {
+                        self.struct_span_err(
+                            attrs[0].span,
+                            &format!("trailing attribute after generic parameter"),
+                        )
+                        .span_label(attrs[0].span, "attributes must go before parameters")
+                        .emit();
+                    } else {
+                        self.struct_span_err(
+                            attrs[0].span,
+                            &format!("attribute without generic parameters"),
+                        )
+                        .span_label(
+                            attrs[0].span,
+                            "attributes are only permitted when preceding parameters",
+                        )
+                        .emit();
+                    }
                 }
                 break
             }
diff --git a/src/test/ui/attribute-with-no-generics-in-parameter-list.rs b/src/test/ui/attribute-with-no-generics-in-parameter-list.rs
index 3342f749dee9..c2cc91d8f770 100644
--- a/src/test/ui/attribute-with-no-generics-in-parameter-list.rs
+++ b/src/test/ui/attribute-with-no-generics-in-parameter-list.rs
@@ -1,5 +1,3 @@
-// run-pass
-
-fn foo<#[attr]>() {} // ok
+fn foo<#[attr]>() {} //~ ERROR attribute without generic parameters
 
 fn main() {}
diff --git a/src/test/ui/attribute-with-no-generics-in-parameter-list.stderr b/src/test/ui/attribute-with-no-generics-in-parameter-list.stderr
new file mode 100644
index 000000000000..f08f107a62ff
--- /dev/null
+++ b/src/test/ui/attribute-with-no-generics-in-parameter-list.stderr
@@ -0,0 +1,8 @@
+error: attribute without generic parameters
+  --> $DIR/attribute-with-no-generics-in-parameter-list.rs:1:8
+   |
+LL | fn foo<#[attr]>() {} //~ ERROR attribute without generic parameters
+   |        ^^^^^^^ attributes are only permitted when preceding parameters
+
+error: aborting due to previous error
+

From 451f1287839451fc097a406fad1a9160c22c280a Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Thu, 7 Feb 2019 14:58:47 +0100
Subject: [PATCH 25/28] Parse negative literals in const generic arguments

---
 src/libsyntax/parse/parser.rs                            | 3 +--
 src/test/ui/const-generics/const-expression-parameter.rs | 4 ++++
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index d9195ebe3122..d71145893c34 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -5796,8 +5796,7 @@ impl<'a> Parser<'a> {
                 } else {
                     // FIXME(const_generics): this currently conflicts with emplacement syntax
                     // with negative integer literals.
-                    let lit = self.parse_lit()?;
-                    self.mk_expr(lit.span, ExprKind::Lit(lit), ThinVec::new())
+                    self.parse_literal_maybe_minus()?
                 };
                 let value = AnonConst {
                     id: ast::DUMMY_NODE_ID,
diff --git a/src/test/ui/const-generics/const-expression-parameter.rs b/src/test/ui/const-generics/const-expression-parameter.rs
index c582c596bfcc..f4e9008dbd0f 100644
--- a/src/test/ui/const-generics/const-expression-parameter.rs
+++ b/src/test/ui/const-generics/const-expression-parameter.rs
@@ -14,6 +14,10 @@ fn foo_b() {
     u32_identity::<1 + 2>(); //~ ERROR expected one of `,` or `>`, found `+`
 }
 
+fn foo_c() {
+    u32_identity::< -1 >(); // ok
+}
+
 fn main() {
     u32_identity::<5>(); // ok
 }

From 4e0e1889990bdf1d6f10c9071144c44eebc80e97 Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Thu, 7 Feb 2019 14:59:59 +0100
Subject: [PATCH 26/28] Make name resolution handle consts in
 GenericParamsFromOuterFunction properly

---
 src/librustc_resolve/lib.rs                   | 49 ++++++++++++++-----
 src/librustc_typeck/diagnostics.rs            |  5 +-
 src/libsyntax/parse/token.rs                  |  3 +-
 src/test/ui/bad/bad-type-env-capture.rs       |  2 +-
 src/test/ui/bad/bad-type-env-capture.stderr   |  8 +--
 src/test/ui/error-codes/E0401.stderr          | 16 +++---
 src/test/ui/inner-static-type-parameter.rs    |  2 +-
 .../ui/inner-static-type-parameter.stderr     |  6 +--
 src/test/ui/issues/issue-12796.rs             |  2 +-
 src/test/ui/issues/issue-12796.stderr         |  4 +-
 src/test/ui/issues/issue-3021-c.rs            |  4 +-
 src/test/ui/issues/issue-3021-c.stderr        | 16 +++---
 src/test/ui/issues/issue-3214.rs              |  2 +-
 src/test/ui/issues/issue-3214.stderr          |  8 +--
 src/test/ui/issues/issue-5997-enum.rs         |  2 +-
 src/test/ui/issues/issue-5997-enum.stderr     |  6 +--
 src/test/ui/issues/issue-5997-struct.rs       |  2 +-
 src/test/ui/issues/issue-5997-struct.stderr   |  8 +--
 src/test/ui/nested-ty-params.rs               |  2 +-
 src/test/ui/nested-ty-params.stderr           | 12 ++---
 .../resolve-type-param-in-item-in-trait.rs    |  8 +--
 ...resolve-type-param-in-item-in-trait.stderr | 24 ++++-----
 src/test/ui/type/type-arg-out-of-scope.rs     |  2 +-
 src/test/ui/type/type-arg-out-of-scope.stderr | 12 ++---
 src/test/ui/use-self-in-inner-fn.rs           |  4 +-
 src/test/ui/use-self-in-inner-fn.stderr       |  4 +-
 26 files changed, 120 insertions(+), 93 deletions(-)

diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index ebd6b0eb5dab..365ba974d5ae 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -142,8 +142,8 @@ impl Ord for BindingError {
 }
 
 enum ResolutionError<'a> {
-    /// error E0401: can't use type parameters from outer function
-    TypeParametersFromOuterFunction(Def),
+    /// error E0401: can't use type or const parameters from outer function
+    GenericParamsFromOuterFunction(Def),
     /// error E0403: the name is already used for a type/const parameter in this list of
     /// generic parameters
     NameAlreadyUsedInParameterList(Name, &'a Span),
@@ -196,13 +196,13 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver<'_>,
                                    resolution_error: ResolutionError<'a>)
                                    -> DiagnosticBuilder<'sess> {
     match resolution_error {
-        ResolutionError::TypeParametersFromOuterFunction(outer_def) => {
+        ResolutionError::GenericParamsFromOuterFunction(outer_def) => {
             let mut err = struct_span_err!(resolver.session,
                 span,
                 E0401,
-                "can't use type parameters from outer function",
+                "can't use generic parameters from outer function",
             );
-            err.span_label(span, format!("use of type variable from outer function"));
+            err.span_label(span, format!("use of generic parameter from outer function"));
 
             let cm = resolver.session.source_map();
             match outer_def {
@@ -231,15 +231,20 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver<'_>,
                         err.span_label(span, "type variable from outer function");
                     }
                 }
+                Def::ConstParam(def_id) => {
+                    if let Some(span) = resolver.definitions.opt_span(def_id) {
+                        err.span_label(span, "const variable from outer function");
+                    }
+                }
                 _ => {
-                    bug!("TypeParametersFromOuterFunction should only be used with Def::SelfTy, \
+                    bug!("GenericParamsFromOuterFunction should only be used with Def::SelfTy, \
                          Def::TyParam");
                 }
             }
 
             // 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 type parameter instead");
+            let sugg_msg = &format!("try using a local generic parameter instead");
             if let Some((sugg_span, new_snippet)) = cm.generate_local_type_param_snippet(span) {
                 // Suggest the modification to the user
                 err.span_suggestion(
@@ -250,9 +255,9 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver<'_>,
                 );
             } else if let Some(sp) = cm.generate_fn_name_span(span) {
                 err.span_label(sp,
-                    format!("try adding a local type parameter in this method instead"));
+                    format!("try adding a local generic parameter in this method instead"));
             } else {
-                err.help(&format!("try using a local type parameter instead"));
+                err.help(&format!("try using a local generic parameter instead"));
             }
 
             err
@@ -549,8 +554,7 @@ impl<'a> PathSource<'a> {
                 Def::Struct(..) | Def::Union(..) | Def::Enum(..) |
                 Def::Trait(..) | Def::TraitAlias(..) | Def::TyAlias(..) |
                 Def::AssociatedTy(..) | Def::PrimTy(..) | Def::TyParam(..) |
-                Def::SelfTy(..) | Def::Existential(..) | Def::ConstParam(..) |
-                Def::ForeignTy(..) => true,
+                Def::SelfTy(..) | Def::Existential(..) | Def::ForeignTy(..) => true,
                 _ => false,
             },
             PathSource::Trait(AliasPossibility::No) => match def {
@@ -803,6 +807,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
                 _: Span,
                 node_id: NodeId)
     {
+        debug!("(resolving function) entering function");
         let (rib_kind, asyncness) = match function_kind {
             FnKind::ItemFn(_, ref header, ..) =>
                 (ItemRibKind, header.asyncness),
@@ -2053,6 +2058,7 @@ impl<'a> Resolver<'a> {
         let record_used = record_used_id.is_some();
         let mut module = self.graph_root;
         for i in (0 .. self.ribs[ns].len()).rev() {
+            debug!("walk rib\n{:?}", self.ribs[ns][i].bindings);
             if let Some(def) = self.ribs[ns][i].bindings.get(&ident).cloned() {
                 // The ident resolves to a type parameter or local variable.
                 return Some(LexicalScopeBinding::Def(
@@ -4223,7 +4229,7 @@ impl<'a> Resolver<'a> {
                                 resolve_error(
                                     self,
                                     span,
-                                    ResolutionError::TypeParametersFromOuterFunction(def),
+                                    ResolutionError::GenericParamsFromOuterFunction(def),
                                 );
                             }
                             return Def::Err;
@@ -4231,6 +4237,25 @@ impl<'a> Resolver<'a> {
                     }
                 }
             }
+            Def::ConstParam(..) => {
+                // A const param is always declared in a signature, which is always followed by
+                // some kind of function rib kind (specifically, ItemRibKind in the case of a
+                // normal function), so we can skip the first rib as it will be guaranteed to
+                // (spuriously) conflict with the const param.
+                for rib in &ribs[1..] {
+                    if let ItemRibKind = rib.kind {
+                        // This was an attempt to use a const parameter outside its scope.
+                        if record_used {
+                            resolve_error(
+                                self,
+                                span,
+                                ResolutionError::GenericParamsFromOuterFunction(def),
+                            );
+                        }
+                        return Def::Err;
+                    }
+                }
+            }
             _ => {}
         }
         def
diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs
index 3ed09dfe9923..e6533ac4b755 100644
--- a/src/librustc_typeck/diagnostics.rs
+++ b/src/librustc_typeck/diagnostics.rs
@@ -348,13 +348,14 @@ fn main() {
 "##,
 
 E0044: r##"
-You can't use type parameters on foreign items. Example of erroneous code:
+You can't use type or const parameters on foreign items.
+Example of erroneous code:
 
 ```compile_fail,E0044
 extern { fn some_func<T>(x: T); }
 ```
 
-To fix this, replace the type parameter with the specializations that you
+To fix this, replace the generic parameter with the specializations that you
 need:
 
 ```
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index c3885f0d04d1..d5856c67156c 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -284,6 +284,7 @@ impl Token {
         match self {
             OpenDelim(Brace) => true,
             Interpolated(ref nt) => match nt.0 {
+                NtExpr(..) => true,
                 NtBlock(..) => true,
                 NtLiteral(..) => true,
                 _ => false,
@@ -306,7 +307,7 @@ impl Token {
         }
     }
 
-    /// Returns `true` if the token is any literal, a minus (which can follow a literal,
+    /// Returns `true` if the token is any literal, a minus (which can prefix a literal,
     /// for example a '-42', or one of the boolean idents).
     crate fn can_begin_literal_or_bool(&self) -> bool {
         match *self {
diff --git a/src/test/ui/bad/bad-type-env-capture.rs b/src/test/ui/bad/bad-type-env-capture.rs
index d2e6dff12527..53dfb13139a5 100644
--- a/src/test/ui/bad/bad-type-env-capture.rs
+++ b/src/test/ui/bad/bad-type-env-capture.rs
@@ -1,4 +1,4 @@
 fn foo<T>() {
-    fn bar(b: T) { } //~ ERROR can't use type parameters from outer
+    fn bar(b: T) { } //~ ERROR can't use generic parameters from outer
 }
 fn main() { }
diff --git a/src/test/ui/bad/bad-type-env-capture.stderr b/src/test/ui/bad/bad-type-env-capture.stderr
index 5558a4400618..ce803e96801f 100644
--- a/src/test/ui/bad/bad-type-env-capture.stderr
+++ b/src/test/ui/bad/bad-type-env-capture.stderr
@@ -1,12 +1,12 @@
-error[E0401]: can't use type parameters from outer function
+error[E0401]: can't use generic parameters from outer function
   --> $DIR/bad-type-env-capture.rs:2:15
    |
 LL | fn foo<T>() {
    |        - type variable from outer function
-LL |     fn bar(b: T) { } //~ ERROR can't use type parameters from outer
-   |        ---    ^ use of type variable from outer function
+LL |     fn bar(b: T) { } //~ ERROR can't use generic parameters from outer
+   |        ---    ^ use of generic parameter from outer function
    |        |
-   |        help: try using a local type parameter instead: `bar<T>`
+   |        help: try using a local generic parameter instead: `bar<T>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/error-codes/E0401.stderr b/src/test/ui/error-codes/E0401.stderr
index c94fa497678e..27f281ee4378 100644
--- a/src/test/ui/error-codes/E0401.stderr
+++ b/src/test/ui/error-codes/E0401.stderr
@@ -1,26 +1,26 @@
-error[E0401]: can't use type parameters from outer function
+error[E0401]: can't use generic parameters from outer function
   --> $DIR/E0401.rs:4:39
    |
 LL | fn foo<T>(x: T) {
    |        - type variable from outer function
 LL |     fn bfnr<U, V: Baz<U>, W: Fn()>(y: T) { //~ ERROR E0401
-   |        ---------------------------    ^ use of type variable from outer function
+   |        ---------------------------    ^ use of generic parameter from outer function
    |        |
-   |        help: try using a local type parameter instead: `bfnr<U, V: Baz<U>, W: Fn(), T>`
+   |        help: try using a local generic parameter instead: `bfnr<U, V: Baz<U>, W: Fn(), T>`
 
-error[E0401]: can't use type parameters from outer function
+error[E0401]: can't use generic parameters from outer function
   --> $DIR/E0401.rs:9:16
    |
 LL | fn foo<T>(x: T) {
    |        - type variable from outer function
 ...
 LL |     fn baz<U,
-   |        --- try adding a local type parameter in this method instead
+   |        --- try adding a local generic parameter in this method instead
 ...
 LL |            (y: T) { //~ ERROR E0401
-   |                ^ use of type variable from outer function
+   |                ^ use of generic parameter from outer function
 
-error[E0401]: can't use type parameters from outer function
+error[E0401]: can't use generic parameters from outer function
   --> $DIR/E0401.rs:22:25
    |
 LL | impl<T> Iterator for A<T> {
@@ -29,7 +29,7 @@ LL | impl<T> Iterator for A<T> {
 LL |         fn helper(sel: &Self) -> u8 { //~ ERROR E0401
    |                         ^^^^
    |                         |
-   |                         use of type variable from outer function
+   |                         use of generic parameter from outer function
    |                         use a type here instead
 
 error: aborting due to 3 previous errors
diff --git a/src/test/ui/inner-static-type-parameter.rs b/src/test/ui/inner-static-type-parameter.rs
index 60b4c5b8131b..c08ccd29d801 100644
--- a/src/test/ui/inner-static-type-parameter.rs
+++ b/src/test/ui/inner-static-type-parameter.rs
@@ -4,7 +4,7 @@ enum Bar<T> { What } //~ ERROR parameter `T` is never used
 
 fn foo<T>() {
     static a: Bar<T> = Bar::What;
-//~^ ERROR can't use type parameters from outer function
+//~^ ERROR can't use generic parameters from outer function
 }
 
 fn main() {
diff --git a/src/test/ui/inner-static-type-parameter.stderr b/src/test/ui/inner-static-type-parameter.stderr
index 2f2856edb0ca..87fb364954d9 100644
--- a/src/test/ui/inner-static-type-parameter.stderr
+++ b/src/test/ui/inner-static-type-parameter.stderr
@@ -1,12 +1,12 @@
-error[E0401]: can't use type parameters from outer function
+error[E0401]: can't use generic parameters from outer function
   --> $DIR/inner-static-type-parameter.rs:6:19
    |
 LL | fn foo<T>() {
    |    --- - type variable from outer function
    |    |
-   |    try adding a local type parameter in this method instead
+   |    try adding a local generic parameter in this method instead
 LL |     static a: Bar<T> = Bar::What;
-   |                   ^ use of type variable from outer function
+   |                   ^ use of generic parameter from outer function
 
 error[E0392]: parameter `T` is never used
   --> $DIR/inner-static-type-parameter.rs:3:10
diff --git a/src/test/ui/issues/issue-12796.rs b/src/test/ui/issues/issue-12796.rs
index acd4584c7370..942d6b9a5686 100644
--- a/src/test/ui/issues/issue-12796.rs
+++ b/src/test/ui/issues/issue-12796.rs
@@ -1,7 +1,7 @@
 trait Trait {
     fn outer(&self) {
         fn inner(_: &Self) {
-            //~^ ERROR can't use type parameters from outer function
+            //~^ ERROR can't use generic parameters from outer function
         }
     }
 }
diff --git a/src/test/ui/issues/issue-12796.stderr b/src/test/ui/issues/issue-12796.stderr
index 4bc29fd37dc4..a01fd2d65420 100644
--- a/src/test/ui/issues/issue-12796.stderr
+++ b/src/test/ui/issues/issue-12796.stderr
@@ -1,10 +1,10 @@
-error[E0401]: can't use type parameters from outer function
+error[E0401]: can't use generic parameters from outer function
   --> $DIR/issue-12796.rs:3:22
    |
 LL |         fn inner(_: &Self) {
    |                      ^^^^
    |                      |
-   |                      use of type variable from outer function
+   |                      use of generic parameter from outer function
    |                      can't use `Self` here
 
 error: aborting due to previous error
diff --git a/src/test/ui/issues/issue-3021-c.rs b/src/test/ui/issues/issue-3021-c.rs
index 491336206ca9..94ed1fdf7819 100644
--- a/src/test/ui/issues/issue-3021-c.rs
+++ b/src/test/ui/issues/issue-3021-c.rs
@@ -1,8 +1,8 @@
 fn siphash<T>() {
 
     trait U {
-        fn g(&self, x: T) -> T;  //~ ERROR can't use type parameters from outer function
-        //~^ ERROR can't use type parameters from outer function
+        fn g(&self, x: T) -> T;  //~ ERROR can't use generic parameters from outer function
+        //~^ ERROR can't use generic parameters from outer function
     }
 }
 
diff --git a/src/test/ui/issues/issue-3021-c.stderr b/src/test/ui/issues/issue-3021-c.stderr
index 323ce4fa3061..5eadf7837c7d 100644
--- a/src/test/ui/issues/issue-3021-c.stderr
+++ b/src/test/ui/issues/issue-3021-c.stderr
@@ -1,24 +1,24 @@
-error[E0401]: can't use type parameters from outer function
+error[E0401]: can't use generic parameters from outer function
   --> $DIR/issue-3021-c.rs:4:24
    |
 LL | fn siphash<T>() {
    |            - type variable from outer function
 ...
-LL |         fn g(&self, x: T) -> T;  //~ ERROR can't use type parameters from outer function
-   |            -           ^ use of type variable from outer function
+LL |         fn g(&self, x: T) -> T;  //~ ERROR can't use generic parameters from outer function
+   |            -           ^ use of generic parameter from outer function
    |            |
-   |            help: try using a local type parameter instead: `g<T>`
+   |            help: try using a local generic parameter instead: `g<T>`
 
-error[E0401]: can't use type parameters from outer function
+error[E0401]: can't use generic parameters from outer function
   --> $DIR/issue-3021-c.rs:4:30
    |
 LL | fn siphash<T>() {
    |            - type variable from outer function
 ...
-LL |         fn g(&self, x: T) -> T;  //~ ERROR can't use type parameters from outer function
-   |            -                 ^ use of type variable from outer function
+LL |         fn g(&self, x: T) -> T;  //~ ERROR can't use generic parameters from outer function
+   |            -                 ^ use of generic parameter from outer function
    |            |
-   |            help: try using a local type parameter instead: `g<T>`
+   |            help: try using a local generic parameter instead: `g<T>`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-3214.rs b/src/test/ui/issues/issue-3214.rs
index 85eae2686e6a..9a727aa30579 100644
--- a/src/test/ui/issues/issue-3214.rs
+++ b/src/test/ui/issues/issue-3214.rs
@@ -1,6 +1,6 @@
 fn foo<T>() {
     struct Foo {
-        x: T, //~ ERROR can't use type parameters from outer function
+        x: T, //~ ERROR can't use generic parameters from outer function
     }
 
     impl<T> Drop for Foo<T> {
diff --git a/src/test/ui/issues/issue-3214.stderr b/src/test/ui/issues/issue-3214.stderr
index 4ecea4f98006..e6526bad3e0d 100644
--- a/src/test/ui/issues/issue-3214.stderr
+++ b/src/test/ui/issues/issue-3214.stderr
@@ -1,13 +1,13 @@
-error[E0401]: can't use type parameters from outer function
+error[E0401]: can't use generic parameters from outer function
   --> $DIR/issue-3214.rs:3:12
    |
 LL | fn foo<T>() {
    |    --- - type variable from outer function
    |    |
-   |    try adding a local type parameter in this method instead
+   |    try adding a local generic parameter in this method instead
 LL |     struct Foo {
-LL |         x: T, //~ ERROR can't use type parameters from outer function
-   |            ^ use of type variable from outer function
+LL |         x: T, //~ ERROR can't use generic parameters from outer function
+   |            ^ use of generic parameter from outer function
 
 error[E0107]: wrong number of type arguments: expected 0, found 1
   --> $DIR/issue-3214.rs:6:26
diff --git a/src/test/ui/issues/issue-5997-enum.rs b/src/test/ui/issues/issue-5997-enum.rs
index 0987117ecd40..3ff4e036c60b 100644
--- a/src/test/ui/issues/issue-5997-enum.rs
+++ b/src/test/ui/issues/issue-5997-enum.rs
@@ -1,6 +1,6 @@
 fn f<Z>() -> bool {
     enum E { V(Z) }
-    //~^ ERROR can't use type parameters from outer function
+    //~^ ERROR can't use generic parameters from outer function
     true
 }
 
diff --git a/src/test/ui/issues/issue-5997-enum.stderr b/src/test/ui/issues/issue-5997-enum.stderr
index 5c26dc92c858..5c778143e13d 100644
--- a/src/test/ui/issues/issue-5997-enum.stderr
+++ b/src/test/ui/issues/issue-5997-enum.stderr
@@ -1,12 +1,12 @@
-error[E0401]: can't use type parameters from outer function
+error[E0401]: can't use generic parameters from outer function
   --> $DIR/issue-5997-enum.rs:2:16
    |
 LL | fn f<Z>() -> bool {
    |    - - type variable from outer function
    |    |
-   |    try adding a local type parameter in this method instead
+   |    try adding a local generic parameter in this method instead
 LL |     enum E { V(Z) }
-   |                ^ use of type variable from outer function
+   |                ^ use of generic parameter from outer function
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-5997-struct.rs b/src/test/ui/issues/issue-5997-struct.rs
index 04ac489a55c5..6cf510b0a9d7 100644
--- a/src/test/ui/issues/issue-5997-struct.rs
+++ b/src/test/ui/issues/issue-5997-struct.rs
@@ -1,5 +1,5 @@
 fn f<T>() -> bool {
-    struct S(T); //~ ERROR can't use type parameters from outer function
+    struct S(T); //~ ERROR can't use generic parameters from outer function
 
     true
 }
diff --git a/src/test/ui/issues/issue-5997-struct.stderr b/src/test/ui/issues/issue-5997-struct.stderr
index 1d05d13242e8..a60987b3f98b 100644
--- a/src/test/ui/issues/issue-5997-struct.stderr
+++ b/src/test/ui/issues/issue-5997-struct.stderr
@@ -1,12 +1,12 @@
-error[E0401]: can't use type parameters from outer function
+error[E0401]: can't use generic parameters from outer function
   --> $DIR/issue-5997-struct.rs:2:14
    |
 LL | fn f<T>() -> bool {
    |    - - type variable from outer function
    |    |
-   |    try adding a local type parameter in this method instead
-LL |     struct S(T); //~ ERROR can't use type parameters from outer function
-   |              ^ use of type variable from outer function
+   |    try adding a local generic parameter in this method instead
+LL |     struct S(T); //~ ERROR can't use generic parameters from outer function
+   |              ^ use of generic parameter from outer function
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nested-ty-params.rs b/src/test/ui/nested-ty-params.rs
index 102f8d02ee41..85413acdb149 100644
--- a/src/test/ui/nested-ty-params.rs
+++ b/src/test/ui/nested-ty-params.rs
@@ -1,4 +1,4 @@
-// error-pattern:can't use type parameters from outer function
+// error-pattern:can't use generic parameters from outer function
 fn hd<U>(v: Vec<U> ) -> U {
     fn hd1(w: [U]) -> U { return w[0]; }
 
diff --git a/src/test/ui/nested-ty-params.stderr b/src/test/ui/nested-ty-params.stderr
index 617eddf6525d..37adeffb9b07 100644
--- a/src/test/ui/nested-ty-params.stderr
+++ b/src/test/ui/nested-ty-params.stderr
@@ -1,22 +1,22 @@
-error[E0401]: can't use type parameters from outer function
+error[E0401]: can't use generic parameters from outer function
   --> $DIR/nested-ty-params.rs:3:16
    |
 LL | fn hd<U>(v: Vec<U> ) -> U {
    |       - type variable from outer function
 LL |     fn hd1(w: [U]) -> U { return w[0]; }
-   |        ---     ^ use of type variable from outer function
+   |        ---     ^ use of generic parameter from outer function
    |        |
-   |        help: try using a local type parameter instead: `hd1<U>`
+   |        help: try using a local generic parameter instead: `hd1<U>`
 
-error[E0401]: can't use type parameters from outer function
+error[E0401]: can't use generic parameters from outer function
   --> $DIR/nested-ty-params.rs:3:23
    |
 LL | fn hd<U>(v: Vec<U> ) -> U {
    |       - type variable from outer function
 LL |     fn hd1(w: [U]) -> U { return w[0]; }
-   |        ---            ^ use of type variable from outer function
+   |        ---            ^ use of generic parameter from outer function
    |        |
-   |        help: try using a local type parameter instead: `hd1<U>`
+   |        help: try using a local generic parameter instead: `hd1<U>`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/resolve/resolve-type-param-in-item-in-trait.rs b/src/test/ui/resolve/resolve-type-param-in-item-in-trait.rs
index 112427a3fcea..c77a66524f73 100644
--- a/src/test/ui/resolve/resolve-type-param-in-item-in-trait.rs
+++ b/src/test/ui/resolve/resolve-type-param-in-item-in-trait.rs
@@ -6,7 +6,7 @@ trait TraitA<A> {
     fn outer(&self) {
         enum Foo<B> {
             Variance(A)
-                //~^ ERROR can't use type parameters from outer function
+                //~^ ERROR can't use generic parameters from outer function
         }
     }
 }
@@ -14,21 +14,21 @@ trait TraitA<A> {
 trait TraitB<A> {
     fn outer(&self) {
         struct Foo<B>(A);
-                //~^ ERROR can't use type parameters from outer function
+                //~^ ERROR can't use generic parameters from outer function
     }
 }
 
 trait TraitC<A> {
     fn outer(&self) {
         struct Foo<B> { a: A }
-                //~^ ERROR can't use type parameters from outer function
+                //~^ ERROR can't use generic parameters from outer function
     }
 }
 
 trait TraitD<A> {
     fn outer(&self) {
         fn foo<B>(a: A) { }
-                //~^ ERROR can't use type parameters from outer function
+                //~^ ERROR can't use generic parameters from outer function
     }
 }
 
diff --git a/src/test/ui/resolve/resolve-type-param-in-item-in-trait.stderr b/src/test/ui/resolve/resolve-type-param-in-item-in-trait.stderr
index 8eca720d88e8..f6b8abf4057e 100644
--- a/src/test/ui/resolve/resolve-type-param-in-item-in-trait.stderr
+++ b/src/test/ui/resolve/resolve-type-param-in-item-in-trait.stderr
@@ -1,44 +1,44 @@
-error[E0401]: can't use type parameters from outer function
+error[E0401]: can't use generic parameters from outer function
   --> $DIR/resolve-type-param-in-item-in-trait.rs:8:22
    |
 LL | trait TraitA<A> {
    |              - type variable from outer function
 LL |     fn outer(&self) {
-   |        ----- try adding a local type parameter in this method instead
+   |        ----- try adding a local generic parameter in this method instead
 LL |         enum Foo<B> {
 LL |             Variance(A)
-   |                      ^ use of type variable from outer function
+   |                      ^ use of generic parameter from outer function
 
-error[E0401]: can't use type parameters from outer function
+error[E0401]: can't use generic parameters from outer function
   --> $DIR/resolve-type-param-in-item-in-trait.rs:16:23
    |
 LL | trait TraitB<A> {
    |              - type variable from outer function
 LL |     fn outer(&self) {
-   |        ----- try adding a local type parameter in this method instead
+   |        ----- try adding a local generic parameter in this method instead
 LL |         struct Foo<B>(A);
-   |                       ^ use of type variable from outer function
+   |                       ^ use of generic parameter from outer function
 
-error[E0401]: can't use type parameters from outer function
+error[E0401]: can't use generic parameters from outer function
   --> $DIR/resolve-type-param-in-item-in-trait.rs:23:28
    |
 LL | trait TraitC<A> {
    |              - type variable from outer function
 LL |     fn outer(&self) {
-   |        ----- try adding a local type parameter in this method instead
+   |        ----- try adding a local generic parameter in this method instead
 LL |         struct Foo<B> { a: A }
-   |                            ^ use of type variable from outer function
+   |                            ^ use of generic parameter from outer function
 
-error[E0401]: can't use type parameters from outer function
+error[E0401]: can't use generic parameters from outer function
   --> $DIR/resolve-type-param-in-item-in-trait.rs:30:22
    |
 LL | trait TraitD<A> {
    |              - type variable from outer function
 LL |     fn outer(&self) {
 LL |         fn foo<B>(a: A) { }
-   |            ------    ^ use of type variable from outer function
+   |            ------    ^ use of generic parameter from outer function
    |            |
-   |            help: try using a local type parameter instead: `foo<B, A>`
+   |            help: try using a local generic parameter instead: `foo<B, A>`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/type/type-arg-out-of-scope.rs b/src/test/ui/type/type-arg-out-of-scope.rs
index b96c9bf6a0e4..d5b815f6a95e 100644
--- a/src/test/ui/type/type-arg-out-of-scope.rs
+++ b/src/test/ui/type/type-arg-out-of-scope.rs
@@ -1,4 +1,4 @@
-// error-pattern:can't use type parameters from outer function
+// error-pattern:can't use generic parameters from outer function
 fn foo<T>(x: T) {
     fn bar(f: Box<FnMut(T) -> T>) { }
 }
diff --git a/src/test/ui/type/type-arg-out-of-scope.stderr b/src/test/ui/type/type-arg-out-of-scope.stderr
index 62b6a86662d0..645cbb33abec 100644
--- a/src/test/ui/type/type-arg-out-of-scope.stderr
+++ b/src/test/ui/type/type-arg-out-of-scope.stderr
@@ -1,22 +1,22 @@
-error[E0401]: can't use type parameters from outer function
+error[E0401]: can't use generic parameters from outer function
   --> $DIR/type-arg-out-of-scope.rs:3:25
    |
 LL | fn foo<T>(x: T) {
    |        - type variable from outer function
 LL |     fn bar(f: Box<FnMut(T) -> T>) { }
-   |        ---              ^ use of type variable from outer function
+   |        ---              ^ use of generic parameter from outer function
    |        |
-   |        help: try using a local type parameter instead: `bar<T>`
+   |        help: try using a local generic parameter instead: `bar<T>`
 
-error[E0401]: can't use type parameters from outer function
+error[E0401]: can't use generic parameters from outer function
   --> $DIR/type-arg-out-of-scope.rs:3:31
    |
 LL | fn foo<T>(x: T) {
    |        - type variable from outer function
 LL |     fn bar(f: Box<FnMut(T) -> T>) { }
-   |        ---                    ^ use of type variable from outer function
+   |        ---                    ^ use of generic parameter from outer function
    |        |
-   |        help: try using a local type parameter instead: `bar<T>`
+   |        help: try using a local generic parameter instead: `bar<T>`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/use-self-in-inner-fn.rs b/src/test/ui/use-self-in-inner-fn.rs
index cde96dc778bb..eccb315feb1e 100644
--- a/src/test/ui/use-self-in-inner-fn.rs
+++ b/src/test/ui/use-self-in-inner-fn.rs
@@ -4,8 +4,8 @@ impl A {
 //~^ NOTE `Self` type implicitly declared here, by this `impl`
     fn banana(&mut self) {
         fn peach(this: &Self) {
-        //~^ ERROR can't use type parameters from outer function
-        //~| NOTE use of type variable from outer function
+        //~^ ERROR can't use generic parameters from outer function
+        //~| NOTE use of generic parameter from outer function
         //~| NOTE use a type here instead
         }
     }
diff --git a/src/test/ui/use-self-in-inner-fn.stderr b/src/test/ui/use-self-in-inner-fn.stderr
index a613804b8038..966093499241 100644
--- a/src/test/ui/use-self-in-inner-fn.stderr
+++ b/src/test/ui/use-self-in-inner-fn.stderr
@@ -1,4 +1,4 @@
-error[E0401]: can't use type parameters from outer function
+error[E0401]: can't use generic parameters from outer function
   --> $DIR/use-self-in-inner-fn.rs:6:25
    |
 LL | impl A {
@@ -7,7 +7,7 @@ LL | impl A {
 LL |         fn peach(this: &Self) {
    |                         ^^^^
    |                         |
-   |                         use of type variable from outer function
+   |                         use of generic parameter from outer function
    |                         use a type here instead
 
 error: aborting due to previous error

From 1b933a5ce911616a2bf64c54c34693387eedb7e1 Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Thu, 7 Feb 2019 15:00:14 +0100
Subject: [PATCH 27/28] Add a test forbidding the use of const parameters in
 inner items

---
 .../const-param-from-outer-fn.rs              | 11 ++++++++
 .../const-param-from-outer-fn.stderr          | 26 +++++++++++++++++++
 2 files changed, 37 insertions(+)
 create mode 100644 src/test/ui/const-generics/const-param-from-outer-fn.rs
 create mode 100644 src/test/ui/const-generics/const-param-from-outer-fn.stderr

diff --git a/src/test/ui/const-generics/const-param-from-outer-fn.rs b/src/test/ui/const-generics/const-param-from-outer-fn.rs
new file mode 100644
index 000000000000..5a8dd92086f8
--- /dev/null
+++ b/src/test/ui/const-generics/const-param-from-outer-fn.rs
@@ -0,0 +1,11 @@
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+fn foo<const X: u32>() {
+    //~^ ERROR const generics in any position are currently unsupported
+    fn bar() -> u32 {
+        X //~ ERROR can't use generic parameters from outer function
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/const-param-from-outer-fn.stderr b/src/test/ui/const-generics/const-param-from-outer-fn.stderr
new file mode 100644
index 000000000000..b238b3a2aa45
--- /dev/null
+++ b/src/test/ui/const-generics/const-param-from-outer-fn.stderr
@@ -0,0 +1,26 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/const-param-from-outer-fn.rs:1:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+
+error[E0401]: can't use generic parameters from outer function
+  --> $DIR/const-param-from-outer-fn.rs:7:9
+   |
+LL | fn foo<const X: u32>() {
+   |              - const variable from outer function
+LL |     //~^ ERROR const generics in any position are currently unsupported
+LL |     fn bar() -> u32 {
+   |        --- try adding a local generic parameter in this method instead
+LL |         X //~ ERROR can't use generic parameters from outer function
+   |         ^ use of generic parameter from outer function
+
+error: const generics in any position are currently unsupported
+  --> $DIR/const-param-from-outer-fn.rs:4:14
+   |
+LL | fn foo<const X: u32>() {
+   |              ^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0401`.

From f2fe71c02ac7ecb29106b1a826d657ff5705ad6c Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Thu, 7 Feb 2019 16:03:12 +0100
Subject: [PATCH 28/28] Resolve incorrect diagnostic for using a non-const
 value in a constant

---
 src/librustc_resolve/lib.rs                   | 18 +++++++++----
 src/test/ui/impl-trait/bindings.rs            |  8 +++---
 src/test/ui/impl-trait/bindings.stderr        | 26 +++++++------------
 src/test/ui/issues/issue-27433.rs             |  2 +-
 src/test/ui/issues/issue-27433.stderr         |  8 +++---
 src/test/ui/issues/issue-3521-2.rs            |  2 +-
 src/test/ui/issues/issue-3521-2.stderr        |  8 +++---
 src/test/ui/issues/issue-3668-2.rs            |  2 +-
 src/test/ui/issues/issue-3668-2.stderr        |  8 +++---
 src/test/ui/issues/issue-3668.rs              |  2 +-
 src/test/ui/issues/issue-3668.stderr          |  8 +++---
 .../ui/type/type-dependent-def-issue-49241.rs |  2 +-
 .../type-dependent-def-issue-49241.stderr     | 10 +++----
 13 files changed, 47 insertions(+), 57 deletions(-)

diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 365ba974d5ae..0d1f6328105b 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -4164,6 +4164,9 @@ impl<'a> Resolver<'a> {
                 span_bug!(span, "unexpected {:?} in bindings", def)
             }
             Def::Local(node_id) => {
+                use ResolutionError::*;
+                let mut res_err = None;
+
                 for rib in ribs {
                     match rib.kind {
                         NormalRibKind | ModuleRibKind(..) | MacroDefinition(..) |
@@ -4199,21 +4202,26 @@ impl<'a> Resolver<'a> {
                             // named function item. This is not allowed, so we
                             // report an error.
                             if record_used {
-                                resolve_error(self, span,
-                                    ResolutionError::CannotCaptureDynamicEnvironmentInFnItem);
+                                // We don't immediately trigger a resolve error, because
+                                // we want certain other resolution errors (namely those
+                                // emitted for `ConstantItemRibKind` below) to take
+                                // precedence.
+                                res_err = Some(CannotCaptureDynamicEnvironmentInFnItem);
                             }
-                            return Def::Err;
                         }
                         ConstantItemRibKind => {
                             // Still doesn't deal with upvars
                             if record_used {
-                                resolve_error(self, span,
-                                    ResolutionError::AttemptToUseNonConstantValueInConstant);
+                                resolve_error(self, span, AttemptToUseNonConstantValueInConstant);
                             }
                             return Def::Err;
                         }
                     }
                 }
+                if let Some(res_err) = res_err {
+                     resolve_error(self, span, res_err);
+                     return Def::Err;
+                }
             }
             Def::TyParam(..) | Def::SelfTy(..) => {
                 for rib in ribs {
diff --git a/src/test/ui/impl-trait/bindings.rs b/src/test/ui/impl-trait/bindings.rs
index 899303646d67..91d092634a90 100644
--- a/src/test/ui/impl-trait/bindings.rs
+++ b/src/test/ui/impl-trait/bindings.rs
@@ -2,27 +2,27 @@
 
 fn a<T: Clone>(x: T) {
     const foo: impl Clone = x;
-//~^ ERROR can't capture dynamic environment in a fn item
+    //~^ ERROR attempt to use a non-constant value in a constant
 }
 
 fn b<T: Clone>(x: T) {
     let _ = move || {
         const foo: impl Clone = x;
-//~^ ERROR can't capture dynamic environment in a fn item
+        //~^ ERROR attempt to use a non-constant value in a constant
     };
 }
 
 trait Foo<T: Clone> {
     fn a(x: T) {
         const foo: impl Clone = x;
-//~^ ERROR can't capture dynamic environment in a fn item
+        //~^ ERROR attempt to use a non-constant value in a constant
     }
 }
 
 impl<T: Clone> Foo<T> for i32 {
     fn a(x: T) {
         const foo: impl Clone = x;
-//~^ ERROR can't capture dynamic environment in a fn item
+        //~^ ERROR attempt to use a non-constant value in a constant
     }
 }
 
diff --git a/src/test/ui/impl-trait/bindings.stderr b/src/test/ui/impl-trait/bindings.stderr
index 2a9be7a270a7..a5bf583afeaf 100644
--- a/src/test/ui/impl-trait/bindings.stderr
+++ b/src/test/ui/impl-trait/bindings.stderr
@@ -1,35 +1,27 @@
-error[E0434]: can't capture dynamic environment in a fn item
+error[E0435]: attempt to use a non-constant value in a constant
   --> $DIR/bindings.rs:4:29
    |
 LL |     const foo: impl Clone = x;
-   |                             ^
-   |
-   = help: use the `|| { ... }` closure form instead
+   |                             ^ non-constant value
 
-error[E0434]: can't capture dynamic environment in a fn item
+error[E0435]: attempt to use a non-constant value in a constant
   --> $DIR/bindings.rs:10:33
    |
 LL |         const foo: impl Clone = x;
-   |                                 ^
-   |
-   = help: use the `|| { ... }` closure form instead
+   |                                 ^ non-constant value
 
-error[E0434]: can't capture dynamic environment in a fn item
+error[E0435]: attempt to use a non-constant value in a constant
   --> $DIR/bindings.rs:17:33
    |
 LL |         const foo: impl Clone = x;
-   |                                 ^
-   |
-   = help: use the `|| { ... }` closure form instead
+   |                                 ^ non-constant value
 
-error[E0434]: can't capture dynamic environment in a fn item
+error[E0435]: attempt to use a non-constant value in a constant
   --> $DIR/bindings.rs:24:33
    |
 LL |         const foo: impl Clone = x;
-   |                                 ^
-   |
-   = help: use the `|| { ... }` closure form instead
+   |                                 ^ non-constant value
 
 error: aborting due to 4 previous errors
 
-For more information about this error, try `rustc --explain E0434`.
+For more information about this error, try `rustc --explain E0435`.
diff --git a/src/test/ui/issues/issue-27433.rs b/src/test/ui/issues/issue-27433.rs
index 2cc7d05e7c69..156ae68efe2c 100644
--- a/src/test/ui/issues/issue-27433.rs
+++ b/src/test/ui/issues/issue-27433.rs
@@ -1,5 +1,5 @@
 fn main() {
     let foo = 42u32;
     const FOO : u32 = foo;
-                   //~^ ERROR can't capture dynamic environment
+                   //~^ ERROR attempt to use a non-constant value in a constant
 }
diff --git a/src/test/ui/issues/issue-27433.stderr b/src/test/ui/issues/issue-27433.stderr
index 78a193dd99a7..e232d17e6d7a 100644
--- a/src/test/ui/issues/issue-27433.stderr
+++ b/src/test/ui/issues/issue-27433.stderr
@@ -1,11 +1,9 @@
-error[E0434]: can't capture dynamic environment in a fn item
+error[E0435]: attempt to use a non-constant value in a constant
   --> $DIR/issue-27433.rs:3:23
    |
 LL |     const FOO : u32 = foo;
-   |                       ^^^
-   |
-   = help: use the `|| { ... }` closure form instead
+   |                       ^^^ non-constant value
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0434`.
+For more information about this error, try `rustc --explain E0435`.
diff --git a/src/test/ui/issues/issue-3521-2.rs b/src/test/ui/issues/issue-3521-2.rs
index 39f7fcb83375..871394f9eaeb 100644
--- a/src/test/ui/issues/issue-3521-2.rs
+++ b/src/test/ui/issues/issue-3521-2.rs
@@ -2,7 +2,7 @@ fn main() {
     let foo = 100;
 
     static y: isize = foo + 1;
-    //~^ ERROR can't capture dynamic environment
+    //~^ ERROR attempt to use a non-constant value in a constant
 
     println!("{}", y);
 }
diff --git a/src/test/ui/issues/issue-3521-2.stderr b/src/test/ui/issues/issue-3521-2.stderr
index 1464fd74bba6..d54bbbcdc332 100644
--- a/src/test/ui/issues/issue-3521-2.stderr
+++ b/src/test/ui/issues/issue-3521-2.stderr
@@ -1,11 +1,9 @@
-error[E0434]: can't capture dynamic environment in a fn item
+error[E0435]: attempt to use a non-constant value in a constant
   --> $DIR/issue-3521-2.rs:4:23
    |
 LL |     static y: isize = foo + 1;
-   |                       ^^^
-   |
-   = help: use the `|| { ... }` closure form instead
+   |                       ^^^ non-constant value
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0434`.
+For more information about this error, try `rustc --explain E0435`.
diff --git a/src/test/ui/issues/issue-3668-2.rs b/src/test/ui/issues/issue-3668-2.rs
index 265a884ded7a..525f6f5684e7 100644
--- a/src/test/ui/issues/issue-3668-2.rs
+++ b/src/test/ui/issues/issue-3668-2.rs
@@ -1,6 +1,6 @@
 fn f(x:isize) {
     static child: isize = x + 1;
-    //~^ ERROR can't capture dynamic environment
+    //~^ ERROR attempt to use a non-constant value in a constant
 }
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-3668-2.stderr b/src/test/ui/issues/issue-3668-2.stderr
index 8dd6f49d8de5..d6a6e8379602 100644
--- a/src/test/ui/issues/issue-3668-2.stderr
+++ b/src/test/ui/issues/issue-3668-2.stderr
@@ -1,11 +1,9 @@
-error[E0434]: can't capture dynamic environment in a fn item
+error[E0435]: attempt to use a non-constant value in a constant
   --> $DIR/issue-3668-2.rs:2:27
    |
 LL |     static child: isize = x + 1;
-   |                           ^
-   |
-   = help: use the `|| { ... }` closure form instead
+   |                           ^ non-constant value
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0434`.
+For more information about this error, try `rustc --explain E0435`.
diff --git a/src/test/ui/issues/issue-3668.rs b/src/test/ui/issues/issue-3668.rs
index 3f61b1b02e77..0e1f19a75bae 100644
--- a/src/test/ui/issues/issue-3668.rs
+++ b/src/test/ui/issues/issue-3668.rs
@@ -6,7 +6,7 @@ trait PTrait {
 impl PTrait for P {
    fn getChildOption(&self) -> Option<Box<P>> {
        static childVal: Box<P> = self.child.get();
-       //~^ ERROR can't capture dynamic environment
+       //~^ ERROR attempt to use a non-constant value in a constant
        panic!();
    }
 }
diff --git a/src/test/ui/issues/issue-3668.stderr b/src/test/ui/issues/issue-3668.stderr
index 7f974de9da8e..98cd3631a536 100644
--- a/src/test/ui/issues/issue-3668.stderr
+++ b/src/test/ui/issues/issue-3668.stderr
@@ -1,11 +1,9 @@
-error[E0434]: can't capture dynamic environment in a fn item
+error[E0435]: attempt to use a non-constant value in a constant
   --> $DIR/issue-3668.rs:8:34
    |
 LL |        static childVal: Box<P> = self.child.get();
-   |                                  ^^^^
-   |
-   = help: use the `|| { ... }` closure form instead
+   |                                  ^^^^ non-constant value
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0434`.
+For more information about this error, try `rustc --explain E0435`.
diff --git a/src/test/ui/type/type-dependent-def-issue-49241.rs b/src/test/ui/type/type-dependent-def-issue-49241.rs
index 4c366a863637..51bd116fbd61 100644
--- a/src/test/ui/type/type-dependent-def-issue-49241.rs
+++ b/src/test/ui/type/type-dependent-def-issue-49241.rs
@@ -1,6 +1,6 @@
 fn main() {
     let v = vec![0];
-    const l: usize = v.count(); //~ ERROR can't capture dynamic environment in a fn item
+    const l: usize = v.count(); //~ ERROR attempt to use a non-constant value in a constant
     let s: [u32; l] = v.into_iter().collect();
     //~^ ERROR evaluation of constant value failed
 }
diff --git a/src/test/ui/type/type-dependent-def-issue-49241.stderr b/src/test/ui/type/type-dependent-def-issue-49241.stderr
index 8783959f45f5..0af777fdcf90 100644
--- a/src/test/ui/type/type-dependent-def-issue-49241.stderr
+++ b/src/test/ui/type/type-dependent-def-issue-49241.stderr
@@ -1,10 +1,8 @@
-error[E0434]: can't capture dynamic environment in a fn item
+error[E0435]: attempt to use a non-constant value in a constant
   --> $DIR/type-dependent-def-issue-49241.rs:3:22
    |
-LL |     const l: usize = v.count(); //~ ERROR can't capture dynamic environment in a fn item
-   |                      ^
-   |
-   = help: use the `|| { ... }` closure form instead
+LL |     const l: usize = v.count(); //~ ERROR attempt to use a non-constant value in a constant
+   |                      ^ non-constant value
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/type-dependent-def-issue-49241.rs:4:18
@@ -14,5 +12,5 @@ LL |     let s: [u32; l] = v.into_iter().collect();
 
 error: aborting due to 2 previous errors
 
-Some errors occurred: E0080, E0434.
+Some errors occurred: E0080, E0435.
 For more information about an error, try `rustc --explain E0080`.