Add MaybeConst
variant to {ast,hir}::TraitBoundModifier
This commit is contained in:
parent
958b0bc8d2
commit
eb60346cc9
@ -1250,7 +1250,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
let bounds =
|
||||
this.arena.alloc_from_iter(bounds.iter().filter_map(
|
||||
|bound| match *bound {
|
||||
GenericBound::Trait(ref ty, TraitBoundModifier::None) => {
|
||||
GenericBound::Trait(ref ty, TraitBoundModifier::None)
|
||||
| GenericBound::Trait(ref ty, TraitBoundModifier::MaybeConst) => {
|
||||
Some(this.lower_poly_trait_ref(ty, itctx.reborrow()))
|
||||
}
|
||||
GenericBound::Trait(_, TraitBoundModifier::Maybe) => None,
|
||||
@ -2158,10 +2159,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
p: &PolyTraitRef,
|
||||
mut itctx: ImplTraitContext<'_, 'hir>,
|
||||
) -> hir::PolyTraitRef<'hir> {
|
||||
if p.trait_ref.constness.is_some() {
|
||||
self.diagnostic().span_err(p.span, "`?const` on trait bounds is not yet implemented");
|
||||
}
|
||||
|
||||
let bound_generic_params = self.lower_generic_params(
|
||||
&p.bound_generic_params,
|
||||
&NodeMap::default(),
|
||||
@ -2301,6 +2298,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
match f {
|
||||
TraitBoundModifier::None => hir::TraitBoundModifier::None,
|
||||
TraitBoundModifier::Maybe => hir::TraitBoundModifier::Maybe,
|
||||
TraitBoundModifier::MaybeConst => hir::TraitBoundModifier::MaybeConst,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -917,22 +917,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||
}
|
||||
|
||||
fn visit_param_bound(&mut self, bound: &'a GenericBound) {
|
||||
if let GenericBound::Trait(poly, maybe_bound) = bound {
|
||||
match poly.trait_ref.constness {
|
||||
Some(Constness::NotConst) => {
|
||||
if *maybe_bound == TraitBoundModifier::Maybe {
|
||||
self.err_handler()
|
||||
.span_err(bound.span(), "`?const` and `?` are mutually exclusive");
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
Some(Constness::Const) => panic!("Parser should reject bare `const` on bounds"),
|
||||
None => {}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -364,6 +364,7 @@ impl GenericArgs<'_> {
|
||||
pub enum TraitBoundModifier {
|
||||
None,
|
||||
Maybe,
|
||||
MaybeConst,
|
||||
}
|
||||
|
||||
/// The AST represents all type param bounds as types.
|
||||
|
@ -27,11 +27,17 @@ 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) -> Result<TraitBoundModifier, &'static str> {
|
||||
let modifier = 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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -215,7 +221,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
|
||||
@ -557,9 +563,18 @@ 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 = 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 poly_trait = PolyTraitRef::new(lifetime_defs, path, lo.to(self.prev_span));
|
||||
Ok(GenericBound::Trait(poly_trait, modifier))
|
||||
}
|
||||
|
||||
/// Optionally parses `for<$generic_params>`.
|
||||
|
@ -361,6 +361,7 @@ impl clean::GenericBound {
|
||||
let modifier_str = match modifier {
|
||||
hir::TraitBoundModifier::None => "",
|
||||
hir::TraitBoundModifier::Maybe => "?",
|
||||
hir::TraitBoundModifier::MaybeConst => "?const",
|
||||
};
|
||||
if f.alternate() {
|
||||
write!(f, "{}{:#}", modifier_str, ty.print())
|
||||
|
@ -266,12 +266,19 @@ pub const CRATE_NODE_ID: NodeId = NodeId::from_u32_const(0);
|
||||
/// small, positive ids.
|
||||
pub const DUMMY_NODE_ID: NodeId = NodeId::MAX;
|
||||
|
||||
/// A modifier on a bound, currently this is only used for `?Sized`, where the
|
||||
/// modifier is `Maybe`. Negative bounds should also be handled here.
|
||||
/// A modifier on a bound, e.g., `?Sized` or `?const Trait`.
|
||||
///
|
||||
/// Negative bounds should also be handled here.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug)]
|
||||
pub enum TraitBoundModifier {
|
||||
/// No modifiers
|
||||
None,
|
||||
|
||||
/// `?Trait`
|
||||
Maybe,
|
||||
|
||||
/// `?const Trait`
|
||||
MaybeConst,
|
||||
}
|
||||
|
||||
/// The AST represents all type param bounds as types.
|
||||
|
Loading…
Reference in New Issue
Block a user