about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-03-27 05:28:32 +0000
committerbors <bors@rust-lang.org>2017-03-27 05:28:32 +0000
commitccce2c6eb914a66571f60fa0afe8a46faa9fb3bd (patch)
tree7c112a7cfdff2de88444779f8fbc04a6cfb6ee13 /src
parent7846dbe0c8de17f59cdfc3d2b914d58faad7eade (diff)
parent8ffe4068a6d8ff79cfccc0244a96e728387bbeb6 (diff)
downloadrust-ccce2c6eb914a66571f60fa0afe8a46faa9fb3bd.tar.gz
rust-ccce2c6eb914a66571f60fa0afe8a46faa9fb3bd.zip
Auto merge of #40764 - arielb1:range-nodes, r=eddyb
keep the AST node-id when lowering ExprKind::Range

When the Range expression is the root of a constant, its node-id is
used for the def-id of the body, so it has to be preserved in the AST ->
HIR lowering.

Fixes #40749.

r? @eddyb
beta-nominating because regression
Diffstat (limited to 'src')
-rw-r--r--src/librustc/hir/lowering.rs95
-rw-r--r--src/test/compile-fail/issue-40749.rs16
2 files changed, 52 insertions, 59 deletions
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 2ac1a036f99..6ca0c971ea4 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -1900,57 +1900,45 @@ impl<'a> LoweringContext<'a> {
                 hir::ExprIndex(P(self.lower_expr(el)), P(self.lower_expr(er)))
             }
             ExprKind::Range(ref e1, ref e2, lims) => {
-                fn make_struct(this: &mut LoweringContext,
-                               ast_expr: &Expr,
-                               path: &[&str],
-                               fields: &[(&str, &P<Expr>)]) -> hir::Expr {
-                    let struct_path = &iter::once(&"ops").chain(path).map(|s| *s)
-                                                         .collect::<Vec<_>>();
-                    let unstable_span = this.allow_internal_unstable("...", ast_expr.span);
-
-                    if fields.len() == 0 {
-                        this.expr_std_path(unstable_span, struct_path,
-                                           ast_expr.attrs.clone())
-                    } else {
-                        let fields = fields.into_iter().map(|&(s, e)| {
-                            let expr = P(this.lower_expr(&e));
-                            let unstable_span = this.allow_internal_unstable("...", e.span);
-                            this.field(Symbol::intern(s), expr, unstable_span)
-                        }).collect();
-                        let attrs = ast_expr.attrs.clone();
-
-                        this.expr_std_struct(unstable_span, struct_path, fields, None, attrs)
-                    }
-                }
-
                 use syntax::ast::RangeLimits::*;
 
-                return match (e1, e2, lims) {
-                    (&None,         &None,         HalfOpen) =>
-                        make_struct(self, e, &["RangeFull"], &[]),
-
-                    (&Some(ref e1), &None,         HalfOpen) =>
-                        make_struct(self, e, &["RangeFrom"],
-                                             &[("start", e1)]),
-
-                    (&None,         &Some(ref e2), HalfOpen) =>
-                        make_struct(self, e, &["RangeTo"],
-                                             &[("end", e2)]),
-
-                    (&Some(ref e1), &Some(ref e2), HalfOpen) =>
-                        make_struct(self, e, &["Range"],
-                                             &[("start", e1), ("end", e2)]),
-
-                    (&None,         &Some(ref e2), Closed)   =>
-                        make_struct(self, e, &["RangeToInclusive"],
-                                             &[("end", e2)]),
-
-                    (&Some(ref e1), &Some(ref e2), Closed)   =>
-                        make_struct(self, e, &["RangeInclusive", "NonEmpty"],
-                                             &[("start", e1), ("end", e2)]),
+                let (path, variant) = match (e1, e2, lims) {
+                    (&None, &None, HalfOpen) => ("RangeFull", None),
+                    (&Some(..), &None, HalfOpen) => ("RangeFrom", None),
+                    (&None, &Some(..), HalfOpen) => ("RangeTo", None),
+                    (&Some(..), &Some(..), HalfOpen) => ("Range", None),
+                    (&None, &Some(..), Closed) => ("RangeToInclusive", None),
+                    (&Some(..), &Some(..), Closed) => ("RangeInclusive", Some("NonEmpty")),
+                    (_, &None, Closed) =>
+                        panic!(self.diagnostic().span_fatal(
+                            e.span, "inclusive range with no end")),
+                };
 
-                    _ => panic!(self.diagnostic()
-                                    .span_fatal(e.span, "inclusive range with no end")),
+                let fields =
+                    e1.iter().map(|e| ("start", e)).chain(e2.iter().map(|e| ("end", e)))
+                    .map(|(s, e)| {
+                        let expr = P(self.lower_expr(&e));
+                        let unstable_span = self.allow_internal_unstable("...", e.span);
+                        self.field(Symbol::intern(s), expr, unstable_span)
+                    }).collect::<P<[hir::Field]>>();
+
+                let is_unit = fields.is_empty();
+                let unstable_span = self.allow_internal_unstable("...", e.span);
+                let struct_path =
+                    iter::once("ops").chain(iter::once(path)).chain(variant)
+                    .collect::<Vec<_>>();
+                let struct_path = self.std_path(unstable_span, &struct_path, is_unit);
+                let struct_path = hir::QPath::Resolved(None, P(struct_path));
+
+                return hir::Expr {
+                    id: self.lower_node_id(e.id),
+                    node: if is_unit {
+                        hir::ExprPath(struct_path)
+                    } else {
+                        hir::ExprStruct(struct_path, fields, None)
+                    },
+                    span: unstable_span,
+                    attrs: e.attrs.clone(),
                 };
             }
             ExprKind::Path(ref qself, ref path) => {
@@ -2613,17 +2601,6 @@ impl<'a> LoweringContext<'a> {
         P(self.expr(sp, hir::ExprTup(exprs), ThinVec::new()))
     }
 
-    fn expr_std_struct(&mut self,
-                       span: Span,
-                       components: &[&str],
-                       fields: hir::HirVec<hir::Field>,
-                       e: Option<P<hir::Expr>>,
-                       attrs: ThinVec<Attribute>) -> hir::Expr {
-        let path = self.std_path(span, components, false);
-        let qpath = hir::QPath::Resolved(None, P(path));
-        self.expr(span, hir::ExprStruct(qpath, fields, e), attrs)
-    }
-
     fn expr(&mut self, span: Span, node: hir::Expr_, attrs: ThinVec<Attribute>) -> hir::Expr {
         hir::Expr {
             id: self.next_id(),
diff --git a/src/test/compile-fail/issue-40749.rs b/src/test/compile-fail/issue-40749.rs
new file mode 100644
index 00000000000..261ed49d10c
--- /dev/null
+++ b/src/test/compile-fail/issue-40749.rs
@@ -0,0 +1,16 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    [0; ..10];
+    //~^ ERROR mismatched types
+    //~| expected type `usize`
+    //~| found type `std::ops::RangeTo<{integer}>`
+}