Skip to content

Commit b5fd2a5

Browse files
authored
Unrolled build for #152001
Rollup merge of #152001 - reddevilmidzy:mgca-i, r=BoxyUwU mGCA: Validate const literal against expected type close: #151625 close: #150983 also fix: #133966 (moved crashes test)
2 parents f846389 + 01d48c6 commit b5fd2a5

40 files changed

+526
-227
lines changed

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,10 @@ use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
3535
use rustc_infer::traits::DynCompatibilityViolation;
3636
use rustc_macros::{TypeFoldable, TypeVisitable};
3737
use rustc_middle::middle::stability::AllowUnstable;
38-
use rustc_middle::mir::interpret::LitToConstInput;
3938
use rustc_middle::ty::print::PrintPolyTraitRefExt as _;
4039
use rustc_middle::ty::{
41-
self, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, Ty, TyCtxt,
42-
TypeSuperFoldable, TypeVisitableExt, TypingMode, Upcast, fold_regions,
40+
self, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, LitToConstInput, Ty, TyCtxt,
41+
TypeSuperFoldable, TypeVisitableExt, TypingMode, Upcast, const_lit_matches_ty, fold_regions,
4342
};
4443
use rustc_middle::{bug, span_bug};
4544
use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS;
@@ -2809,8 +2808,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
28092808
span: Span,
28102809
) -> Const<'tcx> {
28112810
let tcx = self.tcx();
2811+
if let LitKind::Err(guar) = *kind {
2812+
return ty::Const::new_error(tcx, guar);
2813+
}
28122814
let input = LitToConstInput { lit: *kind, ty, neg };
2813-
tcx.at(span).lit_to_const(input)
2815+
match tcx.at(span).lit_to_const(input) {
2816+
Some(value) => ty::Const::new_value(tcx, value.valtree, value.ty),
2817+
None => {
2818+
let e = tcx.dcx().span_err(span, "type annotations needed for the literal");
2819+
ty::Const::new_error(tcx, e)
2820+
}
2821+
}
28142822
}
28152823

28162824
#[instrument(skip(self), level = "debug")]
@@ -2839,11 +2847,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
28392847
_ => None,
28402848
};
28412849

2842-
lit_input
2843-
// Allow the `ty` to be an alias type, though we cannot handle it here, we just go through
2844-
// the more expensive anon const code path.
2845-
.filter(|l| !l.ty.has_aliases())
2846-
.map(|l| tcx.at(expr.span).lit_to_const(l))
2850+
lit_input.and_then(|l| {
2851+
if const_lit_matches_ty(tcx, &l.lit, l.ty, l.neg) {
2852+
tcx.at(expr.span)
2853+
.lit_to_const(l)
2854+
.map(|value| ty::Const::new_value(tcx, value.valtree, value.ty))
2855+
} else {
2856+
None
2857+
}
2858+
})
28472859
}
28482860

28492861
fn require_type_const_attribute(

compiler/rustc_middle/src/mir/interpret/mod.rs

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use std::num::NonZero;
1313
use std::{fmt, io};
1414

1515
use rustc_abi::{AddressSpace, Align, Endian, HasDataLayout, Size};
16-
use rustc_ast::{LitKind, Mutability};
16+
use rustc_ast::Mutability;
1717
use rustc_data_structures::fx::FxHashMap;
1818
use rustc_data_structures::sharded::ShardedHashMap;
1919
use rustc_data_structures::sync::{AtomicU64, Lock};
@@ -73,17 +73,6 @@ impl<'tcx> GlobalId<'tcx> {
7373
}
7474
}
7575

76-
/// Input argument for `tcx.lit_to_const`.
77-
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, HashStable)]
78-
pub struct LitToConstInput<'tcx> {
79-
/// The absolute value of the resultant constant.
80-
pub lit: LitKind,
81-
/// The type of the constant.
82-
pub ty: Ty<'tcx>,
83-
/// If the constant is negative.
84-
pub neg: bool,
85-
}
86-
8776
#[derive(Copy, Clone, Eq, Hash, Ord, PartialEq, PartialOrd)]
8877
pub struct AllocId(pub NonZero<u64>);
8978

