diff options
| author | Mazdak Farrokhzad <twingoow@gmail.com> | 2020-01-21 19:42:20 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-01-21 19:42:20 +0100 |
| commit | 3484e2fab4153068e4e5eaebab215e680efe38f1 (patch) | |
| tree | 4955c22b712892f482ee718f954769726fd66baa /src/librustc_parse/parser | |
| parent | d532a04a1c6afb34c8b0ac5da3e2bbf76aad5800 (diff) | |
| parent | 6bd69a10921785aa8ab68e58d9c7a7ea1ff6ef96 (diff) | |
| download | rust-3484e2fab4153068e4e5eaebab215e680efe38f1.tar.gz rust-3484e2fab4153068e4e5eaebab215e680efe38f1.zip | |
Rollup merge of #68140 - ecstatic-morse:const-trait-bound-opt-out, r=oli-obk
Implement `?const` opt-out for trait bounds For now, such bounds are treated exactly the same as unprefixed ones in all contexts. [RFC 2632](https://github.com/rust-lang/rfcs/pull/2632) does not specify whether such bounds are forbidden outside of `const` contexts, so they are allowed at the moment. Prior to this PR, the constness of a trait bound/impl was stored in `TraitRef`. Now, the constness of an `impl` is stored in `ast::ItemKind::Impl` and the constness of a bound in `ast::TraitBoundModifer`. Additionally, constness of trait bounds is now stored in an additional field of `ty::Predicate::Trait`, and the combination of the constness of the item along with any `TraitBoundModifier` determines the constness of the bound in accordance with the RFC. Encoding the constness of impls at the `ty` level is left for a later PR. After a discussion in \#wg-grammar on Discord, it was decided that the grammar should not encode the mutual exclusivity of trait bound modifiers. The grammar for trait bound modifiers remains `[?const] [?]`. To encode this, I add a dummy variant to `ast::TraitBoundModifier` that is used when the syntax `?const ?` appears. This variant causes an error in AST validation and disappears during HIR lowering. cc #67794 r? @oli-obk
Diffstat (limited to 'src/librustc_parse/parser')
| -rw-r--r-- | src/librustc_parse/parser/item.rs | 18 | ||||
| -rw-r--r-- | src/librustc_parse/parser/ty.rs | 18 |
2 files changed, 16 insertions, 20 deletions
diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 5076aafe4eb..31db7fc5f75 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -4,7 +4,7 @@ use super::{FollowedByType, Parser, PathStyle}; use crate::maybe_whole; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, PResult, StashKey}; -use rustc_span::source_map::{self, respan, Span, Spanned}; +use rustc_span::source_map::{self, respan, Span}; use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::BytePos; use syntax::ast::{self, AttrKind, AttrStyle, AttrVec, Attribute, Ident, DUMMY_NODE_ID}; @@ -565,9 +565,9 @@ impl<'a> Parser<'a> { let constness = if self.eat_keyword(kw::Const) { let span = self.prev_span; self.sess.gated_spans.gate(sym::const_trait_impl, span); - Some(respan(span, Constness::Const)) + Constness::Const } else { - None + Constness::NotConst }; // Disambiguate `impl !Trait for Type { ... }` and `impl ! { ... }` for the never type. @@ -630,13 +630,13 @@ impl<'a> Parser<'a> { err_path(ty_first.span) } }; - let constness = constness.map(|c| c.node); - let trait_ref = TraitRef { path, constness, ref_id: ty_first.id }; + let trait_ref = TraitRef { path, ref_id: ty_first.id }; ItemKind::Impl { unsafety, polarity, defaultness, + constness, generics, of_trait: Some(trait_ref), self_ty: ty_second, @@ -644,18 +644,12 @@ impl<'a> Parser<'a> { } } None => { - // Reject `impl const Type {}` here - if let Some(Spanned { node: Constness::Const, span }) = constness { - self.struct_span_err(span, "`const` cannot modify an inherent impl") - .help("only a trait impl can be `const`") - .emit(); - } - // impl Type ItemKind::Impl { unsafety, polarity, defaultness, + constness, generics, of_trait: None, self_ty: ty_first, diff --git a/src/librustc_parse/parser/ty.rs b/src/librustc_parse/parser/ty.rs index d1875a6c940..a4cc9fa48f2 100644 --- a/src/librustc_parse/parser/ty.rs +++ b/src/librustc_parse/parser/ty.rs @@ -26,10 +26,12 @@ struct BoundModifiers { } impl BoundModifiers { - fn trait_bound_modifier(&self) -> TraitBoundModifier { - match self.maybe { - Some(_) => TraitBoundModifier::Maybe, - None => TraitBoundModifier::None, + fn to_trait_bound_modifier(&self) -> TraitBoundModifier { + match (self.maybe, self.maybe_const) { + (None, None) => TraitBoundModifier::None, + (Some(_), None) => TraitBoundModifier::Maybe, + (None, Some(_)) => TraitBoundModifier::MaybeConst, + (Some(_), Some(_)) => TraitBoundModifier::MaybeConstMaybe, } } } @@ -214,7 +216,7 @@ impl<'a> Parser<'a> { ) -> PResult<'a, TyKind> { assert_ne!(self.token, token::Question); - let poly_trait_ref = PolyTraitRef::new(generic_params, path, None, lo.to(self.prev_span)); + let poly_trait_ref = PolyTraitRef::new(generic_params, path, lo.to(self.prev_span)); let mut bounds = vec![GenericBound::Trait(poly_trait_ref, TraitBoundModifier::None)]; if parse_plus { self.eat_plus(); // `+`, or `+=` gets split and `+` is discarded @@ -556,9 +558,9 @@ impl<'a> Parser<'a> { self.expect(&token::CloseDelim(token::Paren))?; } - let constness = modifiers.maybe_const.map(|_| ast::Constness::NotConst); - let poly_trait = PolyTraitRef::new(lifetime_defs, path, constness, lo.to(self.prev_span)); - Ok(GenericBound::Trait(poly_trait, modifiers.trait_bound_modifier())) + let modifier = modifiers.to_trait_bound_modifier(); + let poly_trait = PolyTraitRef::new(lifetime_defs, path, lo.to(self.prev_span)); + Ok(GenericBound::Trait(poly_trait, modifier)) } /// Optionally parses `for<$generic_params>`. |
