1
Fork 0

Replace AssocOp::DotDot{,Eq} with AssocOp::Range.

It makes `AssocOp` more similar to `ExprKind` and makes things a little
simpler. And the semantic names make more sense here than the syntactic
names.
This commit is contained in:
Nicholas Nethercote 2024-12-19 21:42:46 +11:00
parent ceafbad81f
commit fc8e87b274
4 changed files with 32 additions and 43 deletions

View file

@ -1453,6 +1453,15 @@ pub enum RangeLimits {
Closed, Closed,
} }
impl RangeLimits {
pub fn as_str(&self) -> &'static str {
match self {
RangeLimits::HalfOpen => "..",
RangeLimits::Closed => "..=",
}
}
}
/// A method call (e.g. `x.foo::<Bar, Baz>(a, b, c)`). /// A method call (e.g. `x.foo::<Bar, Baz>(a, b, c)`).
#[derive(Clone, Encodable, Decodable, Debug)] #[derive(Clone, Encodable, Decodable, Debug)]
pub struct MethodCall { pub struct MethodCall {

View file

@ -1,6 +1,6 @@
use rustc_span::kw; use rustc_span::kw;
use crate::ast::{self, BinOpKind}; use crate::ast::{self, BinOpKind, RangeLimits};
use crate::token::{self, BinOpToken, Token}; use crate::token::{self, BinOpToken, Token};
/// Associative operator. /// Associative operator.
@ -14,10 +14,8 @@ pub enum AssocOp {
Assign, Assign,
/// `as` /// `as`
As, As,
/// `..` range /// `..` or `..=` range
DotDot, Range(RangeLimits),
/// `..=` range
DotDotEq,
} }
#[derive(PartialEq, Debug)] #[derive(PartialEq, Debug)]
@ -64,10 +62,9 @@ impl AssocOp {
token::Ne => Some(Binary(BinOpKind::Ne)), token::Ne => Some(Binary(BinOpKind::Ne)),
token::AndAnd => Some(Binary(BinOpKind::And)), token::AndAnd => Some(Binary(BinOpKind::And)),
token::OrOr => Some(Binary(BinOpKind::Or)), token::OrOr => Some(Binary(BinOpKind::Or)),
token::DotDot => Some(DotDot), token::DotDot => Some(Range(RangeLimits::HalfOpen)),
token::DotDotEq => Some(DotDotEq),
// DotDotDot is no longer supported, but we need some way to display the error // DotDotDot is no longer supported, but we need some way to display the error
token::DotDotDot => Some(DotDotEq), token::DotDotEq | token::DotDotDot => Some(Range(RangeLimits::Closed)),
// `<-` should probably be `< -` // `<-` should probably be `< -`
token::LArrow => Some(Binary(BinOpKind::Lt)), token::LArrow => Some(Binary(BinOpKind::Lt)),
_ if t.is_keyword(kw::As) => Some(As), _ if t.is_keyword(kw::As) => Some(As),
@ -81,7 +78,7 @@ impl AssocOp {
match *self { match *self {
As => ExprPrecedence::Cast, As => ExprPrecedence::Cast,
Binary(bin_op) => bin_op.precedence(), Binary(bin_op) => bin_op.precedence(),
DotDot | DotDotEq => ExprPrecedence::Range, Range(_) => ExprPrecedence::Range,
Assign | AssignOp(_) => ExprPrecedence::Assign, Assign | AssignOp(_) => ExprPrecedence::Assign,
} }
} }
@ -94,7 +91,7 @@ impl AssocOp {
Assign | AssignOp(_) => Fixity::Right, Assign | AssignOp(_) => Fixity::Right,
Binary(binop) => binop.fixity(), Binary(binop) => binop.fixity(),
As => Fixity::Left, As => Fixity::Left,
DotDot | DotDotEq => Fixity::None, Range(_) => Fixity::None,
} }
} }
@ -102,7 +99,7 @@ impl AssocOp {
use AssocOp::*; use AssocOp::*;
match *self { match *self {
Binary(binop) => binop.is_comparison(), Binary(binop) => binop.is_comparison(),
Assign | AssignOp(_) | As | DotDot | DotDotEq => false, Assign | AssignOp(_) | As | Range(_) => false,
} }
} }
@ -110,7 +107,7 @@ impl AssocOp {
use AssocOp::*; use AssocOp::*;
match *self { match *self {
Assign | AssignOp(_) => true, Assign | AssignOp(_) => true,
As | Binary(_) | DotDot | DotDotEq => false, As | Binary(_) | Range(_) => false,
} }
} }

View file

