Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit d5598aa

Browse files
committedJan 10, 2020
Introduce #![feature(half_open_range_patterns)].
This feature adds `X..`, `..X`, and `..=X` patterns.
1 parent 2d8d559 commit d5598aa

File tree

56 files changed

+2183
-849
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+2183
-849
lines changed
 

‎src/librustc/ty/util.rs

Lines changed: 73 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,18 @@
33
use crate::hir::map::DefPathData;
44
use crate::ich::NodeIdHashingMode;
55
use crate::mir::interpret::{sign_extend, truncate};
6-
use crate::ty::layout::{Integer, IntegerExt};
6+
use crate::ty::layout::{Integer, IntegerExt, Size};
77
use crate::ty::query::TyCtxtAt;
88
use crate::ty::subst::{GenericArgKind, InternalSubsts, Subst, SubstsRef};
99
use crate::ty::TyKind::*;
1010
use crate::ty::{self, DefIdTree, GenericParamDefKind, Ty, TyCtxt, TypeFoldable};
1111
use crate::util::common::ErrorReported;
12+
use rustc_apfloat::Float as _;
13+
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
14+
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
1215
use rustc_hir as hir;
1316
use rustc_hir::def::DefKind;
1417
use rustc_hir::def_id::DefId;
15-
16-
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
17-
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
1818
use rustc_macros::HashStable;
1919
use rustc_span::Span;
2020
use std::{cmp, fmt};
@@ -43,41 +43,54 @@ impl<'tcx> fmt::Display for Discr<'tcx> {
4343
}
4444
}
4545

46+
fn signed_min(size: Size) -> i128 {
47+
sign_extend(1_u128 << (size.bits() - 1), size) as i128
48+
}
49+
50+
fn signed_max(size: Size) -> i128 {
51+
i128::max_value() >> (128 - size.bits())
52+
}
53+
54+
fn unsigned_max(size: Size) -> u128 {
55+
u128::max_value() >> (128 - size.bits())
56+
}
57+
58+
fn int_size_and_signed<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> (Size, bool) {
59+
let (int, signed) = match ty.kind {
60+
Int(ity) => (Integer::from_attr(&tcx, SignedInt(ity)), true),
61+
Uint(uty) => (Integer::from_attr(&tcx, UnsignedInt(uty)), false),
62+
_ => bug!("non integer discriminant"),
63+
};
64+
(int.size(), signed)
65+
}
66+
4667
impl<'tcx> Discr<'tcx> {
4768
/// Adds `1` to the value and wraps around if the maximum for the type is reached.
4869
pub fn wrap_incr(self, tcx: TyCtxt<'tcx>) -> Self {
4970
self.checked_add(tcx, 1).0
5071
}
5172
pub fn checked_add(self, tcx: TyCtxt<'tcx>, n: u128) -> (Self, bool) {
52-
let (int, signed) = match self.ty.kind {
53-
Int(ity) => (Integer::from_attr(&tcx, SignedInt(ity)), true),
54-
Uint(uty) => (Integer::from_attr(&tcx, UnsignedInt(uty)), false),
55-
_ => bug!("non integer discriminant"),
56-
};
57-
58-
let size = int.size();
59-
let bit_size = int.size().bits();
60-
let shift = 128 - bit_size;
61-
if signed {
62-
let sext = |u| sign_extend(u, size) as i128;
63-
let min = sext(1_u128 << (bit_size - 1));
64-
let max = i128::max_value() >> shift;
65-
let val = sext(self.val);
73+
let (size, signed) = int_size_and_signed(tcx, self.ty);
74+
let (val, oflo) = if signed {
75+
let min = signed_min(size);
76+
let max = signed_max(size);
77+
let val = sign_extend(self.val, size) as i128;
6678
assert!(n < (i128::max_value() as u128));
6779
let n = n as i128;
6880
let oflo = val > max - n;
6981
let val = if oflo { min + (n - (max - val) - 1) } else { val + n };
7082
// zero the upper bits
7183
let val = val as u128;
7284
let val = truncate(val, size);
73-
(Self { val: val as u128, ty: self.ty }, oflo)
85+
(val, oflo)
7486
} else {
75-
let max = u128::max_value() >> shift;
87+
let max = unsigned_max(size);
7688
let val = self.val;
7789
let oflo = val > max - n;
7890
let val = if oflo { n - (max - val) - 1 } else { val + n };
79-
(Self { val: val, ty: self.ty }, oflo)
80-
}
91+
(val, oflo)
92+
};
93+
(Self { val, ty: self.ty }, oflo)
8194
}
8295
}
8396

