Skip to content

Commit 84acfe8

Browse files
committed
Actually create ranged int types in the type system.
1 parent 6b24a9c commit 84acfe8

File tree

97 files changed

+1208
-77
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

97 files changed

+1208
-77
lines changed

compiler/rustc_ast/src/ast.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2152,7 +2152,7 @@ pub enum TyKind {
21522152
MacCall(P<MacCall>),
21532153
/// Placeholder for a `va_list`.
21542154
CVarArgs,
2155-
/// Pattern types like `u32 as 1..=`, which is the same as `NonZeroU32`,
2155+
/// Pattern types like `pattern_type!(u32 is 1..=)`, which is the same as `NonZeroU32`,
21562156
/// just as part of the type system.
21572157
Pat(P<Ty>, P<Pat>),
21582158
/// Sometimes we need a dummy value when no error has occurred.

compiler/rustc_ast_lowering/src/index.rs

+4
Original file line numberDiff line numberDiff line change
@@ -381,4 +381,8 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
381381
ArrayLen::Body(..) => intravisit::walk_array_len(self, len),
382382
}
383383
}
384+
385+
fn visit_pattern_type_pattern(&mut self, p: &'hir hir::Pat<'hir>) {
386+
self.visit_pat(p)
387+
}
384388
}

compiler/rustc_borrowck/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1606,6 +1606,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
16061606
| ty::Foreign(_)
16071607
| ty::Str
16081608
| ty::Array(_, _)
1609+
| ty::Pat(_, _)
16091610
| ty::Slice(_)
16101611
| ty::FnDef(_, _)
16111612
| ty::FnPtr(_)
@@ -1648,6 +1649,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
16481649
| ty::Foreign(_)
16491650
| ty::Str
16501651
| ty::Array(_, _)
1652+
| ty::Pat(_, _)
16511653
| ty::Slice(_)
16521654
| ty::RawPtr(_, _)
16531655
| ty::Ref(_, _, _)

compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs

+10
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,16 @@ fn push_debuginfo_type_name<'tcx>(
202202
}
203203
}
204204
}
205+
ty::Pat(inner_type, pat) => {
206+
if cpp_like_debuginfo {
207+
output.push_str("pat$<");
208+
push_debuginfo_type_name(tcx, inner_type, true, output, visited);
209+
// FIXME(wg-debugging): implement CPP like printing for patterns.
210+
write!(output, ",{:?}>", pat).unwrap();
211+
} else {
212+
write!(output, "{:?}", t).unwrap();
213+
}
214+
}
205215
ty::Slice(inner_type) => {
206216
if cpp_like_debuginfo {
207217
output.push_str("slice2$<");

compiler/rustc_const_eval/src/const_eval/valtrees.rs

+14-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use rustc_data_structures::stack::ensure_sufficient_stack;
12
use rustc_middle::mir;
23
use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId};
34
use rustc_middle::ty::layout::{LayoutCx, LayoutOf, TyAndLayout};
@@ -98,6 +99,16 @@ fn const_to_valtree_inner<'tcx>(
9899
Ok(ty::ValTree::Leaf(val.assert_int()))
99100
}
100101