@ -171,7 +171,7 @@ impl<'a> Parser<'a> {
break; break;
} }
// Check for deprecated `...` syntax // Check for deprecated `...` syntax
if self.token == token::DotDotDot && op.node == AssocOp::DotDotEq { if self.token == token::DotDotDot && op.node == AssocOp::Range(RangeLimits::Closed) {
self.err_dotdotdot_syntax(self.token.span); self.err_dotdotdot_syntax(self.token.span);
} }
@ -267,10 +267,10 @@ impl<'a> Parser<'a> {
if op == AssocOp::As { if op == AssocOp::As {
lhs = self.parse_assoc_op_cast(lhs, lhs_span, ExprKind::Cast)?; lhs = self.parse_assoc_op_cast(lhs, lhs_span, ExprKind::Cast)?;
continue; continue;
} else if op == AssocOp::DotDot || op == AssocOp::DotDotEq { } else if let AssocOp::Range(limits) = op {
// If we didn't have to handle `x..`/`x..=`, it would be pretty easy to // If we didn't have to handle `x..`/`x..=`, it would be pretty easy to
// generalise it to the Fixity::None code. // generalise it to the Fixity::None code.
lhs = self.parse_expr_range(prec, lhs, op, cur_op_span)?; lhs = self.parse_expr_range(prec, lhs, limits, cur_op_span)?;
break; break;
} }
@ -294,7 +294,7 @@ impl<'a> Parser<'a> {
let aopexpr = self.mk_assign_op(source_map::respan(cur_op_span, aop), lhs, rhs); let aopexpr = self.mk_assign_op(source_map::respan(cur_op_span, aop), lhs, rhs);
self.mk_expr(span, aopexpr) self.mk_expr(span, aopexpr)
} }
AssocOp::As | AssocOp::DotDot | AssocOp::DotDotEq => { AssocOp::As | AssocOp::Range(_) => {
self.dcx().span_bug(span, "AssocOp should have been handled by special case") self.dcx().span_bug(span, "AssocOp should have been handled by special case")
} }
}; };
@ -372,8 +372,7 @@ impl<'a> Parser<'a> {
AssocOp::Assign AssocOp::Assign
| AssocOp::AssignOp(_) | AssocOp::AssignOp(_)
| AssocOp::Binary(BinOpKind::BitOr) | AssocOp::Binary(BinOpKind::BitOr)
| AssocOp::DotDot | AssocOp::Range(_),
| AssocOp::DotDotEq,
), ),
_, _,
) if self.restrictions.contains(Restrictions::IS_PAT) => { ) if self.restrictions.contains(Restrictions::IS_PAT) => {
@ -414,7 +413,7 @@ impl<'a> Parser<'a> {
&mut self, &mut self,
prec: ExprPrecedence, prec: ExprPrecedence,
lhs: P<Expr>, lhs: P<Expr>,
op: AssocOp, limits: RangeLimits,
cur_op_span: Span, cur_op_span: Span,
) -> PResult<'a, P<Expr>> { ) -> PResult<'a, P<Expr>> {
let rhs = if self.is_at_start_of_range_notation_rhs() { let rhs = if self.is_at_start_of_range_notation_rhs() {
@ -430,8 +429,6 @@ impl<'a> Parser<'a> {
}; };
let rhs_span = rhs.as_ref().map_or(cur_op_span, |x| x.span); let rhs_span = rhs.as_ref().map_or(cur_op_span, |x| x.span);
let span = self.mk_expr_sp(&lhs, lhs.span, rhs_span); let span = self.mk_expr_sp(&lhs, lhs.span, rhs_span);
let limits =
if op == AssocOp::DotDot { RangeLimits::HalfOpen } else { RangeLimits::Closed };
let range = self.mk_range(Some(lhs), rhs, limits); let range = self.mk_range(Some(lhs), rhs, limits);
Ok(self.mk_expr(span, range)) Ok(self.mk_expr(span, range))
} }

View file

@ -113,10 +113,7 @@ impl<'a> Sugg<'a> {
/// function variants of `Sugg`, since these use different snippet functions. /// function variants of `Sugg`, since these use different snippet functions.
fn hir_from_snippet(expr: &hir::Expr<'_>, mut get_snippet: impl FnMut(Span) -> Cow<'a, str>) -> Self { fn hir_from_snippet(expr: &hir::Expr<'_>, mut get_snippet: impl FnMut(Span) -> Cow<'a, str>) -> Self {
if let Some(range) = higher::Range::hir(expr) { if let Some(range) = higher::Range::hir(expr) {
let op = match range.limits { let op = AssocOp::Range(range.limits);
ast::RangeLimits::HalfOpen => AssocOp::DotDot,
ast::RangeLimits::Closed => AssocOp::DotDotEq,
};
let start = range.start.map_or("".into(), |expr| get_snippet(expr.span)); let start = range.start.map_or("".into(), |expr| get_snippet(expr.span));
let end = range.end.map_or("".into(), |expr| get_snippet(expr.span)); let end = range.end.map_or("".into(), |expr| get_snippet(expr.span));
@ -178,8 +175,6 @@ impl<'a> Sugg<'a> {
ctxt: SyntaxContext, ctxt: SyntaxContext,
app: &mut Applicability, app: &mut Applicability,
) -> Self { ) -> Self {
use rustc_ast::ast::RangeLimits;
let mut snippet = |span: Span| snippet_with_context(cx, span, ctxt, default, app).0; let mut snippet = |span: Span| snippet_with_context(cx, span, ctxt, default, app).0;
match expr.kind { match expr.kind {
@ -228,13 +223,8 @@ impl<'a> Sugg<'a> {
| ast::ExprKind::Err(_) | ast::ExprKind::Err(_)
| ast::ExprKind::Dummy | ast::ExprKind::Dummy
| ast::ExprKind::UnsafeBinderCast(..) => Sugg::NonParen(snippet(expr.span)), | ast::ExprKind::UnsafeBinderCast(..) => Sugg::NonParen(snippet(expr.span)),
ast::ExprKind::Range(ref lhs, ref rhs, RangeLimits::HalfOpen) => Sugg::BinOp( ast::ExprKind::Range(ref lhs, ref rhs, limits) => Sugg::BinOp(
AssocOp::DotDot, AssocOp::Range(limits),
lhs.as_ref().map_or("".into(), |lhs| snippet(lhs.span)),
rhs.as_ref().map_or("".into(), |rhs| snippet(rhs.span)),
),
ast::ExprKind::Range(ref lhs, ref rhs, RangeLimits::Closed) => Sugg::BinOp(
AssocOp::DotDotEq,
lhs.as_ref().map_or("".into(), |lhs| snippet(lhs.span)), lhs.as_ref().map_or("".into(), |lhs| snippet(lhs.span)),
rhs.as_ref().map_or("".into(), |rhs| snippet(rhs.span)), rhs.as_ref().map_or("".into(), |rhs| snippet(rhs.span)),
), ),
@ -326,11 +316,8 @@ impl<'a> Sugg<'a> {
/// Convenience method to create the `<lhs>..<rhs>` or `<lhs>...<rhs>` /// Convenience method to create the `<lhs>..<rhs>` or `<lhs>...<rhs>`
/// suggestion. /// suggestion.
pub fn range(self, end: &Self, limit: ast::RangeLimits) -> Sugg<'static> { pub fn range(self, end: &Self, limits: ast::RangeLimits) -> Sugg<'static> {
match limit { make_assoc(AssocOp::Range(limits), &self, end)
ast::RangeLimits::HalfOpen => make_assoc(AssocOp::DotDot, &self, end),
ast::RangeLimits::Closed => make_assoc(AssocOp::DotDotEq, &self, end),
}
} }
/// Adds parentheses to any expression that might need them. Suitable to the /// Adds parentheses to any expression that might need them. Suitable to the
@ -370,8 +357,7 @@ fn binop_to_string(op: AssocOp, lhs: &str, rhs: &str) -> String {
AssocOp::Assign => format!("{lhs} = {rhs}"), AssocOp::Assign => format!("{lhs} = {rhs}"),
AssocOp::AssignOp(op) => format!("{lhs} {}= {rhs}", op.as_str()), AssocOp::AssignOp(op) => format!("{lhs} {}= {rhs}", op.as_str()),
AssocOp::As => format!("{lhs} as {rhs}"), AssocOp::As => format!("{lhs} as {rhs}"),
AssocOp::DotDot => format!("{lhs}..{rhs}"), AssocOp::Range(limits) => format!("{lhs}{}{rhs}", limits.as_str()),
AssocOp::DotDotEq => format!("{lhs}..={rhs}"),
} }
} }
@ -590,7 +576,7 @@ enum Associativity {
/// associative. /// associative.
#[must_use] #[must_use]
fn associativity(op: AssocOp) -> Associativity { fn associativity(op: AssocOp) -> Associativity {
use rustc_ast::util::parser::AssocOp::{As, Assign, AssignOp, Binary, DotDot, DotDotEq}; use rustc_ast::util::parser::AssocOp::{As, Assign, AssignOp, Binary, Range};
use ast::BinOpKind::{ use ast::BinOpKind::{
Add, BitAnd, BitOr, BitXor, Div, Eq, Gt, Ge, And, Or, Lt, Le, Rem, Mul, Ne, Shl, Shr, Sub, Add, BitAnd, BitOr, BitXor, Div, Eq, Gt, Ge, And, Or, Lt, Le, Rem, Mul, Ne, Shl, Shr, Sub,
}; };
@ -599,7 +585,7 @@ fn associativity(op: AssocOp) -> Associativity {
Assign | AssignOp(_) => Associativity::Right, Assign | AssignOp(_) => Associativity::Right,
Binary(Add | BitAnd | BitOr | BitXor | And | Or | Mul) | As => Associativity::Both, Binary(Add | BitAnd | BitOr | BitXor | And | Or | Mul) | As => Associativity::Both,
Binary(Div | Eq | Gt | Ge | Lt | Le | Rem | Ne | Shl | Shr | Sub) => Associativity::Left, Binary(Div | Eq | Gt | Ge | Lt | Le | Rem | Ne | Shl | Shr | Sub) => Associativity::Left,
DotDot | DotDotEq => Associativity::None, Range(_) => Associativity::None,
} }
} }