Actually create ranged int types in the type system.
This commit is contained in:
parent
6b24a9cf70
commit
84acfe86de
@ -2152,7 +2152,7 @@ pub enum TyKind {
|
||||
MacCall(P<MacCall>),
|
||||
/// Placeholder for a `va_list`.
|
||||
CVarArgs,
|
||||
/// Pattern types like `u32 as 1..=`, which is the same as `NonZeroU32`,
|
||||
/// Pattern types like `pattern_type!(u32 is 1..=)`, which is the same as `NonZeroU32`,
|
||||
/// just as part of the type system.
|
||||
Pat(P<Ty>, P<Pat>),
|
||||
/// Sometimes we need a dummy value when no error has occurred.
|
||||
|
@ -381,4 +381,8 @@ fn visit_array_length(&mut self, len: &'hir ArrayLen) {
|
||||
ArrayLen::Body(..) => intravisit::walk_array_len(self, len),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_pattern_type_pattern(&mut self, p: &'hir hir::Pat<'hir>) {
|
||||
self.visit_pat(p)
|
||||
}
|
||||
}
|
||||
|
@ -1606,6 +1606,7 @@ fn check_movable_place(&mut self, location: Location, place: Place<'tcx>) {
|
||||
| ty::Foreign(_)
|
||||
| ty::Str
|
||||
| ty::Array(_, _)
|
||||
| ty::Pat(_, _)
|
||||
| ty::Slice(_)
|
||||
| ty::FnDef(_, _)
|
||||
| ty::FnPtr(_)
|
||||
@ -1648,6 +1649,7 @@ fn check_movable_place(&mut self, location: Location, place: Place<'tcx>) {
|
||||
| ty::Foreign(_)
|
||||
| ty::Str
|
||||
| ty::Array(_, _)
|
||||
| ty::Pat(_, _)
|
||||
| ty::Slice(_)
|
||||
| ty::RawPtr(_, _)
|
||||
| ty::Ref(_, _, _)
|
||||
|
@ -202,6 +202,16 @@ fn push_debuginfo_type_name<'tcx>(
|
||||
}
|
||||
}
|
||||
}
|
||||
ty::Pat(inner_type, pat) => {
|
||||
if cpp_like_debuginfo {
|
||||
output.push_str("pat$<");
|
||||
push_debuginfo_type_name(tcx, inner_type, true, output, visited);
|
||||
// FIXME(wg-debugging): implement CPP like printing for patterns.
|
||||
write!(output, ",{:?}>", pat).unwrap();
|
||||
} else {
|
||||
write!(output, "{:?}", t).unwrap();
|
||||
}
|
||||
}
|
||||
ty::Slice(inner_type) => {
|
||||
if cpp_like_debuginfo {
|
||||
output.push_str("slice2$<");
|
||||
|
@ -1,3 +1,4 @@
|
||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
use rustc_middle::mir;
|
||||
use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId};
|
||||
use rustc_middle::ty::layout::{LayoutCx, LayoutOf, TyAndLayout};
|
||||
@ -98,6 +99,16 @@ fn const_to_valtree_inner<'tcx>(
|
||||
Ok(ty::ValTree::Leaf(val.assert_int()))
|
||||
}
|
||||
|
||||
ty::Pat(base, ..) => {
|
||||
let mut place = place.clone();
|
||||
// The valtree of the base type is the same as the valtree of the pattern type.
|
||||
// Since the returned valtree does not contain the type or layout, we can just
|
||||
// switch to the base type.
|
||||
place.layout = ecx.layout_of(*base).unwrap();
|
||||
ensure_sufficient_stack(|| const_to_valtree_inner(ecx, &place, num_nodes))
|
||||
},
|
||||
|
||||
|
||||
ty::RawPtr(_, _) => {
|
||||
// Not all raw pointers are allowed, as we cannot properly test them for
|
||||
// equality at compile-time (see `ptr_guaranteed_cmp`).
|
||||
@ -273,7 +284,7 @@ pub fn valtree_to_const_value<'tcx>(
|
||||
|
||||
let (param_env, ty) = param_env_ty.into_parts();
|
||||
|
||||
match ty.kind() {
|
||||
match *ty.kind() {
|
||||
ty::FnDef(..) => {
|
||||
assert!(valtree.unwrap_branch().is_empty());
|
||||
mir::ConstValue::ZeroSized
|
||||
@ -286,10 +297,11 @@ pub fn valtree_to_const_value<'tcx>(
|
||||
),
|
||||
}
|
||||
}
|
||||
ty::Pat(ty, _) => valtree_to_const_value(tcx, param_env.and(ty), valtree),
|
||||
ty::Ref(_, inner_ty, _) => {
|
||||
let mut ecx =
|
||||
mk_eval_cx_to_read_const_val(tcx, DUMMY_SP, param_env, CanAccessMutGlobal::No);
|
||||
let imm = valtree_to_ref(&mut ecx, valtree, *inner_ty);
|
||||
let imm = valtree_to_ref(&mut ecx, valtree, inner_ty);
|
||||
let imm = ImmTy::from_immediate(imm, tcx.layout_of(param_env_ty).unwrap());
|
||||
op_to_const(&ecx, &imm.into(), /* for diagnostics */ false)
|
||||
}
|
||||
|
@ -1060,6 +1060,8 @@ fn is_very_trivially_sized(ty: Ty<'_>) -> bool {
|
||||
|
||||
ty::Tuple(tys) => tys.last().iter().all(|ty| is_very_trivially_sized(**ty)),
|
||||
|
||||
ty::Pat(ty, ..) => is_very_trivially_sized(*ty),
|
||||
|
||||
// We don't want to do any queries, so there is not much we can do with ADTs.
|
||||
ty::Adt(..) => false,
|
||||
|
||||
|
@ -69,6 +69,10 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>(
|
||||
ty::Alias(..) | ty::Param(_) | ty::Placeholder(_) | ty::Infer(_) => {
|
||||
throw_inval!(TooGeneric)
|
||||
}
|
||||
ty::Pat(_, pat) => match **pat {
|
||||
ty::PatternKind::Range { .. } => ConstValue::from_target_usize(0u64, &tcx),
|
||||
// Future pattern kinds may have more variants
|
||||
},
|
||||
ty::Bound(_, _) => bug!("bound ty during ctfe"),
|
||||
ty::Bool
|
||||
| ty::Char
|
||||
|
@ -640,6 +640,7 @@ fn try_visit_primitive(
|
||||
| ty::Str
|
||||
| ty::Dynamic(..)
|
||||
| ty::Closure(..)
|
||||
| ty::Pat(..)
|
||||
| ty::CoroutineClosure(..)
|
||||
| ty::Coroutine(..) => Ok(false),
|
||||
// Some types only occur during typechecking, they have no layout.
|
||||
|
@ -31,6 +31,7 @@ fn print_type(&mut self, ty: Ty<'tcx>) -> Result<(), PrintError> {
|
||||
| ty::Uint(_)
|
||||
| ty::Float(_)
|
||||
| ty::Str
|
||||
| ty::Pat(_, _)
|
||||
| ty::Array(_, _)
|
||||
| ty::Slice(_)
|
||||
| ty::RawPtr(_, _)
|
||||
|
@ -2624,7 +2624,7 @@ pub enum TyKind<'hir> {
|
||||
Infer,
|
||||
/// Placeholder for a type that has failed to be defined.
|
||||
Err(rustc_span::ErrorGuaranteed),
|
||||
/// Pattern types (`u32 as 1..`)
|
||||
/// Pattern types (`pattern_type!(u32 is 1..)`)
|
||||
Pat(&'hir Ty<'hir>, &'hir Pat<'hir>),
|
||||
}
|
||||
|
||||
|
@ -356,6 +356,11 @@ fn visit_expr_field(&mut self, field: &'v ExprField<'v>) -> Self::Result {
|
||||
fn visit_ty(&mut self, t: &'v Ty<'v>) -> Self::Result {
|
||||
walk_ty(self, t)
|
||||
}
|
||||
fn visit_pattern_type_pattern(&mut self, _p: &'v Pat<'v>) {
|
||||
// Do nothing. Only a few visitors need to know the details of the pattern type,
|
||||
// and they opt into it. All other visitors will just choke on our fake patterns
|
||||
// because they aren't in a body.
|
||||
}
|
||||
fn visit_generic_param(&mut self, p: &'v GenericParam<'v>) -> Self::Result {
|
||||
walk_generic_param(self, p)
|
||||
}
|
||||
@ -884,7 +889,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) -> V::Resul
|
||||
}
|
||||
TyKind::Pat(ty, pat) => {
|
||||
try_visit!(visitor.visit_ty(ty));
|
||||
try_visit!(visitor.visit_pat(pat));
|
||||
try_visit!(visitor.visit_pattern_type_pattern(pat));
|
||||
}
|
||||
}
|
||||
V::Result::output()
|
||||
|
@ -349,6 +349,7 @@ hir_analysis_pass_to_variadic_function = can't pass `{$ty}` to variadic function
|
||||
.suggestion = cast the value to `{$cast_ty}`
|
||||
.help = cast the value to `{$cast_ty}`
|
||||
|
||||
hir_analysis_pattern_type_non_const_range = "range patterns must have constant range start and end"
|
||||
hir_analysis_pattern_type_wild_pat = "wildcard patterns are not permitted for pattern types"
|
||||
.label = "this type is the same as the inner type without a pattern"
|
||||
hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is not allowed within types on item signatures for {$kind}
|
||||
|
@ -144,7 +144,12 @@ fn check_item(&mut self, id: hir::ItemId) -> Result<(), ErrorGuaranteed> {
|
||||
let id = id.owner_id.def_id;
|
||||
let item_span = self.tcx.def_span(id);
|
||||
let self_ty = self.tcx.type_of(id).instantiate_identity();
|
||||
let self_ty = self.tcx.peel_off_weak_alias_tys(self_ty);
|
||||
let mut self_ty = self.tcx.peel_off_weak_alias_tys(self_ty);
|
||||
// We allow impls on pattern types exactly when we allow impls on the base type.
|
||||
// FIXME(pattern_types): Figure out the exact coherence rules we want here.
|
||||
while let ty::Pat(base, _) = *self_ty.kind() {
|
||||
self_ty = base;
|
||||
}
|
||||
match *self_ty.kind() {
|
||||
ty::Adt(def, _) => self.check_def_id(id, self_ty, def.did()),
|
||||
ty::Foreign(did) => self.check_def_id(id, self_ty, did),
|
||||
@ -154,6 +159,7 @@ fn check_item(&mut self, id: hir::ItemId) -> Result<(), ErrorGuaranteed> {
|
||||
ty::Dynamic(..) => {
|
||||
Err(self.tcx.dcx().emit_err(errors::InherentDyn { span: item_span }))
|
||||
}
|
||||
ty::Pat(_, _) => unreachable!(),
|
||||
ty::Bool
|
||||
| ty::Char
|
||||
| ty::Int(_)
|
||||
|
@ -206,6 +206,11 @@ enum NonlocalImpl {
|
||||
(LocalImpl::Disallow { problematic_kind }, NonlocalImpl::DisallowOther)
|
||||
}
|
||||
|
||||
ty::Pat(..) => (
|
||||
LocalImpl::Disallow { problematic_kind: "pattern type" },
|
||||
NonlocalImpl::DisallowOther,
|
||||
),
|
||||
|
||||
ty::Bool
|
||||
| ty::Char
|
||||
| ty::Int(..)
|
||||
|
@ -1631,3 +1631,10 @@ pub struct OpaqueCapturesHigherRankedLifetime {
|
||||
pub decl_span: Span,
|
||||
pub bad_place: &'static str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_pattern_type_non_const_range)]
|
||||
pub struct NonConstRange {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
@ -39,6 +39,7 @@
|
||||
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
|
||||
use rustc_infer::traits::ObligationCause;
|
||||
use rustc_middle::middle::stability::AllowUnstable;
|
||||
use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput};
|
||||
use rustc_middle::ty::{
|
||||
self, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, ParamEnv, Ty, TyCtxt,
|
||||
TypeVisitableExt,
|
||||
@ -2195,15 +2196,64 @@ fn lower_ty_common(&self, hir_ty: &hir::Ty<'tcx>, borrowed: bool, in_path: bool)
|
||||
// handled specially and will not descend into this routine.
|
||||
self.ty_infer(None, hir_ty.span)
|
||||
}
|
||||
hir::TyKind::Pat(_ty, pat) => match pat.kind {
|
||||
hir::PatKind::Wild => {
|
||||
let err = tcx.dcx().emit_err(WildPatTy { span: pat.span });
|
||||
Ty::new_error(tcx, err)
|
||||
}
|
||||
hir::PatKind::Range(_, _, _) => Ty::new_misc_error(tcx),
|
||||
hir::PatKind::Err(e) => Ty::new_error(tcx, e),
|
||||
_ => span_bug!(pat.span, "unsupported pattern for pattern type: {pat:#?}"),
|
||||
},
|
||||
hir::TyKind::Pat(ty, pat) => {
|
||||
let ty = self.lower_ty(ty);
|
||||
let pat_ty = match pat.kind {
|
||||
hir::PatKind::Wild => {
|
||||
let err = tcx.dcx().emit_err(WildPatTy { span: pat.span });
|
||||
Ty::new_error(tcx, err)
|
||||
}
|
||||
hir::PatKind::Range(start, end, include_end) => {
|
||||
let expr_to_const = |expr: &'tcx hir::Expr<'tcx>| -> ty::Const<'tcx> {
|
||||
let (expr, neg) = match expr.kind {
|
||||
hir::ExprKind::Unary(hir::UnOp::Neg, negated) => {
|
||||
(negated, Some((expr.hir_id, expr.span)))
|
||||
}
|
||||
_ => (expr, None),
|
||||
};
|
||||
let c = match &expr.kind {
|
||||
hir::ExprKind::Lit(lit) => {
|
||||
let lit_input =
|
||||
LitToConstInput { lit: &lit.node, ty, neg: neg.is_some() };
|
||||
match tcx.lit_to_const(lit_input) {
|
||||
Ok(c) => c,
|
||||
Err(LitToConstError::Reported(err)) => {
|
||||
ty::Const::new_error(tcx, err, ty)
|
||||
}
|
||||
Err(LitToConstError::TypeError) => todo!(),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
let err = tcx
|
||||
.dcx()
|
||||
.emit_err(crate::errors::NonConstRange { span: expr.span });
|
||||
ty::Const::new_error(tcx, err, ty)
|
||||
}
|
||||
};
|
||||
self.record_ty(expr.hir_id, c.ty(), expr.span);
|
||||
if let Some((id, span)) = neg {
|
||||
self.record_ty(id, c.ty(), span);
|
||||
}
|
||||
c
|
||||
};
|
||||
|
||||
let start = start.map(expr_to_const);
|
||||
let end = end.map(expr_to_const);
|
||||
|
||||
let include_end = match include_end {
|
||||
hir::RangeEnd::Included => true,
|
||||
hir::RangeEnd::Excluded => false,
|
||||
};
|
||||
|
||||
let pat = tcx.mk_pat(ty::PatternKind::Range { start, end, include_end });
|
||||
Ty::new_pat(tcx, ty, pat)
|
||||
}
|
||||
hir::PatKind::Err(e) => Ty::new_error(tcx, e),
|
||||
_ => span_bug!(pat.span, "unsupported pattern for pattern type: {pat:#?}"),
|
||||
};
|
||||
self.record_ty(pat.hir_id, ty, pat.span);
|
||||
pat_ty
|
||||
}
|
||||
hir::TyKind::Err(guar) => Ty::new_error(tcx, *guar),
|
||||
};
|
||||
|
||||
|
@ -249,6 +249,20 @@ fn add_constraints_from_ty(
|
||||
self.add_constraints_from_ty(current, typ, variance);
|
||||
}
|
||||
|
||||
ty::Pat(typ, pat) => {
|
||||
match *pat {
|
||||
ty::PatternKind::Range { start, end, include_end: _ } => {
|
||||
if let Some(start) = start {
|
||||
self.add_constraints_from_const(current, start, variance);
|
||||
}
|
||||
if let Some(end) = end {
|
||||
self.add_constraints_from_const(current, end, variance);
|
||||
}
|
||||
}
|
||||
}
|
||||
self.add_constraints_from_ty(current, typ, variance);
|
||||
}
|
||||
|
||||
ty::Slice(typ) => {
|
||||
self.add_constraints_from_ty(current, typ, variance);
|
||||
}
|
||||
|
@ -130,6 +130,7 @@ fn pointer_kind(
|
||||
| ty::CoroutineWitness(..)
|
||||
| ty::RawPtr(_, _)
|
||||
| ty::Ref(..)
|
||||
| ty::Pat(..)
|
||||
| ty::FnDef(..)
|
||||
| ty::FnPtr(..)
|
||||
| ty::Closure(..)
|
||||
|
@ -440,6 +440,7 @@ fn fold_ty(&mut self, mut t: Ty<'tcx>) -> Ty<'tcx> {
|
||||
| ty::Tuple(..)
|
||||
| ty::Alias(..)
|
||||
| ty::Foreign(..)
|
||||
| ty::Pat(..)
|
||||
| ty::Param(..) => {
|
||||
if t.flags().intersects(self.needs_canonical_flags) {
|
||||
t.super_fold_with(self)
|
||||
|
@ -93,6 +93,7 @@ fn compute_components<'tcx>(
|
||||
}
|
||||
}
|
||||
|
||||
ty::Pat(element, _) |
|
||||
ty::Array(element, _) => {
|
||||
// Don't look into the len const as it doesn't affect regions
|
||||
compute_components(tcx, element, out, visited);
|
||||
|
@ -299,6 +299,9 @@ lint_improper_ctypes_only_phantomdata = composed only of `PhantomData`
|
||||
|
||||
lint_improper_ctypes_opaque = opaque types have no C equivalent
|
||||
|
||||
lint_improper_ctypes_pat_help = consider using the base type instead
|
||||
|
||||
lint_improper_ctypes_pat_reason = pattern types have no C equivalent
|
||||
lint_improper_ctypes_slice_help = consider using a raw pointer instead
|
||||
|
||||
lint_improper_ctypes_slice_reason = slices have no C equivalent
|
||||
|
@ -1379,6 +1379,12 @@ fn check_type_for_ffi(&self, cache: &mut FxHashSet<Ty<'tcx>>, ty: Ty<'tcx>) -> F
|
||||
help: Some(fluent::lint_improper_ctypes_char_help),
|
||||
},
|
||||
|
||||
ty::Pat(..) => FfiUnsafe {
|
||||
ty,
|
||||
reason: fluent::lint_improper_ctypes_pat_reason,
|
||||
help: Some(fluent::lint_improper_ctypes_pat_help),
|
||||
},
|
||||
|
||||
ty::Int(ty::IntTy::I128) | ty::Uint(ty::UintTy::U128) => {
|
||||
FfiUnsafe { ty, reason: fluent::lint_improper_ctypes_128bit, help: None }
|
||||
}
|
||||
|
@ -90,6 +90,7 @@ macro_rules! arena_types {
|
||||
[decode] attribute: rustc_ast::Attribute,
|
||||
[] name_set: rustc_data_structures::unord::UnordSet<rustc_span::symbol::Symbol>,
|
||||
[] ordered_name_set: rustc_data_structures::fx::FxIndexSet<rustc_span::symbol::Symbol>,
|
||||
[] pats: rustc_middle::ty::PatternKind<'tcx>,
|
||||
|
||||
// Note that this deliberately duplicates items in the `rustc_hir::arena`,
|
||||
// since we need to allocate this type on both the `rustc_hir` arena
|
||||
|
@ -148,6 +148,12 @@ fn encode(&self, e: &mut E) {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::Pattern<'tcx> {
|
||||
fn encode(&self, e: &mut E) {
|
||||
self.0.0.encode(e);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ConstAllocation<'tcx> {
|
||||
fn encode(&self, e: &mut E) {
|
||||
self.inner().encode(e)
|
||||
@ -364,6 +370,12 @@ fn decode(decoder: &mut D) -> Self {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Pattern<'tcx> {
|
||||
fn decode(decoder: &mut D) -> Self {
|
||||
decoder.interner().mk_pat(Decodable::decode(decoder))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for [ty::ValTree<'tcx>] {
|
||||
fn decode(decoder: &mut D) -> &'tcx Self {
|
||||
decoder
|
||||
|
@ -26,9 +26,10 @@
|
||||
};
|
||||
use crate::ty::{
|
||||
self, AdtDef, AdtDefData, AdtKind, Binder, Clause, Clauses, Const, ConstData,
|
||||
GenericParamDefKind, ImplPolarity, List, ListWithCachedTypeInfo, ParamConst, ParamTy,
|
||||
PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, PredicatePolarity, Region,
|
||||
RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVid, TypeVisitable, Visibility,
|
||||
GenericParamDefKind, ImplPolarity, List, ListWithCachedTypeInfo, ParamConst, ParamTy, Pattern,
|
||||
PatternKind, PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, PredicatePolarity,
|
||||
Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVid, TypeVisitable,
|
||||
Visibility,
|
||||
};
|
||||
use crate::ty::{GenericArg, GenericArgs, GenericArgsRef};
|
||||
use rustc_ast::{self as ast, attr};
|
||||
@ -95,6 +96,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
||||
type CanonicalVars = CanonicalVarInfos<'tcx>;
|
||||
|
||||
type Ty = Ty<'tcx>;
|
||||
type Pat = Pattern<'tcx>;
|
||||
type Tys = &'tcx List<Ty<'tcx>>;
|
||||
type AliasTy = ty::AliasTy<'tcx>;
|
||||
type ParamTy = ParamTy;
|
||||
@ -157,6 +159,7 @@ pub struct CtxtInterners<'tcx> {
|
||||
projs: InternedSet<'tcx, List<ProjectionKind>>,
|
||||
place_elems: InternedSet<'tcx, List<PlaceElem<'tcx>>>,
|
||||
const_: InternedSet<'tcx, WithCachedTypeInfo<ConstData<'tcx>>>,
|
||||
pat: InternedSet<'tcx, PatternKind<'tcx>>,
|
||||
const_allocation: InternedSet<'tcx, Allocation>,
|
||||
bound_variable_kinds: InternedSet<'tcx, List<ty::BoundVariableKind>>,
|
||||
layout: InternedSet<'tcx, LayoutS<FieldIdx, VariantIdx>>,
|
||||
@ -184,6 +187,7 @@ fn new(arena: &'tcx WorkerLocal<Arena<'tcx>>) -> CtxtInterners<'tcx> {
|
||||
projs: Default::default(),
|
||||
place_elems: Default::default(),
|
||||
const_: Default::default(),
|
||||
pat: Default::default(),
|
||||
const_allocation: Default::default(),
|
||||
bound_variable_kinds: Default::default(),
|
||||
layout: Default::default(),
|
||||
@ -1578,6 +1582,7 @@ fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
|
||||
nop_lift! {type_; Ty<'a> => Ty<'tcx>}
|
||||
nop_lift! {region; Region<'a> => Region<'tcx>}
|
||||
nop_lift! {const_; Const<'a> => Const<'tcx>}
|
||||
nop_lift! {pat; Pattern<'a> => Pattern<'tcx>}
|
||||
nop_lift! {const_allocation; ConstAllocation<'a> => ConstAllocation<'tcx>}
|
||||
nop_lift! {predicate; Predicate<'a> => Predicate<'tcx>}
|
||||
nop_lift! {predicate; Clause<'a> => Clause<'tcx>}
|
||||
@ -1715,6 +1720,7 @@ fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
Param,
|
||||
Infer,
|
||||
Alias,
|
||||
Pat,
|
||||
Foreign
|
||||
)?;
|
||||
|
||||
@ -1866,6 +1872,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
// crate only, and have a corresponding `mk_` function.
|
||||
direct_interners! {
|
||||
region: pub(crate) intern_region(RegionKind<'tcx>): Region -> Region<'tcx>,
|
||||
pat: pub mk_pat(PatternKind<'tcx>): Pattern -> Pattern<'tcx>,
|
||||
const_allocation: pub mk_const_alloc(Allocation): ConstAllocation -> ConstAllocation<'tcx>,
|
||||
layout: pub mk_layout(LayoutS<FieldIdx, VariantIdx>): Layout -> Layout<'tcx>,
|
||||
adt_def: pub mk_adt_def_from_data(AdtDefData): AdtDef -> AdtDef<'tcx>,
|
||||
|
@ -285,6 +285,7 @@ pub fn prefix_string(self, tcx: TyCtxt<'_>) -> Cow<'static, str> {
|
||||
ty::Adt(def, _) => def.descr().into(),
|
||||
ty::Foreign(_) => "extern type".into(),
|
||||
ty::Array(..) => "array".into(),
|
||||
ty::Pat(..) => "pattern type".into(),
|
||||
ty::Slice(_) => "slice".into(),
|
||||
ty::RawPtr(_, _) => "raw pointer".into(),
|
||||
ty::Ref(.., mutbl) => match mutbl {
|
||||
|
@ -120,6 +120,7 @@ pub fn simplify_type<'tcx>(
|
||||
ty::Str => Some(SimplifiedType::Str),
|
||||
ty::Array(..) => Some(SimplifiedType::Array),
|
||||
ty::Slice(..) => Some(SimplifiedType::Slice),
|
||||
ty::Pat(ty, ..) => simplify_type(tcx, ty, treat_params),
|
||||
ty::RawPtr(_, mutbl) => Some(SimplifiedType::Ptr(mutbl)),
|
||||
ty::Dynamic(trait_info, ..) => match trait_info.principal_def_id() {
|
||||
Some(principal_def_id) if !tcx.trait_is_auto(principal_def_id) => {
|
||||
@ -231,6 +232,7 @@ pub fn types_may_unify<'tcx>(self, obligation_ty: Ty<'tcx>, impl_ty: Ty<'tcx>) -
|
||||
| ty::Slice(..)
|
||||
| ty::RawPtr(..)
|
||||
| ty::Dynamic(..)
|
||||
| ty::Pat(..)
|
||||
| ty::Ref(..)
|
||||
| ty::Never
|
||||
| ty::Tuple(..)
|
||||
@ -269,6 +271,10 @@ pub fn types_may_unify<'tcx>(self, obligation_ty: Ty<'tcx>, impl_ty: Ty<'tcx>) -
|
||||
}
|
||||
_ => false,
|
||||
},
|
||||
ty::Pat(obl_ty, _) => {
|
||||
// FIXME(pattern_types): take pattern into account
|
||||
matches!(k, &ty::Pat(impl_ty, _) if self.types_may_unify(obl_ty, impl_ty))
|
||||
}
|
||||
ty::Slice(obl_ty) => {
|
||||
matches!(k, &ty::Slice(impl_ty) if self.types_may_unify(obl_ty, impl_ty))
|
||||
}
|
||||
|
@ -218,6 +218,20 @@ fn add_kind(&mut self, kind: &ty::TyKind<'_>) {
|
||||
self.add_const(len);
|
||||
}
|
||||
|
||||
&ty::Pat(ty, pat) => {
|
||||
self.add_ty(ty);
|
||||
match *pat {
|
||||
ty::PatternKind::Range { start, end, include_end: _ } => {
|
||||
if let Some(start) = start {
|
||||
self.add_const(start)
|
||||
}
|
||||
if let Some(end) = end {
|
||||
self.add_const(end)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&ty::Slice(tt) => self.add_ty(tt),
|
||||
|
||||
&ty::RawPtr(ty, _) => {
|
||||
|
@ -316,11 +316,11 @@ pub fn has_impl_trait(&'tcx self) -> bool {
|
||||
/// of this item, excluding `Self`.
|
||||
///
|
||||
/// **This should only be used for diagnostics purposes.**
|
||||
pub fn own_args_no_defaults(
|
||||
pub fn own_args_no_defaults<'a>(
|
||||
&'tcx self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
args: &'tcx [ty::GenericArg<'tcx>],
|
||||
) -> &'tcx [ty::GenericArg<'tcx>] {
|
||||
args: &'a [ty::GenericArg<'tcx>],
|
||||
) -> &'a [ty::GenericArg<'tcx>] {
|
||||
let mut own_params = self.parent_count..self.count();
|
||||
if self.has_self && self.parent.is_none() {
|
||||
own_params.start = 1;
|
||||
|
@ -742,6 +742,7 @@ fn field_ty_or_layout<'tcx>(
|
||||
| ty::FnDef(..)
|
||||
| ty::CoroutineWitness(..)
|
||||
| ty::Foreign(..)
|
||||
| ty::Pat(_, _)
|
||||
| ty::Dynamic(_, _, ty::Dyn) => {
|
||||
bug!("TyAndLayout::field({:?}): not applicable", this)
|
||||
}
|
||||
|
@ -91,6 +91,7 @@
|
||||
pub use self::instance::{Instance, InstanceDef, ReifyReason, ShortInstance, UnusedGenericParams};
|
||||
pub use self::list::{List, ListWithCachedTypeInfo};
|
||||
pub use self::parameterized::ParameterizedOverTcx;
|
||||
pub use self::pattern::{Pattern, PatternKind};
|
||||
pub use self::predicate::{
|
||||
Clause, ClauseKind, CoercePredicate, ExistentialPredicate, ExistentialProjection,
|
||||
ExistentialTraitRef, NormalizesTo, OutlivesPredicate, PolyCoercePredicate,
|
||||
@ -130,6 +131,7 @@
|
||||
pub mod inhabitedness;
|
||||
pub mod layout;
|
||||
pub mod normalize_erasing_regions;
|
||||
pub mod pattern;
|
||||
pub mod print;
|
||||
pub mod relate;
|
||||
pub mod trait_def;
|
||||
|
48
compiler/rustc_middle/src/ty/pattern.rs
Normal file
48
compiler/rustc_middle/src/ty/pattern.rs
Normal file
@ -0,0 +1,48 @@
|
||||
use std::fmt;
|
||||
|
||||
use crate::ty;
|
||||
use rustc_data_structures::intern::Interned;
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable)]
|
||||
#[rustc_pass_by_value]
|
||||
pub struct Pattern<'tcx>(pub Interned<'tcx, PatternKind<'tcx>>);
|
||||
|
||||
impl<'tcx> std::ops::Deref for Pattern<'tcx> {
|
||||
type Target = PatternKind<'tcx>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&*self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> fmt::Debug for Pattern<'tcx> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", **self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> fmt::Debug for PatternKind<'tcx> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match *self {
|
||||
PatternKind::Range { start, end, include_end } => {
|
||||
if let Some(start) = start {
|
||||
write!(f, "{start}")?;
|
||||
}
|
||||
write!(f, "..")?;
|
||||
if include_end {
|
||||
write!(f, "=")?;
|
||||
}
|
||||
if let Some(end) = end {
|
||||
write!(f, "{end}")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||
#[derive(HashStable, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)]
|
||||
pub enum PatternKind<'tcx> {
|
||||
Range { start: Option<ty::Const<'tcx>>, end: Option<ty::Const<'tcx>>, include_end: bool },
|
||||
}
|
@ -259,7 +259,7 @@ fn characteristic_def_id_of_type_cached<'a>(
|
||||
|
||||
ty::Dynamic(data, ..) => data.principal_def_id(),
|
||||
|
||||
ty::Array(subty, _) | ty::Slice(subty) => {
|
||||
ty::Pat(subty, _) | ty::Array(subty, _) | ty::Slice(subty) => {
|
||||
characteristic_def_id_of_type_cached(subty, visited)
|
||||
}
|
||||
|
||||
|
@ -667,6 +667,9 @@ fn pretty_print_type(&mut self, ty: Ty<'tcx>) -> Result<(), PrintError> {
|
||||
ty::Int(t) => p!(write("{}", t.name_str())),
|
||||
ty::Uint(t) => p!(write("{}", t.name_str())),
|
||||
ty::Float(t) => p!(write("{}", t.name_str())),
|
||||
ty::Pat(ty, pat) => {
|
||||
p!("(", print(ty), ") is ", write("{pat:?}"))
|
||||
}
|
||||
ty::RawPtr(ty, mutbl) => {
|
||||
p!(write(
|
||||
"*{} ",
|
||||
|
@ -13,6 +13,8 @@
|
||||
use rustc_target::spec::abi;
|
||||
use std::iter;
|
||||
|
||||
use super::Pattern;
|
||||
|
||||
pub type RelateResult<'tcx, T> = Result<T, TypeError<'tcx>>;
|
||||
|
||||
pub trait TypeRelation<'tcx>: Sized {
|
||||
@ -351,6 +353,36 @@ fn relate<R: TypeRelation<'tcx>>(
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Relate<'tcx> for Pattern<'tcx> {
|
||||
#[inline]
|
||||
fn relate<R: TypeRelation<'tcx>>(
|
||||
relation: &mut R,
|
||||
a: Self,
|
||||
b: Self,
|
||||
) -> RelateResult<'tcx, Self> {
|
||||
match (&*a, &*b) {
|
||||
(
|
||||
&ty::PatternKind::Range { start: start_a, end: end_a, include_end: inc_a },
|
||||
&ty::PatternKind::Range { start: start_b, end: end_b, include_end: inc_b },
|
||||
) => {
|
||||
// FIXME(pattern_types): make equal patterns equal (`0..=` is the same as `..=`).
|
||||
let mut relate_opt_const = |a, b| match (a, b) {
|
||||
(None, None) => Ok(None),
|
||||
(Some(a), Some(b)) => relation.relate(a, b).map(Some),
|
||||
// FIXME(pattern_types): report a better error
|
||||
_ => Err(TypeError::Mismatch),
|
||||
};
|
||||
let start = relate_opt_const(start_a, start_b)?;
|
||||
let end = relate_opt_const(end_a, end_b)?;
|
||||
if inc_a != inc_b {
|
||||
todo!()
|
||||
}
|
||||
Ok(relation.tcx().mk_pat(ty::PatternKind::Range { start, end, include_end: inc_a }))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Relates `a` and `b` structurally, calling the relation for all nested values.
|
||||
/// Any semantic equality, e.g. of projections, and inference variables have to be
|
||||
/// handled by the caller.
|
||||
@ -533,6 +565,12 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>(
|
||||
Ok(Ty::new_alias(tcx, a_kind, alias_ty))
|
||||
}
|
||||
|
||||
(&ty::Pat(a_ty, a_pat), &ty::Pat(b_ty, b_pat)) => {
|
||||
let ty = relation.relate(a_ty, b_ty)?;
|
||||
let pat = relation.relate(a_pat, b_pat)?;
|
||||
Ok(Ty::new_pat(tcx, ty, pat))
|
||||
}
|
||||
|
||||
_ => Err(TypeError::Sorts(expected_found(a, b))),
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,8 @@
|
||||
use super::print::PrettyPrinter;
|
||||
use super::{GenericArg, GenericArgKind, Region};
|
||||
|
||||
use super::Pattern;
|
||||
|
||||
impl fmt::Debug for ty::TraitDef {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
ty::tls::with(|tcx| {
|
||||
@ -210,6 +212,22 @@ fn fmt<Infcx: InferCtxtLike<Interner = TyCtxt<'tcx>>>(
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for Pattern<'tcx> {
|
||||
fn fmt<Infcx: InferCtxtLike<Interner = TyCtxt<'tcx>>>(
|
||||
this: WithInfcx<'_, Infcx, &Self>,
|
||||
f: &mut core::fmt::Formatter<'_>,
|
||||
) -> core::fmt::Result {
|
||||
match &**this.data {
|
||||
ty::PatternKind::Range { start, end, include_end } => f
|
||||
.debug_struct("Pattern::Range")
|
||||
.field("start", start)
|
||||
.field("end", end)
|
||||
.field("include_end", include_end)
|
||||
.finish(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> fmt::Debug for ty::consts::Expr<'tcx> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
WithInfcx::with_no_infcx(self).fmt(f)
|
||||
@ -541,6 +559,22 @@ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for Pattern<'tcx> {
|
||||
fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
|
||||
self,
|
||||
folder: &mut F,
|
||||
) -> Result<Self, F::Error> {
|
||||
let pat = (*self).clone().try_fold_with(folder)?;
|
||||
Ok(if pat == *self { self } else { folder.interner().mk_pat(pat) })
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for Pattern<'tcx> {
|
||||
fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
|
||||
(**self).visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for Ty<'tcx> {
|
||||
fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
|
||||
self,
|
||||
@ -586,6 +620,7 @@ fn try_super_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
|
||||
ty::CoroutineClosure(did, args.try_fold_with(folder)?)
|
||||
}
|
||||
ty::Alias(kind, data) => ty::Alias(kind, data.try_fold_with(folder)?),
|
||||
ty::Pat(ty, pat) => ty::Pat(ty.try_fold_with(folder)?, pat.try_fold_with(folder)?),
|
||||
|
||||
ty::Bool
|
||||
| ty::Char
|
||||
@ -633,6 +668,11 @@ fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::
|
||||
ty::CoroutineClosure(_did, ref args) => args.visit_with(visitor),
|
||||
ty::Alias(_, ref data) => data.visit_with(visitor),
|
||||
|
||||
ty::Pat(ty, pat) => {
|
||||
try_visit!(ty.visit_with(visitor));
|
||||
pat.visit_with(visitor)
|
||||
}
|
||||
|
||||
ty::Bool
|
||||
| ty::Char
|
||||
| ty::Str
|
||||
|
@ -1522,6 +1522,11 @@ pub fn new_alias(
|
||||
Ty::new(tcx, Alias(kind, alias_ty))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn new_pat(tcx: TyCtxt<'tcx>, base: Ty<'tcx>, pat: ty::Pattern<'tcx>) -> Ty<'tcx> {
|
||||
Ty::new(tcx, Pat(base, pat))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn new_opaque(tcx: TyCtxt<'tcx>, def_id: DefId, args: GenericArgsRef<'tcx>) -> Ty<'tcx> {
|
||||
Ty::new_alias(tcx, ty::Opaque, AliasTy::new(tcx, def_id, args))
|
||||
@ -2278,6 +2283,8 @@ pub fn discriminant_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
|
||||
Ty::new_projection(tcx, assoc_items[0], tcx.mk_args(&[self.into()]))
|
||||
}
|
||||
|
||||
ty::Pat(ty, _) => ty.discriminant_ty(tcx),
|
||||
|
||||
ty::Bool
|
||||
| ty::Char
|
||||
| ty::Int(_)
|
||||
@ -2359,6 +2366,7 @@ pub fn ptr_metadata_ty_or_tail(
|
||||
ty::Param(_) | ty::Alias(..) => Err(tail),
|
||||
|
||||
ty::Infer(ty::TyVar(_))
|
||||
| ty::Pat(..)
|
||||
| ty::Bound(..)
|
||||
| ty::Placeholder(..)
|
||||
| ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => bug!(
|
||||
@ -2495,6 +2503,7 @@ pub fn is_trivially_sized(self, tcx: TyCtxt<'tcx>) -> bool {
|
||||
| ty::Coroutine(..)
|
||||
| ty::CoroutineWitness(..)
|
||||
| ty::Array(..)
|
||||
| ty::Pat(..)
|
||||
| ty::Closure(..)
|
||||
| ty::CoroutineClosure(..)
|
||||
| ty::Never
|
||||
@ -2549,6 +2558,8 @@ pub fn is_trivially_pure_clone_copy(self) -> bool {
|
||||
field_tys.len() <= 3 && field_tys.iter().all(Self::is_trivially_pure_clone_copy)
|
||||
}
|
||||
|
||||
ty::Pat(ty, _) => ty.is_trivially_pure_clone_copy(),
|
||||
|
||||
// Sometimes traits aren't implemented for every ABI or arity,
|
||||
// because we can't be generic over everything yet.
|
||||
ty::FnPtr(..) => false,
|
||||
@ -2630,6 +2641,7 @@ pub fn is_known_rigid(self) -> bool {
|
||||
| Foreign(_)
|
||||
| Str
|
||||
| Array(_, _)
|
||||
| Pat(_, _)
|
||||
| Slice(_)
|
||||
| RawPtr(_, _)
|
||||
| Ref(_, _, _)
|
||||
|
@ -245,6 +245,11 @@ pub fn struct_tail_with_normalize(
|
||||
|
||||
ty::Tuple(_) => break,
|
||||
|
||||
ty::Pat(inner, _) => {
|
||||
f();
|
||||
ty = inner;
|
||||
}
|
||||
|
||||
ty::Alias(..) => {
|
||||
let normalized = normalize(ty);
|
||||
if ty == normalized {
|
||||
@ -1242,7 +1247,7 @@ fn is_trivially_freeze(self) -> bool {
|
||||
| ty::Error(_)
|
||||
| ty::FnPtr(_) => true,
|
||||
ty::Tuple(fields) => fields.iter().all(Self::is_trivially_freeze),
|
||||
ty::Slice(elem_ty) | ty::Array(elem_ty, _) => elem_ty.is_trivially_freeze(),
|
||||
ty::Pat(ty, _) | ty::Slice(ty) | ty::Array(ty, _) => ty.is_trivially_freeze(),
|
||||
ty::Adt(..)
|
||||
| ty::Bound(..)
|
||||
| ty::Closure(..)
|
||||
@ -1282,7 +1287,7 @@ fn is_trivially_unpin(self) -> bool {
|
||||
| ty::Error(_)
|
||||
| ty::FnPtr(_) => true,
|
||||
ty::Tuple(fields) => fields.iter().all(Self::is_trivially_unpin),
|
||||
ty::Slice(elem_ty) | ty::Array(elem_ty, _) => elem_ty.is_trivially_unpin(),
|
||||
ty::Pat(ty, _) | ty::Slice(ty) | ty::Array(ty, _) => ty.is_trivially_unpin(),
|
||||
ty::Adt(..)
|
||||
| ty::Bound(..)
|
||||
| ty::Closure(..)
|
||||
@ -1398,7 +1403,7 @@ pub fn is_structural_eq_shallow(self, tcx: TyCtxt<'tcx>) -> bool {
|
||||
//
|
||||
// Because this function is "shallow", we return `true` for these composites regardless
|
||||
// of the type(s) contained within.
|
||||
ty::Ref(..) | ty::Array(..) | ty::Slice(_) | ty::Tuple(..) => true,
|
||||
ty::Pat(..) | ty::Ref(..) | ty::Array(..) | ty::Slice(_) | ty::Tuple(..) => true,
|
||||
|
||||
// Raw pointers use bitwise comparison.
|
||||
ty::RawPtr(_, _) | ty::FnPtr(_) => true,
|
||||
@ -1528,7 +1533,7 @@ pub fn needs_drop_components<'tcx>(
|
||||
|
||||
ty::Dynamic(..) | ty::Error(_) => Err(AlwaysRequiresDrop),
|
||||
|
||||
ty::Slice(ty) => needs_drop_components(tcx, ty),
|
||||
ty::Pat(ty, _) | ty::Slice(ty) => needs_drop_components(tcx, ty),
|
||||
ty::Array(elem_ty, size) => {
|
||||
match needs_drop_components(tcx, elem_ty) {
|
||||
Ok(v) if v.is_empty() => Ok(v),
|
||||
@ -1597,7 +1602,7 @@ pub fn is_trivially_const_drop(ty: Ty<'_>) -> bool {
|
||||
| ty::CoroutineWitness(..)
|
||||
| ty::Adt(..) => false,
|
||||
|
||||
ty::Array(ty, _) | ty::Slice(ty) => is_trivially_const_drop(ty),
|
||||
ty::Array(ty, _) | ty::Slice(ty) | ty::Pat(ty, _) => is_trivially_const_drop(ty),
|
||||
|
||||
ty::Tuple(tys) => tys.iter().all(|ty| is_trivially_const_drop(ty)),
|
||||
}
|
||||
|
@ -151,6 +151,15 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>)
|
||||
| ty::Bound(..)
|
||||
| ty::Foreign(..) => {}
|
||||
|
||||
ty::Pat(ty, pat) => {
|
||||
match *pat {
|
||||
ty::PatternKind::Range { start, end, include_end: _ } => {
|
||||
stack.extend(end.map(Into::into));
|
||||
stack.extend(start.map(Into::into));
|
||||
}
|
||||
}
|
||||
stack.push(ty.into());
|
||||
}
|
||||
ty::Array(ty, len) => {
|
||||
stack.push(len.into());
|
||||
stack.push(ty.into());
|
||||
|
@ -457,7 +457,7 @@ fn recur(
|
||||
PatKind::Constant { value: mir::Const::Ty(ty::Const::new_value(tcx, cv, ty)) }
|
||||
}
|
||||
}
|
||||
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::RawPtr(..) => {
|
||||
ty::Pat(..) | ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::RawPtr(..) => {
|
||||
// The raw pointers we see here have been "vetted" by valtree construction to be
|
||||
// just integers, so we simply allow them.
|
||||
PatKind::Constant { value: mir::Const::Ty(ty::Const::new_value(tcx, cv, ty)) }
|
||||
|
@ -153,6 +153,7 @@ fn move_path_for(&mut self, place: Place<'tcx>) -> MovePathResult {
|
||||
| ty::Foreign(_)
|
||||
| ty::Str
|
||||
| ty::Array(_, _)
|
||||
| ty::Pat(_, _)
|
||||
| ty::Slice(_)
|
||||
| ty::FnDef(_, _)
|
||||
| ty::FnPtr(_)
|
||||
@ -193,6 +194,7 @@ fn move_path_for(&mut self, place: Place<'tcx>) -> MovePathResult {
|
||||
| ty::Foreign(_)
|
||||
| ty::Str
|
||||
| ty::Array(_, _)
|
||||
| ty::Pat(_, _)
|
||||
| ty::Slice(_)
|
||||
| ty::RawPtr(_, _)
|
||||
| ty::Ref(_, _, _)
|
||||
|
@ -684,6 +684,7 @@ fn try_write_constant<'tcx>(
|
||||
|
||||
// Unsupported for now.
|
||||
ty::Array(_, _)
|
||||
| ty::Pat(_, _)
|
||||
|
||||
// Do not attempt to support indirection in constants.
|
||||
| ty::Ref(..) | ty::RawPtr(..) | ty::FnPtr(..) | ty::Str | ty::Slice(_)
|
||||
|
@ -349,6 +349,7 @@ fn fold_ty(&mut self, t: I::Ty) -> I::Ty {
|
||||
| ty::Slice(_)
|
||||
| ty::RawPtr(_, _)
|
||||
| ty::Ref(_, _, _)
|
||||
| ty::Pat(_, _)
|
||||
| ty::FnDef(_, _)
|
||||
| ty::FnPtr(_)
|
||||
| ty::Dynamic(_, _, _)
|
||||
|
@ -161,4 +161,8 @@ fn visit_impl_item(&mut self, i: &'hir hir::ImplItem<'hir>) {
|
||||
let mut inner_visitor = self.new_visitor(self.tcx);
|
||||
inner_visitor.check(i.owner_id, |this| intravisit::walk_impl_item(this, i));
|
||||
}
|
||||
|
||||
fn visit_pattern_type_pattern(&mut self, p: &'hir hir::Pat<'hir>) {
|
||||
self.visit_pat(p)
|
||||
}
|
||||
}
|
||||
|
@ -399,6 +399,7 @@ pub fn ctors_for_ty(
|
||||
| ty::RawPtr(_, _)
|
||||
| ty::FnDef(_, _)
|
||||
| ty::FnPtr(_)
|
||||
| ty::Pat(_, _)
|
||||
| ty::Dynamic(_, _, _)
|
||||
| ty::Closure(..)
|
||||
| ty::CoroutineClosure(..)
|
||||
|
@ -276,6 +276,7 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
|
||||
| ty::Tuple(..)
|
||||
| ty::RawPtr(..)
|
||||
| ty::Ref(..)
|
||||
| ty::Pat(..)
|
||||
| ty::FnPtr(..)
|
||||
| ty::Param(..)
|
||||
| ty::Bound(..)
|
||||
|
@ -14,8 +14,8 @@
|
||||
use stable_mir::ty::{
|
||||
Abi, AdtDef, Binder, BoundRegionKind, BoundTyKind, BoundVariableKind, ClosureKind, Const,
|
||||
DynKind, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FloatTy, FnSig,
|
||||
GenericArgKind, GenericArgs, IndexedVal, IntTy, Movability, Region, RigidTy, Span, TermKind,
|
||||
TraitRef, Ty, UintTy, VariantDef, VariantIdx,
|
||||
GenericArgKind, GenericArgs, IndexedVal, IntTy, Movability, Pattern, Region, RigidTy, Span,
|
||||
TermKind, TraitRef, Ty, UintTy, VariantDef, VariantIdx,
|
||||
};
|
||||
use stable_mir::{CrateItem, CrateNum, DefId};
|
||||
|
||||
@ -76,6 +76,19 @@ fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<
|
||||
}
|
||||
}
|
||||
|
||||
impl RustcInternal for Pattern {
|
||||
type T<'tcx> = rustc_ty::Pattern<'tcx>;
|
||||
fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||
tcx.mk_pat(match self {
|
||||
Pattern::Range { start, end, include_end } => rustc_ty::PatternKind::Range {
|
||||
start: start.as_ref().map(|c| ty_const(c, tables, tcx)),
|
||||
end: end.as_ref().map(|c| ty_const(c, tables, tcx)),
|
||||
include_end: *include_end,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl RustcInternal for RigidTy {
|
||||
type T<'tcx> = rustc_ty::TyKind<'tcx>;
|
||||
|
||||
@ -90,6 +103,9 @@ fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<
|
||||
RigidTy::Array(ty, cnst) => {
|
||||
rustc_ty::TyKind::Array(ty.internal(tables, tcx), ty_const(cnst, tables, tcx))
|
||||
}
|
||||
RigidTy::Pat(ty, pat) => {
|
||||
rustc_ty::TyKind::Pat(ty.internal(tables, tcx), pat.internal(tables, tcx))
|
||||
}
|
||||
RigidTy::Adt(def, args) => {
|
||||
rustc_ty::TyKind::Adt(def.internal(tables, tcx), args.internal(tables, tcx))
|
||||
}
|
||||
|
@ -330,6 +330,9 @@ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
ty::Array(ty, constant) => {
|
||||
TyKind::RigidTy(RigidTy::Array(ty.stable(tables), constant.stable(tables)))
|
||||
}
|
||||
ty::Pat(ty, pat) => {
|
||||
TyKind::RigidTy(RigidTy::Pat(ty.stable(tables), pat.stable(tables)))
|
||||
}
|
||||
ty::Slice(ty) => TyKind::RigidTy(RigidTy::Slice(ty.stable(tables))),
|
||||
ty::RawPtr(ty, mutbl) => {
|
||||
TyKind::RigidTy(RigidTy::RawPtr(ty.stable(tables), mutbl.stable(tables)))
|
||||
@ -385,6 +388,20 @@ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::Pattern<'tcx> {
|
||||
type T = stable_mir::ty::Pattern;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
match **self {
|
||||
ty::PatternKind::Range { start, end, include_end } => stable_mir::ty::Pattern::Range {
|
||||
start: start.stable(tables),
|
||||
end: end.stable(tables),
|
||||
include_end,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::Const<'tcx> {
|
||||
type T = stable_mir::ty::Const;
|
||||
|
||||
|
@ -533,6 +533,16 @@ fn encode_ty<'tcx>(
|
||||
typeid.push_str(&s);
|
||||
}
|
||||
|
||||
ty::Pat(ty0, pat) => {
|
||||
// u3patI<element-type><pattern>E as vendor extended type
|
||||
let mut s = String::from("u3patI");
|
||||
s.push_str(&encode_ty(tcx, *ty0, dict, options));
|
||||
write!(s, "{:?}", **pat).unwrap();
|
||||
s.push('E');
|
||||
compress(dict, DictKey::Ty(ty, TyQ::None), &mut s);
|
||||
typeid.push_str(&s);
|
||||
}
|
||||
|
||||
ty::Slice(ty0) => {
|
||||
// u5sliceI<element-type>E as vendor extended type
|
||||
let mut s = String::from("u5sliceI");
|
||||
@ -782,6 +792,7 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
|
||||
| ty::Foreign(..)
|
||||
| ty::Never
|
||||
| ty::Slice(..)
|
||||
| ty::Pat(..)
|
||||
| ty::Str
|
||||
| ty::Tuple(..) => t.super_fold_with(self),
|
||||
|
||||
|
@ -371,6 +371,25 @@ fn print_type(&mut self, ty: Ty<'tcx>) -> Result<(), PrintError> {
|
||||
ty.print(self)?;
|
||||
}
|
||||
|
||||
ty::Pat(ty, pat) => match *pat {
|
||||
ty::PatternKind::Range { start, end, include_end } => {
|
||||
let consts = [
|
||||
start.unwrap_or(self.tcx.consts.unit),
|
||||
end.unwrap_or(self.tcx.consts.unit),
|
||||
ty::Const::from_bool(self.tcx, include_end).into(),
|
||||
];
|
||||
// HACK: Represent as tuple until we have something better.
|
||||
// HACK: constants are used in arrays, even if the types don't match.
|
||||
self.push("T");
|
||||
ty.print(self)?;
|
||||
for ct in consts {
|
||||
Ty::new_array_with_const_len(self.tcx, self.tcx.types.unit, ct)
|
||||
.print(self)?;
|
||||
}
|
||||
self.push("E");
|
||||
}
|
||||
},
|
||||
|
||||
ty::Array(ty, len) => {
|
||||
self.push("A");
|
||||
ty.print(self)?;
|
||||
|
@ -363,6 +363,7 @@ fn assemble_non_blanket_impl_candidates<G: GoalKind<'tcx>>(
|
||||
| ty::Foreign(_)
|
||||
| ty::Str
|
||||
| ty::Array(_, _)
|
||||
| ty::Pat(_, _)
|
||||
| ty::Slice(_)
|
||||
| ty::RawPtr(_, _)
|
||||
| ty::Ref(_, _, _)
|
||||
@ -596,6 +597,7 @@ fn assemble_alias_bound_candidates_recur<G: GoalKind<'tcx>>(
|
||||
| ty::Foreign(_)
|
||||
| ty::Str
|
||||
| ty::Array(_, _)
|
||||
| ty::Pat(_, _)
|
||||
| ty::Slice(_)
|
||||
| ty::RawPtr(_, _)
|
||||
| ty::Ref(_, _, _)
|
||||
@ -684,6 +686,7 @@ fn assemble_object_bound_candidates<G: GoalKind<'tcx>>(
|
||||
| ty::Foreign(_)
|
||||
| ty::Str
|
||||
| ty::Array(_, _)
|
||||
| ty::Pat(_, _)
|
||||
| ty::Slice(_)
|
||||
| ty::RawPtr(_, _)
|
||||
| ty::Ref(_, _, _)
|
||||
|
@ -50,7 +50,9 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>(
|
||||
Ok(vec![ty::Binder::dummy(element_ty)])
|
||||
}
|
||||
|
||||
ty::Array(element_ty, _) | ty::Slice(element_ty) => Ok(vec![ty::Binder::dummy(element_ty)]),
|
||||
ty::Pat(element_ty, _) | ty::Array(element_ty, _) | ty::Slice(element_ty) => {
|
||||
Ok(vec![ty::Binder::dummy(element_ty)])
|
||||
}
|
||||
|
||||
ty::Tuple(tys) => {
|
||||
// (T1, ..., Tn) -- meets any bound that all of T1...Tn meet
|
||||
@ -114,6 +116,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<'tcx>(
|
||||
| ty::Coroutine(..)
|
||||
| ty::CoroutineWitness(..)
|
||||
| ty::Array(..)
|
||||
| ty::Pat(..)
|
||||
| ty::Closure(..)
|
||||
| ty::CoroutineClosure(..)
|
||||
| ty::Never
|
||||
@ -177,6 +180,10 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>(
|
||||
| ty::Ref(_, _, Mutability::Not)
|
||||
| ty::Array(..) => Err(NoSolution),
|
||||
|
||||
// Cannot implement in core, as we can't be generic over patterns yet,
|
||||
// so we'd have to list all patterns and type combinations.
|
||||
ty::Pat(ty, ..) => Ok(vec![ty::Binder::dummy(ty)]),
|
||||
|
||||
ty::Dynamic(..)
|
||||
| ty::Str
|
||||
| ty::Slice(_)
|
||||
@ -347,6 +354,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<'tcx>(
|
||||
| ty::CoroutineWitness(..)
|
||||
| ty::Never
|
||||
| ty::Tuple(_)
|
||||
| ty::Pat(_, _)
|
||||
| ty::Alias(_, _)
|
||||
| ty::Param(_)
|
||||
| ty::Placeholder(..)
|
||||
@ -526,6 +534,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc
|
||||
| ty::Foreign(_)
|
||||
| ty::Str
|
||||
| ty::Array(_, _)
|
||||
| ty::Pat(_, _)
|
||||
| ty::Slice(_)
|
||||
| ty::RawPtr(_, _)
|
||||
| ty::Ref(_, _, _)
|
||||
|
@ -533,6 +533,7 @@ fn consider_builtin_pointee_candidate(
|
||||
| ty::Uint(..)
|
||||
| ty::Float(..)
|
||||
| ty::Array(..)
|
||||
| ty::Pat(..)
|
||||
| ty::RawPtr(..)
|
||||
| ty::Ref(..)
|
||||
| ty::FnDef(..)
|
||||
@ -768,6 +769,7 @@ fn consider_builtin_discriminant_kind_candidate(
|
||||
| ty::Uint(..)
|
||||
| ty::Float(..)
|
||||
| ty::Array(..)
|
||||
| ty::Pat(..)
|
||||
| ty::RawPtr(..)
|
||||
| ty::Ref(..)
|
||||
| ty::FnDef(..)
|
||||
|
@ -1051,6 +1051,7 @@ fn disqualify_auto_trait_candidate_due_to_possible_impl(
|
||||
| ty::Float(_)
|
||||
| ty::Str
|
||||
| ty::Array(_, _)
|
||||
| ty::Pat(_, _)
|
||||
| ty::Slice(_)
|
||||
| ty::RawPtr(_, _)
|
||||
| ty::Ref(_, _, _)
|
||||
|
@ -883,6 +883,7 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
|
||||
| ty::Float(..)
|
||||
| ty::Str
|
||||
| ty::FnDef(..)
|
||||
| ty::Pat(..)
|
||||
| ty::FnPtr(_)
|
||||
| ty::Array(..)
|
||||
| ty::Slice(..)
|
||||
|
@ -1804,6 +1804,7 @@ fn type_category(tcx: TyCtxt<'_>, t: Ty<'_>) -> Option<u32> {
|
||||
ty::Foreign(..) => Some(19),
|
||||
ty::CoroutineWitness(..) => Some(20),
|
||||
ty::CoroutineClosure(..) => Some(21),
|
||||
ty::Pat(..) => Some(22),
|
||||
ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error(_) => None,
|
||||
}
|
||||
}
|
||||
|
@ -1048,6 +1048,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
|
||||
| ty::Foreign(_)
|
||||
| ty::Str
|
||||
| ty::Array(..)
|
||||
| ty::Pat(..)
|
||||
| ty::Slice(_)
|
||||
| ty::RawPtr(..)
|
||||
| ty::Ref(..)
|
||||
@ -1099,6 +1100,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
|
||||
| ty::Float(_)
|
||||
| ty::Str
|
||||
| ty::Array(..)
|
||||
| ty::Pat(..)
|
||||
| ty::Slice(_)
|
||||
| ty::RawPtr(..)
|
||||
| ty::Ref(..)
|
||||
|
@ -42,8 +42,8 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
|
||||
| ty::Foreign(..)
|
||||
| ty::Error(_) => true,
|
||||
|
||||
// [T; N] and [T] have same properties as T.
|
||||
ty::Array(ty, _) | ty::Slice(ty) => trivial_dropck_outlives(tcx, *ty),
|
||||
// `T is PAT`, `[T; N]`, and `[T]` have same properties as T.
|
||||
ty::Pat(ty, _) | ty::Array(ty, _) | ty::Slice(ty) => trivial_dropck_outlives(tcx, *ty),
|
||||
|
||||
// (T1..Tn) and closures have same properties as T1..Tn --
|
||||
// check if *all* of them are trivial.
|
||||
@ -222,7 +222,7 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
|
||||
// these types never have a destructor
|
||||
}
|
||||
|
||||
ty::Array(ety, _) | ty::Slice(ety) => {
|
||||
ty::Pat(ety, _) | ty::Array(ety, _) | ty::Slice(ety) => {
|
||||
// single-element containers, behave like their element
|
||||
rustc_data_structures::stack::ensure_sufficient_stack(|| {
|
||||
dtorck_constraint_for_ty_inner(tcx, param_env, span, depth + 1, *ety, constraints)
|
||||
|
@ -670,6 +670,7 @@ fn reject_fn_ptr_impls(
|
||||
| ty::Foreign(_)
|
||||
| ty::Str
|
||||
| ty::Array(_, _)
|
||||
| ty::Pat(_, _)
|
||||
| ty::Slice(_)
|
||||
| ty::RawPtr(_, _)
|
||||
| ty::Ref(_, _, _)
|
||||
@ -803,6 +804,7 @@ fn assemble_candidates_from_auto_impls(
|
||||
| ty::Float(_)
|
||||
| ty::Str
|
||||
| ty::Array(_, _)
|
||||
| ty::Pat(_, _)
|
||||
| ty::Slice(_)
|
||||
| ty::Adt(..)
|
||||
| ty::RawPtr(_, _)
|
||||
@ -1193,6 +1195,7 @@ fn assemble_const_destruct_candidates(
|
||||
| ty::Never
|
||||
| ty::Foreign(_)
|
||||
| ty::Array(..)
|
||||
| ty::Pat(..)
|
||||
| ty::Slice(_)
|
||||
| ty::Closure(..)
|
||||
| ty::CoroutineClosure(..)
|
||||
@ -1270,6 +1273,7 @@ fn assemble_candidate_for_tuple(
|
||||
| ty::RawPtr(_, _)
|
||||
| ty::Ref(_, _, _)
|
||||
| ty::FnDef(_, _)
|
||||
| ty::Pat(_, _)
|
||||
| ty::FnPtr(_)
|
||||
| ty::Dynamic(_, _, _)
|
||||
| ty::Closure(..)
|
||||
@ -1329,6 +1333,7 @@ fn assemble_candidates_for_fn_ptr_trait(
|
||||
| ty::Foreign(..)
|
||||
| ty::Str
|
||||
| ty::Array(..)
|
||||
| ty::Pat(..)
|
||||
| ty::Slice(_)
|
||||
| ty::RawPtr(_, _)
|
||||
| ty::Ref(..)
|
||||
|
@ -1417,7 +1417,7 @@ fn confirm_const_destruct_candidate(
|
||||
|
||||
// These types are built-in, so we can fast-track by registering
|
||||
// nested predicates for their constituent type(s)
|
||||
ty::Array(ty, _) | ty::Slice(ty) => {
|
||||
ty::Array(ty, _) | ty::Slice(ty) | ty::Pat(ty, _) => {
|
||||
stack.push(ty);
|
||||
}
|
||||
ty::Tuple(tys) => {
|
||||
@ -1469,7 +1469,15 @@ fn confirm_const_destruct_candidate(
|
||||
// If we have any other type (e.g. an ADT), just register a nested obligation
|
||||
// since it's either not `const Drop` (and we raise an error during selection),
|
||||
// or it's an ADT (and we need to check for a custom impl during selection)
|
||||
_ => {
|
||||
ty::Error(_)
|
||||
| ty::Dynamic(..)
|
||||
| ty::CoroutineClosure(..)
|
||||
| ty::Param(_)
|
||||
| ty::Bound(..)
|
||||
| ty::Adt(..)
|
||||
| ty::Alias(ty::Opaque | ty::Weak, _)
|
||||
| ty::Infer(_)
|
||||
| ty::Placeholder(_) => {
|
||||
let predicate = self_ty.rebind(ty::TraitPredicate {
|
||||
trait_ref: ty::TraitRef::from_lang_item(
|
||||
self.tcx(),
|
||||
|
@ -2142,6 +2142,8 @@ fn sized_conditions(
|
||||
obligation.predicate.rebind(tys.last().map_or_else(Vec::new, |&last| vec![last])),
|
||||
),
|
||||
|
||||
ty::Pat(ty, _) => Where(obligation.predicate.rebind(vec![*ty])),
|
||||
|
||||
ty::Adt(def, args) => {
|
||||
if let Some(sized_crit) = def.sized_constraint(self.tcx()) {
|
||||
// (*) binder moved here
|
||||
@ -2202,6 +2204,11 @@ fn copy_clone_conditions(
|
||||
Where(obligation.predicate.rebind(tys.iter().collect()))
|
||||
}
|
||||
|
||||
ty::Pat(ty, _) => {
|
||||
// (*) binder moved here
|
||||
Where(obligation.predicate.rebind(vec![ty]))
|
||||
}
|
||||
|
||||
ty::Coroutine(coroutine_def_id, args) => {
|
||||
match self.tcx().coroutine_movability(coroutine_def_id) {
|
||||
hir::Movability::Static => None,
|
||||
@ -2340,7 +2347,7 @@ fn constituent_types_for_ty(
|
||||
|
||||
ty::RawPtr(element_ty, _) | ty::Ref(_, element_ty, _) => t.rebind(vec![element_ty]),
|
||||
|
||||
ty::Array(element_ty, _) | ty::Slice(element_ty) => t.rebind(vec![element_ty]),
|
||||
ty::Pat(ty, _) | ty::Array(ty, _) | ty::Slice(ty) => t.rebind(vec![ty]),
|
||||
|
||||
ty::Tuple(tys) => {
|
||||
// (T1, ..., Tn) -- meets any bound that all of T1...Tn meet
|
||||
|
@ -126,7 +126,7 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
|
||||
return ControlFlow::Continue(());
|
||||
}
|
||||
|
||||
ty::Array(..) | ty::Slice(_) | ty::Ref(..) | ty::Tuple(..) => {
|
||||
ty::Pat(..) | ty::Array(..) | ty::Slice(_) | ty::Ref(..) | ty::Tuple(..) => {
|
||||
// First check all contained types and then tell the caller to continue searching.
|
||||
return ty.super_visit_with(self);
|
||||
}
|
||||
|
@ -681,6 +681,10 @@ fn visit_ty(&mut self, t: <TyCtxt<'tcx> as ty::Interner>::Ty) -> Self::Result {
|
||||
// Note that we handle the len is implicitly checked while walking `arg`.
|
||||
}
|
||||
|
||||
ty::Pat(subty, _) => {
|
||||
self.require_sized(subty, traits::MiscObligation);
|
||||
}
|
||||
|
||||
ty::Tuple(tys) => {
|
||||
if let Some((_last, rest)) = tys.split_last() {
|
||||
for &elem in rest {
|
||||
|
@ -126,6 +126,39 @@ fn layout_of_uncached<'tcx>(
|
||||
debug_assert!(!ty.has_non_region_infer());
|
||||
|
||||
Ok(match *ty.kind() {
|
||||
ty::Pat(ty, pat) => {
|
||||
let layout = cx.layout_of(ty)?.layout;
|
||||
let mut layout = LayoutS::clone(&layout.0);
|
||||
match *pat {
|
||||
ty::PatternKind::Range { start, end, include_end } => {
|
||||
if let Abi::Scalar(scalar) | Abi::ScalarPair(scalar, _) = &mut layout.abi {
|
||||
if let Some(start) = start {
|
||||
scalar.valid_range_mut().start = start.eval_bits(tcx, param_env);
|
||||
}
|
||||
if let Some(end) = end {
|
||||
let mut end = end.eval_bits(tcx, param_env);
|
||||
if !include_end {
|
||||
end = end.wrapping_sub(1);
|
||||
}
|
||||
scalar.valid_range_mut().end = end;
|
||||
}
|
||||
|
||||
let niche = Niche {
|
||||
offset: Size::ZERO,
|
||||
value: scalar.primitive(),
|
||||
valid_range: scalar.valid_range(cx),
|
||||
};
|
||||
|
||||
layout.largest_niche = Some(niche);
|
||||
|
||||
tcx.mk_layout(layout)
|
||||
} else {
|
||||
bug!("pattern type with range but not scalar layout: {ty:?}, {layout:?}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Basic scalars.
|
||||
ty::Bool => tcx.mk_layout(LayoutS::scalar(
|
||||
cx,
|
||||
|
@ -221,6 +221,7 @@ fn next(&mut self) -> Option<NeedsDropResult<Ty<'tcx>>> {
|
||||
| ty::Ref(..)
|
||||
| ty::RawPtr(..)
|
||||
| ty::FnDef(..)
|
||||
| ty::Pat(..)
|
||||
| ty::FnPtr(..)
|
||||
| ty::Tuple(_)
|
||||
| ty::Bound(..)
|
||||
|
@ -36,6 +36,8 @@ fn sized_constraint_for_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'
|
||||
// these are never sized
|
||||
Str | Slice(..) | Dynamic(_, _, ty::Dyn) | Foreign(..) => Some(ty),
|
||||
|
||||
Pat(ty, _) => sized_constraint_for_ty(tcx, *ty),
|
||||
|
||||
Tuple(tys) => tys.last().and_then(|&ty| sized_constraint_for_ty(tcx, ty)),
|
||||
|
||||
// recursive case
|
||||
|
@ -49,6 +49,7 @@ pub trait Interner: Sized + Copy {
|
||||
type BoundExistentialPredicates: Copy + DebugWithInfcx<Self> + Hash + Eq;
|
||||
type PolyFnSig: Copy + DebugWithInfcx<Self> + Hash + Eq;
|
||||
type AllocId: Copy + Debug + Hash + Eq;
|
||||
type Pat: Copy + Debug + Hash + Eq + DebugWithInfcx<Self>;
|
||||
|
||||
// Kinds of consts
|
||||
type Const: Copy
|
||||
|
@ -100,6 +100,13 @@ pub enum TyKind<I: Interner> {
|
||||
/// An array with the given length. Written as `[T; N]`.
|
||||
Array(I::Ty, I::Const),
|
||||
|
||||
/// A pattern newtype. Takes any type and restricts its valid values to its pattern.
|
||||
/// This will also change the layout to take advantage of this restriction.
|
||||
/// Only `Copy` and `Clone` will automatically get implemented for pattern types.
|
||||
/// Auto-traits treat this as if it were an aggregate with a single nested type.
|
||||
/// Only supports integer range patterns for now.
|
||||
Pat(I::Ty, I::Pat),
|
||||
|
||||
/// The pointee of an array slice. Written as `[T]`.
|
||||
Slice(I::Ty),
|
||||
|
||||
@ -273,12 +280,13 @@ const fn tykind_discriminant<I: Interner>(value: &TyKind<I>) -> usize {
|
||||
CoroutineWitness(_, _) => 18,
|
||||
Never => 19,
|
||||
Tuple(_) => 20,
|
||||
Alias(_, _) => 21,
|
||||
Param(_) => 22,
|
||||
Bound(_, _) => 23,
|
||||
Placeholder(_) => 24,
|
||||
Infer(_) => 25,
|
||||
Error(_) => 26,
|
||||
Pat(_, _) => 21,
|
||||
Alias(_, _) => 22,
|
||||
Param(_) => 23,
|
||||
Bound(_, _) => 24,
|
||||
Placeholder(_) => 25,
|
||||
Infer(_) => 26,
|
||||
Error(_) => 27,
|
||||
}
|
||||
}
|
||||
|
||||
@ -299,6 +307,7 @@ fn eq(&self, other: &TyKind<I>) -> bool {
|
||||
(Adt(a_d, a_s), Adt(b_d, b_s)) => a_d == b_d && a_s == b_s,
|
||||
(Foreign(a_d), Foreign(b_d)) => a_d == b_d,
|
||||
(Array(a_t, a_c), Array(b_t, b_c)) => a_t == b_t && a_c == b_c,
|
||||
(Pat(a_t, a_c), Pat(b_t, b_c)) => a_t == b_t && a_c == b_c,
|
||||
(Slice(a_t), Slice(b_t)) => a_t == b_t,
|
||||
(RawPtr(a_t, a_m), RawPtr(b_t, b_m)) => a_t == b_t && a_m == b_m,
|
||||
(Ref(a_r, a_t, a_m), Ref(b_r, b_t, b_m)) => a_r == b_r && a_t == b_t && a_m == b_m,
|
||||
@ -322,7 +331,7 @@ fn eq(&self, other: &TyKind<I>) -> bool {
|
||||
_ => {
|
||||
debug_assert!(
|
||||
tykind_discriminant(self) != tykind_discriminant(other),
|
||||
"This branch must be unreachable, maybe the match is missing an arm? self = self = {self:?}, other = {other:?}"
|
||||
"This branch must be unreachable, maybe the match is missing an arm? self = {self:?}, other = {other:?}"
|
||||
);
|
||||
false
|
||||
}
|
||||
@ -362,6 +371,7 @@ fn fmt<Infcx: InferCtxtLike<Interner = I>>(
|
||||
Foreign(d) => f.debug_tuple("Foreign").field(d).finish(),
|
||||
Str => write!(f, "str"),
|
||||
Array(t, c) => write!(f, "[{:?}; {:?}]", &this.wrap(t), &this.wrap(c)),
|
||||
Pat(t, p) => write!(f, "pattern_type!({:?} is {:?})", &this.wrap(t), &this.wrap(p)),
|
||||
Slice(t) => write!(f, "[{:?}]", &this.wrap(t)),
|
||||
RawPtr(ty, mutbl) => {
|
||||
match mutbl {
|
||||
|
@ -99,6 +99,12 @@ pub fn kind(&self) -> TyKind {
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents a pattern in the type system
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub enum Pattern {
|
||||
Range { start: Option<Const>, end: Option<Const>, include_end: bool },
|
||||
}
|
||||
|
||||
/// Represents a constant in MIR or from the Type system.
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct Const {
|
||||
@ -481,6 +487,7 @@ pub enum RigidTy {
|
||||
Foreign(ForeignDef),
|
||||
Str,
|
||||
Array(Ty, Const),
|
||||
Pat(Ty, Pattern),
|
||||
Slice(Ty),
|
||||
RawPtr(Ty, Mutability),
|
||||
Ref(Region, Ty, Mutability),
|
||||
|
@ -139,6 +139,7 @@ fn super_visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> {
|
||||
t.visit(visitor)?;
|
||||
c.visit(visitor)
|
||||
}
|
||||
RigidTy::Pat(t, _p) => t.visit(visitor),
|
||||
RigidTy::Slice(inner) => inner.visit(visitor),
|
||||
RigidTy::RawPtr(ty, _) => ty.visit(visitor),
|
||||
RigidTy::Ref(reg, ty, _) => {
|
||||
|
@ -2009,6 +2009,10 @@ pub(crate) fn clean_middle_ty<'tcx>(
|
||||
ty::Float(float_ty) => Primitive(float_ty.into()),
|
||||
ty::Str => Primitive(PrimitiveType::Str),
|
||||
ty::Slice(ty) => Slice(Box::new(clean_middle_ty(bound_ty.rebind(ty), cx, None, None))),
|
||||
ty::Pat(ty, pat) => Type::Pat(
|
||||
Box::new(clean_middle_ty(bound_ty.rebind(ty), cx, None, None)),
|
||||
format!("{pat:?}").into_boxed_str(),
|
||||
),
|
||||
ty::Array(ty, mut n) => {
|
||||
n = n.normalize(cx.tcx, ty::ParamEnv::reveal_all());
|
||||
let n = print_const(cx, n);
|
||||
|
@ -573,9 +573,10 @@ fn from_tcx(ty: clean::Type, tcx: TyCtxt<'_>) -> Self {
|
||||
Tuple(t) => Type::Tuple(t.into_tcx(tcx)),
|
||||
Slice(t) => Type::Slice(Box::new((*t).into_tcx(tcx))),
|
||||
Array(t, s) => Type::Array { type_: Box::new((*t).into_tcx(tcx)), len: s.to_string() },
|
||||
clean::Type::Pat(t, p) => {
|
||||
Type::Pat { type_: Box::new((*t).into_tcx(tcx)), pat: p.to_string() }
|
||||
}
|
||||
clean::Type::Pat(t, p) => Type::Pat {
|
||||
type_: Box::new((*t).into_tcx(tcx)),
|
||||
__pat_unstable_do_not_use: p.to_string(),
|
||||
},
|
||||
ImplTrait(g) => Type::ImplTrait(g.into_tcx(tcx)),
|
||||
Infer => Type::Infer,
|
||||
RawPointer(mutability, type_) => Type::RawPointer {
|
||||
|
@ -491,6 +491,7 @@ fn def_id_to_res(&self, ty_id: DefId) -> Option<Res> {
|
||||
ty::Str => Res::Primitive(Str),
|
||||
ty::Tuple(tys) if tys.is_empty() => Res::Primitive(Unit),
|
||||
ty::Tuple(_) => Res::Primitive(Tuple),
|
||||
ty::Pat(..) => Res::Primitive(Pat),
|
||||
ty::Array(..) => Res::Primitive(Array),
|
||||
ty::Slice(_) => Res::Primitive(Slice),
|
||||
ty::RawPtr(_, _) => Res::Primitive(RawPointer),
|
||||
|
@ -566,7 +566,7 @@ pub enum Type {
|
||||
Pat {
|
||||
#[serde(rename = "type")]
|
||||
type_: Box<Type>,
|
||||
pat: String,
|
||||
__pat_unstable_do_not_use: String,
|
||||
},
|
||||
/// `impl TraitA + TraitB + ...`
|
||||
ImplTrait(Vec<GenericBound>),
|
||||
|
@ -870,6 +870,7 @@ fn for_mir_ty<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>,
|
||||
| ty::Int(_)
|
||||
| ty::Uint(_)
|
||||
| ty::Array(..)
|
||||
| ty::Pat(..)
|
||||
| ty::Float(_)
|
||||
| ty::RawPtr(..)
|
||||
| ty::FnPtr(_)
|
||||
|
@ -262,6 +262,7 @@ fn check_type(&mut self, x: &'a Type) {
|
||||
Type::DynTrait(dyn_trait) => self.check_dyn_trait(dyn_trait),
|
||||
Type::Generic(_) => {}
|
||||
Type::Primitive(_) => {}
|
||||
Type::Pat { type_, pat: _ } => self.check_type(type_),
|
||||
Type::FunctionPointer(fp) => self.check_function_pointer(&**fp),
|
||||
Type::Tuple(tys) => tys.iter().for_each(|ty| self.check_type(ty)),
|
||||
Type::Slice(inner) => self.check_type(&**inner),
|
||||
|
23
tests/codegen/pattern_type_symbols.rs
Normal file
23
tests/codegen/pattern_type_symbols.rs
Normal file
@ -0,0 +1,23 @@
|
||||
//! Check that symbol names with pattern types in them are
|
||||
//! different from the same symbol with the base type
|
||||
|
||||
//@ compile-flags: -Csymbol-mangling-version=v0 -Copt-level=0 --crate-type=lib
|
||||
|
||||
#![feature(pattern_types)]
|
||||
#![feature(core_pattern_types)]
|
||||
#![feature(core_pattern_type)]
|
||||
|
||||
use std::pat::pattern_type;
|
||||
|
||||
type NanoU32 = crate::pattern_type!(u32 is 0..=999_999_999);
|
||||
|
||||
fn foo<T>() {}
|
||||
|
||||
pub fn bar() {
|
||||
// CHECK: call pattern_type_symbols::foo::<u32>
|
||||
// CHECK: call void @_RINvCs3QvG2ESzx2Q_20pattern_type_symbols3foomEB2_
|
||||
foo::<u32>();
|
||||
// CHECK: call pattern_type_symbols::foo::<(u32, [(); 0], [(); 999999999], [(); true])>
|
||||
// CHECK: call void @_RINvCs3QvG2ESzx2Q_20pattern_type_symbols3fooTmAum0_Aum3b9ac9ff_Aub1_EEB2_
|
||||
foo::<NanoU32>();
|
||||
}
|
@ -22,6 +22,7 @@ fn main() {
|
||||
TyKind::Foreign(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
|
||||
TyKind::Str => (), //~ ERROR usage of `ty::TyKind::<kind>`
|
||||
TyKind::Array(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
|
||||
TyKind::Pat(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
|
||||
TyKind::Slice(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
|
||||
TyKind::RawPtr(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
|
||||
TyKind::Ref(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
|
||||
|
@ -67,119 +67,125 @@ LL | TyKind::Array(..) => (),
|
||||
error: usage of `ty::TyKind::<kind>`
|
||||
--> $DIR/ty_tykind_usage.rs:25:9
|
||||
|
|
||||
LL | TyKind::Slice(..) => (),
|
||||
LL | TyKind::Pat(..) => (),
|
||||
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
|
||||
|
||||
error: usage of `ty::TyKind::<kind>`
|
||||
--> $DIR/ty_tykind_usage.rs:26:9
|
||||
|
|
||||
LL | TyKind::RawPtr(..) => (),
|
||||
LL | TyKind::Slice(..) => (),
|
||||
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
|
||||
|
||||
error: usage of `ty::TyKind::<kind>`
|
||||
--> $DIR/ty_tykind_usage.rs:27:9
|
||||
|
|
||||
LL | TyKind::Ref(..) => (),
|
||||
LL | TyKind::RawPtr(..) => (),
|
||||
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
|
||||
|
||||
error: usage of `ty::TyKind::<kind>`
|
||||
--> $DIR/ty_tykind_usage.rs:28:9
|
||||
|
|
||||
LL | TyKind::FnDef(..) => (),
|
||||
LL | TyKind::Ref(..) => (),
|
||||
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
|
||||
|
||||
error: usage of `ty::TyKind::<kind>`
|
||||
--> $DIR/ty_tykind_usage.rs:29:9
|
||||
|
|
||||
LL | TyKind::FnPtr(..) => (),
|
||||
LL | TyKind::FnDef(..) => (),
|
||||
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
|
||||
|
||||
error: usage of `ty::TyKind::<kind>`
|
||||
--> $DIR/ty_tykind_usage.rs:30:9
|
||||
|
|
||||
LL | TyKind::Dynamic(..) => (),
|
||||
LL | TyKind::FnPtr(..) => (),
|
||||
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
|
||||
|
||||
error: usage of `ty::TyKind::<kind>`
|
||||
--> $DIR/ty_tykind_usage.rs:31:9
|
||||
|
|
||||
LL | TyKind::Closure(..) => (),
|
||||
LL | TyKind::Dynamic(..) => (),
|
||||
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
|
||||
|
||||
error: usage of `ty::TyKind::<kind>`
|
||||
--> $DIR/ty_tykind_usage.rs:32:9
|
||||
|
|
||||
LL | TyKind::CoroutineClosure(..) => (),
|
||||
LL | TyKind::Closure(..) => (),
|
||||
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
|
||||
|
||||
error: usage of `ty::TyKind::<kind>`
|
||||
--> $DIR/ty_tykind_usage.rs:33:9
|
||||
|
|
||||
LL | TyKind::Coroutine(..) => (),
|
||||
LL | TyKind::CoroutineClosure(..) => (),
|
||||
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
|
||||
|
||||
error: usage of `ty::TyKind::<kind>`
|
||||
--> $DIR/ty_tykind_usage.rs:34:9
|
||||
|
|
||||
LL | TyKind::CoroutineWitness(..) => (),
|
||||
LL | TyKind::Coroutine(..) => (),
|
||||
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
|
||||
|
||||
error: usage of `ty::TyKind::<kind>`
|
||||
--> $DIR/ty_tykind_usage.rs:35:9
|
||||
|
|
||||
LL | TyKind::Never => (),
|
||||
LL | TyKind::CoroutineWitness(..) => (),
|
||||
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
|
||||
|
||||
error: usage of `ty::TyKind::<kind>`
|
||||
--> $DIR/ty_tykind_usage.rs:36:9
|
||||
|
|
||||
LL | TyKind::Tuple(..) => (),
|
||||
LL | TyKind::Never => (),
|
||||
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
|
||||
|
||||
error: usage of `ty::TyKind::<kind>`
|
||||
--> $DIR/ty_tykind_usage.rs:37:9
|
||||
|
|
||||
LL | TyKind::Alias(..) => (),
|
||||
LL | TyKind::Tuple(..) => (),
|
||||
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
|
||||
|
||||
error: usage of `ty::TyKind::<kind>`
|
||||
--> $DIR/ty_tykind_usage.rs:38:9
|
||||
|
|
||||
LL | TyKind::Param(..) => (),
|
||||
LL | TyKind::Alias(..) => (),
|
||||
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
|
||||
|
||||
error: usage of `ty::TyKind::<kind>`
|
||||
--> $DIR/ty_tykind_usage.rs:39:9
|
||||
|
|
||||
LL | TyKind::Bound(..) => (),
|
||||
LL | TyKind::Param(..) => (),
|
||||
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
|
||||
|
||||
error: usage of `ty::TyKind::<kind>`
|
||||
--> $DIR/ty_tykind_usage.rs:40:9
|
||||
|
|
||||
LL | TyKind::Placeholder(..) => (),
|
||||
LL | TyKind::Bound(..) => (),
|
||||
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
|
||||
|
||||
error: usage of `ty::TyKind::<kind>`
|
||||
--> $DIR/ty_tykind_usage.rs:41:9
|
||||
|
|
||||
LL | TyKind::Infer(..) => (),
|
||||
LL | TyKind::Placeholder(..) => (),
|
||||
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
|
||||
|
||||
error: usage of `ty::TyKind::<kind>`
|
||||
--> $DIR/ty_tykind_usage.rs:42:9
|
||||
|
|
||||
LL | TyKind::Infer(..) => (),
|
||||
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
|
||||
|
||||
error: usage of `ty::TyKind::<kind>`
|
||||
--> $DIR/ty_tykind_usage.rs:43:9
|
||||
|
|
||||
LL | TyKind::Error(_) => (),
|
||||
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
|
||||
|
||||
error: usage of `ty::TyKind::<kind>`
|
||||
--> $DIR/ty_tykind_usage.rs:47:12
|
||||
--> $DIR/ty_tykind_usage.rs:48:12
|
||||
|
|
||||
LL | if let TyKind::Int(int_ty) = kind {}
|
||||
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
|
||||
|
||||
error: usage of `ty::TyKind`
|
||||
--> $DIR/ty_tykind_usage.rs:49:24
|
||||
--> $DIR/ty_tykind_usage.rs:50:24
|
||||
|
|
||||
LL | fn ty_kind(ty_bad: TyKind<'_>, ty_good: Ty<'_>) {}
|
||||
| ^^^^^^^^^^
|
||||
@ -187,7 +193,7 @@ LL | fn ty_kind(ty_bad: TyKind<'_>, ty_good: Ty<'_>) {}
|
||||
= help: try using `Ty` instead
|
||||
|
||||
error: usage of `ty::TyKind`
|
||||
--> $DIR/ty_tykind_usage.rs:51:37
|
||||
--> $DIR/ty_tykind_usage.rs:52:37
|
||||
|
|
||||
LL | fn ir_ty_kind<I: Interner>(bad: IrTyKind<I>) -> IrTyKind<I> {
|
||||
| ^^^^^^^^^^^
|
||||
@ -195,7 +201,7 @@ LL | fn ir_ty_kind<I: Interner>(bad: IrTyKind<I>) -> IrTyKind<I> {
|
||||
= help: try using `Ty` instead
|
||||
|
||||
error: usage of `ty::TyKind`
|
||||
--> $DIR/ty_tykind_usage.rs:51:53
|
||||
--> $DIR/ty_tykind_usage.rs:52:53
|
||||
|
|
||||
LL | fn ir_ty_kind<I: Interner>(bad: IrTyKind<I>) -> IrTyKind<I> {
|
||||
| ^^^^^^^^^^^
|
||||
@ -203,12 +209,12 @@ LL | fn ir_ty_kind<I: Interner>(bad: IrTyKind<I>) -> IrTyKind<I> {
|
||||
= help: try using `Ty` instead
|
||||
|
||||
error: usage of `ty::TyKind::<kind>`
|
||||
--> $DIR/ty_tykind_usage.rs:54:9
|
||||
--> $DIR/ty_tykind_usage.rs:55:9
|
||||
|
|
||||
LL | IrTyKind::Bool
|
||||
| --------^^^^^^
|
||||
| |
|
||||
| help: try using `ty::<kind>` directly: `ty`
|
||||
|
||||
error: aborting due to 33 previous errors
|
||||
error: aborting due to 34 previous errors
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
error: symbol-name(_ZN5basic4main17h6fc0c8d27b1a289fE)
|
||||
error: symbol-name(_ZN5basic4main17had874e876c8b1028E)
|
||||
--> $DIR/basic.rs:8:1
|
||||
|
|
||||
LL | #[rustc_symbol_name]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: demangling(basic::main::h6fc0c8d27b1a289f)
|
||||
error: demangling(basic::main::had874e876c8b1028)
|
||||
--> $DIR/basic.rs:8:1
|
||||
|
|
||||
LL | #[rustc_symbol_name]
|
||||
|
@ -1,10 +1,10 @@
|
||||
error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17hab58a402db4ebf3aE)
|
||||
error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17haf0d0ad2255e29c6E)
|
||||
--> $DIR/issue-60925.rs:21:9
|
||||
|
|
||||
LL | #[rustc_symbol_name]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: demangling(issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo::hab58a402db4ebf3a)
|
||||
error: demangling(issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo::haf0d0ad2255e29c6)
|
||||
--> $DIR/issue-60925.rs:21:9
|
||||
|
|
||||
LL | #[rustc_symbol_name]
|
||||
|
14
tests/ui/type/pattern_types/derives.noimpl.stderr
Normal file
14
tests/ui/type/pattern_types/derives.noimpl.stderr
Normal file
@ -0,0 +1,14 @@
|
||||
error[E0369]: binary operation `==` cannot be applied to type `(i32) is 0..=999999999`
|
||||
--> $DIR/derives.rs:14:20
|
||||
|
|
||||
LL | #[derive(Clone, Copy, PartialEq)]
|
||||
| --------- in this derive macro expansion
|
||||
LL | #[repr(transparent)]
|
||||
LL | struct Nanoseconds(NanoI32);
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0369`.
|
20
tests/ui/type/pattern_types/derives.rs
Normal file
20
tests/ui/type/pattern_types/derives.rs
Normal file
@ -0,0 +1,20 @@
|
||||
//! Check that pattern types don't implement traits of their base automatically
|
||||
|
||||
#![feature(pattern_types)]
|
||||
#![feature(core_pattern_types)]
|
||||
#![feature(core_pattern_type)]
|
||||
|
||||
use std::pat::pattern_type;
|
||||
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
#[repr(transparent)]
|
||||
struct Nanoseconds(NanoI32);
|
||||
//~^ ERROR: binary operation `==` cannot be applied to type `(i32) is 0..=999999999`
|
||||
|
||||
type NanoI32 = crate::pattern_type!(i32 is 0..=999_999_999);
|
||||
|
||||
fn main() {
|
||||
let x = Nanoseconds(unsafe { std::mem::transmute(42) });
|
||||
let y = x.clone();
|
||||
if y == x {}
|
||||
}
|
14
tests/ui/type/pattern_types/derives.stderr
Normal file
14
tests/ui/type/pattern_types/derives.stderr
Normal file
@ -0,0 +1,14 @@
|
||||
error[E0369]: binary operation `==` cannot be applied to type `(i32) is 0..=999999999`
|
||||
--> $DIR/derives.rs:11:20
|
||||
|
|
||||
LL | #[derive(Clone, Copy, PartialEq)]
|
||||
| --------- in this derive macro expansion
|
||||
LL | #[repr(transparent)]
|
||||
LL | struct Nanoseconds(NanoI32);
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0369`.
|
@ -4,7 +4,7 @@
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
// Check that pattern types do not affect existing macros.
|
||||
// They don't, because `is` was never legal after `ty` fragments.
|
||||
// They don't, because pattern types don't have surface syntax.
|
||||
|
||||
macro_rules! foo {
|
||||
($t:ty is $p:pat) => {}; //~ ERROR `$t:ty` is followed by `is`, which is not allowed for `ty` fragments
|
||||
|
21
tests/ui/type/pattern_types/range_patterns.rs
Normal file
21
tests/ui/type/pattern_types/range_patterns.rs
Normal file
@ -0,0 +1,21 @@
|
||||
#![feature(pattern_types, rustc_attrs)]
|
||||
#![feature(core_pattern_type)]
|
||||
#![feature(core_pattern_types)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
use std::pat::pattern_type;
|
||||
|
||||
#[rustc_layout(debug)]
|
||||
type X = std::num::NonZeroU32; //~ ERROR layout_of
|
||||
#[rustc_layout(debug)]
|
||||
type Y = pattern_type!(u32 is 1..); //~ ERROR layout_of
|
||||
#[rustc_layout(debug)]
|
||||
type Z = Option<pattern_type!(u32 is 1..)>; //~ ERROR layout_of
|
||||
#[rustc_layout(debug)]
|
||||
type A = Option<std::num::NonZeroU32>; //~ ERROR layout_of
|
||||
#[rustc_layout(debug)]
|
||||
struct NonZeroU32New(pattern_type!(u32 is 1..)); //~ ERROR layout_of
|
||||
|
||||
fn main() {
|
||||
let x: pattern_type!(u32 is 1..) = unsafe { std::mem::transmute(42_u32) };
|
||||
}
|
343
tests/ui/type/pattern_types/range_patterns.stderr
Normal file
343
tests/ui/type/pattern_types/range_patterns.stderr
Normal file
@ -0,0 +1,343 @@
|
||||
error: layout_of(NonZero<u32>) = Layout {
|
||||
size: Size(4 bytes),
|
||||
align: AbiAndPrefAlign {
|
||||
abi: Align(4 bytes),
|
||||
pref: Align(8 bytes),
|
||||
},
|
||||
abi: Scalar(
|
||||
Initialized {
|
||||
value: Int(
|
||||
I32,
|
||||
false,
|
||||
),
|
||||
valid_range: 1..=4294967295,
|
||||
},
|
||||
),
|
||||
fields: Arbitrary {
|
||||
offsets: [
|
||||
Size(0 bytes),
|
||||
],
|
||||
memory_index: [
|
||||
0,
|
||||
],
|
||||
},
|
||||
largest_niche: Some(
|
||||
Niche {
|
||||
offset: Size(0 bytes),
|
||||
value: Int(
|
||||
I32,
|
||||
false,
|
||||
),
|
||||
valid_range: 1..=4294967295,
|
||||
},
|
||||
),
|
||||
variants: Single {
|
||||
index: 0,
|
||||
},
|
||||
max_repr_align: None,
|
||||
unadjusted_abi_align: Align(4 bytes),
|
||||
}
|
||||
--> $DIR/range_patterns.rs:9:1
|
||||
|
|
||||
LL | type X = std::num::NonZeroU32;
|
||||
| ^^^^^^
|
||||
|
||||
error: layout_of((u32) is 1..=) = Layout {
|
||||
size: Size(4 bytes),
|
||||
align: AbiAndPrefAlign {
|
||||
abi: Align(4 bytes),
|
||||
pref: Align(4 bytes),
|
||||
},
|
||||
abi: Scalar(
|
||||
Initialized {
|
||||
value: Int(
|
||||
I32,
|
||||
false,
|
||||
),
|
||||
valid_range: 1..=4294967295,
|
||||
},
|
||||
),
|
||||
fields: Primitive,
|
||||
largest_niche: Some(
|
||||
Niche {
|
||||
offset: Size(0 bytes),
|
||||
value: Int(
|
||||
I32,
|
||||
false,
|
||||
),
|
||||
valid_range: 1..=4294967295,
|
||||
},
|
||||
),
|
||||
variants: Single {
|
||||
index: 0,
|
||||
},
|
||||
max_repr_align: None,
|
||||
unadjusted_abi_align: Align(4 bytes),
|
||||
}
|
||||
--> $DIR/range_patterns.rs:11:1
|
||||
|
|
||||
LL | type Y = pattern_type!(u32 is 1..);
|
||||
| ^^^^^^
|
||||
|
||||
error: layout_of(Option<(u32) is 1..=>) = Layout {
|
||||
size: Size(4 bytes),
|
||||
align: AbiAndPrefAlign {
|
||||
abi: Align(4 bytes),
|
||||
pref: Align(8 bytes),
|
||||
},
|
||||
abi: Scalar(
|
||||
Initialized {
|
||||
value: Int(
|
||||
I32,
|
||||
false,
|
||||
),
|
||||
valid_range: (..=0) | (1..),
|
||||
},
|
||||
),
|
||||
fields: Arbitrary {
|
||||
offsets: [
|
||||
Size(0 bytes),
|
||||
],
|
||||
memory_index: [
|
||||
0,
|
||||
],
|
||||
},
|
||||
largest_niche: None,
|
||||
variants: Multiple {
|
||||
tag: Initialized {
|
||||
value: Int(
|
||||
I32,
|
||||
false,
|
||||
),
|
||||
valid_range: (..=0) | (1..),
|
||||
},
|
||||
tag_encoding: Niche {
|
||||
untagged_variant: 1,
|
||||
niche_variants: 0..=0,
|
||||
niche_start: 0,
|
||||
},
|
||||
tag_field: 0,
|
||||
variants: [
|
||||
Layout {
|
||||
size: Size(0 bytes),
|
||||
align: AbiAndPrefAlign {
|
||||
abi: Align(1 bytes),
|
||||
pref: Align(8 bytes),
|
||||
},
|
||||
abi: Aggregate {
|
||||
sized: true,
|
||||
},
|
||||
fields: Arbitrary {
|
||||
offsets: [],
|
||||
memory_index: [],
|
||||
},
|
||||
largest_niche: None,
|
||||
variants: Single {
|
||||
index: 0,
|
||||
},
|
||||
max_repr_align: None,
|
||||
unadjusted_abi_align: Align(1 bytes),
|
||||
},
|
||||
Layout {
|
||||
size: Size(4 bytes),
|
||||
align: AbiAndPrefAlign {
|
||||
abi: Align(4 bytes),
|
||||
pref: Align(8 bytes),
|
||||
},
|
||||
abi: Scalar(
|
||||
Initialized {
|
||||
value: Int(
|
||||
I32,
|
||||
false,
|
||||
),
|
||||
valid_range: 1..=4294967295,
|
||||
},
|
||||
),
|
||||
fields: Arbitrary {
|
||||
offsets: [
|
||||
Size(0 bytes),
|
||||
],
|
||||
memory_index: [
|
||||
0,
|
||||
],
|
||||
},
|
||||
largest_niche: Some(
|
||||
Niche {
|
||||
offset: Size(0 bytes),
|
||||
value: Int(
|
||||
I32,
|
||||
false,
|
||||
),
|
||||
valid_range: 1..=4294967295,
|
||||
},
|
||||
),
|
||||
variants: Single {
|
||||
index: 1,
|
||||
},
|
||||
max_repr_align: None,
|
||||
unadjusted_abi_align: Align(4 bytes),
|
||||
},
|
||||
],
|
||||
},
|
||||
max_repr_align: None,
|
||||
unadjusted_abi_align: Align(4 bytes),
|
||||
}
|
||||
--> $DIR/range_patterns.rs:13:1
|
||||
|
|
||||
LL | type Z = Option<pattern_type!(u32 is 1..)>;
|
||||
| ^^^^^^
|
||||
|
||||
error: layout_of(Option<NonZero<u32>>) = Layout {
|
||||
size: Size(4 bytes),
|
||||
align: AbiAndPrefAlign {
|
||||
abi: Align(4 bytes),
|
||||
pref: Align(8 bytes),
|
||||
},
|
||||
abi: Scalar(
|
||||
Initialized {
|
||||
value: Int(
|
||||
I32,
|
||||
false,
|
||||
),
|
||||
valid_range: (..=0) | (1..),
|
||||
},
|
||||
),
|
||||
fields: Arbitrary {
|
||||
offsets: [
|
||||
Size(0 bytes),
|
||||
],
|
||||
memory_index: [
|
||||
0,
|
||||
],
|
||||
},
|
||||
largest_niche: None,
|
||||
variants: Multiple {
|
||||
tag: Initialized {
|
||||
value: Int(
|
||||
I32,
|
||||
false,
|
||||
),
|
||||
valid_range: (..=0) | (1..),
|
||||
},
|
||||
tag_encoding: Niche {
|
||||
untagged_variant: 1,
|
||||
niche_variants: 0..=0,
|
||||
niche_start: 0,
|
||||
},
|
||||
tag_field: 0,
|
||||
variants: [
|
||||
Layout {
|
||||
size: Size(0 bytes),
|
||||
align: AbiAndPrefAlign {
|
||||
abi: Align(1 bytes),
|
||||
pref: Align(8 bytes),
|
||||
},
|
||||
abi: Aggregate {
|
||||
sized: true,
|
||||
},
|
||||
fields: Arbitrary {
|
||||
offsets: [],
|
||||
memory_index: [],
|
||||
},
|
||||
largest_niche: None,
|
||||
variants: Single {
|
||||
index: 0,
|
||||
},
|
||||
max_repr_align: None,
|
||||
unadjusted_abi_align: Align(1 bytes),
|
||||
},
|
||||
Layout {
|
||||
size: Size(4 bytes),
|
||||
align: AbiAndPrefAlign {
|
||||
abi: Align(4 bytes),
|
||||
pref: Align(8 bytes),
|
||||
},
|
||||
abi: Scalar(
|
||||
Initialized {
|
||||
value: Int(
|
||||
I32,
|
||||
false,
|
||||
),
|
||||
valid_range: 1..=4294967295,
|
||||
},
|
||||
),
|
||||
fields: Arbitrary {
|
||||
offsets: [
|
||||
Size(0 bytes),
|
||||
],
|
||||
memory_index: [
|
||||
0,
|
||||
],
|
||||
},
|
||||
largest_niche: Some(
|
||||
Niche {
|
||||
offset: Size(0 bytes),
|
||||
value: Int(
|
||||
I32,
|
||||
false,
|
||||
),
|
||||
valid_range: 1..=4294967295,
|
||||
},
|
||||
),
|
||||
variants: Single {
|
||||
index: 1,
|
||||
},
|
||||
max_repr_align: None,
|
||||
unadjusted_abi_align: Align(4 bytes),
|
||||
},
|
||||
],
|
||||
},
|
||||
max_repr_align: None,
|
||||
unadjusted_abi_align: Align(4 bytes),
|
||||
}
|
||||
--> $DIR/range_patterns.rs:15:1
|
||||
|
|
||||
LL | type A = Option<std::num::NonZeroU32>;
|
||||
| ^^^^^^
|
||||
|
||||
error: layout_of(NonZeroU32New) = Layout {
|
||||
size: Size(4 bytes),
|
||||
align: AbiAndPrefAlign {
|
||||
abi: Align(4 bytes),
|
||||
pref: Align(8 bytes),
|
||||
},
|
||||
abi: Scalar(
|
||||
Initialized {
|
||||
value: Int(
|
||||
I32,
|
||||
false,
|
||||
),
|
||||
valid_range: 1..=4294967295,
|
||||
},
|
||||
),
|
||||
fields: Arbitrary {
|
||||
offsets: [
|
||||
Size(0 bytes),
|
||||
],
|
||||
memory_index: [
|
||||
0,
|
||||
],
|
||||
},
|
||||
largest_niche: Some(
|
||||
Niche {
|
||||
offset: Size(0 bytes),
|
||||
value: Int(
|
||||
I32,
|
||||
false,
|
||||
),
|
||||
valid_range: 1..=4294967295,
|
||||
},
|
||||
),
|
||||
variants: Single {
|
||||
index: 0,
|
||||
},
|
||||
max_repr_align: None,
|
||||
unadjusted_abi_align: Align(4 bytes),
|
||||
}
|
||||
--> $DIR/range_patterns.rs:17:1
|
||||
|
|
||||
LL | struct NonZeroU32New(pattern_type!(u32 is 1..));
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
30
tests/ui/type/pattern_types/range_patterns_inherent_impls.rs
Normal file
30
tests/ui/type/pattern_types/range_patterns_inherent_impls.rs
Normal file
@ -0,0 +1,30 @@
|
||||
#![feature(pattern_types, rustc_attrs)]
|
||||
#![feature(core_pattern_type)]
|
||||
#![feature(core_pattern_types)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
//! check that pattern types can have traits implemented for them if
|
||||
//! their base type is a local type.
|
||||
|
||||
use std::pat::pattern_type;
|
||||
|
||||
type Y = pattern_type!(u32 is 1..);
|
||||
|
||||
impl Y {
|
||||
//~^ ERROR cannot define inherent `impl`
|
||||
fn foo() {}
|
||||
}
|
||||
|
||||
struct MyStruct<T>(T);
|
||||
|
||||
impl MyStruct<Y> {
|
||||
fn foo() {}
|
||||
}
|
||||
|
||||
struct Wrapper(Y);
|
||||
|
||||
impl Wrapper {
|
||||
fn foo() {}
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,16 @@
|
||||
error[E0390]: cannot define inherent `impl` for primitive types outside of `core`
|
||||
--> $DIR/range_patterns_inherent_impls.rs:13:1
|
||||
|
|
||||
LL | impl Y {
|
||||
| ^^^^^^
|
||||
|
|
||||
= help: consider moving this inherent impl into `core` if possible
|
||||
help: alternatively add `#[rustc_allow_incoherent_impl]` to the relevant impl items
|
||||
--> $DIR/range_patterns_inherent_impls.rs:15:5
|
||||
|
|
||||
LL | fn foo() {}
|
||||
| ^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0390`.
|
19
tests/ui/type/pattern_types/range_patterns_trait_impls.rs
Normal file
19
tests/ui/type/pattern_types/range_patterns_trait_impls.rs
Normal file
@ -0,0 +1,19 @@
|
||||
#![feature(pattern_types, rustc_attrs)]
|
||||
#![feature(core_pattern_type)]
|
||||
#![feature(core_pattern_types)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
//! check that pattern types can have local traits
|
||||
//! implemented for them.
|
||||
|
||||
//@ check-pass
|
||||
|
||||
use std::pat::pattern_type;
|
||||
|
||||
type Y = pattern_type!(u32 is 1..);
|
||||
|
||||
trait Trait {}
|
||||
|
||||
impl Trait for Y {}
|
||||
|
||||
fn main() {}
|
16
tests/ui/type/pattern_types/range_patterns_trait_impls2.rs
Normal file
16
tests/ui/type/pattern_types/range_patterns_trait_impls2.rs
Normal file
@ -0,0 +1,16 @@
|
||||
#![feature(pattern_types, rustc_attrs)]
|
||||
#![feature(core_pattern_type)]
|
||||
#![feature(core_pattern_types)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
//! check that pattern types can have local traits
|
||||
//! implemented for them.
|
||||
|
||||
use std::pat::pattern_type;
|
||||
|
||||
type Y = pattern_type!(u32 is 1..);
|
||||
|
||||
impl Eq for Y {}
|
||||
//~^ ERROR: only traits defined in the current crate can be implemented for arbitrary types
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,14 @@
|
||||
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
|
||||
--> $DIR/range_patterns_trait_impls2.rs:13:1
|
||||
|
|
||||
LL | impl Eq for Y {}
|
||||
| ^^^^^^^^^^^^-
|
||||
| | |
|
||||
| | `(u32) is 1..=` is not defined in the current crate
|
||||
| impl doesn't use only types from inside the current crate
|
||||
|
|
||||
= note: define and implement a trait or new type instead
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0117`.
|
15
tests/ui/type/pattern_types/range_patterns_unusable.rs
Normal file
15
tests/ui/type/pattern_types/range_patterns_unusable.rs
Normal file
@ -0,0 +1,15 @@
|
||||
#![feature(pattern_types, rustc_attrs)]
|
||||
#![feature(core_pattern_type)]
|
||||
#![feature(core_pattern_types)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
//! Some practical niche checks.
|
||||
|
||||
use std::pat::pattern_type;
|
||||
|
||||
type Z = Option<pattern_type!(u32 is 1..)>;
|
||||
|
||||
fn main() {
|
||||
let z: Z = Some(unsafe { std::mem::transmute(42_u32) });
|
||||
let _: Option<u32> = unsafe { std::mem::transmute(z) }; //~ ERROR: different sizes
|
||||
}
|
12
tests/ui/type/pattern_types/range_patterns_unusable.stderr
Normal file
12
tests/ui/type/pattern_types/range_patterns_unusable.stderr
Normal file
@ -0,0 +1,12 @@
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/range_patterns_unusable.rs:14:35
|
||||
|
|
||||
LL | let _: Option<u32> = unsafe { std::mem::transmute(z) };
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: source type: `Option<(u32) is 1..=>` (32 bits)
|
||||
= note: target type: `Option<u32>` (64 bits)
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0512`.
|
16
tests/ui/type/pattern_types/range_patterns_unusable_math.rs
Normal file
16
tests/ui/type/pattern_types/range_patterns_unusable_math.rs
Normal file
@ -0,0 +1,16 @@
|
||||
#![feature(pattern_types, rustc_attrs)]
|
||||
#![feature(core_pattern_type)]
|
||||
#![feature(core_pattern_types)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
//! check that pattern types don't have an `Add` impl.
|
||||
|
||||
use std::pat::pattern_type;
|
||||
|
||||
type Y = pattern_type!(u32 is 1..);
|
||||
type Z = Option<pattern_type!(u32 is 1..)>;
|
||||
|
||||
fn main() {
|
||||
let x: Y = unsafe { std::mem::transmute(42_u32) };
|
||||
let x = x + 1_u32; //~ ERROR cannot add `u32` to `(u32) is 1..=`
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
error[E0369]: cannot add `u32` to `(u32) is 1..=`
|
||||
--> $DIR/range_patterns_unusable_math.rs:15:15
|
||||
|
|
||||
LL | let x = x + 1_u32;
|
||||
| - ^ ----- u32
|
||||
| |
|
||||
| (u32) is 1..=
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0369`.
|
26
tests/ui/type/pattern_types/range_patterns_usage.rs
Normal file
26
tests/ui/type/pattern_types/range_patterns_usage.rs
Normal file
@ -0,0 +1,26 @@
|
||||
#![feature(pattern_types, rustc_attrs)]
|
||||
#![feature(core_pattern_type)]
|
||||
#![feature(core_pattern_types)]
|
||||
#![allow(incomplete_features)]
|
||||
//@ check-pass
|
||||
|
||||
//! check that pattern types can actually be part of code that compiles successfully.
|
||||
|
||||
use std::pat::pattern_type;
|
||||
|
||||
type X = std::num::NonZeroU32;
|
||||
type Y = pattern_type!(u32 is 1..);
|
||||
type Z = Option<pattern_type!(u32 is 1..)>;
|
||||
struct NonZeroU32New(pattern_type!(u32 is 1..));
|
||||
|
||||
fn main() {
|
||||
let x: Y = unsafe { std::mem::transmute(42_u32) };
|
||||
let z: Z = Some(unsafe { std::mem::transmute(42_u32) });
|
||||
match z {
|
||||
Some(y) => {
|
||||
let _: Y = y;
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
let x: X = unsafe { std::mem::transmute(x) };
|
||||
}
|
Loading…
Reference in New Issue
Block a user