mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
Move {hir::lowering -> hir}::is_range_literal
.
The function is never used inside lowering, but only ever in external crates. By moving it, we faciliate lowering as its own crate.
This commit is contained in:
parent
a916ac22b9
commit
45acee3090
@ -3437,65 +3437,3 @@ fn body_ids(bodies: &BTreeMap<hir::BodyId, hir::Body<'hir>>) -> Vec<hir::BodyId>
|
||||
body_ids.sort_by_key(|b| bodies[b].value.span);
|
||||
body_ids
|
||||
}
|
||||
|
||||
/// Checks if the specified expression is a built-in range literal.
|
||||
/// (See: `LoweringContext::lower_expr()`).
|
||||
pub fn is_range_literal(sess: &Session, expr: &hir::Expr) -> bool {
|
||||
use hir::{Path, QPath, ExprKind, TyKind};
|
||||
|
||||
// Returns whether the given path represents a (desugared) range,
|
||||
// either in std or core, i.e. has either a `::std::ops::Range` or
|
||||
// `::core::ops::Range` prefix.
|
||||
fn is_range_path(path: &Path) -> bool {
|
||||
let segs: Vec<_> = path.segments.iter().map(|seg| seg.ident.to_string()).collect();
|
||||
let segs: Vec<_> = segs.iter().map(|seg| &**seg).collect();
|
||||
|
||||
// "{{root}}" is the equivalent of `::` prefix in `Path`.
|
||||
if let ["{{root}}", std_core, "ops", range] = segs.as_slice() {
|
||||
(*std_core == "std" || *std_core == "core") && range.starts_with("Range")
|
||||
} else {
|
||||
false
|
||||
}
|
||||
};
|
||||
|
||||
// Check whether a span corresponding to a range expression is a
|
||||
// range literal, rather than an explicit struct or `new()` call.
|
||||
fn is_lit(sess: &Session, span: &Span) -> bool {
|
||||
let source_map = sess.source_map();
|
||||
let end_point = source_map.end_point(*span);
|
||||
|
||||
if let Ok(end_string) = source_map.span_to_snippet(end_point) {
|
||||
!(end_string.ends_with("}") || end_string.ends_with(")"))
|
||||
} else {
|
||||
false
|
||||
}
|
||||
};
|
||||
|
||||
match expr.kind {
|
||||
// All built-in range literals but `..=` and `..` desugar to `Struct`s.
|
||||
ExprKind::Struct(ref qpath, _, _) => {
|
||||
if let QPath::Resolved(None, ref path) = **qpath {
|
||||
return is_range_path(&path) && is_lit(sess, &expr.span);
|
||||
}
|
||||
}
|
||||
|
||||
// `..` desugars to its struct path.
|
||||
ExprKind::Path(QPath::Resolved(None, ref path)) => {
|
||||
return is_range_path(&path) && is_lit(sess, &expr.span);
|
||||
}
|
||||
|
||||
// `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
|
||||
ExprKind::Call(ref func, _) => {
|
||||
if let ExprKind::Path(QPath::TypeRelative(ref ty, ref segment)) = func.kind {
|
||||
if let TyKind::Path(QPath::Resolved(None, ref path)) = ty.kind {
|
||||
let new_call = segment.ident.name == sym::new;
|
||||
return is_range_path(&path) && is_lit(sess, &expr.span) && new_call;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_ => {}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
@ -1564,6 +1564,68 @@ impl fmt::Debug for Expr {
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks if the specified expression is a built-in range literal.
|
||||
/// (See: `LoweringContext::lower_expr()`).
|
||||
pub fn is_range_literal(sess: &Session, expr: &hir::Expr) -> bool {
|
||||
use hir::{Path, QPath, ExprKind, TyKind};
|
||||
|
||||
// Returns whether the given path represents a (desugared) range,
|
||||
// either in std or core, i.e. has either a `::std::ops::Range` or
|
||||
// `::core::ops::Range` prefix.
|
||||
fn is_range_path(path: &Path) -> bool {
|
||||
let segs: Vec<_> = path.segments.iter().map(|seg| seg.ident.to_string()).collect();
|
||||
let segs: Vec<_> = segs.iter().map(|seg| &**seg).collect();
|
||||
|
||||
// "{{root}}" is the equivalent of `::` prefix in `Path`.
|
||||
if let ["{{root}}", std_core, "ops", range] = segs.as_slice() {
|
||||
(*std_core == "std" || *std_core == "core") && range.starts_with("Range")
|
||||
} else {
|
||||
false
|
||||
}
|
||||
};
|
||||
|
||||
// Check whether a span corresponding to a range expression is a
|
||||
// range literal, rather than an explicit struct or `new()` call.
|
||||
fn is_lit(sess: &Session, span: &Span) -> bool {
|
||||
let source_map = sess.source_map();
|
||||
let end_point = source_map.end_point(*span);
|
||||
|
||||
if let Ok(end_string) = source_map.span_to_snippet(end_point) {
|
||||
!(end_string.ends_with("}") || end_string.ends_with(")"))
|
||||
} else {
|
||||
false
|
||||
}
|
||||
};
|
||||
|
||||
match expr.kind {
|
||||
// All built-in range literals but `..=` and `..` desugar to `Struct`s.
|
||||
ExprKind::Struct(ref qpath, _, _) => {
|
||||
if let QPath::Resolved(None, ref path) = **qpath {
|
||||
return is_range_path(&path) && is_lit(sess, &expr.span);
|
||||
}
|
||||
}
|
||||
|
||||
// `..` desugars to its struct path.
|
||||
ExprKind::Path(QPath::Resolved(None, ref path)) => {
|
||||
return is_range_path(&path) && is_lit(sess, &expr.span);
|
||||
}
|
||||
|
||||
// `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
|
||||
ExprKind::Call(ref func, _) => {
|
||||
if let ExprKind::Path(QPath::TypeRelative(ref ty, ref segment)) = func.kind {
|
||||
if let TyKind::Path(QPath::Resolved(None, ref path)) = ty.kind {
|
||||
let new_call = segment.ident.name == sym::new;
|
||||
return is_range_path(&path) && is_lit(sess, &expr.span) && new_call;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_ => {}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
|
||||
pub enum ExprKind {
|
||||
/// A `box x` expression.
|
||||
|
Loading…
Reference in New Issue
Block a user