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 =
|
let bounds =
|
||||||
this.arena.alloc_from_iter(bounds.iter().filter_map(
|
this.arena.alloc_from_iter(bounds.iter().filter_map(
|
||||||
|bound| match *bound {
|
|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()))
|
Some(this.lower_poly_trait_ref(ty, itctx.reborrow()))
|
||||||
}
|
}
|
||||||
GenericBound::Trait(_, TraitBoundModifier::Maybe) => None,
|
GenericBound::Trait(_, TraitBoundModifier::Maybe) => None,
|
||||||
@ -2158,10 +2159,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
p: &PolyTraitRef,
|
p: &PolyTraitRef,
|
||||||
mut itctx: ImplTraitContext<'_, 'hir>,
|
mut itctx: ImplTraitContext<'_, 'hir>,
|
||||||
) -> hir::PolyTraitRef<'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(
|
let bound_generic_params = self.lower_generic_params(
|
||||||
&p.bound_generic_params,
|
&p.bound_generic_params,
|
||||||
&NodeMap::default(),
|
&NodeMap::default(),
|
||||||
@ -2301,6 +2298,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
match f {
|
match f {
|
||||||
TraitBoundModifier::None => hir::TraitBoundModifier::None,
|
TraitBoundModifier::None => hir::TraitBoundModifier::None,
|
||||||
TraitBoundModifier::Maybe => hir::TraitBoundModifier::Maybe,
|
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) {
|
fn visit_param_bound(&mut self, bound: &'a GenericBound) {
|
||||||
if let GenericBound::Trait(poly, maybe_bound) = bound {
|
if let GenericBound::Trait(_, TraitBoundModifier::MaybeConst) = bound {
|
||||||
match poly.trait_ref.constness {
|
if let Some(ctx) = self.bound_context {
|
||||||
Some(Constness::NotConst) => {
|
let msg = format!("`?const` is not permitted in {}", ctx.description());
|
||||||
if *maybe_bound == TraitBoundModifier::Maybe {
|
self.err_handler().span_err(bound.span(), &msg);
|
||||||
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 => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -364,6 +364,7 @@ impl GenericArgs<'_> {
|
|||||||
pub enum TraitBoundModifier {
|
pub enum TraitBoundModifier {
|
||||||
None,
|
None,
|
||||||
Maybe,
|
Maybe,
|
||||||
|
MaybeConst,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The AST represents all type param bounds as types.
|
/// The AST represents all type param bounds as types.
|
||||||
|
@ -27,11 +27,17 @@ struct BoundModifiers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl BoundModifiers {
|
impl BoundModifiers {
|
||||||
fn trait_bound_modifier(&self) -> TraitBoundModifier {
|
fn to_trait_bound_modifier(&self) -> Result<TraitBoundModifier, &'static str> {
|
||||||
match self.maybe {
|
let modifier = match (self.maybe, self.maybe_const) {
|
||||||
Some(_) => TraitBoundModifier::Maybe,
|
(None, None) => TraitBoundModifier::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> {
|
) -> PResult<'a, TyKind> {
|
||||||
assert_ne!(self.token, token::Question);
|
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)];
|
let mut bounds = vec![GenericBound::Trait(poly_trait_ref, TraitBoundModifier::None)];
|
||||||
if parse_plus {
|
if parse_plus {
|
||||||
self.eat_plus(); // `+`, or `+=` gets split and `+` is discarded
|
self.eat_plus(); // `+`, or `+=` gets split and `+` is discarded
|
||||||
@ -557,9 +563,18 @@ impl<'a> Parser<'a> {
|
|||||||
self.expect(&token::CloseDelim(token::Paren))?;
|
self.expect(&token::CloseDelim(token::Paren))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let constness = modifiers.maybe_const.map(|_| ast::Constness::NotConst);
|
let modifier = match modifiers.to_trait_bound_modifier() {
|
||||||
let poly_trait = PolyTraitRef::new(lifetime_defs, path, constness, lo.to(self.prev_span));
|
Ok(m) => m,
|
||||||
Ok(GenericBound::Trait(poly_trait, modifiers.trait_bound_modifier()))
|
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>`.
|
/// Optionally parses `for<$generic_params>`.
|
||||||
|
@ -361,6 +361,7 @@ impl clean::GenericBound {
|
|||||||
let modifier_str = match modifier {
|
let modifier_str = match modifier {
|
||||||
hir::TraitBoundModifier::None => "",
|
hir::TraitBoundModifier::None => "",
|
||||||
hir::TraitBoundModifier::Maybe => "?",
|
hir::TraitBoundModifier::Maybe => "?",
|
||||||
|
hir::TraitBoundModifier::MaybeConst => "?const",
|
||||||
};
|
};
|
||||||
if f.alternate() {
|
if f.alternate() {
|
||||||
write!(f, "{}{:#}", modifier_str, ty.print())
|
write!(f, "{}{:#}", modifier_str, ty.print())
|
||||||
|
@ -266,12 +266,19 @@ pub const CRATE_NODE_ID: NodeId = NodeId::from_u32_const(0);
|
|||||||
/// small, positive ids.
|
/// small, positive ids.
|
||||||
pub const DUMMY_NODE_ID: NodeId = NodeId::MAX;
|
pub const DUMMY_NODE_ID: NodeId = NodeId::MAX;
|
||||||
|
|
||||||
/// A modifier on a bound, currently this is only used for `?Sized`, where the
|
/// A modifier on a bound, e.g., `?Sized` or `?const Trait`.
|
||||||
/// modifier is `Maybe`. Negative bounds should also be handled here.
|
///
|
||||||
|
/// Negative bounds should also be handled here.
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug)]
|
||||||
pub enum TraitBoundModifier {
|
pub enum TraitBoundModifier {
|
||||||
|
/// No modifiers
|
||||||
None,
|
None,
|
||||||
|
|
||||||
|
/// `?Trait`
|
||||||
Maybe,
|
Maybe,
|
||||||
|
|
||||||
|
/// `?const Trait`
|
||||||
|
MaybeConst,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The AST represents all type param bounds as types.
|
/// The AST represents all type param bounds as types.
|
||||||
|
Loading…
Reference in New Issue
Block a user