compiler/rustc_middle/src/queries.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ use crate::middle::resolve_bound_vars::{ObjectLifetimeDefault, ResolveBoundVars,
111111
use crate::middle::stability::DeprecationEntry;
112112
use crate::mir::interpret::{
113113
EvalStaticInitializerRawResult, EvalToAllocationRawResult, EvalToConstValueResult,
114-
EvalToValTreeResult, GlobalId, LitToConstInput,
114+
EvalToValTreeResult, GlobalId,
115115
};
116116
use crate::mir::mono::{
117117
CodegenUnit, CollectionMode, MonoItem, MonoItemPartitions, NormalizationErrorInMono,
@@ -134,8 +134,8 @@ use crate::ty::layout::ValidityRequirement;
134134
use crate::ty::print::PrintTraitRefExt;
135135
use crate::ty::util::AlwaysRequiresDrop;
136136
use crate::ty::{
137-
self, CrateInherentImpls, GenericArg, GenericArgsRef, PseudoCanonicalInput, SizedTraitKind, Ty,
138-
TyCtxt, TyCtxtFeed,
137+
self, CrateInherentImpls, GenericArg, GenericArgsRef, LitToConstInput, PseudoCanonicalInput,
138+
SizedTraitKind, Ty, TyCtxt, TyCtxtFeed,
139139
};
140140
use crate::{dep_graph, mir, thir};
141141

@@ -1411,7 +1411,7 @@ rustc_queries! {
14111411
// FIXME get rid of this with valtrees
14121412
query lit_to_const(
14131413
key: LitToConstInput<'tcx>
1414-
) -> ty::Const<'tcx> {
1414+
) -> Option<ty::Value<'tcx>> {
14151415
desc { "converting literal to const" }
14161416
}
14171417

compiler/rustc_middle/src/query/erase.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,10 @@ impl Erasable for Option<ty::EarlyBinder<'_, Ty<'_>>> {
256256
type Storage = [u8; size_of::<Option<ty::EarlyBinder<'static, Ty<'static>>>>()];
257257
}
258258

259+
impl Erasable for Option<ty::Value<'_>> {
260+
type Storage = [u8; size_of::<Option<ty::Value<'static>>>()];
261+
}
262+
259263
impl Erasable for rustc_hir::MaybeOwner<'_> {
260264
type Storage = [u8; size_of::<rustc_hir::MaybeOwner<'static>>()];
261265
}
@@ -441,7 +445,6 @@ impl_erasable_for_single_lifetime_types! {
441445
rustc_middle::mir::DestructuredConstant,
442446
rustc_middle::mir::ConstAlloc,
443447
rustc_middle::mir::interpret::GlobalId,
444-
rustc_middle::mir::interpret::LitToConstInput,
445448
rustc_middle::mir::interpret::EvalStaticInitializerRawResult,
446449
rustc_middle::mir::mono::MonoItemPartitions,
447450
rustc_middle::traits::query::MethodAutoderefStepsResult,
@@ -466,6 +469,7 @@ impl_erasable_for_single_lifetime_types! {
466469
rustc_middle::ty::InstanceKind,
467470
rustc_middle::ty::layout::FnAbiError,
468471
rustc_middle::ty::layout::LayoutError,
472+
rustc_middle::ty::LitToConstInput,
469473
rustc_middle::ty::ParamEnv,
470474
rustc_middle::ty::TypingEnv,
471475
rustc_middle::ty::Predicate,

compiler/rustc_middle/src/query/keys.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ impl<'tcx> Key for (Ty<'tcx>, Option<ty::ExistentialTraitRef<'tcx>>) {
8787
}
8888
}
8989

90-
impl<'tcx> Key for mir::interpret::LitToConstInput<'tcx> {
90+
impl<'tcx> Key for ty::LitToConstInput<'tcx> {
9191
fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
9292
DUMMY_SP
9393
}

compiler/rustc_middle/src/ty/consts.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,12 @@ use crate::ty::{self, Ty, TyCtxt};
1111

1212
mod int;
1313
mod kind;
14+
mod lit;
1415
mod valtree;
1516

1617
pub use int::*;
1718
pub use kind::*;
19+
pub use lit::*;
1820
use rustc_span::{DUMMY_SP, ErrorGuaranteed};
1921
pub use valtree::*;
2022

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
use rustc_ast::LitKind;
2+
use rustc_hir;
3+
use rustc_macros::HashStable;
4+
5+
use crate::ty::{self, Ty, TyCtxt};
6+
7+
/// Input argument for `tcx.lit_to_const`.
8+
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, HashStable)]
9+
pub struct LitToConstInput<'tcx> {
10+
/// The absolute value of the resultant constant.
11+
pub lit: LitKind,
12+
/// The type of the constant.
13+
pub ty: Ty<'tcx>,
14+
/// If the constant is negative.
15+
pub neg: bool,
16+
}
17+
18+
/// Checks whether a literal can be interpreted as a const of the given type.
19+
pub fn const_lit_matches_ty<'tcx>(
20+
tcx: TyCtxt<'tcx>,
21+
kind: &LitKind,
22+
ty: Ty<'tcx>,
23+
neg: bool,
24+
) -> bool {
25+
match (*kind, ty.kind()) {
26+
(LitKind::Str(..), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => true,
27+
(LitKind::Str(..), ty::Str) if tcx.features().deref_patterns() => true,
28+
(LitKind::ByteStr(..), ty::Ref(_, inner_ty, _))
29+
if let ty::Slice(ty) | ty::Array(ty, _) = inner_ty.kind()
30+
&& matches!(ty.kind(), ty::Uint(ty::UintTy::U8)) =>
31+
{
32+
true
33+
}
34+
(LitKind::ByteStr(..), ty::Slice(inner_ty) | ty::Array(inner_ty, _))
35+
if tcx.features().deref_patterns()
36+
&& matches!(inner_ty.kind(), ty::Uint(ty::UintTy::U8)) =>
37+
{
38+
true
39+
}
40+
(LitKind::Byte(..), ty::Uint(ty::UintTy::U8)) => true,
41+
(LitKind::CStr(..), ty::Ref(_, inner_ty, _))
42+
if matches!(inner_ty.kind(), ty::Adt(def, _)
43+
if tcx.is_lang_item(def.did(), rustc_hir::LangItem::CStr)) =>
44+
{
45+
true
46+
}
47+
(LitKind::Int(..), ty::Uint(_)) if !neg => true,
48+
(LitKind::Int(..), ty::Int(_)) => true,
49+
(LitKind::Bool(..), ty::Bool) => true,
50+
(LitKind::Float(..), ty::Float(_)) => true,
51+
(LitKind::Char(..), ty::Char) => true,
52+
(LitKind::Err(..), _) => true,
53+
_ => false,
54+
}
55+
}

compiler/rustc_middle/src/ty/mod.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,9 @@ pub use self::closure::{
7676
place_to_string_for_capture,
7777
};
7878
pub use self::consts::{
79-
AtomicOrdering, Const, ConstInt, ConstKind, ConstToValTreeResult, Expr, ExprKind, ScalarInt,
80-
SimdAlign, UnevaluatedConst, ValTree, ValTreeKindExt, Value,
79+
AtomicOrdering, Const, ConstInt, ConstKind, ConstToValTreeResult, Expr, ExprKind,
80+
LitToConstInput, ScalarInt, SimdAlign, UnevaluatedConst, ValTree, ValTreeKindExt, Value,
81+
const_lit_matches_ty,
8182
};
8283
pub use self::context::{
8384
CtxtInterners, CurrentGcx, Feed, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, TyCtxtFeed, tls,

compiler/rustc_mir_build/src/builder/expr/as_constant.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
//! See docs in build/expr/mod.rs
1+
//! See docs in builder/expr/mod.rs
22
33
use rustc_abi::Size;
44
use rustc_ast::{self as ast};
55
use rustc_hir::LangItem;
6-
use rustc_middle::mir::interpret::{CTFE_ALLOC_SALT, LitToConstInput, Scalar};
6+
use rustc_middle::mir::interpret::{CTFE_ALLOC_SALT, Scalar};
77
use rustc_middle::mir::*;
88
use rustc_middle::thir::*;
99
use rustc_middle::ty::{
10-
self, CanonicalUserType, CanonicalUserTypeAnnotation, Ty, TyCtxt, TypeVisitableExt as _,
11-
UserTypeAnnotationIndex,
10+
self, CanonicalUserType, CanonicalUserTypeAnnotation, LitToConstInput, Ty, TyCtxt,
11+
TypeVisitableExt as _, UserTypeAnnotationIndex,
1212
};
1313
use rustc_middle::{bug, mir, span_bug};
1414
use tracing::{instrument, trace};

compiler/rustc_mir_build/src/thir/constant.rs

Lines changed: 55 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,19 @@ use rustc_abi::Size;
22
use rustc_ast::{self as ast, UintTy};
33
use rustc_hir::LangItem;
44
use rustc_middle::bug;
5-
use rustc_middle::mir::interpret::LitToConstInput;
6-
use rustc_middle::ty::{self, ScalarInt, TyCtxt, TypeVisitableExt as _};
5+
use rustc_middle::ty::{self, LitToConstInput, ScalarInt, Ty, TyCtxt, TypeVisitableExt as _};
76
use tracing::trace;
87

98
use crate::builder::parse_float_into_scalar;
109

1110
pub(crate) fn lit_to_const<'tcx>(
1211
tcx: TyCtxt<'tcx>,
1312
lit_input: LitToConstInput<'tcx>,
14-
) -> ty::Const<'tcx> {
15-
let LitToConstInput { lit, ty, neg } = lit_input;
13+
) -> Option<ty::Value<'tcx>> {
14+
let LitToConstInput { lit, ty: expected_ty, neg } = lit_input;
1615

