Rollup merge of #64858 - skinny121:str-const-generics, r=varkor
Add support for relating slices in `super_relate_consts` This allows passing strings as generic arguments. Fixes #63773 Fixes #60813 r? @varkor
This commit is contained in:
commit
4ada68e325
@ -101,7 +101,7 @@ pub use self::error::{
|
||||
InvalidProgramInfo, ResourceExhaustionInfo, UndefinedBehaviorInfo,
|
||||
};
|
||||
|
||||
pub use self::value::{Scalar, ScalarMaybeUndef, RawConst, ConstValue};
|
||||
pub use self::value::{Scalar, ScalarMaybeUndef, RawConst, ConstValue, get_slice_bytes};
|
||||
|
||||
pub use self::allocation::{Allocation, AllocationExtra, Relocations, UndefMask};
|
||||
|
||||
|
@ -611,3 +611,18 @@ impl_stable_hash_for!(enum crate::mir::interpret::ScalarMaybeUndef {
|
||||
Scalar(v),
|
||||
Undef
|
||||
});
|
||||
|
||||
/// Gets the bytes of a constant slice value.
|
||||
pub fn get_slice_bytes<'tcx>(cx: &impl HasDataLayout, val: ConstValue<'tcx>) -> &'tcx [u8] {
|
||||
if let ConstValue::Slice { data, start, end } = val {
|
||||
let len = end - start;
|
||||
data.get_bytes(
|
||||
cx,
|
||||
// invent a pointer, only the offset is relevant anyway
|
||||
Pointer::new(AllocId(0), Size::from_bytes(start as u64)),
|
||||
Size::from_bytes(len as u64),
|
||||
).unwrap_or_else(|err| bug!("const slice is invalid: {:?}", err))
|
||||
} else {
|
||||
bug!("expected const slice, but found another const value");
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ use crate::hir::def_id::DefId;
|
||||
use crate::ty::subst::{GenericArg, GenericArgKind, SubstsRef};
|
||||
use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
|
||||
use crate::ty::error::{ExpectedFound, TypeError};
|
||||
use crate::mir::interpret::{ConstValue, Scalar};
|
||||
use crate::mir::interpret::{ConstValue, get_slice_bytes, Scalar};
|
||||
use std::rc::Rc;
|
||||
use std::iter;
|
||||
use rustc_target::spec::abi;
|
||||
@ -584,7 +584,20 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
|
||||
// FIXME(const_generics): we should either handle `Scalar::Ptr` or add a comment
|
||||
// saying that we're not handling it intentionally.
|
||||
|
||||
// FIXME(const_generics): handle `ConstValue::ByRef` and `ConstValue::Slice`.
|
||||
(a_val @ ConstValue::Slice { .. }, b_val @ ConstValue::Slice { .. }) => {
|
||||
let a_bytes = get_slice_bytes(&tcx, a_val);
|
||||
let b_bytes = get_slice_bytes(&tcx, b_val);
|
||||
if a_bytes == b_bytes {
|
||||
Ok(tcx.mk_const(ty::Const {
|
||||
val: a_val,
|
||||
ty: a.ty,
|
||||
}))
|
||||
} else {
|
||||
Err(TypeError::ConstMismatch(expected_found(relation, &a, &b)))
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(const_generics): handle `ConstValue::ByRef`.
|
||||
|
||||
// FIXME(const_generics): this is wrong, as it is a projection
|
||||
(ConstValue::Unevaluated(a_def_id, a_substs),
|
||||
|
@ -13,12 +13,12 @@ use crate::hair::constant::*;
|
||||
use rustc::lint;
|
||||
use rustc::mir::{Field, BorrowKind, Mutability};
|
||||
use rustc::mir::{UserTypeProjection};
|
||||
use rustc::mir::interpret::{GlobalId, ConstValue, sign_extend, AllocId, Pointer};
|
||||
use rustc::mir::interpret::{GlobalId, ConstValue, get_slice_bytes, sign_extend};
|
||||
use rustc::traits::{ObligationCause, PredicateObligation};
|
||||
use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty, UserType, DefIdTree};
|
||||
use rustc::ty::{CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations};
|
||||
use rustc::ty::subst::{SubstsRef, GenericArg};
|
||||
use rustc::ty::layout::{VariantIdx, Size};
|
||||
use rustc::ty::layout::VariantIdx;
|
||||
use rustc::hir::{self, RangeEnd};
|
||||
use rustc::hir::def::{CtorOf, Res, DefKind, CtorKind};
|
||||
use rustc::hir::pat_util::EnumerateAndAdjustIterator;
|
||||
@ -1526,27 +1526,10 @@ pub fn compare_const_vals<'tcx>(
|
||||
|
||||
if let ty::Str = ty.kind {
|
||||
match (a.val, b.val) {
|
||||
(
|
||||
ConstValue::Slice { data: alloc_a, start: offset_a, end: end_a },
|
||||
ConstValue::Slice { data: alloc_b, start: offset_b, end: end_b },
|
||||
) => {
|
||||
let len_a = end_a - offset_a;
|
||||
let len_b = end_b - offset_b;
|
||||
let a = alloc_a.get_bytes(
|
||||
&tcx,
|
||||
// invent a pointer, only the offset is relevant anyway
|
||||
Pointer::new(AllocId(0), Size::from_bytes(offset_a as u64)),
|
||||
Size::from_bytes(len_a as u64),
|
||||
);
|
||||
let b = alloc_b.get_bytes(
|
||||
&tcx,
|
||||
// invent a pointer, only the offset is relevant anyway
|
||||
Pointer::new(AllocId(0), Size::from_bytes(offset_b as u64)),
|
||||
Size::from_bytes(len_b as u64),
|
||||
);
|
||||
if let (Ok(a), Ok(b)) = (a, b) {
|
||||
return from_bool(a == b);
|
||||
}
|
||||
(ConstValue::Slice { .. }, ConstValue::Slice { .. }) => {
|
||||
let a_bytes = get_slice_bytes(&tcx, a.val);
|
||||
let b_bytes = get_slice_bytes(&tcx, b.val);
|
||||
return from_bool(a_bytes == b_bytes);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
14
src/test/ui/const-generics/slice-const-param-mismatch.rs
Normal file
14
src/test/ui/const-generics/slice-const-param-mismatch.rs
Normal file
@ -0,0 +1,14 @@
|
||||
#![feature(const_generics)]
|
||||
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
|
||||
|
||||
struct ConstString<const T: &'static str>;
|
||||
struct ConstBytes<const T: &'static [u8]>;
|
||||
|
||||
pub fn main() {
|
||||
let _: ConstString<"Hello"> = ConstString::<"Hello">;
|
||||
let _: ConstString<"Hello"> = ConstString::<"World">; //~ ERROR mismatched types
|
||||
let _: ConstString<"ℇ㇈↦"> = ConstString::<"ℇ㇈↦">;
|
||||
let _: ConstString<"ℇ㇈↦"> = ConstString::<"ℇ㇈↥">; //~ ERROR mismatched types
|
||||
let _: ConstBytes<b"AAA"> = ConstBytes::<{&[0x41, 0x41, 0x41]}>;
|
||||
let _: ConstBytes<b"AAA"> = ConstBytes::<b"BBB">; //~ ERROR mismatched types
|
||||
}
|
38
src/test/ui/const-generics/slice-const-param-mismatch.stderr
Normal file
38
src/test/ui/const-generics/slice-const-param-mismatch.stderr
Normal file
@ -0,0 +1,38 @@
|
||||
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
|
||||
--> $DIR/slice-const-param-mismatch.rs:1:12
|
||||
|
|
||||
LL | #![feature(const_generics)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/slice-const-param-mismatch.rs:9:35
|
||||
|
|
||||
LL | let _: ConstString<"Hello"> = ConstString::<"World">;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ expected `"Hello"`, found `"World"`
|
||||
|
|
||||
= note: expected type `ConstString<>`
|
||||
found type `ConstString<>`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/slice-const-param-mismatch.rs:11:33
|
||||
|
|
||||
LL | let _: ConstString<"ℇ㇈↦"> = ConstString::<"ℇ㇈↥">;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ expected `"ℇ㇈↦"`, found `"ℇ㇈↥"`
|
||||
|
|
||||
= note: expected type `ConstString<>`
|
||||
found type `ConstString<>`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/slice-const-param-mismatch.rs:13:33
|
||||
|
|
||||
LL | let _: ConstBytes<b"AAA"> = ConstBytes::<b"BBB">;
|
||||
| ^^^^^^^^^^^^^^^^^^^^ expected `b"AAA"`, found `b"BBB"`
|
||||
|
|
||||
= note: expected type `ConstBytes<>`
|
||||
found type `ConstBytes<>`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
19
src/test/ui/const-generics/slice-const-param.rs
Normal file
19
src/test/ui/const-generics/slice-const-param.rs
Normal file
@ -0,0 +1,19 @@
|
||||
// run-pass
|
||||
|
||||
#![feature(const_generics)]
|
||||
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
|
||||
|
||||
pub fn function_with_str<const STRING: &'static str>() -> &'static str {
|
||||
STRING
|
||||
}
|
||||
|
||||
pub fn function_with_bytes<const BYTES: &'static [u8]>() -> &'static [u8] {
|
||||
BYTES
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
assert_eq!(function_with_str::<"Rust">(), "Rust");
|
||||
assert_eq!(function_with_str::<"ℇ㇈↦">(), "ℇ㇈↦");
|
||||
assert_eq!(function_with_bytes::<b"AAAA">(), &[0x41, 0x41, 0x41, 0x41]);
|
||||
assert_eq!(function_with_bytes::<{&[0x41, 0x41, 0x41, 0x41]}>(), b"AAAA");
|
||||
}
|
8
src/test/ui/const-generics/slice-const-param.stderr
Normal file
8
src/test/ui/const-generics/slice-const-param.stderr
Normal file
@ -0,0 +1,8 @@
|
||||
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
|
||||
--> $DIR/slice-const-param.rs:3:12
|
||||
|
|
||||
LL | #![feature(const_generics)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
Loading…
Reference in New Issue
Block a user