102+
ty::Pat(base, ..) => {
103+
let mut place = place.clone();
104+
// The valtree of the base type is the same as the valtree of the pattern type.
105+
// Since the returned valtree does not contain the type or layout, we can just
106+
// switch to the base type.
107+
place.layout = ecx.layout_of(*base).unwrap();
108+
ensure_sufficient_stack(|| const_to_valtree_inner(ecx, &place, num_nodes))
109+
},
110+
111+
101112
ty::RawPtr(_, _) => {
102113
// Not all raw pointers are allowed, as we cannot properly test them for
103114
// equality at compile-time (see `ptr_guaranteed_cmp`).
@@ -273,7 +284,7 @@ pub fn valtree_to_const_value<'tcx>(
273284

274285
let (param_env, ty) = param_env_ty.into_parts();
275286

276-
match ty.kind() {
287+
match *ty.kind() {
277288
ty::FnDef(..) => {
278289
assert!(valtree.unwrap_branch().is_empty());
279290
mir::ConstValue::ZeroSized
@@ -286,10 +297,11 @@ pub fn valtree_to_const_value<'tcx>(
286297
),
287298
}
288299
}
300+
ty::Pat(ty, _) => valtree_to_const_value(tcx, param_env.and(ty), valtree),
289301
ty::Ref(_, inner_ty, _) => {
290302
let mut ecx =
291303
mk_eval_cx_to_read_const_val(tcx, DUMMY_SP, param_env, CanAccessMutGlobal::No);
292-
let imm = valtree_to_ref(&mut ecx, valtree, *inner_ty);
304+
let imm = valtree_to_ref(&mut ecx, valtree, inner_ty);
293305
let imm = ImmTy::from_immediate(imm, tcx.layout_of(param_env_ty).unwrap());
294306
op_to_const(&ecx, &imm.into(), /* for diagnostics */ false)
295307
}

compiler/rustc_const_eval/src/interpret/eval_context.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1060,6 +1060,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
10601060

10611061
ty::Tuple(tys) => tys.last().iter().all(|ty| is_very_trivially_sized(**ty)),
10621062

1063+
ty::Pat(ty, ..) => is_very_trivially_sized(*ty),
1064+
10631065
// We don't want to do any queries, so there is not much we can do with ADTs.
10641066
ty::Adt(..) => false,
10651067

compiler/rustc_const_eval/src/interpret/intrinsics.rs

+4
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>(
6969
ty::Alias(..) | ty::Param(_) | ty::Placeholder(_) | ty::Infer(_) => {
7070
throw_inval!(TooGeneric)
7171
}
72+
ty::Pat(_, pat) => match **pat {
73+
ty::PatternKind::Range { .. } => ConstValue::from_target_usize(0u64, &tcx),
74+
// Future pattern kinds may have more variants
75+
},
7276
ty::Bound(_, _) => bug!("bound ty during ctfe"),
7377
ty::Bool
7478
| ty::Char

compiler/rustc_const_eval/src/interpret/validity.rs

+1
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
640640
| ty::Str
641641
| ty::Dynamic(..)
642642
| ty::Closure(..)
643+
| ty::Pat(..)
643644
| ty::CoroutineClosure(..)
644645
| ty::Coroutine(..) => Ok(false),
645646
// Some types only occur during typechecking, they have no layout.

compiler/rustc_const_eval/src/util/type_name.rs

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
3131
| ty::Uint(_)
3232
| ty::Float(_)
3333
| ty::Str
34+
| ty::Pat(_, _)
3435
| ty::Array(_, _)
3536
| ty::Slice(_)
3637
| ty::RawPtr(_, _)

compiler/rustc_hir/src/hir.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2624,7 +2624,7 @@ pub enum TyKind<'hir> {
26242624
Infer,
26252625
/// Placeholder for a type that has failed to be defined.
26262626
Err(rustc_span::ErrorGuaranteed),
2627-
/// Pattern types (`u32 as 1..`)
2627+
/// Pattern types (`pattern_type!(u32 is 1..)`)
26282628
Pat(&'hir Ty<'hir>, &'hir Pat<'hir>),
26292629
}
26302630

compiler/rustc_hir/src/intravisit.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,11 @@ pub trait Visitor<'v>: Sized {
356356
fn visit_ty(&mut self, t: &'v Ty<'v>) -> Self::Result {
357357
walk_ty(self, t)
358358
}
359+
fn visit_pattern_type_pattern(&mut self, _p: &'v Pat<'v>) {
360+
// Do nothing. Only a few visitors need to know the details of the pattern type,
361+
// and they opt into it. All other visitors will just choke on our fake patterns
362+
// because they aren't in a body.
363+
}
359364
fn visit_generic_param(&mut self, p: &'v GenericParam<'v>) -> Self::Result {
360365
walk_generic_param(self, p)
361366
}
@@ -884,7 +889,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) -> V::Resul
884889
}
885890
TyKind::Pat(ty, pat) => {
886891
try_visit!(visitor.visit_ty(ty));
887-
try_visit!(visitor.visit_pat(pat));
892+
try_visit!(visitor.visit_pattern_type_pattern(pat));
888893
}
889894
}
890895
V::Result::output()

