-
Notifications
You must be signed in to change notification settings - Fork 12.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Split out lit_to_const_for_patterns
#116251
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,6 +8,66 @@ use crate::build::parse_float_into_scalar; | |
pub(crate) fn lit_to_const<'tcx>( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. naming: we could call this |
||
tcx: TyCtxt<'tcx>, | ||
lit_input: LitToConstInput<'tcx>, | ||
) -> Option<ty::Const<'tcx>> { | ||
let LitToConstInput { lit, ty, neg } = lit_input; | ||
|
||
let valtree = match (lit, &ty.kind()) { | ||
(ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this function could ignore the types in the litkinds that don't actually matter? |
||
let str_bytes = s.as_str().as_bytes(); | ||
ty::ValTree::from_raw_bytes(tcx, str_bytes) | ||
} | ||
(ast::LitKind::ByteStr(data, _), ty::Ref(_, inner_ty, _)) | ||
if matches!(inner_ty.kind(), ty::Slice(_)) => | ||
{ | ||
let bytes = data as &[u8]; | ||
ty::ValTree::from_raw_bytes(tcx, bytes) | ||
} | ||
(ast::LitKind::ByteStr(data, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => { | ||
let bytes = data as &[u8]; | ||
ty::ValTree::from_raw_bytes(tcx, bytes) | ||
} | ||
(ast::LitKind::Byte(n), ty::Uint(ty::UintTy::U8)) => { | ||
ty::ValTree::from_scalar_int((*n).into()) | ||
} | ||
(ast::LitKind::CStr(data, _), ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Adt(def, _) if Some(def.did()) == tcx.lang_items().c_str()) => | ||
{ | ||
let bytes = data as &[u8]; | ||
ty::ValTree::from_raw_bytes(tcx, bytes) | ||
} | ||
(ast::LitKind::Int(n, _), ty::Uint(_)) | (ast::LitKind::Int(n, _), ty::Int(_)) => { | ||
let n = if neg { (*n as i128).overflowing_neg().0 as u128 } else { *n }; | ||
let param_ty = ParamEnv::reveal_all().and(ty); | ||
let width = tcx | ||
.layout_of(param_ty) | ||
.unwrap_or_else(|_| bug!("should always be able to compute the layout of a scalar")) | ||
.size; | ||
trace!("trunc {} with size {} and shift {}", n, width.bits(), 128 - width.bits()); | ||
let result = width.truncate(n); | ||
trace!("trunc result: {}", result); | ||
|
||
let scalar_int = ScalarInt::try_from_uint(result, width) | ||
.unwrap_or_else(|| bug!("expected to create ScalarInt from uint {:?}", result)); | ||
|
||
ty::ValTree::from_scalar_int(scalar_int) | ||
} | ||
(ast::LitKind::Bool(b), ty::Bool) => ty::ValTree::from_scalar_int((*b).into()), | ||
(ast::LitKind::Char(c), ty::Char) => ty::ValTree::from_scalar_int((*c).into()), | ||
// If there's a type mismatch, it may be a legitimate type mismatch, or | ||
// it might be an unnormalized type. Return `None`, which falls back | ||
// to an unevaluated const, and the error will be caught (or we will see | ||
// that it's ok) elsewhere. | ||
_ => return None, | ||
}; | ||
|
||
Some(ty::Const::new_value(tcx, valtree, ty)) | ||
} | ||
|
||
/// The old "lit_to_const", which assumes that the type passed in `lit_input` | ||
/// is normalized, and will error out if that is not true. This should only | ||
/// be used in pattern building code (and ideally we'd get rid of this altogether). | ||
pub(crate) fn lit_to_const_for_patterns<'tcx>( | ||
tcx: TyCtxt<'tcx>, | ||
lit_input: LitToConstInput<'tcx>, | ||
) -> Result<ty::Const<'tcx>, LitToConstError> { | ||
let LitToConstInput { lit, ty, neg } = lit_input; | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -117,7 +117,11 @@ fn recurse_build<'tcx>( | |
} | ||
&ExprKind::Literal { lit, neg } => { | ||
let sp = node.span; | ||
match tcx.at(sp).lit_to_const(LitToConstInput { lit: &lit.node, ty: node.ty, neg }) { | ||
match tcx.at(sp).lit_to_const_for_patterns(LitToConstInput { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is definitely not a pattern xd we'd end up here for things like the |
||
lit: &lit.node, | ||
ty: node.ty, | ||
neg, | ||
}) { | ||
Ok(c) => c, | ||
Err(LitToConstError::Reported(guar)) => ty::Const::new_error(tcx, guar, node.ty), | ||
Err(LitToConstError::TypeError) => { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
// This is currently not possible to use projections as const generics. | ||
// More information about this available here: | ||
// https://github.com/rust-lang/rust/pull/104443#discussion_r1029375633 | ||
// build-pass | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. imo this should be a revision, we want to keep asserting that aliases dont work as the type of const params without adt_const_param i think |
||
#![feature(adt_const_params)] | ||
//~^ WARN the feature `adt_const_params` is incomplete | ||
|
||
pub trait Identity { | ||
type Identity; | ||
|
@@ -11,7 +12,6 @@ impl<T> Identity for T { | |
} | ||
|
||
pub fn foo<const X: <i32 as Identity>::Identity>() { | ||
//~^ ERROR | ||
assert!(X == 12); | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,11 @@ | ||
error: `<i32 as Identity>::Identity` is forbidden as the type of a const generic parameter | ||
--> $DIR/projection-as-arg-const.rs:13:21 | ||
warning: the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes | ||
--> $DIR/projection-as-arg-const.rs:3:12 | ||
| | ||
LL | pub fn foo<const X: <i32 as Identity>::Identity>() { | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
LL | #![feature(adt_const_params)] | ||
| ^^^^^^^^^^^^^^^^ | ||
| | ||
= note: the only supported types are integers, `bool` and `char` | ||
= help: more complex types are supported with `#![feature(adt_const_params)]` | ||
= note: see issue #95174 <https://github.com/rust-lang/rust/issues/95174> for more information | ||
= note: `#[warn(incomplete_features)]` on by default | ||
|
||
error: aborting due to previous error | ||
warning: 1 warning emitted | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this query could alternatively just return an (option of) valtree to make it clear what it's doing