Parse `?const ?Trait`
diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs
index 90560c3..bc922fa 100644
--- a/src/librustc_ast_lowering/lib.rs
+++ b/src/librustc_ast_lowering/lib.rs
@@ -1254,7 +1254,10 @@
| GenericBound::Trait(ref ty, TraitBoundModifier::MaybeConst) => {
Some(this.lower_poly_trait_ref(ty, itctx.reborrow()))
}
- GenericBound::Trait(_, TraitBoundModifier::Maybe) => None,
+ GenericBound::Trait(_, TraitBoundModifier::Maybe)
+ | GenericBound::Trait(_, TraitBoundModifier::MaybeConstMaybe) => {
+ None
+ }
GenericBound::Outlives(ref lifetime) => {
if lifetime_bound.is_none() {
lifetime_bound = Some(this.lower_lifetime(lifetime));
@@ -2297,8 +2300,10 @@
fn lower_trait_bound_modifier(&mut self, f: TraitBoundModifier) -> hir::TraitBoundModifier {
match f {
TraitBoundModifier::None => hir::TraitBoundModifier::None,
- TraitBoundModifier::Maybe => hir::TraitBoundModifier::Maybe,
TraitBoundModifier::MaybeConst => hir::TraitBoundModifier::MaybeConst,
+ TraitBoundModifier::MaybeConstMaybe | TraitBoundModifier::Maybe => {
+ hir::TraitBoundModifier::Maybe
+ }
}
}
diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs
index 23cb973..9b71704 100644
--- a/src/librustc_ast_passes/ast_validation.rs
+++ b/src/librustc_ast_passes/ast_validation.rs
@@ -917,11 +917,20 @@
}
fn visit_param_bound(&mut self, bound: &'a GenericBound) {
- if let GenericBound::Trait(_, TraitBoundModifier::MaybeConst) = bound {
- if let Some(ctx) = self.bound_context {
- let msg = format!("`?const` is not permitted in {}", ctx.description());
- self.err_handler().span_err(bound.span(), &msg);
+ match bound {
+ GenericBound::Trait(_, TraitBoundModifier::MaybeConst) => {
+ if let Some(ctx) = self.bound_context {
+ let msg = format!("`?const` is not permitted in {}", ctx.description());
+ self.err_handler().span_err(bound.span(), &msg);
+ }
}
+
+ GenericBound::Trait(_, TraitBoundModifier::MaybeConstMaybe) => {
+ self.err_handler()
+ .span_err(bound.span(), "`?const` and `?` are mutually exclusive");
+ }
+
+ _ => {}
}
visit::walk_param_bound(self, bound)
diff --git a/src/librustc_parse/parser/ty.rs b/src/librustc_parse/parser/ty.rs
index 9c91807..efd8acc 100644
--- a/src/librustc_parse/parser/ty.rs
+++ b/src/librustc_parse/parser/ty.rs
@@ -27,17 +27,13 @@
}
impl BoundModifiers {
- fn to_trait_bound_modifier(&self) -> Result<TraitBoundModifier, &'static str> {
- let modifier = match (self.maybe, self.maybe_const) {
+ 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(_)) => {
- return Err("`?const` and `?` are mutually exclusive");
- }
- };
-
- Ok(modifier)
+ (Some(_), Some(_)) => TraitBoundModifier::MaybeConstMaybe,
+ }
}
}
@@ -563,16 +559,7 @@
self.expect(&token::CloseDelim(token::Paren))?;
}
- let modifier = match modifiers.to_trait_bound_modifier() {
- Ok(m) => m,
- Err(msg) => {
- self.struct_span_err(lo.to(self.prev_span), msg).emit();
-
- // Continue compilation as if the user had written `?Trait`.
- TraitBoundModifier::Maybe
- }
- };
-
+ 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))
}
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 88bfb8c..5f38ac4 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -279,6 +279,11 @@
/// `?const Trait`
MaybeConst,
+
+ /// `?const ?Trait`
+ //
+ // This parses but will be rejected during AST validation.
+ MaybeConstMaybe,
}
/// The AST represents all type param bounds as types.