compiler/rustc_hir_analysis/messages.ftl

+1
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,7 @@ hir_analysis_pass_to_variadic_function = can't pass `{$ty}` to variadic function
349349
.suggestion = cast the value to `{$cast_ty}`
350350
.help = cast the value to `{$cast_ty}`
351351
352+
hir_analysis_pattern_type_non_const_range = "range patterns must have constant range start and end"
352353
hir_analysis_pattern_type_wild_pat = "wildcard patterns are not permitted for pattern types"
353354
.label = "this type is the same as the inner type without a pattern"
354355
hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is not allowed within types on item signatures for {$kind}

compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,12 @@ impl<'tcx> InherentCollect<'tcx> {
144144
let id = id.owner_id.def_id;
145145
let item_span = self.tcx.def_span(id);
146146
let self_ty = self.tcx.type_of(id).instantiate_identity();
147-
let self_ty = self.tcx.peel_off_weak_alias_tys(self_ty);
147+
let mut self_ty = self.tcx.peel_off_weak_alias_tys(self_ty);
148+
// We allow impls on pattern types exactly when we allow impls on the base type.
149+
// FIXME(pattern_types): Figure out the exact coherence rules we want here.
150+
while let ty::Pat(base, _) = *self_ty.kind() {
151+
self_ty = base;
152+
}
148153
match *self_ty.kind() {
149154
ty::Adt(def, _) => self.check_def_id(id, self_ty, def.did()),
150155
ty::Foreign(did) => self.check_def_id(id, self_ty, did),
@@ -154,6 +159,7 @@ impl<'tcx> InherentCollect<'tcx> {
154159
ty::Dynamic(..) => {
155160
Err(self.tcx.dcx().emit_err(errors::InherentDyn { span: item_span }))
156161
}
162+
ty::Pat(_, _) => unreachable!(),
157163
ty::Bool
158164
| ty::Char
159165
| ty::Int(_)

compiler/rustc_hir_analysis/src/coherence/orphan.rs

+5
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,11 @@ pub(crate) fn orphan_check_impl(
206206
(LocalImpl::Disallow { problematic_kind }, NonlocalImpl::DisallowOther)
207207
}
208208

209+
ty::Pat(..) => (
210+
LocalImpl::Disallow { problematic_kind: "pattern type" },
211+
NonlocalImpl::DisallowOther,
212+
),
213+
209214
ty::Bool
210215
| ty::Char
211216
| ty::Int(..)

compiler/rustc_hir_analysis/src/errors.rs

+7
Original file line numberDiff line numberDiff line change
@@ -1631,3 +1631,10 @@ pub struct OpaqueCapturesHigherRankedLifetime {
16311631
pub decl_span: Span,
16321632
pub bad_place: &'static str,
16331633
}
1634+
1635+
#[derive(Diagnostic)]
1636+
#[diag(hir_analysis_pattern_type_non_const_range)]
1637+
pub struct NonConstRange {
1638+
#[primary_span]
1639+
pub span: Span,
1640+
}

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

+59-9
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ use rustc_hir::{GenericArg, GenericArgs};
3939
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
4040
use rustc_infer::traits::ObligationCause;
4141
use rustc_middle::middle::stability::AllowUnstable;
42+
use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput};
4243
use rustc_middle::ty::{
4344
self, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, ParamEnv, Ty, TyCtxt,
4445
TypeVisitableExt,
@@ -2195,15 +2196,64 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
21952196
// handled specially and will not descend into this routine.
21962197
self.ty_infer(None, hir_ty.span)
21972198
}
2198-
hir::TyKind::Pat(_ty, pat) => match pat.kind {
2199-
hir::PatKind::Wild => {
2200-
let err = tcx.dcx().emit_err(WildPatTy { span: pat.span });
2201-
Ty::new_error(tcx, err)
2202-
}
2203-
hir::PatKind::Range(_, _, _) => Ty::new_misc_error(tcx),
2204-
hir::PatKind::Err(e) => Ty::new_error(tcx, e),
2205-
_ => span_bug!(pat.span, "unsupported pattern for pattern type: {pat:#?}"),
2206-
},
2199+
hir::TyKind::Pat(ty, pat) => {
2200+
let ty = self.lower_ty(ty);
2201+
let pat_ty = match pat.kind {
2202+
hir::PatKind::Wild => {
2203+
let err = tcx.dcx().emit_err(WildPatTy { span: pat.span });
2204+
Ty::new_error(tcx, err)
2205+
}
2206+
hir::PatKind::Range(start, end, include_end) => {
2207+
let expr_to_const = |expr: &'tcx hir::Expr<'tcx>| -> ty::Const<'tcx> {
2208+
let (expr, neg) = match expr.kind {
2209+
hir::ExprKind::Unary(hir::UnOp::Neg, negated) => {
2210+
(negated, Some((expr.hir_id, expr.span)))
2211+
}
2212+
_ => (expr, None),
2213+
};
2214+
let c = match &expr.kind {
2215+
hir::ExprKind::Lit(lit) => {
2216+
let lit_input =
2217+
LitToConstInput { lit: &lit.node, ty, neg: neg.is_some() };
2218+
match tcx.lit_to_const(lit_input) {
2219+
Ok(c) => c,
2220+
Err(LitToConstError::Reported(err)) => {
2221+
ty::Const::new_error(tcx, err, ty)
2222+
}
2223+
Err(LitToConstError::TypeError) => todo!(),
2224+
}
2225+
}
2226+
_ => {
2227+
let err = tcx
2228+
.dcx()
2229+
.emit_err(crate::errors::NonConstRange { span: expr.span });
2230+
ty::Const::new_error(tcx, err, ty)
2231+
}
2232+
};
2233+
self.record_ty(expr.hir_id, c.ty(), expr.span);
2234+
if let Some((id, span)) = neg {
2235+
self.record_ty(id, c.ty(), span);
2236+
}
2237+
c
2238+
};
2239+
2240+
let start = start.map(expr_to_const);
2241+
let end = end.map(expr_to_const);
2242+
2243+
let include_end = match include_end {
2244+
hir::RangeEnd::Included => true,
2245+
hir::RangeEnd::Excluded => false,
2246+
};
2247+
2248+
let pat = tcx.mk_pat(ty::PatternKind::Range { start, end, include_end });
2249+
Ty::new_pat(tcx, ty, pat)
2250+
}
2251+
hir::PatKind::Err(e) => Ty::new_error(tcx, e),
2252+
_ => span_bug!(pat.span, "unsupported pattern for pattern type: {pat:#?}"),
2253+
};
2254+
self.record_ty(pat.hir_id, ty, pat.span);
2255+
pat_ty
2256+
}
22072257
hir::TyKind::Err(guar) => Ty::new_error(tcx, *guar),
22082258
};
22092259