@@ -621,6 +634,44 @@ impl<'tcx> TyCtxt<'tcx> {
621634
}
622635

623636
impl<'tcx> ty::TyS<'tcx> {
637+
/// Returns the maximum value for the given numeric type (including `char`s)
638+
/// or returns `None` if the type is not numeric.
639+
pub fn numeric_max_val(&'tcx self, tcx: TyCtxt<'tcx>) -> Option<&'tcx ty::Const<'tcx>> {
640+
let val = match self.kind {
641+
ty::Int(_) | ty::Uint(_) => {
642+
let (size, signed) = int_size_and_signed(tcx, self);
643+
let val = if signed { signed_max(size) as u128 } else { unsigned_max(size) };
644+
Some(val)
645+
}
646+
ty::Char => Some(std::char::MAX as u128),
647+
ty::Float(fty) => Some(match fty {
648+
ast::FloatTy::F32 => ::rustc_apfloat::ieee::Single::INFINITY.to_bits(),
649+
ast::FloatTy::F64 => ::rustc_apfloat::ieee::Double::INFINITY.to_bits(),
650+
}),
651+
_ => None,
652+
};
653+
val.map(|v| ty::Const::from_bits(tcx, v, ty::ParamEnv::empty().and(self)))
654+
}
655+
656+
/// Returns the minimum value for the given numeric type (including `char`s)
657+
/// or returns `None` if the type is not numeric.
658+
pub fn numeric_min_val(&'tcx self, tcx: TyCtxt<'tcx>) -> Option<&'tcx ty::Const<'tcx>> {
659+
let val = match self.kind {
660+
ty::Int(_) | ty::Uint(_) => {
661+
let (size, signed) = int_size_and_signed(tcx, self);
662+
let val = if signed { truncate(signed_min(size) as u128, size) } else { 0 };
663+
Some(val)
664+
}
665+
ty::Char => Some(0),
666+
ty::Float(fty) => Some(match fty {
667+
ast::FloatTy::F32 => (-::rustc_apfloat::ieee::Single::INFINITY).to_bits(),
668+
ast::FloatTy::F64 => (-::rustc_apfloat::ieee::Double::INFINITY).to_bits(),
669+
}),
670+
_ => None,
671+
};
672+
val.map(|v| ty::Const::from_bits(tcx, v, ty::ParamEnv::empty().and(self)))
673+
}
674+
624675
/// Checks whether values of this type `T` are *moved* or *copied*
625676
/// when referenced -- this amounts to a check for whether `T:
626677
/// Copy`, but note that we **don't** consider lifetimes when

‎src/librustc_ast_lowering/pat.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
6565
PatKind::Box(ref inner) => hir::PatKind::Box(self.lower_pat(inner)),
6666
PatKind::Ref(ref inner, mutbl) => hir::PatKind::Ref(self.lower_pat(inner), mutbl),
6767
PatKind::Range(ref e1, ref e2, Spanned { node: ref end, .. }) => hir::PatKind::Range(
68-
self.lower_expr(e1),
69-
self.lower_expr(e2),
70-
self.lower_range_end(end),
68+
e1.as_deref().map(|e| self.lower_expr(e)),
69+
e2.as_deref().map(|e| self.lower_expr(e)),
70+
self.lower_range_end(end, e2.is_some()),
7171
),
7272
PatKind::Slice(ref pats) => self.lower_pat_slice(pats),
7373
PatKind::Rest => {
@@ -253,10 +253,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
253253
hir::PatKind::Wild
254254
}
255255

256-
fn lower_range_end(&mut self, e: &RangeEnd) -> hir::RangeEnd {
256+
fn lower_range_end(&mut self, e: &RangeEnd, has_end: bool) -> hir::RangeEnd {
257257
match *e {
258-
RangeEnd::Included(_) => hir::RangeEnd::Included,
259-
RangeEnd::Excluded => hir::RangeEnd::Excluded,
258+
RangeEnd::Excluded if has_end => hir::RangeEnd::Excluded,
259+
// No end; so `X..` behaves like `RangeFrom`.
260+
RangeEnd::Excluded | RangeEnd::Included(_) => hir::RangeEnd::Included,
260261
}
261262
}
262263
}

0 commit comments

Comments
 (0)
Please sign in to comment.