Skip to content

Commit 0e7b283

Browse files
committed
Avoid having to handle an Option in the type system
1 parent 4f2b108 commit 0e7b283

File tree

21 files changed

+147
-110
lines changed

21 files changed

+147
-110
lines changed

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

+78-11
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,9 @@ pub mod generics;
2121
mod lint;
2222

2323
use std::assert_matches::assert_matches;
24-
use std::slice;
24+
use std::{char, slice};
2525

26+
use rustc_abi::Size;
2627
use rustc_ast::TraitObjectSyntax;
2728
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
2829
use rustc_errors::codes::*;
@@ -31,7 +32,7 @@ use rustc_errors::{
3132
};
3233
use rustc_hir::def::{CtorKind, CtorOf, DefKind, Namespace, Res};
3334
use rustc_hir::def_id::{DefId, LocalDefId};
34-
use rustc_hir::{self as hir, AnonConst, GenericArg, GenericArgs, HirId};
35+
use rustc_hir::{self as hir, AnonConst, ConstArg, GenericArg, GenericArgs, HirId};
3536
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
3637
use rustc_infer::traits::ObligationCause;
3738
use rustc_middle::middle::stability::AllowUnstable;
@@ -2693,20 +2694,22 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
26932694
let ty = self.lower_ty(ty);
26942695
let pat_ty = match pat.kind {
26952696
hir::TyPatKind::Range(start, end, include_end) => {
2696-
let ty = match ty.kind() {
2697-
ty::Int(_) | ty::Uint(_) | ty::Char => ty,
2698-
_ => Ty::new_error(
2699-
tcx,
2700-
self.dcx().emit_err(InvalidBaseType {
2697+
let (ty, start, end) = match ty.kind() {
2698+
ty::Int(_) | ty::Uint(_) | ty::Char => {
2699+
let (start, end) = self.lower_ty_pat_range(ty, start, end);
2700+
(ty, start, end)
2701+
}
2702+
_ => {
2703+
let guar = self.dcx().emit_err(InvalidBaseType {
27012704
ty,
27022705
pat: "range",
27032706
ty_span,
27042707
pat_span: pat.span,
2705-
}),
2706-
),
2708+
});
2709+
let errc = ty::Const::new_error(tcx, guar);
2710+
(Ty::new_error(tcx, guar), errc, errc)
2711+
}
27072712
};
2708-
let start = start.map(|expr| self.lower_const_arg(expr, FeedConstTy::No));
2709-
let end = end.map(|expr| self.lower_const_arg(expr, FeedConstTy::No));
27102713

27112714
let pat = tcx.mk_pat(ty::PatternKind::Range { start, end, include_end });
27122715
Ty::new_pat(tcx, ty, pat)
@@ -2723,6 +2726,70 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
27232726
result_ty
27242727
}
27252728

2729+
fn lower_ty_pat_range(
2730+
&self,
2731+
base: Ty<'tcx>,
2732+
start: Option<&ConstArg<'tcx>>,
2733+
end: Option<&ConstArg<'tcx>>,
2734+
) -> (ty::Const<'tcx>, ty::Const<'tcx>) {
2735+
let tcx = self.tcx();
2736+
let size = match base.kind() {
2737+
ty::Int(i) => {
2738+
i.bit_width().map_or(tcx.data_layout.pointer_size, |bits| Size::from_bits(bits))
2739+
}
2740+
ty::Uint(ui) => {
2741+
ui.bit_width().map_or(tcx.data_layout.pointer_size, |bits| Size::from_bits(bits))
2742+
}
2743+
ty::Char => Size::from_bytes(4),
2744+
_ => unreachable!(),
2745+
};
2746+
let start =
2747+
start.map(|expr| self.lower_const_arg(expr, FeedConstTy::No)).unwrap_or_else(|| {
2748+
match base.kind() {
2749+
ty::Char | ty::Uint(_) => ty::Const::new_value(
2750+
tcx,
2751+
ty::ValTree::from_scalar_int(ty::ScalarInt::null(size)),
2752+
base,
2753+
),
2754+
ty::Int(_) => ty::Const::new_value(
2755+
tcx,
2756+
ty::ValTree::from_scalar_int(
2757+
ty::ScalarInt::truncate_from_int(size.signed_int_min(), size).0,
2758+
),
2759+
base,
2760+
),
2761+
_ => unreachable!(),
2762+
}
2763+
});
2764+
let end = end.map(|expr| self.lower_const_arg(expr, FeedConstTy::No)).unwrap_or_else(
2765+
|| match base.kind() {
2766+
ty::Char => ty::Const::new_value(
2767+
tcx,
2768+
ty::ValTree::from_scalar_int(
2769+
ty::ScalarInt::truncate_from_uint(char::MAX, size).0,
2770+
),
2771+
base,
2772+
),
2773+
ty::Uint(_) => ty::Const::new_value(
2774+
tcx,
2775+
ty::ValTree::from_scalar_int(
2776+
ty::ScalarInt::truncate_from_uint(size.unsigned_int_max(), size).0,
2777+
),
2778+
base,
2779+
),
2780+
ty::Int(_) => ty::Const::new_value(
2781+
tcx,
2782+
ty::ValTree::from_scalar_int(
2783+
ty::ScalarInt::truncate_from_int(size.signed_int_max(), size).0,
2784+
),
2785+
base,
2786+
),
2787+
_ => unreachable!(),
2788+
},
2789+
);
2790+
(start, end)
2791+
}
2792+
27262793
/// Lower an opaque type (i.e., an existential impl-Trait type) from the HIR.
27272794
#[instrument(level = "debug", skip(self), ret)]
27282795
fn lower_opaque_ty(&self, def_id: LocalDefId, in_trait: bool) -> Ty<'tcx> {

compiler/rustc_hir_analysis/src/variance/constraints.rs

+2-6
Original file line numberDiff line numberDiff line change
@@ -253,12 +253,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
253253
ty::Pat(typ, pat) => {
254254
match *pat {
255255
ty::PatternKind::Range { start, end, include_end: _ } => {
256-
if let Some(start) = start {
257-
self.add_constraints_from_const(current, start, variance);
258-
}
259-
if let Some(end) = end {
260-
self.add_constraints_from_const(current, end, variance);
261-
}
256+
self.add_constraints_from_const(current, start, variance);
257+
self.add_constraints_from_const(current, end, variance);
262258
}
263259
}
264260
self.add_constraints_from_ty(current, typ, variance);

compiler/rustc_lint/src/types.rs

+8-16
Original file line numberDiff line numberDiff line change
@@ -883,22 +883,14 @@ fn ty_is_known_nonnull<'tcx>(
883883
try {
884884
match **pat {
885885
ty::PatternKind::Range { start, end, include_end } => {
886-
match (start, end) {
887-
(Some(start), None) => {
888-
start.try_to_value()?.try_to_bits(tcx, typing_env)? > 0
889-
}
890-
(Some(start), Some(end)) => {
891-
let start =
892-
start.try_to_value()?.try_to_bits(tcx, typing_env)?;
893-
let end =
894-
end.try_to_value()?.try_to_bits(tcx, typing_env)?;
895-
896-
match include_end {
897-
RangeEnd::Included => start > 0 && end >= start,
898-
RangeEnd::Excluded => start > 0 && end > start,
899-
}
900-
}
901-
_ => false,
886+
let start = start.try_to_value()?.try_to_bits(tcx, typing_env)?;
887+
let end = end.try_to_value()?.try_to_bits(tcx, typing_env)?;
888+
889+
match include_end {
890+
// This also works for negative numbers, as we just need
891+
// to ensure we aren't wrapping over zero.
892+
RangeEnd::Included => start > 0 && end >= start,
893+
RangeEnd::Excluded => start > 0 && end > start,
902894
}
903895
}
904896
}

compiler/rustc_middle/src/ty/flags.rs

+2-6
Original file line numberDiff line numberDiff line change
@@ -221,12 +221,8 @@ impl FlagComputation {
221221
self.add_ty(ty);
222222
match *pat {
223223
ty::PatternKind::Range { start, end, include_end: _ } => {
224-
if let Some(start) = start {
225-
self.add_const(start)
226-
}
227-
if let Some(end) = end {
228-
self.add_const(end)
229-
}
224+
self.add_const(start);
225+
self.add_const(end);
230226
}
231227
}
232228
}

compiler/rustc_middle/src/ty/pattern.rs

+2-9
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,7 @@ impl<'tcx> fmt::Debug for PatternKind<'tcx> {
2828
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2929
match *self {
3030
PatternKind::Range { start, end, include_end } => {
31-
if let Some(start) = start {
32-
write!(f, "{start}")?;
33-
}
34-
write!(f, "{include_end}")?;
35-
if let Some(end) = end {
36-
write!(f, "{end}")?;
37-
}
38-
Ok(())
31+
write!(f, "{start}{include_end}{end}")
3932
}
4033
}
4134
}
@@ -44,5 +37,5 @@ impl<'tcx> fmt::Debug for PatternKind<'tcx> {
4437
#[derive(Clone, PartialEq, Eq, Hash)]
4538
#[derive(HashStable, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)]
4639
pub enum PatternKind<'tcx> {
47-
Range { start: Option<ty::Const<'tcx>>, end: Option<ty::Const<'tcx>>, include_end: RangeEnd },
40+
Range { start: ty::Const<'tcx>, end: ty::Const<'tcx>, include_end: RangeEnd },
4841
}

compiler/rustc_middle/src/ty/relate.rs

+11-12
Original file line numberDiff line numberDiff line change
@@ -54,19 +54,18 @@ impl<'tcx> Relate<TyCtxt<'tcx>> for ty::Pattern<'tcx> {
5454
&ty::PatternKind::Range { start: start_a, end: end_a, include_end: inc_a },
5555
&ty::PatternKind::Range { start: start_b, end: end_b, include_end: inc_b },
5656
) => {
57-
// FIXME(pattern_types): make equal patterns equal (`0..=` is the same as `..=`).
58-
let mut relate_opt_const = |a, b| match (a, b) {
59-
(None, None) => Ok(None),
60-
(Some(a), Some(b)) => relation.relate(a, b).map(Some),
61-
// FIXME(pattern_types): report a better error
62-
_ => Err(TypeError::Mismatch),
63-
};
64-
let start = relate_opt_const(start_a, start_b)?;
65-
let end = relate_opt_const(end_a, end_b)?;
66-
if inc_a != inc_b {
67-
todo!()
57+
let start = relation.relate(start_a, start_b)?;
58+
// FIXME(pattern_types): make equal patterns equal (`0..5` is the same as `0..=6`).
59+
let end = relation.relate(end_a, end_b)?;
60+
if inc_a == inc_b {
61+
Ok(relation.cx().mk_pat(ty::PatternKind::Range {
62+
start,
63+
end,
64+
include_end: inc_a,
65+
}))
66+
} else {
67+
Err(TypeError::Mismatch)
6868
}
69-
Ok(relation.cx().mk_pat(ty::PatternKind::Range { start, end, include_end: inc_a }))
7069
}
7170
}
7271
}

compiler/rustc_middle/src/ty/walk.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -138,8 +138,8 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>)
138138
ty::Pat(ty, pat) => {
139139
match *pat {
140140
ty::PatternKind::Range { start, end, include_end: _ } => {
141-
stack.extend(end.map(Into::into));
142-
stack.extend(start.map(Into::into));
141+
stack.push(end.into());
142+
stack.push(start.into());
143143
}
144144
}
145145
stack.push(ty.into());

compiler/rustc_smir/src/rustc_internal/internal.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,8 @@ impl RustcInternal for Pattern {
9090
fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
9191
tcx.mk_pat(match self {
9292
Pattern::Range { start, end, include_end } => rustc_ty::PatternKind::Range {
93-
start: start.as_ref().map(|c| c.internal(tables, tcx)),
94-
end: end.as_ref().map(|c| c.internal(tables, tcx)),
93+
start: start.as_ref().unwrap().internal(tables, tcx),
94+
end: end.as_ref().unwrap().internal(tables, tcx),
9595
include_end: if *include_end { RangeEnd::Included } else { RangeEnd::Excluded },
9696
},
9797
})

compiler/rustc_smir/src/rustc_smir/convert/ty.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -406,8 +406,9 @@ impl<'tcx> Stable<'tcx> for ty::Pattern<'tcx> {
406406
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
407407
match **self {
408408
ty::PatternKind::Range { start, end, include_end } => stable_mir::ty::Pattern::Range {
409-
start: start.stable(tables),
410-
end: end.stable(tables),
409+
// FIXME(SMIR): update data structures to not have an Option here anymore
410+
start: Some(start.stable(tables)),
411+
end: Some(end.stable(tables)),
411412
include_end: matches!(include_end, rustc_hir::RangeEnd::Included),
412413
},
413414
}

compiler/rustc_symbol_mangling/src/v0.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -415,8 +415,8 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
415415
ty::Pat(ty, pat) => match *pat {
416416
ty::PatternKind::Range { start, end, include_end } => {
417417
let consts = [
418-
start.unwrap_or(self.tcx.consts.unit),
419-
end.unwrap_or(self.tcx.consts.unit),
418+
start,
419+
end,
420420
ty::Const::from_bool(
421421
self.tcx,
422422
matches!(include_end, rustc_hir::RangeEnd::Included),

compiler/rustc_trait_selection/src/traits/wf.rs

+2-6
Original file line numberDiff line numberDiff line change
@@ -738,12 +738,8 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
738738
}
739739
}
740740
};
741-
if let Some(start) = start {
742-
check(start)
743-
}
744-
if let Some(end) = end {
745-
check(end)
746-
}
741+
check(start);
742+
check(end);
747743
}
748744
}
749745
}

compiler/rustc_ty_utils/src/layout.rs

+11-14
Original file line numberDiff line numberDiff line change
@@ -209,21 +209,18 @@ fn layout_of_uncached<'tcx>(
209209
if let BackendRepr::Scalar(scalar) | BackendRepr::ScalarPair(scalar, _) =
210210
&mut layout.backend_repr
211211
{
212-
if let Some(start) = start {
213-
scalar.valid_range_mut().start = extract_const_value(cx, ty, start)?
214-
.try_to_bits(tcx, cx.typing_env)
215-
.ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
216-
}
217-
if let Some(end) = end {
218-
let mut end = extract_const_value(cx, ty, end)?
219-
.try_to_bits(tcx, cx.typing_env)
220-
.ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
221-
match include_end {
222-
rustc_hir::RangeEnd::Included => {}
223-
rustc_hir::RangeEnd::Excluded => end = end.wrapping_sub(1),
224-
}
225-
scalar.valid_range_mut().end = end;
212+
scalar.valid_range_mut().start = extract_const_value(cx, ty, start)?
213+
.try_to_bits(tcx, cx.typing_env)
214+
.ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
215+
216+
let mut end = extract_const_value(cx, ty, end)?
217+
.try_to_bits(tcx, cx.typing_env)
218+
.ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
219+
match include_end {
220+
rustc_hir::RangeEnd::Included => {}
221+
rustc_hir::RangeEnd::Excluded => end = end.wrapping_sub(1),
226222
}
223+
scalar.valid_range_mut().end = end;
227224

228225
let niche = Niche {
229226
offset: Size::ZERO,

tests/mir-opt/pattern_types.main.PreCodegen.after.mir

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
fn main() -> () {
44
let mut _0: ();
55
scope 1 {
6-
debug x => const 2_u32 is 1..=;
6+
debug x => const 2_u32 is 1..=u32::MAX;
77
scope 2 {
8-
debug y => const {transmute(0x00000000): (u32) is 1..=};
8+
debug y => const {transmute(0x00000000): (u32) is 1..=u32::MAX};
99
}
1010
}
1111

tests/mir-opt/pattern_types.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ use std::pat::pattern_type;
55

66
// EMIT_MIR pattern_types.main.PreCodegen.after.mir
77
fn main() {
8-
// CHECK: debug x => const 2_u32 is 1..=
8+
// CHECK: debug x => const 2_u32 is 1..=u32::MAX
99
let x: pattern_type!(u32 is 1..) = unsafe { std::mem::transmute(2) };
10-
// CHECK: debug y => const {transmute(0x00000000): (u32) is 1..=}
10+
// CHECK: debug y => const {transmute(0x00000000): (u32) is 1..=u32::MAX}
1111
let y: pattern_type!(u32 is 1..) = unsafe { std::mem::transmute(0) };
1212
}

tests/ui/lint/clashing-extern-fn.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ LL | fn hidden_niche_unsafe_cell() -> Option<UnsafeCell<NonZero<usiz
1717
= help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
1818
= note: enum has no representation hint
1919

20-
warning: `extern` block uses type `Option<(usize) is 0..=>`, which is not FFI-safe
20+
warning: `extern` block uses type `Option<(usize) is 0..=usize::MAX>`, which is not FFI-safe
2121
--> $DIR/clashing-extern-fn.rs:502:54
2222
|
2323
LL | fn pt_non_zero_usize_opt_full_range() -> Option<pattern_type!(usize is 0..)>;
@@ -276,7 +276,7 @@ LL | fn pt_non_null_ptr() -> pattern_type!(usize is 1..);
276276
LL | fn pt_non_null_ptr() -> *const ();
277277
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
278278
|
279-
= note: expected `unsafe extern "C" fn() -> (usize) is 1..=`
279+
= note: expected `unsafe extern "C" fn() -> (usize) is 1..=usize::MAX`
280280
found `unsafe extern "C" fn() -> *const ()`
281281

282282
warning: 24 warnings emitted

0 commit comments

Comments
 (0)