Skip to content

Commit f1a3ceb

Browse files
authored
Rollup merge of rust-lang#64858 - skinny121:str-const-generics, r=varkor
Add support for relating slices in `super_relate_consts` This allows passing strings as generic arguments. Fixes rust-lang#63773 Fixes rust-lang#60813 r? @varkor
2 parents 8c3fd1c + 54bad93 commit f1a3ceb

File tree

8 files changed

+116
-26
lines changed

8 files changed

+116
-26
lines changed

src/librustc/mir/interpret/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ pub use self::error::{
101101
InvalidProgramInfo, ResourceExhaustionInfo, UndefinedBehaviorInfo,
102102
};
103103

104-
pub use self::value::{Scalar, ScalarMaybeUndef, RawConst, ConstValue};
104+
pub use self::value::{Scalar, ScalarMaybeUndef, RawConst, ConstValue, get_slice_bytes};
105105

106106
pub use self::allocation::{Allocation, AllocationExtra, Relocations, UndefMask};
107107

src/librustc/mir/interpret/value.rs

+15
Original file line numberDiff line numberDiff line change
@@ -611,3 +611,18 @@ impl_stable_hash_for!(enum crate::mir::interpret::ScalarMaybeUndef {
611611
Scalar(v),
612612
Undef
613613
});
614+
615+
/// Gets the bytes of a constant slice value.
616+
pub fn get_slice_bytes<'tcx>(cx: &impl HasDataLayout, val: ConstValue<'tcx>) -> &'tcx [u8] {
617+
if let ConstValue::Slice { data, start, end } = val {
618+
let len = end - start;
619+
data.get_bytes(
620+
cx,
621+
// invent a pointer, only the offset is relevant anyway
622+
Pointer::new(AllocId(0), Size::from_bytes(start as u64)),
623+
Size::from_bytes(len as u64),
624+
).unwrap_or_else(|err| bug!("const slice is invalid: {:?}", err))
625+
} else {
626+
bug!("expected const slice, but found another const value");
627+
}
628+
}

src/librustc/ty/relate.rs

+15-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use crate::hir::def_id::DefId;
88
use crate::ty::subst::{GenericArg, GenericArgKind, SubstsRef};
99
use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
1010
use crate::ty::error::{ExpectedFound, TypeError};
11-
use crate::mir::interpret::{ConstValue, Scalar};
11+
use crate::mir::interpret::{ConstValue, get_slice_bytes, Scalar};
1212
use std::rc::Rc;
1313
use std::iter;
1414
use rustc_target::spec::abi;
@@ -584,7 +584,20 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
584584
// FIXME(const_generics): we should either handle `Scalar::Ptr` or add a comment
585585
// saying that we're not handling it intentionally.
586586

587-
// FIXME(const_generics): handle `ConstValue::ByRef` and `ConstValue::Slice`.
587+
(a_val @ ConstValue::Slice { .. }, b_val @ ConstValue::Slice { .. }) => {
588+
let a_bytes = get_slice_bytes(&tcx, a_val);
589+
let b_bytes = get_slice_bytes(&tcx, b_val);
590+
if a_bytes == b_bytes {
591+
Ok(tcx.mk_const(ty::Const {
592+
val: a_val,
593+
ty: a.ty,
594+
}))
595+
} else {
596+
Err(TypeError::ConstMismatch(expected_found(relation, &a, &b)))
597+
}
598+
}
599+
600+
// FIXME(const_generics): handle `ConstValue::ByRef`.
588601

589602
// FIXME(const_generics): this is wrong, as it is a projection
590603
(ConstValue::Unevaluated(a_def_id, a_substs),

src/librustc_mir/hair/pattern/mod.rs

+6-23
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@ use crate::hair::constant::*;
1313
use rustc::lint;
1414
use rustc::mir::{Field, BorrowKind, Mutability};
1515
use rustc::mir::{UserTypeProjection};
16-
use rustc::mir::interpret::{GlobalId, ConstValue, sign_extend, AllocId, Pointer};
16+
use rustc::mir::interpret::{GlobalId, ConstValue, get_slice_bytes, sign_extend};
1717
use rustc::traits::{ObligationCause, PredicateObligation};
1818
use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty, UserType, DefIdTree};
1919
use rustc::ty::{CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations};
2020
use rustc::ty::subst::{SubstsRef, GenericArg};
21-
use rustc::ty::layout::{VariantIdx, Size};
21+
use rustc::ty::layout::VariantIdx;
2222
use rustc::hir::{self, RangeEnd};
2323
use rustc::hir::def::{CtorOf, Res, DefKind, CtorKind};
2424
use rustc::hir::pat_util::EnumerateAndAdjustIterator;
@@ -1526,27 +1526,10 @@ pub fn compare_const_vals<'tcx>(
15261526

