Skip to content

Commit 0e75539

Browse files
author
Lukas Markeffsky
committed
check the types in ty::Value to value conversion
and remove `ty::Const::try_to_scalar` because it becomes redundant
1 parent 03d3088 commit 0e75539

File tree

8 files changed

+83
-28
lines changed

8 files changed

+83
-28
lines changed

compiler/rustc_middle/src/ty/consts.rs

-7
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ use rustc_error_messages::MultiSpan;
55
use rustc_macros::HashStable;
66
use rustc_type_ir::{self as ir, TypeFlags, WithCachedTypeInfo};
77

8-
use crate::mir::interpret::Scalar;
98
use crate::ty::{self, Ty, TyCtxt};
109

1110
mod int;
@@ -230,12 +229,6 @@ impl<'tcx> Const<'tcx> {
230229
}
231230
}
232231

233-
#[inline]
234-
pub fn try_to_scalar(self) -> Option<(Scalar, Ty<'tcx>)> {
235-
let cv = self.try_to_value()?;
236-
Some((cv.valtree.try_to_scalar()?, cv.ty))
237-
}
238-
239232
#[inline]
240233
pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> {
241234
self.try_to_value()?.try_to_target_usize(tcx)

compiler/rustc_middle/src/ty/consts/valtree.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -117,20 +117,30 @@ pub struct Value<'tcx> {
117117
impl<'tcx> Value<'tcx> {
118118
/// Attempts to extract the raw bits from the constant.
119119
///
120-
/// Fails if the value can't be represented as bits (e.g. because it is an aggregate).
120+
/// Fails if the value can't be represented as bits (e.g. because it is a reference
121+
/// or an aggregate).
121122
#[inline]
122123
pub fn try_to_bits(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> Option<u128> {
124+
let (ty::Bool | ty::Char | ty::Uint(_) | ty::Int(_) | ty::Float(_)) = self.ty.kind() else {
125+
return None;
126+
};
123127
let scalar = self.valtree.try_to_scalar_int()?;
124128
let input = typing_env.with_post_analysis_normalized(tcx).as_query_input(self.ty);
125129
let size = tcx.layout_of(input).ok()?.size;
126130
Some(scalar.to_bits(size))
127131
}
128132

129133
pub fn try_to_bool(self) -> Option<bool> {
134+
if !self.ty.is_bool() {
135+
return None;
136+
}
130137
self.valtree.try_to_scalar_int()?.try_to_bool().ok()
131138
}
132139

133140
pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> {
141+
if !self.ty.is_usize() {
142+
return None;
143+
}
134144
self.valtree.try_to_scalar_int().map(|s| s.to_target_usize(tcx))
135145
}
136146
}

compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for TransformTy<'tcx> {
5151
// Transforms a ty:Ty for being encoded and used in the substitution dictionary.
5252
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
5353
match t.kind() {
54-
ty::Array(..)
55-
| ty::Closure(..)
54+
ty::Closure(..)
5655
| ty::Coroutine(..)
5756
| ty::CoroutineClosure(..)
5857
| ty::CoroutineWitness(..)
@@ -67,6 +66,13 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for TransformTy<'tcx> {
6766
| ty::Tuple(..)
6867
| ty::UnsafeBinder(_) => t.super_fold_with(self),
6968

69+
// Don't transform the type of the array length and keep it as `usize`.
70+
// This is required for `try_to_target_usize` to work correctly.
71+
&ty::Array(inner, len) => {
72+
let inner = self.fold_ty(inner);
73+
Ty::new_array_with_const_len(self.tcx, inner, len)
74+
}
75+
7076
ty::Bool => {
7177
if self.options.contains(EncodeTyOptions::NORMALIZE_INTEGERS) {
7278
// Note: on all platforms that Rust's currently supports, its size and alignment

compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs

+4-6
Original file line numberDiff line numberDiff line change
@@ -2023,14 +2023,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
20232023
_ => None,
20242024
};
20252025
if let Some(tykind) = tykind
2026-
&& let hir::TyKind::Array(_, length) = tykind
2027-
&& let Some((scalar, ty)) = sz.found.try_to_scalar()
2028-
&& ty == self.tcx.types.usize
2026+
&& let hir::TyKind::Array(_, length_arg) = tykind
2027+
&& let Some(length_val) = sz.found.try_to_target_usize(self.tcx)
20292028
{
2030-
let span = length.span();
20312029
Some(TypeErrorAdditionalDiags::ConsiderSpecifyingLength {
2032-
span,
2033-
length: scalar.to_target_usize(&self.tcx).unwrap(),
2030+
span: length_arg.span(),
2031+
length: length_val,
20342032
})
20352033
} else {
20362034
None

tests/crashes/131102.rs

-4
This file was deleted.

tests/crashes/131103.rs

-6
This file was deleted.

tests/ui/consts/bad-array-size-in-type-err.rs

+17
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,20 @@ fn main() {
88
//~^ ERROR mismatched types
99
//~| ERROR the constant `2` is not of type `usize`
1010
}
11+
12+
fn iter(val: BadArraySize::<2>) {
13+
for _ in val.arr {}
14+
//~^ ERROR the constant `2` is not of type `usize`
15+
//~| ERROR `[i32; 2]` is not an iterator
16+
}
17+
18+
// issue #131102
19+
pub struct Blorb<const N: u16>([String; N]); //~ ERROR the constant `N` is not of type `usize`
20+
pub struct Wrap(Blorb<0>);
21+
pub const fn i(_: Wrap) {} //~ ERROR destructor of `Wrap` cannot be evaluated at compile-time
22+
23+
// issue #131103
24+
struct Struct<const N: i128>(pub [u8; N]); //~ ERROR the constant `N` is not of type `usize`
25+
pub fn function(value: Struct<3>) -> u8 {
26+
value.0[0]
27+
}

tests/ui/consts/bad-array-size-in-type-err.stderr

+43-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,18 @@ error: the constant `N` is not of type `usize`
44
LL | arr: [i32; N],
55
| ^^^^^^^^ expected `usize`, found `u8`
66

7+
error: the constant `N` is not of type `usize`
8+
--> $DIR/bad-array-size-in-type-err.rs:19:32
9+
|
10+
LL | pub struct Blorb<const N: u16>([String; N]);
11+
| ^^^^^^^^^^^ expected `usize`, found `u16`
12+
13+
error: the constant `N` is not of type `usize`
14+
--> $DIR/bad-array-size-in-type-err.rs:24:34
15+
|
16+
LL | struct Struct<const N: i128>(pub [u8; N]);
17+
| ^^^^^^^ expected `usize`, found `i128`
18+
719
error[E0308]: mismatched types
820
--> $DIR/bad-array-size-in-type-err.rs:7:38
921
|
@@ -16,6 +28,35 @@ error: the constant `2` is not of type `usize`
1628
LL | let _ = BadArraySize::<2> { arr: [0, 0, 0] };
1729
| ^^^^^^^^^ expected `usize`, found `u8`
1830

19-
error: aborting due to 3 previous errors
31+
error: the constant `2` is not of type `usize`
32+
--> $DIR/bad-array-size-in-type-err.rs:13:14
33+
|
34+
LL | for _ in val.arr {}
35+
| ^^^^^^^ expected `usize`, found `u8`
36+
37+
error[E0277]: `[i32; 2]` is not an iterator
38+
--> $DIR/bad-array-size-in-type-err.rs:13:14
39+
|
40+
LL | for _ in val.arr {}
41+
| ^^^^^^^ `[i32; 2]` is not an iterator; try calling `.into_iter()` or `.iter()`
42+
|
43+
= help: the trait `IntoIterator` is not implemented for `[i32; 2]`
44+
= help: the following other types implement trait `IntoIterator`:
45+
&[T; N]
46+
&[T]
47+
&mut [T; N]
48+
&mut [T]
49+
[T; N]
50+
51+
error[E0493]: destructor of `Wrap` cannot be evaluated at compile-time
52+
--> $DIR/bad-array-size-in-type-err.rs:21:16
53+
|
54+
LL | pub const fn i(_: Wrap) {}
55+
| ^ - value is dropped here
56+
| |
57+
| the destructor for this type cannot be evaluated in constant functions
58+
59+
error: aborting due to 8 previous errors
2060

21-
For more information about this error, try `rustc --explain E0308`.
61+
Some errors have detailed explanations: E0277, E0308, E0493.
62+
For more information about an error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)