Skip to content

Commit

Permalink
Actually create ranged int types in the type system.
Browse files Browse the repository at this point in the history
  • Loading branch information
oli-obk committed Jan 19, 2024
1 parent 241a61c commit b993b7a
Show file tree
Hide file tree
Showing 68 changed files with 530 additions and 51 deletions.
2 changes: 2 additions & 0 deletions compiler/rustc_borrowck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1608,6 +1608,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
| ty::Foreign(_)
| ty::Str
| ty::Array(_, _)
| ty::Pat(_, _)
| ty::Slice(_)
| ty::FnDef(_, _)
| ty::FnPtr(_)
Expand Down Expand Up @@ -1646,6 +1647,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
| ty::Foreign(_)
| ty::Str
| ty::Array(_, _)
| ty::Pat(_, _)
| ty::Slice(_)
| ty::RawPtr(_)
| ty::Ref(_, _, _)
Expand Down
9 changes: 9 additions & 0 deletions compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,15 @@ 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);
write!(output, ",{:?}>", pat).unwrap();
} else {
write!(output, "{:?}", t).unwrap();
}
}
ty::Slice(inner_type) => {
if cpp_like_debuginfo {
output.push_str("slice2$<");
Expand Down
7 changes: 5 additions & 2 deletions compiler/rustc_const_eval/src/const_eval/valtrees.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ pub(crate) fn const_to_valtree_inner<'tcx>(
Ok(ty::ValTree::Leaf(val.assert_int()))
}

ty::Pat(..) => const_to_valtree_inner(ecx, &ecx.project_field(place, 0).unwrap(), 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`).
Expand Down Expand Up @@ -238,7 +240,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
Expand All @@ -251,9 +253,10 @@ 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(tcx, DUMMY_SP, param_env, CanAccessStatics::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)
}
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_const_eval/src/interpret/eval_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1014,6 +1014,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {

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,

Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_const_eval/src/interpret/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>(
ty::Alias(..) | ty::Param(_) | ty::Placeholder(_) | ty::Infer(_) => {
throw_inval!(TooGeneric)
}
ty::Pat(..) => {
unimplemented!("pattern types need to calculate pattern from their pattern")
}
ty::Bound(_, _) => bug!("bound ty during ctfe"),
ty::Bool
| ty::Char
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_const_eval/src/interpret/validity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -571,6 +571,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
// Nothing to check.
Ok(true)
}
ty::Pat(..) => unimplemented!(),
// The above should be all the primitive types. The rest is compound, we
// check them by visiting their fields/variants.
ty::Adt(..)
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_const_eval/src/util/type_name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
| ty::Uint(_)
| ty::Float(_)
| ty::Str
| ty::Pat(_, _)
| ty::Array(_, _)
| ty::Slice(_)
| ty::RawPtr(_)
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir_analysis/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,7 @@ hir_analysis_pass_to_variadic_function = can't pass `{$ty}` to variadic function
.suggestion = cast the value to `{$cast_ty}`
.help = cast the value to `{$cast_ty}`
hir_analysis_pattern_type_non_const_range = "range patterns must have constant range start and end"
hir_analysis_pattern_type_wild_pat = "wildcard patterns are not permitted for pattern types"
.label = "this type is the same as the inner type without a pattern"
hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is not allowed within types on item signatures for {$kind}
Expand Down
90 changes: 71 additions & 19 deletions compiler/rustc_hir_analysis/src/astconv/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ use rustc_hir::{GenericArg, GenericArgs, OpaqueTyOrigin};
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, IsSuggestable, ParamEnv, Ty,
TyCtxt, TypeVisitableExt,
Expand Down Expand Up @@ -2559,25 +2560,76 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// handled specially and will not descend into this routine.
self.ty_infer(None, ast_ty.span)
}
hir::TyKind::Pat(_ty, pat) => match pat.kind {
hir::PatKind::Wild => {
let err = tcx.dcx().emit_err(WildPatTy { span: pat.span });
Ty::new_error(tcx, err)
}
hir::PatKind::Binding(_, _, _, _) => todo!(),
hir::PatKind::Struct(_, _, _) => todo!(),
hir::PatKind::TupleStruct(_, _, _) => todo!(),
hir::PatKind::Or(_) => todo!(),
hir::PatKind::Path(_) => todo!(),
hir::PatKind::Tuple(_, _) => todo!(),
hir::PatKind::Box(_) => todo!(),
hir::PatKind::Ref(_, _) => todo!(),
hir::PatKind::Lit(_) => todo!(),
hir::PatKind::Range(_, _, _) => Ty::new_misc_error(tcx),
hir::PatKind::Slice(_, _, _) => todo!(),
hir::PatKind::Never => todo!(),
hir::PatKind::Err(e) => Ty::new_error(tcx, e),
},
hir::TyKind::Pat(ty, pat) => {
let ty = self.ast_ty_to_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::Binding(_, _, _, _) => todo!(),
hir::PatKind::Struct(_, _, _) => todo!(),
hir::PatKind::TupleStruct(_, _, _) => todo!(),
hir::PatKind::Or(_) => todo!(),
hir::PatKind::Path(_) => todo!(),
hir::PatKind::Tuple(_, _) => todo!(),
hir::PatKind::Box(_) => todo!(),
hir::PatKind::Ref(_, _) => todo!(),
hir::PatKind::Lit(_) => todo!(),
hir::PatKind::Range(start, end, include_end) => {
let expr_to_const = |expr: &'tcx hir::Expr<'tcx>, neg| -> ty::Const<'tcx> {
match &expr.kind {
hir::ExprKind::Lit(lit) => {
let lit_input = LitToConstInput { lit: &lit.node, ty, neg };
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)
}
}
};
let expr_to_const = |expr, neg| {
let c = expr_to_const(expr, neg);
self.record_ty(expr.hir_id, c.ty(), expr.span);
c
};
let expr_to_const = |expr: &'tcx hir::Expr<'tcx>| match &expr.kind {
hir::ExprKind::Unary(hir::UnOp::Neg, expr) => expr_to_const(expr, true),
_ => expr_to_const(expr, false),
};
let expr_to_const = |expr| {
let c = expr_to_const(expr);
self.record_ty(expr.hir_id, c.ty(), expr.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::Slice(_, _, _) => todo!(),
hir::PatKind::Never => todo!(),
hir::PatKind::Err(e) => Ty::new_error(tcx, e),
};
self.record_ty(pat.hir_id, ty, pat.span);
pat_ty
}
hir::TyKind::Err(guar) => Ty::new_error(tcx, *guar),
};

Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,10 @@ impl<'tcx> InherentCollect<'tcx> {
ty::Dynamic(..) => {
Err(self.tcx.dcx().emit_err(errors::InherentDyn { span: item_span }))
}
ty::Pat(..) => Err(self
.tcx
.dcx()
.span_err(item_span, "cannot define inherent `impl` for pattern types")),
ty::Bool
| ty::Char
| ty::Int(_)
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_hir_analysis/src/coherence/orphan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,11 @@ fn do_orphan_check_impl<'tcx>(
(LocalImpl::Disallow { problematic_kind }, NonlocalImpl::DisallowOther)
}

ty::Pat(..) => (
LocalImpl::Disallow { problematic_kind: "pattern type" },
NonlocalImpl::DisallowOther,
),

ty::Bool
| ty::Char
| ty::Int(..)
Expand Down
7 changes: 7 additions & 0 deletions compiler/rustc_hir_analysis/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1513,3 +1513,10 @@ pub struct NotSupportedDelegation<'a> {
#[label]
pub callee_span: Span,
}

#[derive(Diagnostic)]
#[diag(hir_analysis_pattern_type_non_const_range)]
pub struct NonConstRange {
#[primary_span]
pub span: Span,
}
14 changes: 14 additions & 0 deletions compiler/rustc_hir_analysis/src/variance/constraints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,20 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
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);
}
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir_typeck/src/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
| ty::CoroutineWitness(..)
| ty::RawPtr(_)
| ty::Ref(..)
| ty::Pat(..)
| ty::FnDef(..)
| ty::FnPtr(..)
| ty::Closure(..)
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
| ty::Tuple(..)
| ty::Alias(..)
| ty::Foreign(..)
| ty::Pat(..)
| ty::Param(..) => {
if t.flags().intersects(self.needs_canonical_flags) {
t.super_fold_with(self)
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_infer/src/infer/outlives/components.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_lint/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,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 patterned 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
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_lint/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1335,6 +1335,12 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
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 }
}
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/arena.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,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
Expand Down
12 changes: 12 additions & 0 deletions compiler/rustc_middle/src/ty/codec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,12 @@ impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::Const<'tcx> {
}
}

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)
Expand Down Expand Up @@ -363,6 +369,12 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Const<'tcx> {
}
}

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
Expand Down
Loading

0 comments on commit b993b7a

Please sign in to comment.