15271527
if let ty::Str = ty.kind {
15281528
match (a.val, b.val) {
1529-
(
1530-
ConstValue::Slice { data: alloc_a, start: offset_a, end: end_a },
1531-
ConstValue::Slice { data: alloc_b, start: offset_b, end: end_b },
1532-
) => {
1533-
let len_a = end_a - offset_a;
1534-
let len_b = end_b - offset_b;
1535-
let a = alloc_a.get_bytes(
1536-
&tcx,
1537-
// invent a pointer, only the offset is relevant anyway
1538-
Pointer::new(AllocId(0), Size::from_bytes(offset_a as u64)),
1539-
Size::from_bytes(len_a as u64),
1540-
);
1541-
let b = alloc_b.get_bytes(
1542-
&tcx,
1543-
// invent a pointer, only the offset is relevant anyway
1544-
Pointer::new(AllocId(0), Size::from_bytes(offset_b as u64)),
1545-
Size::from_bytes(len_b as u64),
1546-
);
1547-
if let (Ok(a), Ok(b)) = (a, b) {
1548-
return from_bool(a == b);
1549-
}
1529+
(ConstValue::Slice { .. }, ConstValue::Slice { .. }) => {
1530+
let a_bytes = get_slice_bytes(&tcx, a.val);
1531+
let b_bytes = get_slice_bytes(&tcx, b.val);
1532+
return from_bool(a_bytes == b_bytes);
15501533
}
15511534
_ => (),
15521535
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#![feature(const_generics)]
2+
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
3+
4+
struct ConstString<const T: &'static str>;
5+
struct ConstBytes<const T: &'static [u8]>;
6+
7+
pub fn main() {
8+
let _: ConstString<"Hello"> = ConstString::<"Hello">;
9+
let _: ConstString<"Hello"> = ConstString::<"World">; //~ ERROR mismatched types
10+
let _: ConstString<"ℇ㇈↦"> = ConstString::<"ℇ㇈↦">;
11+
let _: ConstString<"ℇ㇈↦"> = ConstString::<"ℇ㇈↥">; //~ ERROR mismatched types
12+
let _: ConstBytes<b"AAA"> = ConstBytes::<{&[0x41, 0x41, 0x41]}>;
13+
let _: ConstBytes<b"AAA"> = ConstBytes::<b"BBB">; //~ ERROR mismatched types
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
2+
--> $DIR/slice-const-param-mismatch.rs:1:12
3+
|
4+
LL | #![feature(const_generics)]
5+
| ^^^^^^^^^^^^^^
6+
|
7+
= note: `#[warn(incomplete_features)]` on by default
8+
9+
error[E0308]: mismatched types
10+
--> $DIR/slice-const-param-mismatch.rs:9:35
11+
|
12+
LL | let _: ConstString<"Hello"> = ConstString::<"World">;
13+
| ^^^^^^^^^^^^^^^^^^^^^^ expected `"Hello"`, found `"World"`
14+
|
15+
= note: expected type `ConstString<>`
16+
found type `ConstString<>`
17+
18+
error[E0308]: mismatched types
19+
--> $DIR/slice-const-param-mismatch.rs:11:33
20+
|
21+
LL | let _: ConstString<"ℇ㇈↦"> = ConstString::<"ℇ㇈↥">;
22+
| ^^^^^^^^^^^^^^^^^^^^^ expected `"ℇ㇈↦"`, found `"ℇ㇈↥"`
23+
|
24+
= note: expected type `ConstString<>`
25+
found type `ConstString<>`
26+
27+
error[E0308]: mismatched types
28+
--> $DIR/slice-const-param-mismatch.rs:13:33
29+
|
30+
LL | let _: ConstBytes<b"AAA"> = ConstBytes::<b"BBB">;
31+
| ^^^^^^^^^^^^^^^^^^^^ expected `b"AAA"`, found `b"BBB"`
32+
|
33+
= note: expected type `ConstBytes<>`
34+
found type `ConstBytes<>`
35+
36+
error: aborting due to 3 previous errors
37+
38+
For more information about this error, try `rustc --explain E0308`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// run-pass
2+
3+
#![feature(const_generics)]
4+
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
5+
6+
pub fn function_with_str<const STRING: &'static str>() -> &'static str {
7+
STRING
8+
}
9+
10+
pub fn function_with_bytes<const BYTES: &'static [u8]>() -> &'static [u8] {
11+
BYTES
12+
}
13+
14+
pub fn main() {
15+
assert_eq!(function_with_str::<"Rust">(), "Rust");
16+
assert_eq!(function_with_str::<"ℇ㇈↦">(), "ℇ㇈↦");
17+
assert_eq!(function_with_bytes::<b"AAAA">(), &[0x41, 0x41, 0x41, 0x41]);
18+
assert_eq!(function_with_bytes::<{&[0x41, 0x41, 0x41, 0x41]}>(), b"AAAA");
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
2+
--> $DIR/slice-const-param.rs:3:12
3+
|
4+
LL | #![feature(const_generics)]
5+
| ^^^^^^^^^^^^^^
6+
|
7+
= note: `#[warn(incomplete_features)]` on by default
8+

0 commit comments

Comments
 (0)