Skip to content

Commit

Permalink
Rollup merge of rust-lang#67536 - Centril:move-is_range_literal, r=Ma…
Browse files Browse the repository at this point in the history
…rk-Simulacrum

Move `{hir::lowering -> hir}::is_range_literal`

The function is never used inside lowering, but only ever in external crates.
By moving it, we facilitate lowering as its own crate.

Best read commit-by-commit.

r? @Mark-Simulacrum
  • Loading branch information
Centril authored Dec 22, 2019
2 parents 6f92548 + db4cc3b commit e1e5348
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 73 deletions.
62 changes: 0 additions & 62 deletions src/librustc/hir/lowering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
65 changes: 64 additions & 1 deletion src/librustc/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@ use syntax::ast::{AttrVec, Attribute, Label, LitKind, StrStyle, FloatTy, IntTy,
pub use syntax::ast::{Mutability, Constness, Unsafety, Movability, CaptureBy};
pub use syntax::ast::{IsAuto, ImplPolarity, BorrowKind};
use syntax::attr::{InlineAttr, OptimizeAttr};
use syntax::symbol::{Symbol, kw};
use syntax::tokenstream::TokenStream;
use syntax::util::parser::ExprPrecedence;
use syntax_pos::symbol::{Symbol, kw, sym};
use syntax_pos::source_map::SourceMap;
use rustc_target::spec::abi::Abi;
use rustc_data_structures::sync::{par_for_each_in, Send, Sync};
use rustc_macros::HashStable;
Expand Down Expand Up @@ -1595,6 +1596,68 @@ impl fmt::Debug for Expr {
}
}

/// Checks if the specified expression is a built-in range literal.
/// (See: `LoweringContext::lower_expr()`).
///
/// FIXME(#60607): This function is a hack. If and when we have `QPath::Lang(...)`,
/// we can use that instead as simpler, more reliable mechanism, as opposed to using `SourceMap`.
pub fn is_range_literal(sm: &SourceMap, expr: &Expr) -> bool {
// 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(sm: &SourceMap, span: &Span) -> bool {
let end_point = sm.end_point(*span);

if let Ok(end_string) = sm.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(sm, &expr.span);
}
}

// `..` desugars to its struct path.
ExprKind::Path(QPath::Resolved(None, ref path)) => {
return is_range_path(&path) && is_lit(sm, &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(sm, &expr.span) && new_call;
}
}
}

_ => {}
}

false
}

#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
pub enum ExprKind {
/// A `box x` expression.
Expand Down
8 changes: 3 additions & 5 deletions src/librustc_lint/types.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
#![allow(non_snake_case)]

use rustc::hir::{ExprKind, Node};
use crate::hir::def_id::DefId;
use rustc::hir::lowering::is_range_literal;
use rustc::hir::{ExprKind, Node, is_range_literal, def_id::DefId};
use rustc::ty::subst::SubstsRef;
use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt};
use rustc::ty::layout::{self, IntegerExt, LayoutOf, VariantIdx, SizeSkeleton};
Expand Down Expand Up @@ -275,7 +273,7 @@ fn lint_int_literal<'a, 'tcx>(
let par_id = cx.tcx.hir().get_parent_node(e.hir_id);
if let Node::Expr(par_e) = cx.tcx.hir().get(par_id) {
if let hir::ExprKind::Struct(..) = par_e.kind {
if is_range_literal(cx.sess(), par_e)
if is_range_literal(cx.sess().source_map(), par_e)
&& lint_overflowing_range_endpoint(cx, lit, v, max, e, par_e, t.name_str())
{
// The overflowing literal lint was overridden.
Expand Down Expand Up @@ -328,7 +326,7 @@ fn lint_uint_literal<'a, 'tcx>(
}
}
hir::ExprKind::Struct(..)
if is_range_literal(cx.sess(), par_e) => {
if is_range_literal(cx.sess().source_map(), par_e) => {
let t = t.name_str();
if lint_overflowing_range_endpoint(cx, lit, lit_val, max, e, par_e, t) {
// The overflowing literal lint was overridden.
Expand Down
8 changes: 3 additions & 5 deletions src/librustc_typeck/check/demand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@ use crate::check::FnCtxt;
use rustc::infer::InferOk;
use rustc::traits::{self, ObligationCause, ObligationCauseCode};

use syntax::symbol::sym;
use syntax::util::parser::PREC_POSTFIX;
use syntax_pos::symbol::sym;
use syntax_pos::Span;
use rustc::hir;
use rustc::hir::Node;
use rustc::hir::{print, lowering::is_range_literal};
use rustc::hir::{self, Node, print, is_range_literal};
use rustc::ty::{self, Ty, AssocItem};
use rustc::ty::adjustment::AllowTwoPhase;
use errors::{Applicability, DiagnosticBuilder};
Expand Down Expand Up @@ -466,7 +464,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
hir::ExprKind::Cast(_, _) |
hir::ExprKind::Binary(_, _, _) => true,
// parenthesize borrows of range literals (Issue #54505)
_ if is_range_literal(self.tcx.sess, expr) => true,
_ if is_range_literal(self.tcx.sess.source_map(), expr) => true,
_ => false,
};
let sugg_expr = if needs_parens {
Expand Down

0 comments on commit e1e5348

Please sign in to comment.