Skip to content

Commit d80a0b4

Browse files
committed
Use ScalarInt as early as possible...
...instead of carrying around ty::Const and erroring later
1 parent 854e311 commit d80a0b4

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::{cmp, 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`).
@@ -631,40 +633,38 @@ impl<'tcx> TypeFolder<'tcx> for OpaqueTypeExpander<'tcx> {
631633
impl<'tcx> ty::TyS<'tcx> {
632634
/// Returns the maximum value for the given numeric type (including `char`s)
633635
/// or returns `None` if the type is not numeric.
634-
pub fn numeric_max_val(&'tcx self, tcx: TyCtxt<'tcx>) -> Option<&'tcx ty::Const<'tcx>> {
635-
let val = match self.kind() {
636+
pub fn numeric_max_val(&'tcx self, tcx: TyCtxt<'tcx>) -> Option<ScalarInt> {
637+
match self.kind() {
636638
ty::Int(_) | ty::Uint(_) => {
637639
let (size, signed) = int_size_and_signed(tcx, self);
638640
let val = if signed { signed_max(size) as u128 } else { unsigned_max(size) };
639-
Some(val)
641+
Some(ScalarInt::from_uint(val, size))
640642
}
641-
ty::Char => Some(std::char::MAX as u128),
643+
ty::Char => Some(ScalarInt::from(std::char::MAX)),
642644
ty::Float(fty) => Some(match fty {
643-
ty::FloatTy::F32 => rustc_apfloat::ieee::Single::INFINITY.to_bits(),
644-
ty::FloatTy::F64 => rustc_apfloat::ieee::Double::INFINITY.to_bits(),
645+
ty::FloatTy::F32 => ScalarInt::from(rustc_apfloat::ieee::Single::INFINITY),
646+
ty::FloatTy::F64 => ScalarInt::from(rustc_apfloat::ieee::Double::INFINITY),
645647
}),
646648
_ => None,
647-
};
648-
val.map(|v| ty::Const::from_bits(tcx, v, ty::ParamEnv::empty().and(self)))
649+
}
649650
}
650651

651652
/// Returns the minimum value for the given numeric type (including `char`s)
652653
/// or returns `None` if the type is not numeric.
653-
pub fn numeric_min_val(&'tcx self, tcx: TyCtxt<'tcx>) -> Option<&'tcx ty::Const<'tcx>> {
654-
let val = match self.kind() {
654+
pub fn numeric_min_val(&'tcx self, tcx: TyCtxt<'tcx>) -> Option<ScalarInt> {
655+
match self.kind() {
655656
ty::Int(_) | ty::Uint(_) => {
656657
let (size, signed) = int_size_and_signed(tcx, self);
657658
let val = if signed { size.truncate(signed_min(size) as u128) } else { 0 };
658-
Some(val)
659+
Some(ScalarInt::from_uint(val, size))
659660
}
660-
ty::Char => Some(0),
661+
ty::Char => Some(ScalarInt::from('\0')),
661662
ty::Float(fty) => Some(match fty {
662-
ty::FloatTy::F32 => (-::rustc_apfloat::ieee::Single::INFINITY).to_bits(),
663-
ty::FloatTy::F64 => (-::rustc_apfloat::ieee::Double::INFINITY).to_bits(),
663+
ty::FloatTy::F32 => ScalarInt::from(-::rustc_apfloat::ieee::Single::INFINITY),
664+
ty::FloatTy::F64 => ScalarInt::from(-::rustc_apfloat::ieee::Double::INFINITY),
664665
}),
665666
_ => None,
666-
};
667-
val.map(|v| ty::Const::from_bits(tcx, v, ty::ParamEnv::empty().and(self)))
667+
}
668668
}
669669

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

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

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -443,25 +443,14 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
443443
fn lower_pattern_range(
444444
&mut self,
445445
ty: Ty<'tcx>,
446-
lo: &'tcx ty::Const<'tcx>,
447-
hi: &'tcx ty::Const<'tcx>,
446+
lo: ScalarInt,
447+
hi: ScalarInt,
448448
end: RangeEnd,
449449
span: Span,
450450
) -> PatKind<'tcx> {
451-
assert_eq!(lo.ty, ty);
452-
assert_eq!(hi.ty, ty);
453-
let cmp = compare_const_vals(self.tcx, lo, hi, self.param_env, ty);
454-
let lo_const = lo;
455-
let lo = lo
456-
.val
457-
.eval(self.tcx, self.param_env)
458-
.try_to_scalar_int()
459-
.expect("range patterns must be integral");
460-
let hi = hi
461-
.val
462-
.eval(self.tcx, self.param_env)
463-
.try_to_scalar_int()
464-
.expect("range patterns must be integral");
451+
let lo_const = ty::Const::from_value(self.tcx, ConstValue::Scalar(lo.into()), ty);
452+
let hi_const = ty::Const::from_value(self.tcx, ConstValue::Scalar(hi.into()), ty);
453+
let cmp = compare_const_vals(self.tcx, lo_const, hi_const, self.param_env, ty);
465454
match (end, cmp) {
466455
// `x..y` where `x < y`.
467456
// Non-empty because the range includes at least `x`.
@@ -514,16 +503,18 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
514503
ty: Ty<'tcx>,
515504
lo: Option<&PatKind<'tcx>>,
516505
hi: Option<&PatKind<'tcx>>,
517-
) -> Option<(&'tcx ty::Const<'tcx>, &'tcx ty::Const<'tcx>)> {
506+
) -> Option<(ScalarInt, ScalarInt)> {
507+
let eval =
508+
|value: &ty::Const<'tcx>| value.val.eval(self.tcx, self.param_env).try_to_scalar_int();
518509
match (lo, hi) {
519510
(Some(PatKind::Constant { value: lo }), Some(PatKind::Constant { value: hi })) => {
520-
Some((lo, hi))
511+
Some((eval(lo)?, eval(hi)?))
521512
}
522513
(Some(PatKind::Constant { value: lo }), None) => {
523-
Some((lo, ty.numeric_max_val(self.tcx)?))
514+
Some((eval(lo)?, ty.numeric_max_val(self.tcx)?))
524515
}
525516
(None, Some(PatKind::Constant { value: hi })) => {
526-
Some((ty.numeric_min_val(self.tcx)?, hi))
517+
Some((ty.numeric_min_val(self.tcx)?, eval(hi)?))
527518
}
528519
_ => None,
529520
}

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 crate::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
@@ -23,6 +23,7 @@ use rustc_hir::{
2323
use rustc_lint::{LateContext, LateLintPass, LintContext};
2424
use rustc_middle::lint::in_external_macro;
2525
use rustc_middle::ty::{self, Ty, TyS, VariantDef};
26+
use rustc_middle::mir::{self, interpret::ConstValue};
2627
use rustc_semver::RustcVersion;
2728
use rustc_session::{declare_tool_lint, impl_lint_pass};
2829
use rustc_span::source_map::{Span, Spanned};
@@ -1503,11 +1504,17 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>)
15031504
if let PatKind::Range(ref lhs, ref rhs, range_end) = pat.kind {
15041505
let lhs = match lhs {
15051506
Some(lhs) => constant(cx, cx.typeck_results(), lhs)?.0,
1506-
None => miri_to_const(ty.numeric_min_val(cx.tcx)?)?,
1507+
None => miri_to_const(mir::ConstantKind::Val(
1508+
ConstValue::Scalar(ty.numeric_min_val(cx.tcx)?.into()),
1509+
ty,
1510+
))?,
15071511
};
15081512
let rhs = match rhs {
15091513
Some(rhs) => constant(cx, cx.typeck_results(), rhs)?.0,
1510-
None => miri_to_const(ty.numeric_max_val(cx.tcx)?)?,
1514+
None => miri_to_const(mir::ConstantKind::Val(
1515+
ConstValue::Scalar(ty.numeric_max_val(cx.tcx)?.into()),
1516+
ty,
1517+
))?,
15111518
};
15121519
let rhs = match range_end {
15131520
RangeEnd::Included => Bound::Included(rhs),

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

Lines changed: 22 additions & 28 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};
@@ -350,8 +350,8 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
350350
None,
351351
)
352352
.ok()
353-
.map(|val| rustc_middle::ty::Const::from_value(self.lcx.tcx, val, ty))?;
354-
let result = miri_to_const(&result);
353+
.map(|val| mir::ConstantKind::Val(val, ty))?;
354+
let result = miri_to_const(result);
355355
if result.is_some() {
356356
self.needed_resolution = true;
357357
}
@@ -501,44 +501,38 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
501501
}
502502
}
503503

504-
pub fn miri_to_const(result: &ty::Const<'_>) -> Option<Constant> {
504+
pub fn miri_to_const(result: mir::ConstantKind<'tcx>) -> Option<Constant> {
505505
use rustc_middle::mir::interpret::ConstValue;
506-
match result.val {
507-
ty::ConstKind::Value(ConstValue::Scalar(Scalar::Int(int))) => {
508-
match result.ty.kind() {
509-
ty::Bool => Some(Constant::Bool(int == ScalarInt::TRUE)),
510-
ty::Uint(_) | ty::Int(_) => Some(Constant::Int(int.assert_bits(int.size()))),
506+
match *result.ty().kind() {
507+
ty::Bool => Some(Constant::Bool(result.try_to_scalar_int()? == ScalarInt::TRUE)),
508+
ty::Uint(_) | ty::Int(_) => {
509+
let int = result.try_to_scalar_int()?;
510+
Some(Constant::Int(int.assert_bits(int.size())))
511+
}
511512
ty::Float(FloatTy::F32) => Some(Constant::F32(f32::from_bits(
512-
int.try_into().expect("invalid f32 bit representation"),
513+
result.try_to_scalar_int()?.try_into().expect("invalid f32 bit representation"),
513514
))),
514515
ty::Float(FloatTy::F64) => Some(Constant::F64(f64::from_bits(
515-
int.try_into().expect("invalid f64 bit representation"),
516+
result.try_to_scalar_int()?.try_into().expect("invalid f64 bit representation"),
516517
))),
517-
ty::RawPtr(type_and_mut) => {
518-
if let ty::Uint(_) = type_and_mut.ty.kind() {
519-
return Some(Constant::RawPtr(int.assert_bits(int.size())));
518+
ty::RawPtr(_) => {
519+
let int = result.try_to_scalar_int()?;
520+
Some(Constant::RawPtr(int.assert_bits(int.size())))
520521
}
521-
None
522-
},
523-
// FIXME: implement other conversions.
524-
_ => None,
525-
}
526-
},
527-
ty::ConstKind::Value(ConstValue::Slice { data, start, end }) => match result.ty.kind() {
528522
ty::Ref(_, tam, _) => match tam.kind() {
529-
ty::Str => String::from_utf8(
530-
data.inspect_with_uninit_and_ptr_outside_interpreter(start..end)
531-
.to_owned(),
523+
ty::Str => match result.try_to_value()? {
524+
ConstValue::Slice { data, start, end } => String::from_utf8(
525+
data.inspect_with_uninit_and_ptr_outside_interpreter(start..end).to_owned(),
532526
)
533527
.ok()
534528
.map(Constant::Str),
535529
_ => None,
536530
},
537531
_ => None,
538532
},
539-
ty::ConstKind::Value(ConstValue::ByRef { alloc, offset: _ }) => match result.ty.kind() {
540-
ty::Array(sub_type, len) => match sub_type.kind() {
541-
ty::Float(FloatTy::F32) => match miri_to_const(len) {
533+
ty::Array(sub_type, len) => match result.try_to_value()? {
534+
ConstValue::ByRef { alloc, offset: _ } => match sub_type.kind() {
535+
ty::Float(FloatTy::F32) => match miri_to_const(len.into()) {
542536
Some(Constant::Int(len)) => alloc
543537
.inspect_with_uninit_and_ptr_outside_interpreter(0..(4 * len as usize))
544538
.to_owned()
@@ -552,7 +546,7 @@ pub fn miri_to_const(result: &ty::Const<'_>) -> Option<Constant> {
552546
.map(Constant::Vec),
553547
_ => None,
554548
},
555-
ty::Float(FloatTy::F64) => match miri_to_const(len) {
549+
ty::Float(FloatTy::F64) => match miri_to_const(len.into()) {
556550
Some(Constant::Int(len)) => alloc
557551
.inspect_with_uninit_and_ptr_outside_interpreter(0..(8 * len as usize))
558552
.to_owned()

0 commit comments

Comments
 (0)