diff --git a/src/libcore/alloc.rs b/src/libcore/alloc.rs index cb476acfb3a9e..4210737e379a5 100644 --- a/src/libcore/alloc.rs +++ b/src/libcore/alloc.rs @@ -17,7 +17,7 @@ use crate::num::NonZeroUsize; #[derive(Debug)] pub struct Excess(pub NonNull, pub usize); -fn size_align() -> (usize, usize) { +const fn size_align() -> (usize, usize) { (mem::size_of::(), mem::align_of::()) } @@ -118,14 +118,14 @@ impl Layout { /// Constructs a `Layout` suitable for holding a value of type `T`. #[stable(feature = "alloc_layout", since = "1.28.0")] + #[rustc_const_stable(feature = "alloc_layout_const_new", since = "1.42.0")] #[inline] - pub fn new() -> Self { + pub const fn new() -> Self { let (size, align) = size_align::(); // Note that the align is guaranteed by rustc to be a power of two and // the size+align combo is guaranteed to fit in our address space. As a // result use the unchecked constructor here to avoid inserting code // that panics if it isn't optimized well enough. - debug_assert!(Layout::from_size_align(size, align).is_ok()); unsafe { Layout::from_size_align_unchecked(size, align) } diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 26e287037f72c..cf2971cd8f1cf 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -1056,9 +1056,9 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { walk_list!(visitor, visit_label, opt_label); visitor.visit_block(block); } - ExprKind::Assign(ref left_hand_expression, ref right_hand_expression) => { - visitor.visit_expr(right_hand_expression); - visitor.visit_expr(left_hand_expression) + ExprKind::Assign(ref lhs, ref rhs, _) => { + visitor.visit_expr(rhs); + visitor.visit_expr(lhs) } ExprKind::AssignOp(_, ref left_expression, ref right_expression) => { visitor.visit_expr(right_expression); diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 83869951ea2a1..a702eb839845e 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -3437,65 +3437,3 @@ fn body_ids(bodies: &BTreeMap>) -> Vec 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 -} diff --git a/src/librustc/hir/lowering/expr.rs b/src/librustc/hir/lowering/expr.rs index 08b00ce69addb..cfcc1f3d3bcff 100644 --- a/src/librustc/hir/lowering/expr.rs +++ b/src/librustc/hir/lowering/expr.rs @@ -112,8 +112,8 @@ impl LoweringContext<'_, '_> { opt_label.is_some()), self.lower_label(opt_label)) } - ExprKind::Assign(ref el, ref er) => { - hir::ExprKind::Assign(P(self.lower_expr(el)), P(self.lower_expr(er))) + ExprKind::Assign(ref el, ref er, span) => { + hir::ExprKind::Assign(P(self.lower_expr(el)), P(self.lower_expr(er)), span) } ExprKind::AssignOp(op, ref el, ref er) => hir::ExprKind::AssignOp( self.lower_binop(op), @@ -1084,7 +1084,7 @@ impl LoweringContext<'_, '_> { let next_expr = P(self.expr_ident(pat.span, next_ident, next_pat_hid)); let assign = P(self.expr( pat.span, - hir::ExprKind::Assign(next_expr, val_expr), + hir::ExprKind::Assign(next_expr, val_expr, pat.span), ThinVec::new(), )); let some_pat = self.pat_some(pat.span, val_pat); diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index ff6801a85c7e1..147b8f37853d1 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -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; @@ -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. @@ -1659,7 +1722,8 @@ pub enum ExprKind { Block(P, Option