about summary refs log tree commit diff
path: root/compiler/rustc_parse/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-01-01 13:17:42 +0000
committerbors <bors@rust-lang.org>2021-01-01 13:17:42 +0000
commita609fb45efad59dfd459c76e50899be9f0583b5a (patch)
treec1fdab60473e830ac13b75ffaa0175c46bb27f57 /compiler/rustc_parse/src
parent18d27b2c94cff9a5f6d8e4d2ea45f6f2e434e5f6 (diff)
parent942b7ce2c14b1c4fde5b9f27aa5bef39e0b990d5 (diff)
downloadrust-a609fb45efad59dfd459c76e50899be9f0583b5a.tar.gz
rust-a609fb45efad59dfd459c76e50899be9f0583b5a.zip
Auto merge of #80547 - lqd:const_generics_defaults, r=varkor
In which we start to parse const generics defaults

As discussed in this [zulip topic](https://rust-lang.zulipchat.com/#narrow/stream/260443-project-const-generics/topic/const.20generic.20defaults), this PR extracts the parsing parts from `@JulianKnodt's` PR #75384 for a better user-experience using the newly stabilized `min_const_generics` (albeit temporary) as shown in #80507: trying to use default values on const generics currently results in parse errors, as if the user didn't use the correct syntax (which is somewhat true but also misleading).

This PR extracts (and slightly modifies in a couple places) `@JulianKnodt's` parsing code (with attribution if I've done everything correctly), AST and HIR changes, and feature gate setup.

This feature is now marked as "incomplete" and thus will also print out the expected "const generics default values are unstable" error instead of a syntax error. Note that, as I've only extracted the parsing part, the actual feature will not work at all if enabled. There will be ICEs, and inference errors on the const generics default values themselves.

Fixes #80507.

Once this merges, I'll:
- modify the const generics tracking issue to refer to the `const_generics_defaults` gate rather than the older temporary name it uses there.
- create the GH `F-const_generics_defaults` label

r? `@varkor`
Diffstat (limited to 'compiler/rustc_parse/src')
-rw-r--r--compiler/rustc_parse/src/parser/generics.rs18
-rw-r--r--compiler/rustc_parse/src/parser/path.rs29
2 files changed, 34 insertions, 13 deletions
diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs
index 860e63020bb..42a13376863 100644
--- a/compiler/rustc_parse/src/parser/generics.rs
+++ b/compiler/rustc_parse/src/parser/generics.rs
@@ -5,7 +5,7 @@ use rustc_ast::{
     self as ast, Attribute, GenericBounds, GenericParam, GenericParamKind, WhereClause,
 };
 use rustc_errors::PResult;
-use rustc_span::symbol::kw;
+use rustc_span::symbol::{kw, sym};
 
 impl<'a> Parser<'a> {
     /// Parses bounds of a lifetime parameter `BOUND + BOUND + BOUND`, possibly with trailing `+`.
@@ -56,12 +56,26 @@ impl<'a> Parser<'a> {
         self.expect(&token::Colon)?;
         let ty = self.parse_ty()?;
 
+        // Parse optional const generics default value, taking care of feature gating the spans
+        // with the unstable syntax mechanism.
+        let default = if self.eat(&token::Eq) {
+            // The gated span goes from the `=` to the end of the const argument that follows (and
+            // which could be a block expression).
+            let start = self.prev_token.span;
+            let const_arg = self.parse_const_arg()?;
+            let span = start.to(const_arg.value.span);
+            self.sess.gated_spans.gate(sym::const_generics_defaults, span);
+            Some(const_arg)
+        } else {
+            None
+        };
+
         Ok(GenericParam {
             ident,
             id: ast::DUMMY_NODE_ID,
             attrs: preceding_attrs.into(),
             bounds: Vec::new(),
-            kind: GenericParamKind::Const { ty, kw_span: const_span },
+            kind: GenericParamKind::Const { ty, kw_span: const_span, default },
             is_placeholder: false,
         })
     }
diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs
index 60a47ca12b8..43dee391c17 100644
--- a/compiler/rustc_parse/src/parser/path.rs
+++ b/compiler/rustc_parse/src/parser/path.rs
@@ -515,6 +515,23 @@ impl<'a> Parser<'a> {
         }
     }
 
+    /// Parse a const argument, e.g. `<3>`. It is assumed the angle brackets will be parsed by
+    /// the caller.
+    pub(super) fn parse_const_arg(&mut self) -> PResult<'a, AnonConst> {
+        // Parse const argument.
+        let value = if let token::OpenDelim(token::Brace) = self.token.kind {
+            self.parse_block_expr(
+                None,
+                self.token.span,
+                BlockCheckMode::Default,
+                ast::AttrVec::new(),
+            )?
+        } else {
+            self.handle_unambiguous_unbraced_const_arg()?
+        };
+        Ok(AnonConst { id: ast::DUMMY_NODE_ID, value })
+    }
+
     /// Parse a generic argument in a path segment.
     /// This does not include constraints, e.g., `Item = u8`, which is handled in `parse_angle_arg`.
     fn parse_generic_arg(&mut self) -> PResult<'a, Option<GenericArg>> {
@@ -524,17 +541,7 @@ impl<'a> Parser<'a> {
             GenericArg::Lifetime(self.expect_lifetime())
         } else if self.check_const_arg() {
             // Parse const argument.
-            let value = if let token::OpenDelim(token::Brace) = self.token.kind {
-                self.parse_block_expr(
-                    None,
-                    self.token.span,
-                    BlockCheckMode::Default,
-                    ast::AttrVec::new(),
-                )?
-            } else {
-                self.handle_unambiguous_unbraced_const_arg()?
-            };
-            GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value })
+            GenericArg::Const(self.parse_const_arg()?)
         } else if self.check_type() {
             // Parse type argument.
             match self.parse_ty() {