diff options
| author | Nick Cameron <ncameron@mozilla.com> | 2014-12-18 17:55:04 +1300 |
|---|---|---|
| committer | Nick Cameron <ncameron@mozilla.com> | 2014-12-30 13:06:24 +1300 |
| commit | ed8f5039115308ca9d5591126e4d8a77864d4730 (patch) | |
| tree | fef6c67dd64068ff73c4509d078d25ba88fa4f21 /src | |
| parent | 71123902e17ad339649f33423995eac78da40e3c (diff) | |
| download | rust-ed8f5039115308ca9d5591126e4d8a77864d4730.tar.gz rust-ed8f5039115308ca9d5591126e4d8a77864d4730.zip | |
Add hypothetical support for ranges with only an upper bound
Note that this doesn't add the surface syntax.
Diffstat (limited to 'src')
| -rw-r--r-- | src/libcore/ops.rs | 8 | ||||
| -rw-r--r-- | src/libcoretest/ops.rs | 6 | ||||
| -rw-r--r-- | src/librustc/middle/cfg/construct.rs | 2 | ||||
| -rw-r--r-- | src/librustc/middle/expr_use_visitor.rs | 2 | ||||
| -rw-r--r-- | src/librustc/middle/lang_items.rs | 1 | ||||
| -rw-r--r-- | src/librustc/middle/liveness.rs | 2 | ||||
| -rw-r--r-- | src/librustc_trans/trans/debuginfo.rs | 2 | ||||
| -rw-r--r-- | src/librustc_trans/trans/expr.rs | 24 | ||||
| -rw-r--r-- | src/librustc_typeck/check/mod.rs | 62 | ||||
| -rw-r--r-- | src/libsyntax/ast.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/fold.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 4 | ||||
| -rw-r--r-- | src/libsyntax/visit.rs | 2 |
14 files changed, 81 insertions, 40 deletions
diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs index 0cd8c1d69d1..f6b79ccc42b 100644 --- a/src/libcore/ops.rs +++ b/src/libcore/ops.rs @@ -908,6 +908,14 @@ impl<Idx: Clone + Step> Iterator<Idx> for RangeFrom<Idx> { } } +/// A range which is only bounded above. +#[deriving(Copy)] +#[lang="range_to"] +pub struct RangeTo<Idx> { + /// The upper bound of the range (exclusive). + pub end: Idx, +} + /// The `Deref` trait is used to specify the functionality of dereferencing /// operations like `*v`. diff --git a/src/libcoretest/ops.rs b/src/libcoretest/ops.rs index a8889ce9e34..3c8a6d480f7 100644 --- a/src/libcoretest/ops.rs +++ b/src/libcoretest/ops.rs @@ -56,6 +56,12 @@ fn test_range_from() { } #[test] +fn test_range_to() { + // Not much to test. + let _ = RangeTo { end: 42u }; +} + +#[test] fn test_full_range() { // Not much to test. let _ = FullRange; diff --git a/src/librustc/middle/cfg/construct.rs b/src/librustc/middle/cfg/construct.rs index f50790f7e9b..540f8a20dde 100644 --- a/src/librustc/middle/cfg/construct.rs +++ b/src/librustc/middle/cfg/construct.rs @@ -440,7 +440,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { } ast::ExprRange(ref start, ref end) => { - let fields = Some(&**start).into_iter() + let fields = start.as_ref().map(|e| &**e).into_iter() .chain(end.as_ref().map(|e| &**e).into_iter()); self.straightline(expr, pred, fields) } diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 1dfd602794f..f564e5cfefb 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -450,7 +450,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { } ast::ExprRange(ref start, ref end) => { - self.consume_expr(&**start); + start.as_ref().map(|e| self.consume_expr(&**e)); end.as_ref().map(|e| self.consume_expr(&**e)); } diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 90e3e2bb34a..2aef4307199 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -269,6 +269,7 @@ lets_do_this! { SliceMutTraitLangItem, "slice_mut", slice_mut_trait; RangeStructLangItem, "range", range_struct; RangeFromStructLangItem, "range_from", range_from_struct; + RangeToStructLangItem, "range_to", range_to_struct; FullRangeStructLangItem, "full_range", full_range_struct; UnsafeTypeLangItem, "unsafe", unsafe_type; diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index f59a67e2e80..cbd34c7f258 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -1199,7 +1199,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { ast::ExprRange(ref e1, ref e2) => { let succ = e2.as_ref().map_or(succ, |e| self.propagate_through_expr(&**e, succ)); - self.propagate_through_expr(&**e1, succ) + e1.as_ref().map_or(succ, |e| self.propagate_through_expr(&**e, succ)) } ast::ExprBox(None, ref e) | diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs index ea2d42bebdf..0b0a5ecb59e 100644 --- a/src/librustc_trans/trans/debuginfo.rs +++ b/src/librustc_trans/trans/debuginfo.rs @@ -3546,7 +3546,7 @@ fn create_scope_map(cx: &CrateContext, } ast::ExprRange(ref start, ref end) => { - walk_expr(cx, &**start, scope_stack, scope_map); + start.as_ref().map(|e| walk_expr(cx, &**e, scope_stack, scope_map)); end.as_ref().map(|e| walk_expr(cx, &**e, scope_stack, scope_map)); } diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs index 60b5a08c7c5..7c4788a29ef 100644 --- a/src/librustc_trans/trans/expr.rs +++ b/src/librustc_trans/trans/expr.rs @@ -1064,22 +1064,34 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } // A range just desugars into a struct. - let (did, fields) = match end { - &Some(ref end) => { + // Note that the type of the start and end may not be the same, but + // they should only differ in their lifetime, which should not matter + // in trans. + let (did, fields, ty_params) = match (start, end) { + (&Some(ref start), &Some(ref end)) => { // Desugar to Range let fields = vec!(make_field("start", start.clone()), make_field("end", end.clone())); - (tcx.lang_items.range_struct(), fields) + (tcx.lang_items.range_struct(), fields, vec![node_id_type(bcx, start.id)]) } - &None => { + (&Some(ref start), &None) => { // Desugar to RangeFrom let fields = vec!(make_field("start", start.clone())); - (tcx.lang_items.range_from_struct(), fields) + (tcx.lang_items.range_from_struct(), fields, vec![node_id_type(bcx, start.id)]) + } + (&None, &Some(ref end)) => { + // Desugar to RangeTo + let fields = vec!(make_field("end", end.clone())); + (tcx.lang_items.range_to_struct(), fields, vec![node_id_type(bcx, end.id)]) + } + _ => { + // Desugar to FullRange + (tcx.lang_items.full_range_struct(), vec![], vec![]) } }; if let Some(did) = did { - let substs = Substs::new_type(vec![node_id_type(bcx, start.id)], vec![]); + let substs = Substs::new_type(ty_params, vec![]); trans_struct(bcx, fields.as_slice(), None, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 68cf139338a..b677fb1af92 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4308,46 +4308,58 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, } } ast::ExprRange(ref start, ref end) => { - check_expr(fcx, &**start); - let t_start = fcx.expr_ty(&**start); - - let idx_type = if let &Some(ref e) = end { + let t_start = start.as_ref().map(|e| { check_expr(fcx, &**e); - let t_end = fcx.expr_ty(&**e); - if ty::type_is_error(t_end) { - ty::mk_err() - } else if t_start == ty::mk_err() { - ty::mk_err() - } else { - infer::common_supertype(fcx.infcx(), - infer::RangeExpression(expr.span), - true, - t_start, - t_end) + fcx.expr_ty(&**e) + }); + let t_end = end.as_ref().map(|e| { + check_expr(fcx, &**e); + fcx.expr_ty(&**e) + }); + + let idx_type = match (t_start, t_end) { + (Some(ty), None) | (None, Some(ty)) => Some(ty), + (Some(t_start), Some(t_end)) if t_start == ty::mk_err() || t_end == ty::mk_err() => { + Some(ty::mk_err()) } - } else { - t_start + (Some(t_start), Some(t_end)) => { + Some(infer::common_supertype(fcx.infcx(), + infer::RangeExpression(expr.span), + true, + t_start, + t_end)) + } + _ => None }; // Note that we don't check the type of start/end satisfy any // bounds because right the range structs do not have any. If we add // some bounds, then we'll need to check `t_start` against them here. - let range_type = if idx_type == ty::mk_err() { + let range_type = if idx_type == Some(ty::mk_err()) { ty::mk_err() + } else if idx_type.is_none() { + // Neither start nor end => FullRange + if let Some(did) = tcx.lang_items.full_range_struct() { + let substs = Substs::new_type(vec![], vec![]); + ty::mk_struct(tcx, did, substs) + } else { + ty::mk_err() + } } else { // Find the did from the appropriate lang item. - let did = if end.is_some() { - // Range - tcx.lang_items.range_struct() - } else { - // RangeFrom - tcx.lang_items.range_from_struct() + let did = match (start, end) { + (&Some(_), &Some(_)) => tcx.lang_items.range_struct(), + (&Some(_), &None) => tcx.lang_items.range_from_struct(), + (&None, &Some(_)) => tcx.lang_items.range_to_struct(), + (&None, &None) => { + tcx.sess.span_bug(expr.span,"full range should be dealt with above") + } }; if let Some(did) = did { let polytype = ty::lookup_item_type(tcx, did); - let substs = Substs::new_type(vec![idx_type], vec![]); + let substs = Substs::new_type(vec![idx_type.unwrap()], vec![]); let bounds = polytype.generics.to_bounds(tcx, &substs); fcx.add_obligations_for_parameters( traits::ObligationCause::new(expr.span, diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index d4932fbb5f1..e53e2cea1cc 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -724,7 +724,7 @@ pub enum Expr_ { ExprTupField(P<Expr>, Spanned<uint>), ExprIndex(P<Expr>, P<Expr>), ExprSlice(P<Expr>, Option<P<Expr>>, Option<P<Expr>>, Mutability), - ExprRange(P<Expr>, Option<P<Expr>>), + ExprRange(Option<P<Expr>>, Option<P<Expr>>), /// Variable reference, possibly containing `::` and/or /// type parameters, e.g. foo::bar::<baz> diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index c58901701f5..ede023c4e8b 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -1391,7 +1391,7 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span}: Expr, folder: &mut T) -> m) } ExprRange(e1, e2) => { - ExprRange(folder.fold_expr(e1), + ExprRange(e1.map(|x| folder.fold_expr(x)), e2.map(|x| folder.fold_expr(x))) } ExprPath(pth) => ExprPath(folder.fold_path(pth)), diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index a2e2abab03e..ec1e966926a 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2144,7 +2144,7 @@ impl<'a> Parser<'a> { start: P<Expr>, end: Option<P<Expr>>) -> ast::Expr_ { - ExprRange(start, end) + ExprRange(Some(start), end) } pub fn mk_field(&mut self, expr: P<Expr>, ident: ast::SpannedIdent) -> ast::Expr_ { diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 623f20bccd2..a4b349c5f23 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1760,7 +1760,9 @@ impl<'a> State<'a> { try!(word(&mut self.s, "]")); } ast::ExprRange(ref start, ref end) => { - try!(self.print_expr(&**start)); + if let &Some(ref e) = start { + try!(self.print_expr(&**e)); + } try!(word(&mut self.s, "..")); if let &Some(ref e) = end { try!(self.print_expr(&**e)); diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 714339d0f0a..cde9ba932be 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -872,7 +872,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { walk_expr_opt(visitor, end) } ExprRange(ref start, ref end) => { - visitor.visit_expr(&**start); + walk_expr_opt(visitor, start); walk_expr_opt(visitor, end) } ExprPath(ref path) => { |
