diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs index 90560c371e2..bc922fa0f55 100644 --- a/src/librustc_ast_lowering/lib.rs +++ b/src/librustc_ast_lowering/lib.rs @@ -1254,7 +1254,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { | 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 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { 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 23cb9734833..9b71704f52d 100644 --- a/src/librustc_ast_passes/ast_validation.rs +++ b/src/librustc_ast_passes/ast_validation.rs @@ -917,11 +917,20 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } 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 9c9180778e5..efd8acc933a 100644 --- a/src/librustc_parse/parser/ty.rs +++ b/src/librustc_parse/parser/ty.rs @@ -27,17 +27,13 @@ struct BoundModifiers { } impl BoundModifiers { - fn to_trait_bound_modifier(&self) -> Result { - 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 @@ impl<'a> Parser<'a> { 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 88bfb8ccb95..5f38ac4cc0f 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -279,6 +279,11 @@ pub enum TraitBoundModifier { /// `?const Trait` MaybeConst, + + /// `?const ?Trait` + // + // This parses but will be rejected during AST validation. + MaybeConstMaybe, } /// The AST represents all type param bounds as types.