compiler/rustc_hir_analysis/src/variance/constraints.rs

+14
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,20 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
249249
self.add_constraints_from_ty(current, typ, variance);
250250
}
251251

252+
ty::Pat(typ, pat) => {
253+
match *pat {
254+
ty::PatternKind::Range { start, end, include_end: _ } => {
255+
if let Some(start) = start {
256+
self.add_constraints_from_const(current, start, variance);
257+
}
258+
if let Some(end) = end {
259+
self.add_constraints_from_const(current, end, variance);
260+
}
261+
}
262+
}
263+
self.add_constraints_from_ty(current, typ, variance);
264+
}
265+
252266
ty::Slice(typ) => {
253267
self.add_constraints_from_ty(current, typ, variance);
254268
}

compiler/rustc_hir_typeck/src/cast.rs

+1
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
130130
| ty::CoroutineWitness(..)
131131
| ty::RawPtr(_, _)
132132
| ty::Ref(..)
133+
| ty::Pat(..)
133134
| ty::FnDef(..)
134135
| ty::FnPtr(..)
135136
| ty::Closure(..)

compiler/rustc_infer/src/infer/canonical/canonicalizer.rs

+1
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
440440
| ty::Tuple(..)
441441
| ty::Alias(..)
442442
| ty::Foreign(..)
443+
| ty::Pat(..)
443444
| ty::Param(..) => {
444445
if t.flags().intersects(self.needs_canonical_flags) {
445446
t.super_fold_with(self)

compiler/rustc_infer/src/infer/outlives/components.rs

+1
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ fn compute_components<'tcx>(
9393
}
9494
}
9595

