Auto merge of #120131 - oli-obk:pattern_types_syntax, r=compiler-errors
Implement minimal, internal-only pattern types in the type system rebase of https://github.com/rust-lang/rust/pull/107606 You can create pattern types with `std::pat::pattern_type!(ty is pat)`. The feature is incomplete and will panic on you if you use any pattern other than integral range patterns. The only way to create or deconstruct a pattern type is via `transmute`. This PR's implementation differs from the MCP's text. Specifically > This means you could implement different traits for different pattern types with the same base type. Thus, we just forbid implementing any traits for pattern types. is violated in this PR. The reason is that we do need impls after all in order to make them usable as fields. constants of type `std::time::Nanoseconds` struct are used in patterns, so the type must be structural-eq, which it only can be if you derive several traits on it. It doesn't need to be structural-eq recursively, so we can just manually implement the relevant traits on the pattern type and use the pattern type as a private field. Waiting on: * [x] move all unrelated commits into their own PRs. * [x] fix niche computation (see 2db07f94f44f078daffe5823680d07d4fded883f) * [x] add lots more tests * [x] T-types MCP https://github.com/rust-lang/types-team/issues/126 to finish * [x] some commit cleanup * [x] full self-review * [x] remove 61bd325da19a918cc3e02bbbdce97281a389c648, it's not necessary anymore I think. * [ ] ~~make sure we never accidentally leak pattern types to user code (add stability checks or feature gate checks and appopriate tests)~~ we don't even do this for the new float primitives * [x] get approval that [the scope expansion to trait impls](https://rust-lang.zulipchat.com/#narrow/stream/326866-t-types.2Fnominated/topic/Pattern.20types.20types-team.23126/near/427670099) is ok r? `@BoxyUwU`
This commit is contained in:
commit
537aab7a2e
@ -2152,6 +2152,9 @@ pub enum TyKind {
|
||||
MacCall(P<MacCall>),
|
||||
/// Placeholder for a `va_list`.
|
||||
CVarArgs,
|
||||
/// 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.
|
||||
Dummy,
|
||||
/// Placeholder for a kind that has failed to be defined.
|
||||
|
@ -502,6 +502,10 @@ pub fn noop_visit_ty<T: MutVisitor>(ty: &mut P<Ty>, vis: &mut T) {
|
||||
}
|
||||
TyKind::Tup(tys) => visit_thin_vec(tys, |ty| vis.visit_ty(ty)),
|
||||
TyKind::Paren(ty) => vis.visit_ty(ty),
|
||||
TyKind::Pat(ty, pat) => {
|
||||
vis.visit_ty(ty);
|
||||
vis.visit_pat(pat);
|
||||
}
|
||||
TyKind::Path(qself, path) => {
|
||||
vis.visit_qself(qself);
|
||||
vis.visit_path(path);
|
||||
|
@ -446,6 +446,10 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) -> V::Result {
|
||||
}
|
||||
try_visit!(visitor.visit_path(path, typ.id));
|
||||
}
|
||||
TyKind::Pat(ty, pat) => {
|
||||
try_visit!(visitor.visit_ty(ty));
|
||||
try_visit!(visitor.visit_pat(pat));
|
||||
}
|
||||
TyKind::Array(ty, length) => {
|
||||
try_visit!(visitor.visit_ty(ty));
|
||||
try_visit!(visitor.visit_anon_const(length));
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -1463,7 +1463,10 @@ fn lower_ty_direct(&mut self, t: &Ty, itctx: ImplTraitContext) -> hir::Ty<'hir>
|
||||
}
|
||||
}
|
||||
}
|
||||
TyKind::MacCall(_) => panic!("`TyKind::MacCall` should have been expanded by now"),
|
||||
TyKind::Pat(ty, pat) => hir::TyKind::Pat(self.lower_ty(ty, itctx), self.lower_pat(pat)),
|
||||
TyKind::MacCall(_) => {
|
||||
span_bug!(t.span, "`TyKind::MacCall` should have been expanded by now")
|
||||
}
|
||||
TyKind::CVarArgs => {
|
||||
let guar = self.dcx().span_delayed_bug(
|
||||
t.span,
|
||||
|
@ -332,6 +332,9 @@ fn visit_ty(&mut self, ty: &'a ast::Ty) {
|
||||
ast::TyKind::Never => {
|
||||
gate!(&self, never_type, ty.span, "the `!` type is experimental");
|
||||
}
|
||||
ast::TyKind::Pat(..) => {
|
||||
gate!(&self, pattern_types, ty.span, "pattern types are unstable");
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
visit::walk_ty(self, ty)
|
||||
|
@ -1188,6 +1188,11 @@ pub fn print_type(&mut self, ty: &ast::Ty) {
|
||||
ast::TyKind::CVarArgs => {
|
||||
self.word("...");
|
||||
}
|
||||
ast::TyKind::Pat(ty, pat) => {
|
||||
self.print_type(ty);
|
||||
self.word(" is ");
|
||||
self.print_pat(pat);
|
||||
}
|
||||
}
|
||||
self.end();
|
||||
}
|
||||
|
@ -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(_, _, _)
|
||||
|
@ -46,6 +46,7 @@
|
||||
mod format_foreign;
|
||||
mod global_allocator;
|
||||
mod log_syntax;
|
||||
mod pattern_type;
|
||||
mod source_util;
|
||||
mod test;
|
||||
mod trace_macros;
|
||||
@ -95,6 +96,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
|
||||
log_syntax: log_syntax::expand_log_syntax,
|
||||
module_path: source_util::expand_mod,
|
||||
option_env: env::expand_option_env,
|
||||
pattern_type: pattern_type::expand,
|
||||
std_panic: edition_panic::expand_panic,
|
||||
stringify: source_util::expand_stringify,
|
||||
trace_macros: trace_macros::expand_trace_macros,
|
||||
|
29
compiler/rustc_builtin_macros/src/pattern_type.rs
Normal file
29
compiler/rustc_builtin_macros/src/pattern_type.rs
Normal file
@ -0,0 +1,29 @@
|
||||
use rustc_ast::{ast, ptr::P, tokenstream::TokenStream, Pat, Ty};
|
||||
use rustc_errors::PResult;
|
||||
use rustc_expand::base::{self, DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult};
|
||||
use rustc_span::{sym, Span};
|
||||
|
||||
pub fn expand<'cx>(
|
||||
cx: &'cx mut ExtCtxt<'_>,
|
||||
sp: Span,
|
||||
tts: TokenStream,
|
||||
) -> MacroExpanderResult<'cx> {
|
||||
let (ty, pat) = match parse_pat_ty(cx, tts) {
|
||||
Ok(parsed) => parsed,
|
||||
Err(err) => {
|
||||
return ExpandResult::Ready(DummyResult::any(sp, err.emit()));
|
||||
}
|
||||
};
|
||||
|
||||
ExpandResult::Ready(base::MacEager::ty(cx.ty(sp, ast::TyKind::Pat(ty, pat))))
|
||||
}
|
||||
|
||||
fn parse_pat_ty<'a>(cx: &mut ExtCtxt<'a>, stream: TokenStream) -> PResult<'a, (P<Ty>, P<Pat>)> {
|
||||
let mut parser = cx.new_parser_from_tts(stream);
|
||||
|
||||
let ty = parser.parse_ty()?;
|
||||
parser.eat_keyword(sym::is);
|
||||
let pat = parser.parse_pat_no_top_alt(None, None)?;
|
||||
|
||||
Ok((ty, pat))
|
||||
}
|
@ -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(_, _)
|
||||
|
@ -215,6 +215,8 @@ pub fn internal(&self, feature: Symbol) -> bool {
|
||||
(internal, omit_gdb_pretty_printer_section, "1.5.0", None),
|
||||
/// Set the maximum pattern complexity allowed (not limited by default).
|
||||
(internal, pattern_complexity, "1.78.0", None),
|
||||
/// Allows using pattern types.
|
||||
(internal, pattern_types, "CURRENT_RUSTC_VERSION", Some(54882)),
|
||||
/// Allows using `#[prelude_import]` on glob `use` items.
|
||||
(internal, prelude_import, "1.2.0", None),
|
||||
/// Used to identify crates that contain the profiler runtime.
|
||||
|
@ -2624,6 +2624,8 @@ pub enum TyKind<'hir> {
|
||||
Infer,
|
||||
/// Placeholder for a type that has failed to be defined.
|
||||
Err(rustc_span::ErrorGuaranteed),
|
||||
/// Pattern types (`pattern_type!(u32 is 1..)`)
|
||||
Pat(&'hir Ty<'hir>, &'hir Pat<'hir>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
||||
|
@ -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)
|
||||
}
|
||||
@ -882,6 +887,10 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) -> V::Resul
|
||||
TyKind::AnonAdt(item_id) => {
|
||||
try_visit!(visitor.visit_nested_item(item_id));
|
||||
}
|
||||
TyKind::Pat(ty, pat) => {
|
||||
try_visit!(visitor.visit_ty(ty));
|
||||
try_visit!(visitor.visit_pattern_type_pattern(pat));
|
||||
}
|
||||
}
|
||||
V::Result::output()
|
||||
}
|
||||
|
@ -349,6 +349,9 @@ 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}
|
||||
.label = not allowed in type signatures
|
||||
|
||||
|
@ -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(..)
|
||||
|
@ -7,6 +7,8 @@
|
||||
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
|
||||
use rustc_middle::ty::Ty;
|
||||
use rustc_span::{symbol::Ident, Span, Symbol};
|
||||
mod pattern_types;
|
||||
pub use pattern_types::*;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_ambiguous_assoc_item)]
|
||||
@ -1629,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,
|
||||
}
|
||||
|
9
compiler/rustc_hir_analysis/src/errors/pattern_types.rs
Normal file
9
compiler/rustc_hir_analysis/src/errors/pattern_types.rs
Normal file
@ -0,0 +1,9 @@
|
||||
use rustc_macros::Diagnostic;
|
||||
use rustc_span::Span;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_pattern_type_wild_pat)]
|
||||
pub struct WildPatTy {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
@ -21,7 +21,7 @@
|
||||
|
||||
use crate::bounds::Bounds;
|
||||
use crate::collect::HirPlaceholderCollector;
|
||||
use crate::errors::AmbiguousLifetimeBound;
|
||||
use crate::errors::{AmbiguousLifetimeBound, WildPatTy};
|
||||
use crate::hir_ty_lowering::errors::{prohibit_assoc_item_binding, GenericsArgsErrExtend};
|
||||
use crate::hir_ty_lowering::generics::{check_generic_arg_count, lower_generic_args};
|
||||
use crate::middle::resolve_bound_vars as rbv;
|
||||
@ -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,6 +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) => {
|
||||
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);
|
||||
}
|
||||
|
@ -330,6 +330,11 @@ fn print_type(&mut self, ty: &hir::Ty<'_>) {
|
||||
self.word("_");
|
||||
}
|
||||
hir::TyKind::AnonAdt(..) => self.word("/* anonymous adt */"),
|
||||
hir::TyKind::Pat(ty, pat) => {
|
||||
self.print_type(ty);
|
||||
self.word(" is ");
|
||||
self.print_pat(pat);
|
||||
}
|
||||
}
|
||||
self.end()
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -157,6 +157,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
|
||||
| TyKind::Never
|
||||
| TyKind::Tup(_)
|
||||
| TyKind::Path(_)
|
||||
| TyKind::Pat(..)
|
||||
| TyKind::AnonAdt(_)
|
||||
| TyKind::OpaqueDef(_, _, _)
|
||||
| TyKind::Typeof(_)
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -352,6 +352,7 @@ fn visit_ty(&mut self, t: &'v hir::Ty<'v>) {
|
||||
TraitObject,
|
||||
Typeof,
|
||||
Infer,
|
||||
Pat,
|
||||
Err
|
||||
]
|
||||
);
|
||||
@ -611,6 +612,7 @@ fn visit_ty(&mut self, t: &'v ast::Ty) {
|
||||
AnonStruct,
|
||||
AnonUnion,
|
||||
Path,
|
||||
Pat,
|
||||
TraitObject,
|
||||
ImplTrait,
|
||||
Paren,
|
||||
|
@ -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;
|
||||
|
||||
|
@ -1009,6 +1009,7 @@
|
||||
io_stderr,
|
||||
io_stdout,
|
||||
irrefutable_let_patterns,
|
||||
is,
|
||||
is_val_statically_known,
|
||||
isa_attribute,
|
||||
isize,
|
||||
@ -1347,6 +1348,8 @@
|
||||
path,
|
||||
pattern_complexity,
|
||||
pattern_parentheses,
|
||||
pattern_type,
|
||||
pattern_types,
|
||||
phantom_data,
|
||||
pic,
|
||||
pie,
|
||||
|
@ -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, _) => {
|
||||
|
@ -396,6 +396,9 @@ pub mod assert_matches {
|
||||
pub mod option;
|
||||
pub mod panic;
|
||||
pub mod panicking;
|
||||
#[cfg(not(bootstrap))]
|
||||
#[unstable(feature = "core_pattern_types", issue = "none")]
|
||||
pub mod pat;
|
||||
pub mod pin;
|
||||
pub mod result;
|
||||
pub mod sync;
|
||||
|
14
library/core/src/pat.rs
Normal file
14
library/core/src/pat.rs
Normal file
@ -0,0 +1,14 @@
|
||||
//! Helper module for exporting the `pattern_type` macro
|
||||
|
||||
/// Creates a pattern type.
|
||||
/// ```ignore (cannot test this from within core yet)
|
||||
/// type Positive = std::pat::pattern_type!(i32 is 1..);
|
||||
/// ```
|
||||
#[macro_export]
|
||||
#[rustc_builtin_macro(pattern_type)]
|
||||
#[unstable(feature = "core_pattern_type", issue = "none")]
|
||||
macro_rules! pattern_type {
|
||||
($($arg:tt)*) => {
|
||||
/* compiler built-in */
|
||||
};
|
||||
}
|
@ -576,6 +576,9 @@
|
||||
pub mod num;
|
||||
pub mod os;
|
||||
pub mod panic;
|
||||
#[cfg(not(bootstrap))]
|
||||
#[unstable(feature = "core_pattern_types", issue = "none")]
|
||||
pub mod pat;
|
||||
pub mod path;
|
||||
pub mod process;
|
||||
pub mod sync;
|
||||
|
3
library/std/src/pat.rs
Normal file
3
library/std/src/pat.rs
Normal file
@ -0,0 +1,3 @@
|
||||
//! Helper module for exporting the `pattern_type` macro
|
||||
|
||||
pub use core::pattern_type;
|
@ -1782,6 +1782,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
|
||||
BorrowedRef { lifetime, mutability: m.mutbl, type_: Box::new(clean_ty(m.ty, cx)) }
|
||||
}
|
||||
TyKind::Slice(ty) => Slice(Box::new(clean_ty(ty, cx))),
|
||||
TyKind::Pat(ty, pat) => Type::Pat(Box::new(clean_ty(ty, cx)), format!("{pat:?}").into()),
|
||||
TyKind::Array(ty, ref length) => {
|
||||
let length = match length {
|
||||
hir::ArrayLen::Infer(..) => "_".to_string(),
|
||||
@ -2008,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);
|
||||
|
@ -1483,7 +1483,9 @@ pub(crate) enum Type {
|
||||
///
|
||||
/// This is mostly Rustdoc's version of [`hir::Path`].
|
||||
/// It has to be different because Rustdoc's [`PathSegment`] can contain cleaned generics.
|
||||
Path { path: Path },
|
||||
Path {
|
||||
path: Path,
|
||||
},
|
||||
/// A `dyn Trait` object: `dyn for<'a> Trait<'a> + Send + 'static`
|
||||
DynTrait(Vec<PolyTrait>, Option<Lifetime>),
|
||||
/// A type parameter.
|
||||
@ -1500,10 +1502,15 @@ pub(crate) enum Type {
|
||||
///
|
||||
/// The `String` field is a stringified version of the array's length parameter.
|
||||
Array(Box<Type>, Box<str>),
|
||||
Pat(Box<Type>, Box<str>),
|
||||
/// A raw pointer type: `*const i32`, `*mut i32`
|
||||
RawPointer(Mutability, Box<Type>),
|
||||
/// A reference type: `&i32`, `&'a mut Foo`
|
||||
BorrowedRef { lifetime: Option<Lifetime>, mutability: Mutability, type_: Box<Type> },
|
||||
BorrowedRef {
|
||||
lifetime: Option<Lifetime>,
|
||||
mutability: Mutability,
|
||||
type_: Box<Type>,
|
||||
},
|
||||
|
||||
/// A qualified path to an associated item: `<Type as Trait>::Name`
|
||||
QPath(Box<QPathData>),
|
||||
@ -1700,6 +1707,7 @@ fn inner_def_id(&self, cache: Option<&Cache>) -> Option<DefId> {
|
||||
BareFunction(..) => PrimitiveType::Fn,
|
||||
Slice(..) => PrimitiveType::Slice,
|
||||
Array(..) => PrimitiveType::Array,
|
||||
Type::Pat(..) => PrimitiveType::Pat,
|
||||
RawPointer(..) => PrimitiveType::RawPointer,
|
||||
QPath(box QPathData { ref self_type, .. }) => return self_type.inner_def_id(cache),
|
||||
Generic(_) | Infer | ImplTrait(_) => return None,
|
||||
@ -1753,6 +1761,7 @@ pub(crate) enum PrimitiveType {
|
||||
Str,
|
||||
Slice,
|
||||
Array,
|
||||
Pat,
|
||||
Tuple,
|
||||
Unit,
|
||||
RawPointer,
|
||||
@ -1907,6 +1916,7 @@ pub(crate) fn as_sym(&self) -> Symbol {
|
||||
Bool => sym::bool,
|
||||
Char => sym::char,
|
||||
Array => sym::array,
|
||||
Pat => sym::pat,
|
||||
Slice => sym::slice,
|
||||
Tuple => sym::tuple,
|
||||
Unit => sym::unit,
|
||||
|
@ -1071,6 +1071,10 @@ fn fmt_type<'cx>(
|
||||
write!(f, "]")
|
||||
}
|
||||
},
|
||||
clean::Type::Pat(ref t, ref pat) => {
|
||||
fmt::Display::fmt(&t.print(cx), f)?;
|
||||
write!(f, " is {pat}")
|
||||
}
|
||||
clean::Array(ref t, ref n) => match **t {
|
||||
clean::Generic(name) if !f.alternate() => primitive_link(
|
||||
f,
|
||||
|
@ -668,7 +668,7 @@ fn get_index_type_id(
|
||||
}
|
||||
}
|
||||
// Not supported yet
|
||||
clean::Generic(_) | clean::ImplTrait(_) | clean::Infer => None,
|
||||
clean::Type::Pat(..) | clean::Generic(_) | clean::ImplTrait(_) | clean::Infer => None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -573,6 +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_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),
|
||||
|
@ -8,7 +8,7 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
/// rustdoc format-version.
|
||||
pub const FORMAT_VERSION: u32 = 28;
|
||||
pub const FORMAT_VERSION: u32 = 29;
|
||||
|
||||
/// A `Crate` is the root of the emitted JSON blob. It contains all type/documentation information
|
||||
/// about the language items in the local crate, as well as info about external items to allow
|
||||
@ -562,6 +562,13 @@ pub enum Type {
|
||||
type_: Box<Type>,
|
||||
len: String,
|
||||
},
|
||||
/// `u32 is 1..`
|
||||
Pat {
|
||||
#[serde(rename = "type")]
|
||||
type_: Box<Type>,
|
||||
#[doc(hidden)]
|
||||
__pat_unstable_do_not_use: String,
|
||||
},
|
||||
/// `impl TraitA + TraitB + ...`
|
||||
ImplTrait(Vec<GenericBound>),
|
||||
/// `_`
|
||||
|
@ -821,6 +821,7 @@ fn for_hir_ty<'tcx>(ty: &'tcx hir::Ty<'tcx>) -> Self {
|
||||
| TyKind::Array(..)
|
||||
| TyKind::Ptr(_)
|
||||
| TyKind::BareFn(_)
|
||||
| TyKind::Pat(..)
|
||||
| TyKind::Never
|
||||
| TyKind::Tup(_)
|
||||
| TyKind::Path(_) => Self::Deref,
|
||||
@ -869,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(_)
|
||||
|
@ -1068,6 +1068,10 @@ pub fn hash_tykind(&mut self, ty: &TyKind<'_>) {
|
||||
self.hash_ty(ty);
|
||||
self.hash_array_length(len);
|
||||
},
|
||||
TyKind::Pat(ty, pat) => {
|
||||
self.hash_ty(ty);
|
||||
self.hash_pat(pat);
|
||||
},
|
||||
TyKind::Ptr(ref mut_ty) => {
|
||||
self.hash_ty(mut_ty.ty);
|
||||
mut_ty.mutbl.hash(&mut self.s);
|
||||
|
@ -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_unstable_do_not_use: _ } => 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),
|
||||
|
@ -867,6 +867,11 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>
|
||||
self.span,
|
||||
shape,
|
||||
),
|
||||
ast::TyKind::Pat(ref ty, ref pat) => {
|
||||
let ty = ty.rewrite(context, shape)?;
|
||||
let pat = pat.rewrite(context, shape)?;
|
||||
Some(format!("{ty} is {pat}"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
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>`
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user