Compile-Time Reflection MVP: tuples

This commit is contained in:
Oli Scherer
2025-03-12 10:26:37 +00:00
committed by Oli Scherer
parent e8f3cfc0de
commit a3359bdd4f
31 changed files with 456 additions and 53 deletions
@@ -8,7 +8,7 @@
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::{self as hir, CRATE_HIR_ID, LangItem};
use rustc_middle::mir::AssertMessage;
use rustc_middle::mir::interpret::ReportedErrorInfo;
use rustc_middle::mir::interpret::{Pointer, ReportedErrorInfo};
use rustc_middle::query::TyCtxtAt;
use rustc_middle::ty::layout::{HasTypingEnv, TyAndLayout, ValidityRequirement};
use rustc_middle::ty::{self, Ty, TyCtxt};
@@ -22,7 +22,7 @@
use crate::fluent_generated as fluent;
use crate::interpret::{
self, AllocId, AllocInit, AllocRange, ConstAllocation, CtfeProvenance, FnArg, Frame,
GlobalAlloc, ImmTy, InterpCx, InterpResult, OpTy, PlaceTy, Pointer, RangeSet, Scalar,
GlobalAlloc, ImmTy, InterpCx, InterpResult, OpTy, PlaceTy, RangeSet, Scalar,
compile_time_machine, err_inval, interp_ok, throw_exhaust, throw_inval, throw_ub,
throw_ub_custom, throw_unsup, throw_unsup_format,
};
@@ -586,6 +586,11 @@ fn call_intrinsic(
}
}
sym::type_of => {
let ty = ecx.read_type_id(&args[0])?;
ecx.write_type_info(ty, dest)?;
}
_ => {
// We haven't handled the intrinsic, let's see if we can use a fallback body.
if ecx.tcx.intrinsic(instance.def_id()).unwrap().must_be_overridden {
@@ -13,6 +13,7 @@
mod eval_queries;
mod fn_queries;
mod machine;
mod type_info;
mod valtrees;
pub use self::dummy_machine::*;
@@ -0,0 +1,158 @@
use rustc_abi::FieldIdx;
use rustc_hir::LangItem;
use rustc_middle::mir::interpret::CtfeProvenance;
use rustc_middle::span_bug;
use rustc_middle::ty::layout::TyAndLayout;
use rustc_middle::ty::{self, ScalarInt, Ty};
use rustc_span::{Symbol, sym};
use crate::const_eval::CompileTimeMachine;
use crate::interpret::{
Immediate, InterpCx, InterpResult, MPlaceTy, MemoryKind, Writeable, interp_ok,
};
impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
/// Writes a `core::mem::type_info::TypeInfo` for a given type, `ty` to the given place.
pub(crate) fn write_type_info(
&mut self,
ty: Ty<'tcx>,
dest: &impl Writeable<'tcx, CtfeProvenance>,
) -> InterpResult<'tcx> {
let ty_struct = self.tcx.require_lang_item(LangItem::Type, self.tcx.span);
let ty_struct = self.tcx.type_of(ty_struct).no_bound_vars().unwrap();
assert_eq!(ty_struct, dest.layout().ty);
let ty_struct = ty_struct.ty_adt_def().unwrap().non_enum_variant();
// Fill all fields of the `TypeInfo` struct.
for (idx, field) in ty_struct.fields.iter_enumerated() {
let field_dest = self.project_field(dest, idx)?;
let downcast = |name: Symbol| {
let variants = field_dest.layout().ty.ty_adt_def().unwrap().variants();
let variant_id = variants
.iter_enumerated()
.find(|(_idx, var)| var.name == name)
.unwrap_or_else(|| panic!("got {name} but expected one of {variants:#?}"))
.0;
interp_ok((variant_id, self.project_downcast(&field_dest, variant_id)?))
};
match field.name {
sym::kind => {
let variant_index = match ty.kind() {
ty::Tuple(fields) => {
let (variant, variant_place) = downcast(sym::Tuple)?;
// project to the single tuple variant field of `type_info::Tuple` struct type
let tuple_place = self.project_field(&variant_place, FieldIdx::ZERO)?;
assert_eq!(
1,
tuple_place
.layout()
.ty
.ty_adt_def()
.unwrap()
.non_enum_variant()
.fields
.len()
);
self.write_tuple_fields(tuple_place, fields, ty)?;
variant
}
// For now just merge all primitives into one `Leaf` variant with no data
ty::Uint(_) | ty::Int(_) | ty::Float(_) | ty::Char | ty::Bool => {
downcast(sym::Leaf)?.0
}
ty::Adt(_, _)
| ty::Foreign(_)
| ty::Str
| ty::Array(_, _)
| ty::Pat(_, _)
| ty::Slice(_)
| ty::RawPtr(..)
| ty::Ref(..)
| ty::FnDef(..)
| ty::FnPtr(..)
| ty::UnsafeBinder(..)
| ty::Dynamic(..)
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Coroutine(..)
| ty::CoroutineWitness(..)
| ty::Never
| ty::Alias(..)
| ty::Param(_)
| ty::Bound(..)
| ty::Placeholder(_)
| ty::Infer(..)
| ty::Error(_) => downcast(sym::Other)?.0,
};
self.write_discriminant(variant_index, &field_dest)?
}
other => span_bug!(self.tcx.span, "unknown `Type` field {other}"),
}
}
interp_ok(())
}
pub(crate) fn write_tuple_fields(
&mut self,
tuple_place: impl Writeable<'tcx, CtfeProvenance>,
fields: &[Ty<'tcx>],
tuple_ty: Ty<'tcx>,
) -> InterpResult<'tcx> {
// project into the `type_info::Tuple::fields` field
let fields_slice_place = self.project_field(&tuple_place, FieldIdx::ZERO)?;
// get the `type_info::Field` type from `fields: &[Field]`
let field_type = fields_slice_place
.layout()
.ty
.builtin_deref(false)
.unwrap()
.sequence_element_type(self.tcx.tcx);
// Create an array with as many elements as the number of fields in the inspected tuple
let fields_layout =
self.layout_of(Ty::new_array(self.tcx.tcx, field_type, fields.len() as u64))?;
let fields_place = self.allocate(fields_layout, MemoryKind::Stack)?;
let mut fields_places = self.project_array_fields(&fields_place)?;
let tuple_layout = self.layout_of(tuple_ty)?;
while let Some((i, place)) = fields_places.next(self)? {
let field_ty = fields[i as usize];
self.write_field(field_ty, place, tuple_layout, i)?;
}
let fields_place = fields_place.map_provenance(CtfeProvenance::as_immutable);
let ptr = Immediate::new_slice(fields_place.ptr(), fields.len() as u64, self);
self.write_immediate(ptr, &fields_slice_place)
}
fn write_field(
&mut self,
field_ty: Ty<'tcx>,
place: MPlaceTy<'tcx>,
layout: TyAndLayout<'tcx>,
idx: u64,
) -> InterpResult<'tcx> {
for (field_idx, field_ty_field) in
place.layout.ty.ty_adt_def().unwrap().non_enum_variant().fields.iter_enumerated()
{
let field_place = self.project_field(&place, field_idx)?;
match field_ty_field.name {
sym::ty => self.write_type_id(field_ty, &field_place)?,
sym::offset => {
let offset = layout.fields.offset(idx as usize);
self.write_scalar(
ScalarInt::try_from_target_usize(offset.bytes(), self.tcx.tcx).unwrap(),
&field_place,
)?;
}
other => {
span_bug!(self.tcx.def_span(field_ty_field.did), "unimplemented field {other}")
}
}
}
interp_ok(())
}
}
@@ -27,6 +27,7 @@
throw_ub_custom, throw_ub_format,
};
use crate::fluent_generated as fluent;
use crate::interpret::Writeable;
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum MulAddType {
@@ -68,10 +69,10 @@ pub(crate) fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> (AllocId
}
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
/// Generates a value of `TypeId` for `ty` in-place.
fn write_type_id(
pub(crate) fn write_type_id(
&mut self,
ty: Ty<'tcx>,
dest: &PlaceTy<'tcx, M::Provenance>,
dest: &impl Writeable<'tcx, M::Provenance>,
) -> InterpResult<'tcx, ()> {
let tcx = self.tcx;
let type_id_hash = tcx.type_id_hash(ty).as_u128();
+1
View File
@@ -278,6 +278,7 @@ pub fn extract(attrs: &[impl AttributeExt]) -> Option<(Symbol, Span)> {
PartialOrd, sym::partial_ord, partial_ord_trait, Target::Trait, GenericRequirement::Exact(1);
CVoid, sym::c_void, c_void, Target::Enum, GenericRequirement::None;
Type, sym::type_info, type_struct, Target::Struct, GenericRequirement::None;
TypeId, sym::type_id, type_id, Target::Struct, GenericRequirement::None;
// A number of panic-related lang items. The `panic` item corresponds to divide-by-zero and
@@ -213,6 +213,7 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi
| sym::type_id
| sym::type_id_eq
| sym::type_name
| sym::type_of
| sym::ub_checks
| sym::variant_count
| sym::vtable_for
@@ -308,13 +309,22 @@ pub(crate) fn check_intrinsic_type(
sym::needs_drop => (1, 0, vec![], tcx.types.bool),
sym::type_name => (1, 0, vec![], Ty::new_static_str(tcx)),
sym::type_id => {
(1, 0, vec![], tcx.type_of(tcx.lang_items().type_id().unwrap()).instantiate_identity())
}
sym::type_id => (
1,
0,
vec![],
tcx.type_of(tcx.lang_items().type_id().unwrap()).no_bound_vars().unwrap(),
),
sym::type_id_eq => {
let type_id = tcx.type_of(tcx.lang_items().type_id().unwrap()).instantiate_identity();
let type_id = tcx.type_of(tcx.lang_items().type_id().unwrap()).no_bound_vars().unwrap();
(0, 0, vec![type_id, type_id], tcx.types.bool)
}
sym::type_of => (
0,
0,
vec![tcx.type_of(tcx.lang_items().type_id().unwrap()).no_bound_vars().unwrap()],
tcx.type_of(tcx.lang_items().type_struct().unwrap()).no_bound_vars().unwrap(),
),
sym::offload => (
3,
0,
+5
View File
@@ -284,6 +284,7 @@
IteratorItem,
IteratorMap,
Layout,
Leaf,
Left,
LinkedList,
LintDiagnostic,
@@ -302,6 +303,7 @@
Ordering,
OsStr,
OsString,
Other,
Output,
Param,
ParamSet,
@@ -380,6 +382,7 @@
TryCapturePrintable,
TryFrom,
TryInto,
Tuple,
Ty,
TyCtxt,
TyKind,
@@ -2317,6 +2320,7 @@
type_const,
type_id,
type_id_eq,
type_info,
type_ir,
type_ir_infer_ctxt_like,
type_ir_inherent,
@@ -2324,6 +2328,7 @@
type_length_limit,
type_macros,
type_name,
type_of,
type_privacy_lints,
typed_swap_nonoverlapping,
u8,
+9
View File
@@ -2849,6 +2849,15 @@ pub const fn vtable_for<T, U: ptr::Pointee<Metadata = ptr::DynMetadata<U>> + ?Si
#[rustc_intrinsic_const_stable_indirect]
pub const unsafe fn align_of_val<T: ?Sized>(ptr: *const T) -> usize;
/// Compute the type information of a concrete type.
/// It can only be called at compile time, the backends do
/// not implement it.
#[rustc_intrinsic]
#[unstable(feature = "core_intrinsics", issue = "none")]
pub const fn type_of(_id: crate::any::TypeId) -> crate::mem::type_info::Type {
panic!("`TypeId::info` can only be called at compile-time")
}
/// Gets a static string slice containing the name of a type.
///
/// Note that, unlike most intrinsics, this can only be called at compile-time
+1
View File
@@ -124,6 +124,7 @@
#![feature(str_internals)]
#![feature(str_split_inclusive_remainder)]
#![feature(str_split_remainder)]
#![feature(type_info)]
#![feature(ub_checks)]
#![feature(unsafe_pinned)]
#![feature(utf16_extra)]
+3
View File
@@ -37,6 +37,9 @@
#[doc(inline)]
pub use crate::intrinsics::transmute;
#[unstable(feature = "type_info", issue = "146922")]
pub mod type_info;
/// Takes ownership and "forgets" about the value **without running its destructor**.
///
/// Any resources the value manages, such as heap memory or a file handle, will linger
+69
View File
@@ -0,0 +1,69 @@
//! MVP for exposing compile-time information about types in a
//! runtime or const-eval processable way.
use crate::any::TypeId;
use crate::intrinsics::type_of;
/// Compile-time type information.
#[derive(Debug)]
#[non_exhaustive]
#[lang = "type_info"]
#[unstable(feature = "type_info", issue = "146922")]
pub struct Type {
/// Per-type information
pub kind: TypeKind,
}
impl TypeId {
/// Compute the type information of a concrete type.
/// It can only be called at compile time.
#[unstable(feature = "type_info", issue = "146922")]
#[rustc_const_unstable(feature = "type_info", issue = "146922")]
pub const fn info(self) -> Type {
type_of(self)
}
}
impl Type {
/// Returns the type information of the generic type parameter.
#[unstable(feature = "type_info", issue = "146922")]
#[rustc_const_unstable(feature = "type_info", issue = "146922")]
// FIXME(reflection): don't require the 'static bound
pub const fn of<T: 'static>() -> Self {
const { TypeId::of::<T>().info() }
}
}
/// Compile-time type information.
#[derive(Debug)]
#[non_exhaustive]
#[unstable(feature = "type_info", issue = "146922")]
pub enum TypeKind {
/// Tuples.
Tuple(Tuple),
/// Primitives
/// FIXME(#146922): disambiguate further
Leaf,
/// FIXME(#146922): add all the common types
Other,
}
/// Compile-time type information about tuples.
#[derive(Debug)]
#[non_exhaustive]
#[unstable(feature = "type_info", issue = "146922")]
pub struct Tuple {
/// All fields of a tuple.
pub fields: &'static [Field],
}
/// Compile-time type information about fields of tuples, structs and enum variants.
#[derive(Debug)]
#[non_exhaustive]
#[unstable(feature = "type_info", issue = "146922")]
pub struct Field {
/// The field's type.
pub ty: TypeId,
/// Offset in bytes from the parent type
pub offset: usize,
}
-1
View File
@@ -62,7 +62,6 @@ macro_rules! generate {
MsrvStack,
Octal,
OpenOptions,
Other,
PathLookup,
Regex,
RegexBuilder,
@@ -2,7 +2,7 @@ error[E0277]: functions with the "rust-call" ABI must take a single non-self tup
--> $DIR/issue-22565-rust-call.rs:3:1
|
LL | extern "rust-call" fn b(_i: i32) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Tuple` is not implemented for `i32`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Tuple` is not implemented for `i32`
error: functions with the "rust-call" ABI must take a single non-self tuple argument
--> $DIR/issue-22565-rust-call.rs:17:5
@@ -32,7 +32,7 @@ error[E0277]: functions with the "rust-call" ABI must take a single non-self tup
--> $DIR/issue-22565-rust-call.rs:27:7
|
LL | b(10);
| ^^ the trait `Tuple` is not implemented for `i32`
| ^^ the trait `std::marker::Tuple` is not implemented for `i32`
error: functions with the "rust-call" ABI must take a single non-self tuple argument
--> $DIR/issue-22565-rust-call.rs:29:5
+2 -2
View File
@@ -2,7 +2,7 @@ error[E0059]: type parameter to bare `Fn` trait must be a tuple
--> $DIR/E0059.rs:3:11
|
LL | fn foo<F: Fn<i32>>(f: F) -> F::Output { f(3) }
| ^^^^^^^ the trait `Tuple` is not implemented for `i32`
| ^^^^^^^ the trait `std::marker::Tuple` is not implemented for `i32`
|
note: required by a bound in `Fn`
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
@@ -11,7 +11,7 @@ error[E0277]: `i32` is not a tuple
--> $DIR/E0059.rs:3:41
|
LL | fn foo<F: Fn<i32>>(f: F) -> F::Output { f(3) }
| ^^^^ the trait `Tuple` is not implemented for `i32`
| ^^^^ the trait `std::marker::Tuple` is not implemented for `i32`
error[E0059]: cannot use call notation; the first type parameter for the function trait is neither a tuple nor unit
--> $DIR/E0059.rs:3:41
+3 -3
View File
@@ -384,11 +384,11 @@ LL | fn in_impl_Fn_return_in_return() -> &'static impl Fn() -> impl Debug { pani
|
= note: multiple `impl`s satisfying `_: Fn()` found in the following crates: `alloc`, `core`:
- impl<A, F> Fn<A> for &F
where A: Tuple, F: Fn<A>, F: ?Sized;
where A: std::marker::Tuple, F: Fn<A>, F: ?Sized;
- impl<Args, F, A> Fn<Args> for Box<F, A>
where Args: Tuple, F: Fn<Args>, A: Allocator, F: ?Sized;
where Args: std::marker::Tuple, F: Fn<Args>, A: Allocator, F: ?Sized;
- impl<F, Args> Fn<Args> for Exclusive<F>
where F: Sync, F: Fn<Args>, Args: Tuple;
where F: Sync, F: Fn<Args>, Args: std::marker::Tuple;
error[E0118]: no nominal type found for inherent implementation
--> $DIR/where-allowed.rs:241:1
@@ -2,7 +2,7 @@ error[E0059]: type parameter to bare `FnOnce` trait must be a tuple
--> $DIR/rust-call-abi-not-a-tuple-ice-81974.rs:31:5
|
LL | extern "rust-call" fn call_once(mut self, a: A) -> Self::Output {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Tuple` is not implemented for `A`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Tuple` is not implemented for `A`
|
note: required by a bound in `FnOnce`
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
@@ -15,7 +15,7 @@ error[E0059]: type parameter to bare `FnOnce` trait must be a tuple
--> $DIR/rust-call-abi-not-a-tuple-ice-81974.rs:24:12
|
LL | impl<A, B> FnOnce<A> for CachedFun<A, B>
| ^^^^^^^^^ the trait `Tuple` is not implemented for `A`
| ^^^^^^^^^ the trait `std::marker::Tuple` is not implemented for `A`
|
note: required by a bound in `FnOnce`
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
@@ -28,7 +28,7 @@ error[E0059]: type parameter to bare `FnOnce` trait must be a tuple
--> $DIR/rust-call-abi-not-a-tuple-ice-81974.rs:45:5
|
LL | extern "rust-call" fn call_mut(&mut self, a: A) -> Self::Output {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Tuple` is not implemented for `A`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Tuple` is not implemented for `A`
|
note: required by a bound in `FnOnce`
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
@@ -41,7 +41,7 @@ error[E0059]: type parameter to bare `FnMut` trait must be a tuple
--> $DIR/rust-call-abi-not-a-tuple-ice-81974.rs:39:12
|
LL | impl<A, B> FnMut<A> for CachedFun<A, B>
| ^^^^^^^^ the trait `Tuple` is not implemented for `A`
| ^^^^^^^^ the trait `std::marker::Tuple` is not implemented for `A`
|
note: required by a bound in `FnMut`
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
@@ -54,7 +54,7 @@ error[E0277]: functions with the "rust-call" ABI must take a single non-self tup
--> $DIR/rust-call-abi-not-a-tuple-ice-81974.rs:31:5
|
LL | extern "rust-call" fn call_once(mut self, a: A) -> Self::Output {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Tuple` is not implemented for `A`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Tuple` is not implemented for `A`
|
help: consider further restricting type parameter `A` with unstable trait `Tuple`
|
@@ -65,7 +65,7 @@ error[E0277]: functions with the "rust-call" ABI must take a single non-self tup
--> $DIR/rust-call-abi-not-a-tuple-ice-81974.rs:45:5
|
LL | extern "rust-call" fn call_mut(&mut self, a: A) -> Self::Output {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Tuple` is not implemented for `A`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Tuple` is not implemented for `A`
|
help: consider further restricting type parameter `A` with unstable trait `Tuple`
|
@@ -76,7 +76,7 @@ error[E0277]: `A` is not a tuple
--> $DIR/rust-call-abi-not-a-tuple-ice-81974.rs:34:19
|
LL | self.call_mut(a)
| -------- ^ the trait `Tuple` is not implemented for `A`
| -------- ^ the trait `std::marker::Tuple` is not implemented for `A`
| |
| required by a bound introduced by this call
|
@@ -91,7 +91,7 @@ error[E0277]: `i32` is not a tuple
--> $DIR/rust-call-abi-not-a-tuple-ice-81974.rs:59:26
|
LL | cachedcoso.call_once(1);
| --------- ^ the trait `Tuple` is not implemented for `i32`
| --------- ^ the trait `std::marker::Tuple` is not implemented for `i32`
| |
| required by a bound introduced by this call
|
@@ -2,7 +2,7 @@ error[E0059]: type parameter to bare `FnMut` trait must be a tuple
--> $DIR/overloaded-calls-nontuple.rs:10:6
|
LL | impl FnMut<isize> for S {
| ^^^^^^^^^^^^ the trait `Tuple` is not implemented for `isize`
| ^^^^^^^^^^^^ the trait `std::marker::Tuple` is not implemented for `isize`
|
note: required by a bound in `FnMut`
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
@@ -11,7 +11,7 @@ error[E0059]: type parameter to bare `FnOnce` trait must be a tuple
--> $DIR/overloaded-calls-nontuple.rs:18:6
|
LL | impl FnOnce<isize> for S {
| ^^^^^^^^^^^^^ the trait `Tuple` is not implemented for `isize`
| ^^^^^^^^^^^^^ the trait `std::marker::Tuple` is not implemented for `isize`
|
note: required by a bound in `FnOnce`
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
@@ -20,19 +20,19 @@ error[E0277]: functions with the "rust-call" ABI must take a single non-self tup
--> $DIR/overloaded-calls-nontuple.rs:12:5
|
LL | extern "rust-call" fn call_mut(&mut self, z: isize) -> isize {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Tuple` is not implemented for `isize`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Tuple` is not implemented for `isize`
error[E0277]: functions with the "rust-call" ABI must take a single non-self tuple argument
--> $DIR/overloaded-calls-nontuple.rs:21:5
|
LL | extern "rust-call" fn call_once(mut self, z: isize) -> isize {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Tuple` is not implemented for `isize`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Tuple` is not implemented for `isize`
error[E0277]: `isize` is not a tuple
--> $DIR/overloaded-calls-nontuple.rs:23:23
|
LL | self.call_mut(z)
| -------- ^ the trait `Tuple` is not implemented for `isize`
| -------- ^ the trait `std::marker::Tuple` is not implemented for `isize`
| |
| required by a bound introduced by this call
|
@@ -53,7 +53,7 @@ error[E0277]: `isize` is not a tuple
--> $DIR/overloaded-calls-nontuple.rs:29:10
|
LL | drop(s(3))
| ^^^^ the trait `Tuple` is not implemented for `isize`
| ^^^^ the trait `std::marker::Tuple` is not implemented for `isize`
error: aborting due to 7 previous errors
+30
View File
@@ -0,0 +1,30 @@
#![feature(type_info)]
//@ run-pass
//@ check-run-results
#![allow(dead_code)]
use std::mem::type_info::Type;
struct Foo {
a: u32,
}
enum Bar {
Some(u32),
None,
Foomp { a: (), b: &'static str },
}
struct Unsized {
x: u16,
s: str,
}
fn main() {
println!("{:#?}", const { Type::of::<(u8, u8, ())>() }.kind);
println!("{:#?}", const { Type::of::<Foo>() }.kind);
println!("{:#?}", const { Type::of::<Bar>() }.kind);
println!("{:#?}", const { Type::of::<&Unsized>() }.kind);
println!("{:#?}", const { Type::of::<&str>() }.kind);
println!("{:#?}", const { Type::of::<&[u8]>() }.kind);
}
+23
View File
@@ -0,0 +1,23 @@
Tuple(
Tuple {
fields: [
Field {
ty: TypeId(0x0596b48cc04376e64d5c788c2aa46bdb),
offset: 0,
},
Field {
ty: TypeId(0x0596b48cc04376e64d5c788c2aa46bdb),
offset: 1,
},
Field {
ty: TypeId(0x41223169ff28813ba79b7268a2a968d9),
offset: 2,
},
],
},
)
Other
Other
Other
Other
Other
+8
View File
@@ -0,0 +1,8 @@
use std::mem::type_info::Type;
//~^ ERROR: use of unstable library feature `type_info`
fn main() {
let ty = std::mem::type_info::Type::of::<()>();
//~^ ERROR: use of unstable library feature `type_info`
//~| ERROR: use of unstable library feature `type_info`
}
+33
View File
@@ -0,0 +1,33 @@
error[E0658]: use of unstable library feature `type_info`
--> $DIR/feature_gate.rs:1:5
|
LL | use std::mem::type_info::Type;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #146922 <https://github.com/rust-lang/rust/issues/146922> for more information
= help: add `#![feature(type_info)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: use of unstable library feature `type_info`
--> $DIR/feature_gate.rs:5:14
|
LL | let ty = std::mem::type_info::Type::of::<()>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #146922 <https://github.com/rust-lang/rust/issues/146922> for more information
= help: add `#![feature(type_info)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: use of unstable library feature `type_info`
--> $DIR/feature_gate.rs:5:14
|
LL | let ty = std::mem::type_info::Type::of::<()>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #146922 <https://github.com/rust-lang/rust/issues/146922> for more information
= help: add `#![feature(type_info)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0658`.
+36
View File
@@ -0,0 +1,36 @@
#![feature(type_info)]
//@ run-pass
use std::mem::type_info::{Type, TypeKind};
fn assert_tuple_arity<T: 'static, const N: usize>() {
const {
match &Type::of::<T>().kind {
TypeKind::Tuple(tup) => {
assert!(tup.fields.len() == N);
}
_ => unreachable!(),
}
}
}
fn main() {
assert_tuple_arity::<(), 0>();
assert_tuple_arity::<(u8,), 1>();
assert_tuple_arity::<(u8, u8), 2>();
const {
match &Type::of::<(u8, u8)>().kind {
TypeKind::Tuple(tup) => {
let [a, b] = tup.fields else { unreachable!() };
assert!(a.offset == 0);
assert!(b.offset == 1);
match (&a.ty.info().kind, &b.ty.info().kind) {
(TypeKind::Leaf, TypeKind::Leaf) => {}
_ => unreachable!(),
}
}
_ => unreachable!(),
}
}
}
@@ -31,6 +31,10 @@ help: you might have meant to use the associated type
|
LL | let _: Self::Type;
| ++++++
help: consider importing this struct
|
LL + use std::mem::type_info::Type;
|
error[E0531]: cannot find tuple struct or tuple variant `Type` in this scope
--> $DIR/resolve-assoc-suggestions.rs:25:13
@@ -32,7 +32,7 @@ error[E0059]: type parameter to bare `Fn` trait must be a tuple
--> $DIR/fn-trait-notation.rs:4:8
|
LL | F: Fn<i32, Output = i32>,
| ^^^^^^^^^^^^^^^^^^^^^ the trait `Tuple` is not implemented for `i32`
| ^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Tuple` is not implemented for `i32`
|
note: required by a bound in `Fn`
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
@@ -47,7 +47,7 @@ error[E0277]: `i32` is not a tuple
--> $DIR/fn-trait-notation.rs:9:5
|
LL | f(3);
| ^^^^ the trait `Tuple` is not implemented for `i32`
| ^^^^ the trait `std::marker::Tuple` is not implemented for `i32`
error[E0308]: mismatched types
--> $DIR/fn-trait-notation.rs:17:5
+9 -9
View File
@@ -68,7 +68,7 @@ body:
)
else_block: None
lint_level: Explicit(HirId(DefId(offset_of::concrete).10))
span: $DIR/offset_of.rs:37:5: 1437:57 (#0)
span: $DIR/offset_of.rs:37:5: 1440:57 (#0)
}
}
Stmt {
@@ -117,7 +117,7 @@ body:
)
else_block: None
lint_level: Explicit(HirId(DefId(offset_of::concrete).20))
span: $DIR/offset_of.rs:38:5: 1437:57 (#0)
span: $DIR/offset_of.rs:38:5: 1440:57 (#0)
}
}
Stmt {
@@ -166,7 +166,7 @@ body:
)
else_block: None
lint_level: Explicit(HirId(DefId(offset_of::concrete).30))
span: $DIR/offset_of.rs:39:5: 1437:57 (#0)
span: $DIR/offset_of.rs:39:5: 1440:57 (#0)
}
}
Stmt {
@@ -215,7 +215,7 @@ body:
)
else_block: None
lint_level: Explicit(HirId(DefId(offset_of::concrete).40))
span: $DIR/offset_of.rs:40:5: 1437:57 (#0)
span: $DIR/offset_of.rs:40:5: 1440:57 (#0)
}
}
Stmt {
@@ -264,7 +264,7 @@ body:
)
else_block: None
lint_level: Explicit(HirId(DefId(offset_of::concrete).50))
span: $DIR/offset_of.rs:41:5: 1437:57 (#0)
span: $DIR/offset_of.rs:41:5: 1440:57 (#0)
}
}
]
@@ -864,7 +864,7 @@ body:
)
else_block: None
lint_level: Explicit(HirId(DefId(offset_of::generic).12))
span: $DIR/offset_of.rs:45:5: 1437:57 (#0)
span: $DIR/offset_of.rs:45:5: 1440:57 (#0)
}
}
Stmt {
@@ -913,7 +913,7 @@ body:
)
else_block: None
lint_level: Explicit(HirId(DefId(offset_of::generic).24))
span: $DIR/offset_of.rs:46:5: 1437:57 (#0)
span: $DIR/offset_of.rs:46:5: 1440:57 (#0)
}
}
Stmt {
@@ -962,7 +962,7 @@ body:
)
else_block: None
lint_level: Explicit(HirId(DefId(offset_of::generic).36))
span: $DIR/offset_of.rs:47:5: 1437:57 (#0)
span: $DIR/offset_of.rs:47:5: 1440:57 (#0)
}
}
Stmt {
@@ -1011,7 +1011,7 @@ body:
)
else_block: None
lint_level: Explicit(HirId(DefId(offset_of::generic).48))
span: $DIR/offset_of.rs:48:5: 1437:57 (#0)
span: $DIR/offset_of.rs:48:5: 1440:57 (#0)
}
}
]
+3 -3
View File
@@ -4,10 +4,10 @@ error[E0425]: cannot find type `Type` in this scope
LL | impl Generic<Type> for S {}
| ^^^^ not found in this scope
|
help: you might be missing a type parameter
help: consider importing this struct
|
LL + use std::mem::type_info::Type;
|
LL | impl<Type> Generic<Type> for S {}
| ++++++
error: aborting due to 1 previous error
@@ -9,11 +9,11 @@ LL | x = unconstrained_map();
|
= note: multiple `impl`s satisfying `_: Fn()` found in the following crates: `alloc`, `core`:
- impl<A, F> Fn<A> for &F
where A: Tuple, F: Fn<A>, F: ?Sized;
where A: std::marker::Tuple, F: Fn<A>, F: ?Sized;
- impl<Args, F, A> Fn<Args> for Box<F, A>
where Args: Tuple, F: Fn<Args>, A: Allocator, F: ?Sized;
where Args: std::marker::Tuple, F: Fn<Args>, A: Allocator, F: ?Sized;
- impl<F, Args> Fn<Args> for Exclusive<F>
where F: Sync, F: Fn<Args>, Args: Tuple;
where F: Sync, F: Fn<Args>, Args: std::marker::Tuple;
note: required by a bound in `unconstrained_map`
--> $DIR/well-formed-in-relate.rs:21:25
|
+4 -4
View File
@@ -2,7 +2,7 @@ error[E0277]: `T` is not a tuple
--> $DIR/builtin-fail.rs:8:23
|
LL | assert_is_tuple::<T>();
| ^ the trait `Tuple` is not implemented for `T`
| ^ the trait `std::marker::Tuple` is not implemented for `T`
|
note: required by a bound in `assert_is_tuple`
--> $DIR/builtin-fail.rs:3:23
@@ -18,7 +18,7 @@ error[E0277]: `i32` is not a tuple
--> $DIR/builtin-fail.rs:13:23
|
LL | assert_is_tuple::<i32>();
| ^^^ the trait `Tuple` is not implemented for `i32`
| ^^^ the trait `std::marker::Tuple` is not implemented for `i32`
|
note: required by a bound in `assert_is_tuple`
--> $DIR/builtin-fail.rs:3:23
@@ -30,7 +30,7 @@ error[E0277]: `i32` is not a tuple
--> $DIR/builtin-fail.rs:15:24
|
LL | assert_is_tuple::<(i32)>();
| ^^^ the trait `Tuple` is not implemented for `i32`
| ^^^ the trait `std::marker::Tuple` is not implemented for `i32`
|
note: required by a bound in `assert_is_tuple`
--> $DIR/builtin-fail.rs:3:23
@@ -44,7 +44,7 @@ error[E0277]: `TupleStruct` is not a tuple
LL | assert_is_tuple::<TupleStruct>();
| ^^^^^^^^^^^ unsatisfied trait bound
|
help: the trait `Tuple` is not implemented for `TupleStruct`
help: the trait `std::marker::Tuple` is not implemented for `TupleStruct`
--> $DIR/builtin-fail.rs:5:1
|
LL | struct TupleStruct(i32, i32);
+1 -1
View File
@@ -2,7 +2,7 @@ error[E0277]: `&mut ()` is not a tuple
--> $DIR/issue-57404.rs:6:41
|
LL | handlers.unwrap().as_mut().call_mut(&mut ());
| -------- ^^^^^^^ the trait `Tuple` is not implemented for `&mut ()`
| -------- ^^^^^^^ the trait `std::marker::Tuple` is not implemented for `&mut ()`
| |
| required by a bound introduced by this call
|
@@ -2,7 +2,7 @@ error[E0059]: type parameter to bare `Fn` trait must be a tuple
--> $DIR/non-tupled-arg-mismatch.rs:3:9
|
LL | fn a<F: Fn<usize>>(f: F) {}
| ^^^^^^^^^ the trait `Tuple` is not implemented for `usize`
| ^^^^^^^^^ the trait `std::marker::Tuple` is not implemented for `usize`
|
note: required by a bound in `Fn`
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
+7
View File
@@ -1003,6 +1003,13 @@ cc = ["@lcnr"]
message = "HIR ty lowering was modified"
cc = ["@fmease"]
[mentions."library/core/src/mem/type_info.rs"]
message = """
The reflection data structures are tied exactly to the implementation
in the compiler. Make sure to also adjust `rustc_const_eval/src/const_eval/type_info.rs
"""
cc = ["@oli-obk"]
[mentions."compiler/rustc_error_codes/src/lib.rs"]
message = "Some changes occurred in diagnostic error codes"
cc = ["@GuillaumeGomez"]