Skip to content

Commit

Permalink
keep the AST node-id when lowering ExprKind::Range
Browse files Browse the repository at this point in the history
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 rust-lang#40749.
  • Loading branch information
arielb1 committed Mar 23, 2017
1 parent 90346ea commit 8ffe406
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 59 deletions.
95 changes: 36 additions & 59 deletions src/librustc/hir/lowering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand Down Expand Up @@ -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(),
Expand Down
16 changes: 16 additions & 0 deletions src/test/compile-fail/issue-40749.rs
Original file line number Diff line number Diff line change
@@ -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}>`
}

0 comments on commit 8ffe406

Please sign in to comment.