Move unsugar_range to utils::higher

This commit is contained in:
mcarton
2016-06-29 23:16:44 +02:00
parent ebf72cb67f
commit 92b04129fe
5 changed files with 99 additions and 97 deletions

View File

@@ -13,7 +13,7 @@ use std::borrow::Cow;
use std::env;
use std::mem;
use std::str::FromStr;
use syntax::ast::{self, LitKind, RangeLimits};
use syntax::ast::{self, LitKind};
use syntax::codemap::{ExpnInfo, Span, ExpnFormat};
use syntax::errors::DiagnosticBuilder;
use syntax::ptr::P;
@@ -683,93 +683,6 @@ pub fn camel_case_from(s: &str) -> usize {
last_i
}
/// Represent a range akin to `ast::ExprKind::Range`.
#[derive(Debug, Copy, Clone)]
pub struct UnsugaredRange<'a> {
pub start: Option<&'a Expr>,
pub end: Option<&'a Expr>,
pub limits: RangeLimits,
}
/// Unsugar a `hir` range.
pub fn unsugar_range(expr: &Expr) -> Option<UnsugaredRange> {
// To be removed when ranges get stable.
fn unwrap_unstable(expr: &Expr) -> &Expr {
if let ExprBlock(ref block) = expr.node {
if block.rules == BlockCheckMode::PushUnstableBlock || block.rules == BlockCheckMode::PopUnstableBlock {
if let Some(ref expr) = block.expr {
return expr;
}
}
}
expr
}
fn get_field<'a>(name: &str, fields: &'a [Field]) -> Option<&'a Expr> {
let expr = &fields.iter()
.find(|field| field.name.node.as_str() == name)
.unwrap_or_else(|| panic!("missing {} field for range", name))
.expr;
Some(unwrap_unstable(expr))
}
// The range syntax is expanded to literal paths starting with `core` or `std` depending on
// `#[no_std]`. Testing both instead of resolving the paths.
match unwrap_unstable(expr).node {
ExprPath(None, ref path) => {
if match_path(path, &paths::RANGE_FULL_STD) || match_path(path, &paths::RANGE_FULL) {
Some(UnsugaredRange {
start: None,
end: None,
limits: RangeLimits::HalfOpen,
})
} else {
None
}
}
ExprStruct(ref path, ref fields, None) => {
if match_path(path, &paths::RANGE_FROM_STD) || match_path(path, &paths::RANGE_FROM) {
Some(UnsugaredRange {
start: get_field("start", fields),
end: None,
limits: RangeLimits::HalfOpen,
})
} else if match_path(path, &paths::RANGE_INCLUSIVE_NON_EMPTY_STD) ||
match_path(path, &paths::RANGE_INCLUSIVE_NON_EMPTY) {
Some(UnsugaredRange {
start: get_field("start", fields),
end: get_field("end", fields),
limits: RangeLimits::Closed,
})
} else if match_path(path, &paths::RANGE_STD) || match_path(path, &paths::RANGE) {
Some(UnsugaredRange {
start: get_field("start", fields),
end: get_field("end", fields),
limits: RangeLimits::HalfOpen,
})
} else if match_path(path, &paths::RANGE_TO_INCLUSIVE_STD) || match_path(path, &paths::RANGE_TO_INCLUSIVE) {
Some(UnsugaredRange {
start: None,
end: get_field("end", fields),
limits: RangeLimits::Closed,
})
} else if match_path(path, &paths::RANGE_TO_STD) || match_path(path, &paths::RANGE_TO) {
Some(UnsugaredRange {
start: None,
end: get_field("end", fields),
limits: RangeLimits::HalfOpen,
})
} else {
None
}
}
_ => None,
}
}
/// Convenience function to get the return type of a function or `None` if the function diverges.
pub fn return_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, fn_item: NodeId) -> Option<ty::Ty<'tcx>> {
let parameter_env = ty::ParameterEnvironment::for_item(cx.tcx, fn_item);