96+
ty::Pat(element, _) |
9697
ty::Array(element, _) => {
9798
// Don't look into the len const as it doesn't affect regions
9899
compute_components(tcx, element, out, visited);

compiler/rustc_lint/messages.ftl

+3
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,9 @@ lint_improper_ctypes_only_phantomdata = composed only of `PhantomData`
299299
300300
lint_improper_ctypes_opaque = opaque types have no C equivalent
301301
302+
lint_improper_ctypes_pat_help = consider using the base type instead
303+
304+
lint_improper_ctypes_pat_reason = pattern types have no C equivalent
302305
lint_improper_ctypes_slice_help = consider using a raw pointer instead
303306
304307
lint_improper_ctypes_slice_reason = slices have no C equivalent

compiler/rustc_lint/src/types.rs

+6
Original file line numberDiff line numberDiff line change
@@ -1379,6 +1379,12 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
13791379
help: Some(fluent::lint_improper_ctypes_char_help),
13801380
},
13811381

1382+
ty::Pat(..) => FfiUnsafe {
1383+
ty,
1384+
reason: fluent::lint_improper_ctypes_pat_reason,
1385+
help: Some(fluent::lint_improper_ctypes_pat_help),
1386+
},
1387+
13821388
ty::Int(ty::IntTy::I128) | ty::Uint(ty::UintTy::U128) => {
13831389
FfiUnsafe { ty, reason: fluent::lint_improper_ctypes_128bit, help: None }
13841390
}

compiler/rustc_middle/src/arena.rs

+1
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ macro_rules! arena_types {
9090
[decode] attribute: rustc_ast::Attribute,
9191
[] name_set: rustc_data_structures::unord::UnordSet<rustc_span::symbol::Symbol>,
9292
[] ordered_name_set: rustc_data_structures::fx::FxIndexSet<rustc_span::symbol::Symbol>,
93+
[] pats: rustc_middle::ty::PatternKind<'tcx>,
9394

9495
// Note that this deliberately duplicates items in the `rustc_hir::arena`,
9596
// since we need to allocate this type on both the `rustc_hir` arena

compiler/rustc_middle/src/ty/codec.rs

+12
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,12 @@ impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::Const<'tcx> {
148148
}
149149
}
150150

151+
impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::Pattern<'tcx> {
152+
fn encode(&self, e: &mut E) {
153+
self.0.0.encode(e);
154+
}
155+
}
156+
151157
impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ConstAllocation<'tcx> {
152158
fn encode(&self, e: &mut E) {
153159
self.inner().encode(e)
@@ -364,6 +370,12 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Const<'tcx> {
364370
}
365371
}
366372

373+
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Pattern<'tcx> {
374+
fn decode(decoder: &mut D) -> Self {
375+
decoder.interner().mk_pat(Decodable::decode(decoder))
376+
}
377+
}
378+
367379
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for [ty::ValTree<'tcx>] {
368380
fn decode(decoder: &mut D) -> &'tcx Self {
369381
decoder

0 commit comments

Comments
 (0)