Skip to content

Commit b2a2286

Browse files
committed
Use ScalarInt as early as possible...
...instead of carrying around ty::Const and erroring later
1 parent 987b9fc commit b2a2286

File tree

5 files changed

+61
-69
lines changed

5 files changed

+61
-69
lines changed

compiler/rustc_middle/src/ty/util.rs

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ use rustc_target::abi::{Integer, Size, TargetDataLayout};
2323
use smallvec::SmallVec;
2424
use std::{fmt, iter};
2525

26+
use super::ScalarInt;
27+
2628
#[derive(Copy, Clone, Debug)]
2729
pub struct Discr<'tcx> {
2830
/// Bit representation of the discriminant (e.g., `-128i8` is `0xFF_u128`).
@@ -616,40 +618,38 @@ impl<'tcx> TypeFolder<'tcx> for OpaqueTypeExpander<'tcx> {
616618
impl<'tcx> ty::TyS<'tcx> {
617619
/// Returns the maximum value for the given numeric type (including `char`s)
618620
/// or returns `None` if the type is not numeric.
619-
pub fn numeric_max_val(&'tcx self, tcx: TyCtxt<'tcx>) -> Option<&'tcx ty::Const<'tcx>> {
620-
let val = match self.kind() {
621+
pub fn numeric_max_val(&'tcx self, tcx: TyCtxt<'tcx>) -> Option<ScalarInt> {
622+
match self.kind() {
621623
ty::Int(_) | ty::Uint(_) => {
622624
let (size, signed) = int_size_and_signed(tcx, self);
623625
let val = if signed { signed_max(size) as u128 } else { unsigned_max(size) };
624-
Some(val)
626+
Some(ScalarInt::from_uint(val, size))
625627
}
626-
ty::Char => Some(std::char::MAX as u128),
628+
ty::Char => Some(ScalarInt::from(std::char::MAX)),
627629
ty::Float(fty) => Some(match fty {
628-
ty::FloatTy::F32 => rustc_apfloat::ieee::Single::INFINITY.to_bits(),
629-
ty::FloatTy::F64 => rustc_apfloat::ieee::Double::INFINITY.to_bits(),
630+
ty::FloatTy::F32 => ScalarInt::from(rustc_apfloat::ieee::Single::INFINITY),
631+
ty::FloatTy::F64 => ScalarInt::from(rustc_apfloat::ieee::Double::INFINITY),
630632
}),
631633
_ => None,
632-
};
633-
val.map(|v| ty::Const::from_bits(tcx, v, ty::ParamEnv::empty().and(self)))
634+
}
634635
}
635636

636637
/// Returns the minimum value for the given numeric type (including `char`s)
637638
/// or returns `None` if the type is not numeric.
638-
pub fn numeric_min_val(&'tcx self, tcx: TyCtxt<'tcx>) -> Option<&'tcx ty::Const<'tcx>> {
639-
let val = match self.kind() {
639+
pub fn numeric_min_val(&'tcx self, tcx: TyCtxt<'tcx>) -> Option<ScalarInt> {
640+
match self.kind() {
640641
ty::Int(_) | ty::Uint(_) => {
641642
let (size, signed) = int_size_and_signed(tcx, self);
642643
let val = if signed { size.truncate(signed_min(size) as u128) } else { 0 };
643-
Some(val)
644+
Some(ScalarInt::from_uint(val, size))
644645
}
645-
ty::Char => Some(0),
646+
ty::Char => Some(ScalarInt::from('\0')),
646647
ty::Float(fty) => Some(match fty {
647-
ty::FloatTy::F32 => (-::rustc_apfloat::ieee::Single::INFINITY).to_bits(),
648-
ty::FloatTy::F64 => (-::rustc_apfloat::ieee::Double::INFINITY).to_bits(),
648+
ty::FloatTy::F32 => ScalarInt::from(-::rustc_apfloat::ieee::Single::INFINITY),
649+
ty::FloatTy::F64 => ScalarInt::from(-::rustc_apfloat::ieee::Double::INFINITY),
649650
}),
650651
_ => None,
651-
};
652-
val.map(|v| ty::Const::from_bits(tcx, v, ty::ParamEnv::empty().and(self)))
652+
}
653653
}
654654

655655
/// Checks whether values of this type `T` are *moved* or *copied*

compiler/rustc_mir_build/src/thir/pattern/mod.rs

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use rustc_middle::mir::UserTypeProjection;
2121
use rustc_middle::mir::{BorrowKind, Field, Mutability};
2222
use rustc_middle::thir::{Ascription, BindingMode, FieldPat, Pat, PatKind, PatRange, PatTyProj};
2323
use rustc_middle::ty::subst::{GenericArg, SubstsRef};
24-
use rustc_middle::ty::{self, AdtDef, DefIdTree, Region, Ty, TyCtxt, UserType};
24+
use rustc_middle::ty::{self, AdtDef, DefIdTree, Region, ScalarInt, Ty, TyCtxt, UserType};
2525
use rustc_span::{Span, Symbol};
2626

2727
use std::cmp::Ordering;
@@ -122,25 +122,14 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
122122
fn lower_pattern_range(
123123
&mut self,
124124
ty: Ty<'tcx>,
125-
lo: &'tcx ty::Const<'tcx>,
126-
hi: &'tcx ty::Const<'tcx>,
125+
lo: ScalarInt,
126+
hi: ScalarInt,
127127
end: RangeEnd,
128128
span: Span,
129129
) -> PatKind<'tcx> {
130-
assert_eq!(lo.ty, ty);
131-
assert_eq!(hi.ty, ty);
132-
let cmp = compare_const_vals(self.tcx, lo, hi, self.param_env, ty);
133-
let lo_const = lo;
134-
let lo = lo
135-
.val
136-
.eval(self.tcx, self.param_env)
137-
.try_to_scalar_int()
138-
.expect("range patterns must be integral");
139-
let hi = hi
140-
.val
141-
.eval(self.tcx, self.param_env)
142-
.try_to_scalar_int()
143-
.expect("range patterns must be integral");
130+
let lo_const = ty::Const::from_value(self.tcx, ConstValue::Scalar(lo.into()), ty);
131+
let hi_const = ty::Const::from_value(self.tcx, ConstValue::Scalar(hi.into()), ty);
132+
let cmp = compare_const_vals(self.tcx, lo_const, hi_const, self.param_env, ty);
144133
match (end, cmp) {
145134
// `x..y` where `x < y`.
146135
// Non-empty because the range includes at least `x`.
@@ -193,16 +182,18 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
193182
ty: Ty<'tcx>,
194183
lo: Option<&PatKind<'tcx>>,
195184
hi: Option<&PatKind<'tcx>>,
196-
) -> Option<(&'tcx ty::Const<'tcx>, &'tcx ty::Const<'tcx>)> {
185+
) -> Option<(ScalarInt, ScalarInt)> {
186+
let eval =
187+
|value: &ty::Const<'tcx>| value.val.eval(self.tcx, self.param_env).try_to_scalar_int();
197188
match (lo, hi) {
198189
(Some(PatKind::Constant { value: lo }), Some(PatKind::Constant { value: hi })) => {
199-
Some((lo, hi))
190+
Some((eval(lo)?, eval(hi)?))
200191
}
201192
(Some(PatKind::Constant { value: lo }), None) => {
202-
Some((lo, ty.numeric_max_val(self.tcx)?))
193+
Some((eval(lo)?, ty.numeric_max_val(self.tcx)?))
203194
}
204195
(None, Some(PatKind::Constant { value: hi })) => {
205-
Some((ty.numeric_min_val(self.tcx)?, hi))
196+
Some((ty.numeric_min_val(self.tcx)?, eval(hi)?))
206197
}
207198
_ => None,
208199
}

src/tools/clippy/clippy_lints/src/enum_clike.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
//! lint on C-like enums that are `repr(isize/usize)` and have values that
22
//! don't fit into an `i32`
33
4-
use clippy_utils::consts::{miri_to_const, Constant};
54
use clippy_utils::diagnostics::span_lint;
65
use rustc_hir::{Item, ItemKind};
76
use rustc_lint::{LateContext, LateLintPass};
@@ -50,8 +49,9 @@ impl<'tcx> LateLintPass<'tcx> for UnportableVariant {
5049
.tcx
5150
.const_eval_poly(def_id.to_def_id())
5251
.ok()
53-
.map(|val| rustc_middle::ty::Const::from_value(cx.tcx, val, ty));
54-
if let Some(Constant::Int(val)) = constant.and_then(miri_to_const) {
52+
.and_then(|c| c.try_to_scalar_int());
53+
if let Some(scalar) = constant {
54+
let val = scalar.to_bits(cx.tcx.layout_of(cx.param_env.and(ty)).unwrap().size).unwrap();
5555
if let ty::Adt(adt, _) = ty.kind() {
5656
if adt.is_enum() {
5757
ty = adt.repr.discr_type().to_ty(cx.tcx);

src/tools/clippy/clippy_lints/src/matches.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ use rustc_hir::{HirIdMap, HirIdSet};
2525
use rustc_lint::{LateContext, LateLintPass, LintContext};
2626
use rustc_middle::lint::in_external_macro;
2727
use rustc_middle::ty::{self, Ty, TyS, VariantDef};
28+
use rustc_middle::mir::{self, interpret::ConstValue};
2829
use rustc_semver::RustcVersion;
2930
use rustc_session::{declare_tool_lint, impl_lint_pass};
3031
use rustc_span::source_map::{Span, Spanned};
@@ -1533,11 +1534,17 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>)
15331534
if let PatKind::Range(ref lhs, ref rhs, range_end) = pat.kind {
15341535
let lhs = match lhs {
15351536
Some(lhs) => constant(cx, cx.typeck_results(), lhs)?.0,
1536-
None => miri_to_const(ty.numeric_min_val(cx.tcx)?)?,
1537+
None => miri_to_const(mir::ConstantKind::Val(
1538+
ConstValue::Scalar(ty.numeric_min_val(cx.tcx)?.into()),
1539+
ty,
1540+
))?,
15371541
};
15381542
let rhs = match rhs {
15391543
Some(rhs) => constant(cx, cx.typeck_results(), rhs)?.0,
1540-
None => miri_to_const(ty.numeric_max_val(cx.tcx)?)?,
1544+
None => miri_to_const(mir::ConstantKind::Val(
1545+
ConstValue::Scalar(ty.numeric_max_val(cx.tcx)?.into()),
1546+
ty,
1547+
))?,
15411548
};
15421549
let rhs = match range_end {
15431550
RangeEnd::Included => Bound::Included(rhs),

src/tools/clippy/clippy_utils/src/consts.rs

Lines changed: 21 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use rustc_data_structures::sync::Lrc;
77
use rustc_hir::def::{DefKind, Res};
88
use rustc_hir::{BinOp, BinOpKind, Block, Expr, ExprKind, HirId, QPath, UnOp};
99
use rustc_lint::LateContext;
10-
use rustc_middle::mir::interpret::Scalar;
10+
use rustc_middle::mir;
1111
use rustc_middle::ty::subst::{Subst, SubstsRef};
1212
use rustc_middle::ty::{self, FloatTy, ScalarInt, Ty, TyCtxt};
1313
use rustc_middle::{bug, span_bug};
@@ -354,7 +354,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
354354
None,
355355
)
356356
.ok()
357-
.map(|val| rustc_middle::ty::Const::from_value(self.lcx.tcx, val, ty))?;
357+
.map(|val| mir::ConstantKind::Val(val, ty))?;
358358
let result = miri_to_const(result);
359359
if result.is_some() {
360360
self.needed_resolution = true;
@@ -505,44 +505,38 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
505505
}
506506
}
507507

508-
pub fn miri_to_const(result: &ty::Const<'_>) -> Option<Constant> {
508+
pub fn miri_to_const(result: mir::ConstantKind<'tcx>) -> Option<Constant> {
509509
use rustc_middle::mir::interpret::ConstValue;
510-
match result.val {
511-
ty::ConstKind::Value(ConstValue::Scalar(Scalar::Int(int))) => {
512-
match result.ty.kind() {
513-
ty::Bool => Some(Constant::Bool(int == ScalarInt::TRUE)),
514-
ty::Uint(_) | ty::Int(_) => Some(Constant::Int(int.assert_bits(int.size()))),
510+
match *result.ty().kind() {
511+
ty::Bool => Some(Constant::Bool(result.try_to_scalar_int()? == ScalarInt::TRUE)),
512+
ty::Uint(_) | ty::Int(_) => {
513+
let int = result.try_to_scalar_int()?;
514+
Some(Constant::Int(int.assert_bits(int.size())))
515+
}
515516
ty::Float(FloatTy::F32) => Some(Constant::F32(f32::from_bits(
516-
int.try_into().expect("invalid f32 bit representation"),
517+
result.try_to_scalar_int()?.try_into().expect("invalid f32 bit representation"),
517518
))),
518519
ty::Float(FloatTy::F64) => Some(Constant::F64(f64::from_bits(
519-
int.try_into().expect("invalid f64 bit representation"),
520+
result.try_to_scalar_int()?.try_into().expect("invalid f64 bit representation"),
520521
))),
521-
ty::RawPtr(type_and_mut) => {
522-
if let ty::Uint(_) = type_and_mut.ty.kind() {
523-
return Some(Constant::RawPtr(int.assert_bits(int.size())));
522+
ty::RawPtr(_) => {
523+
let int = result.try_to_scalar_int()?;
524+
Some(Constant::RawPtr(int.assert_bits(int.size())))
524525
}
525-
None
526-
},
527-
// FIXME: implement other conversions.
528-
_ => None,
529-
}
530-
},
531-
ty::ConstKind::Value(ConstValue::Slice { data, start, end }) => match result.ty.kind() {
532526
ty::Ref(_, tam, _) => match tam.kind() {
533-
ty::Str => String::from_utf8(
534-
data.inspect_with_uninit_and_ptr_outside_interpreter(start..end)
535-
.to_owned(),
527+
ty::Str => match result.try_to_value()? {
528+
ConstValue::Slice { data, start, end } => String::from_utf8(
529+
data.inspect_with_uninit_and_ptr_outside_interpreter(start..end).to_owned(),
536530
)
537531
.ok()
538532
.map(Constant::Str),
539533
_ => None,
540534
},
541535
_ => None,
542536
},
543-
ty::ConstKind::Value(ConstValue::ByRef { alloc, offset: _ }) => match result.ty.kind() {
544-
ty::Array(sub_type, len) => match sub_type.kind() {
545-
ty::Float(FloatTy::F32) => match miri_to_const(len) {
537+
ty::Array(sub_type, len) => match result.try_to_value()? {
538+
ConstValue::ByRef { alloc, offset: _ } => match sub_type.kind() {
539+
ty::Float(FloatTy::F32) => match miri_to_const(len.into()) {
546540
Some(Constant::Int(len)) => alloc
547541
.inspect_with_uninit_and_ptr_outside_interpreter(0..(4 * len as usize))
548542
.to_owned()
@@ -556,7 +550,7 @@ pub fn miri_to_const(result: &ty::Const<'_>) -> Option<Constant> {
556550
.map(Constant::Vec),
557551
_ => None,
558552
},
559-
ty::Float(FloatTy::F64) => match miri_to_const(len) {
553+
ty::Float(FloatTy::F64) => match miri_to_const(len.into()) {
560554
Some(Constant::Int(len)) => alloc
561555
.inspect_with_uninit_and_ptr_outside_interpreter(0..(8 * len as usize))
562556
.to_owned()

0 commit comments

Comments
 (0)