Parse ?const ?Trait

This commit is contained in:
Dylan MacKenzie 2020-01-20 01:20:45 -08:00
parent 3b1a9d35c8
commit 0ac4ba0eed
4 changed files with 30 additions and 24 deletions

View File

@ -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
}
}
}

View File

@ -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)

View File

@ -27,17 +27,13 @@ struct BoundModifiers {
}
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 @@ 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))
}

View File

@ -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.