17-
if let Err(guar) = ty.error_reported() {
18-
return ty::Const::new_error(tcx, guar);
16+
if expected_ty.error_reported().is_err() {
17+
return None;
1918
}
2019

2120
let trunc = |n, width: ty::UintTy| {
@@ -32,63 +31,84 @@ pub(crate) fn lit_to_const<'tcx>(
3231
.unwrap_or_else(|| bug!("expected to create ScalarInt from uint {:?}", result))
3332
};
3433

35-
let valtree = match (lit, ty.kind()) {
36-
(ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => {
34+
let (valtree, valtree_ty) = match (lit, expected_ty.kind()) {
35+
(ast::LitKind::Str(s, _), _) => {
3736
let str_bytes = s.as_str().as_bytes();
38-
ty::ValTree::from_raw_bytes(tcx, str_bytes)
39-
}
40-
(ast::LitKind::Str(s, _), ty::Str) if tcx.features().deref_patterns() => {
41-
// String literal patterns may have type `str` if `deref_patterns` is enabled, in order
42-
// to allow `deref!("..."): String`.
43-
let str_bytes = s.as_str().as_bytes();
44-
ty::ValTree::from_raw_bytes(tcx, str_bytes)
37+
let valtree_ty = Ty::new_imm_ref(tcx, tcx.lifetimes.re_static, tcx.types.str_);
38+
(ty::ValTree::from_raw_bytes(tcx, str_bytes), valtree_ty)
4539
}
4640
(ast::LitKind::ByteStr(byte_sym, _), ty::Ref(_, inner_ty, _))
4741
if let ty::Slice(ty) | ty::Array(ty, _) = inner_ty.kind()
4842
&& let ty::Uint(UintTy::U8) = ty.kind() =>
4943
{
50-
ty::ValTree::from_raw_bytes(tcx, byte_sym.as_byte_str())
44+
(ty::ValTree::from_raw_bytes(tcx, byte_sym.as_byte_str()), expected_ty)
5145
}
5246
(ast::LitKind::ByteStr(byte_sym, _), ty::Slice(inner_ty) | ty::Array(inner_ty, _))
5347
if tcx.features().deref_patterns()
5448
&& let ty::Uint(UintTy::U8) = inner_ty.kind() =>
5549
{
5650
// Byte string literal patterns may have type `[u8]` or `[u8; N]` if `deref_patterns` is
5751
// enabled, in order to allow, e.g., `deref!(b"..."): Vec<u8>`.
58-
ty::ValTree::from_raw_bytes(tcx, byte_sym.as_byte_str())
52+
(ty::ValTree::from_raw_bytes(tcx, byte_sym.as_byte_str()), expected_ty)
5953
}
60-
(ast::LitKind::Byte(n), ty::Uint(ty::UintTy::U8)) => {
61-
ty::ValTree::from_scalar_int(tcx, n.into())
54+
(ast::LitKind::ByteStr(byte_sym, _), _) => {
55+
let valtree = ty::ValTree::from_raw_bytes(tcx, byte_sym.as_byte_str());
56+
let valtree_ty = Ty::new_array(tcx, tcx.types.u8, byte_sym.as_byte_str().len() as u64);
57+
(valtree, valtree_ty)
6258
}
63-
(ast::LitKind::CStr(byte_sym, _), ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Adt(def, _) if tcx.is_lang_item(def.did(), LangItem::CStr)) =>
59+
(ast::LitKind::Byte(n), _) => (ty::ValTree::from_scalar_int(tcx, n.into()), tcx.types.u8),
60+
(ast::LitKind::CStr(byte_sym, _), _)
61+
if let Some(cstr_def_id) = tcx.lang_items().get(LangItem::CStr) =>
6462
{
6563
// A CStr is a newtype around a byte slice, so we create the inner slice here.
6664
// We need a branch for each "level" of the data structure.
65+
let cstr_ty = tcx.type_of(cstr_def_id).skip_binder();
6766
let bytes = ty::ValTree::from_raw_bytes(tcx, byte_sym.as_byte_str());
68-
ty::ValTree::from_branches(tcx, [ty::Const::new_value(tcx, bytes, *inner_ty)])
67+
let valtree =
68+
ty::ValTree::from_branches(tcx, [ty::Const::new_value(tcx, bytes, cstr_ty)]);
69+
let valtree_ty = Ty::new_imm_ref(tcx, tcx.lifetimes.re_static, cstr_ty);
70+
(valtree, valtree_ty)
6971
}
70-
(ast::LitKind::Int(n, _), ty::Uint(ui)) if !neg => {
72+
(ast::LitKind::Int(n, ast::LitIntType::Unsigned(ui)), _) if !neg => {
73+
let scalar_int = trunc(n.get(), ui);
74+
(ty::ValTree::from_scalar_int(tcx, scalar_int), Ty::new_uint(tcx, ui))
75+
}
76+
(ast::LitKind::Int(_, ast::LitIntType::Unsigned(_)), _) if neg => return None,
77+
(ast::LitKind::Int(n, ast::LitIntType::Signed(i)), _) => {
78+
let scalar_int =
79+
trunc(if neg { u128::wrapping_neg(n.get()) } else { n.get() }, i.to_unsigned());
80+
(ty::ValTree::from_scalar_int(tcx, scalar_int), Ty::new_int(tcx, i))
81+
}
82+
(ast::LitKind::Int(n, ast::LitIntType::Unsuffixed), ty::Uint(ui)) if !neg => {
7183
let scalar_int = trunc(n.get(), *ui);
72-
ty::ValTree::from_scalar_int(tcx, scalar_int)
84+
(ty::ValTree::from_scalar_int(tcx, scalar_int), Ty::new_uint(tcx, *ui))
7385
}
74-
(ast::LitKind::Int(n, _), ty::Int(i)) => {
86+
(ast::LitKind::Int(n, ast::LitIntType::Unsuffixed), ty::Int(i)) => {
7587
// Unsigned "negation" has the same bitwise effect as signed negation,
7688
// which gets the result we want without additional casts.
7789
let scalar_int =
7890
trunc(if neg { u128::wrapping_neg(n.get()) } else { n.get() }, i.to_unsigned());
79-
ty::ValTree::from_scalar_int(tcx, scalar_int)
91+
(ty::ValTree::from_scalar_int(tcx, scalar_int), Ty::new_int(tcx, *i))
92+
}
93+
(ast::LitKind::Bool(b), _) => (ty::ValTree::from_scalar_int(tcx, b.into()), tcx.types.bool),
94+
(ast::LitKind::Float(n, ast::LitFloatType::Suffixed(fty)), _) => {
95+
let fty = match fty {
96+
ast::FloatTy::F16 => ty::FloatTy::F16,
97+
ast::FloatTy::F32 => ty::FloatTy::F32,
98+
ast::FloatTy::F64 => ty::FloatTy::F64,
99+
ast::FloatTy::F128 => ty::FloatTy::F128,
100+
};
101+
let bits = parse_float_into_scalar(n, fty, neg)?;
102+
(ty::ValTree::from_scalar_int(tcx, bits), Ty::new_float(tcx, fty))
80103
}
81-
(ast::LitKind::Bool(b), ty::Bool) => ty::ValTree::from_scalar_int(tcx, b.into()),
82-
(ast::LitKind::Float(n, _), ty::Float(fty)) => {
83-
let bits = parse_float_into_scalar(n, *fty, neg).unwrap_or_else(|| {
84-
tcx.dcx().bug(format!("couldn't parse float literal: {:?}", lit_input.lit))
85-
});
86-
ty::ValTree::from_scalar_int(tcx, bits)
104+
(ast::LitKind::Float(n, ast::LitFloatType::Unsuffixed), ty::Float(fty)) => {
105+
let bits = parse_float_into_scalar(n, *fty, neg)?;
106+
(ty::ValTree::from_scalar_int(tcx, bits), Ty::new_float(tcx, *fty))
87107
}
88-
(ast::LitKind::Char(c), ty::Char) => ty::ValTree::from_scalar_int(tcx, c.into()),
89-
(ast::LitKind::Err(guar), _) => return ty::Const::new_error(tcx, guar),
90-
_ => return ty::Const::new_misc_error(tcx),
108+
(ast::LitKind::Char(c), _) => (ty::ValTree::from_scalar_int(tcx, c.into()), tcx.types.char),
109+
(ast::LitKind::Err(_), _) => return None,
110+
_ => return None,
91111
};
92112

93-
ty::Const::new_value(tcx, valtree, ty)
113+
Some(ty::Value { ty: valtree_ty, valtree })
94114
}

0 commit comments

Comments
 (0)