Auto merge of #146923 - oli-obk:comptime-reflect, r=BoxyUwU
Reflection MVP I am opening this PR for discussion about the general design we should start out with, as there are various options (that are not too hard to transition between each other, so we should totally just pick one and go with it and reiterate later) r? @scottmcm and @joshtriplett project goal issue: https://github.com/rust-lang/rust-project-goals/issues/406 tracking issue: https://github.com/rust-lang/rust/issues/146922 The design currently implemented by this PR is * `TypeId::info` (method, usually used as `id.info()` returns a `Type` struct * the `Type` struct has fields that contain information about the type * the most notable field is `kind`, which is a non-exhaustive enum over all possible type kinds and their specific information. So it has a `Tuple(Tuple)` variant, where the only field is a `Tuple` struct type that contains more information (The list of type ids that make up the tuple). * To get nested type information (like the type of fields) you need to call `TypeId::info` again. * There is only one language intrinsic to go from `TypeId` to `Type`, and it does all the work An alternative design could be * Lots of small methods (each backed by an intrinsic) on `TypeId` that return all the individual information pieces (size, align, number of fields, number of variants, ...) * This is how C++ does it (see https://lemire.me/blog/2025/06/22/c26-will-include-compile-time-reflection-why-should-you-care/ and https://isocpp.org/files/papers/P2996R13.html#member-queries) * Advantage: you only get the information you ask for, so it's probably cheaper if you get just one piece of information for lots of types (e.g. reimplementing size_of in terms of `TypeId::info` is likely expensive and wasteful) * Disadvantage: lots of method calling (and `Option` return types, or "general" methods like `num_fields` returning 0 for primitives) instead of matching and field accesses * a crates.io crate could implement `TypeId::info` in terms of this design The backing implementation is modular enough that switching from one to the other is probably not an issue, and the alternative design could be easier for the CTFE engine's implementation, just not as nice to use for end users (without crates wrapping the logic) One wart of this design that I'm fixing in separate branches is that `TypeId::info` will panic if used at runtime, while it should be uncallable
This commit is contained in:
commit
f57eac1bf9
31 changed files with 475 additions and 53 deletions
|
|
@ -8,7 +8,7 @@ use rustc_data_structures::fx::{FxHashMap, FxIndexMap, IndexEntry};
|
|||
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::errors::{LongRunning, LongRunningWarn};
|
|||
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 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
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 error;
|
|||
mod eval_queries;
|
||||
mod fn_queries;
|
||||
mod machine;
|
||||
mod type_info;
|
||||
mod valtrees;
|
||||
|
||||
pub use self::dummy_machine::*;
|
||||
|
|
|
|||
175
compiler/rustc_const_eval/src/const_eval/type_info.rs
Normal file
175
compiler/rustc_const_eval/src/const_eval/type_info.rs
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
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)?
|
||||
}
|
||||
sym::size => {
|
||||
let layout = self.layout_of(ty)?;
|
||||
let variant_index = if layout.is_sized() {
|
||||
let (variant, variant_place) = downcast(sym::Some)?;
|
||||
let size_field_place =
|
||||
self.project_field(&variant_place, FieldIdx::ZERO)?;
|
||||
self.write_scalar(
|
||||
ScalarInt::try_from_target_usize(layout.size.bytes(), self.tcx.tcx)
|
||||
.unwrap(),
|
||||
&size_field_place,
|
||||
)?;
|
||||
variant
|
||||
} else {
|
||||
downcast(sym::None)?.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 @@ use super::{
|
|||
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();
|
||||
|
|
|
|||
|
|
@ -278,6 +278,7 @@ language_item_table! {
|
|||
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,
|
||||
|
|
|
|||
|
|
@ -284,6 +284,7 @@ symbols! {
|
|||
IteratorItem,
|
||||
IteratorMap,
|
||||
Layout,
|
||||
Leaf,
|
||||
Left,
|
||||
LinkedList,
|
||||
LintDiagnostic,
|
||||
|
|
@ -302,6 +303,7 @@ symbols! {
|
|||
Ordering,
|
||||
OsStr,
|
||||
OsString,
|
||||
Other,
|
||||
Output,
|
||||
Param,
|
||||
ParamSet,
|
||||
|
|
@ -380,6 +382,7 @@ symbols! {
|
|||
TryCapturePrintable,
|
||||
TryFrom,
|
||||
TryInto,
|
||||
Tuple,
|
||||
Ty,
|
||||
TyCtxt,
|
||||
TyKind,
|
||||
|
|
@ -2318,6 +2321,7 @@ symbols! {
|
|||
type_const,
|
||||
type_id,
|
||||
type_id_eq,
|
||||
type_info,
|
||||
type_ir,
|
||||
type_ir_infer_ctxt_like,
|
||||
type_ir_inherent,
|
||||
|
|
@ -2325,6 +2329,7 @@ symbols! {
|
|||
type_length_limit,
|
||||
type_macros,
|
||||
type_name,
|
||||
type_of,
|
||||
type_privacy_lints,
|
||||
typed_swap_nonoverlapping,
|
||||
u8,
|
||||
|
|
|
|||
|
|
@ -2845,6 +2845,15 @@ pub const unsafe fn size_of_val<T: ?Sized>(ptr: *const T) -> usize;
|
|||
#[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
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -37,6 +37,9 @@ pub use drop_guard::DropGuard;
|
|||
#[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
|
||||
|
|
|
|||
71
library/core/src/mem/type_info.rs
Normal file
71
library/core/src/mem/type_info.rs
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
//! 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,
|
||||
/// Size of the type. `None` if it is unsized
|
||||
pub size: Option<usize>,
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
||||
|
|
@ -62,7 +62,6 @@ 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,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
|
||||
|
|
|
|||
|
|
@ -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
tests/ui/reflection/dump.rs
Normal file
30
tests/ui/reflection/dump.rs
Normal 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
tests/ui/reflection/dump.run.stdout
Normal file
23
tests/ui/reflection/dump.run.stdout
Normal 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
tests/ui/reflection/feature_gate.rs
Normal file
8
tests/ui/reflection/feature_gate.rs
Normal 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
tests/ui/reflection/feature_gate.stderr
Normal file
33
tests/ui/reflection/feature_gate.stderr
Normal 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
tests/ui/reflection/tuples.rs
Normal file
36
tests/ui/reflection/tuples.rs
Normal 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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue