mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-28 02:57:37 +00:00
Rollup merge of #136922 - oli-obk:pattern-types-option-ends, r=BoxyUwU
Pattern types: Avoid having to handle an Option for range ends in the type system or the HIR Instead, 1. during hir_ty_lowering, we now generate constants for the min/max when the range doesn't have a start/end specified. 2. in a later commit we generate those constants during ast lowering, simplifying everything further by not having to handle the range end inclusivity anymore in the type system (and thus avoiding any issues of `0..5` being different from `0..=4` I think it makes all the type system code simpler, and the cost of the extra `ConstKind::Value` processing seems negligible. r? `@BoxyUwU` cc `@joshtriplett` `@scottmcm`
This commit is contained in:
commit
6ac714d526
@ -136,6 +136,7 @@ struct LoweringContext<'a, 'hir> {
|
||||
|
||||
allow_try_trait: Arc<[Symbol]>,
|
||||
allow_gen_future: Arc<[Symbol]>,
|
||||
allow_pattern_type: Arc<[Symbol]>,
|
||||
allow_async_iterator: Arc<[Symbol]>,
|
||||
allow_for_await: Arc<[Symbol]>,
|
||||
allow_async_fn_traits: Arc<[Symbol]>,
|
||||
@ -176,6 +177,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
impl_trait_defs: Vec::new(),
|
||||
impl_trait_bounds: Vec::new(),
|
||||
allow_try_trait: [sym::try_trait_v2, sym::yeet_desugar_details].into(),
|
||||
allow_pattern_type: [sym::pattern_types, sym::pattern_type_range_trait].into(),
|
||||
allow_gen_future: if tcx.features().async_fn_track_caller() {
|
||||
[sym::gen_future, sym::closure_track_caller].into()
|
||||
} else {
|
||||
@ -1365,7 +1367,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
}
|
||||
}
|
||||
TyKind::Pat(ty, pat) => {
|
||||
hir::TyKind::Pat(self.lower_ty(ty, itctx), self.lower_ty_pat(pat))
|
||||
hir::TyKind::Pat(self.lower_ty(ty, itctx), self.lower_ty_pat(pat, ty.span))
|
||||
}
|
||||
TyKind::MacCall(_) => {
|
||||
span_bug!(t.span, "`TyKind::MacCall` should have been expanded by now")
|
||||
|
@ -3,11 +3,11 @@ use std::sync::Arc;
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::*;
|
||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::Res;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::{self as hir, LangItem};
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_span::source_map::{Spanned, respan};
|
||||
use rustc_span::{Ident, Span};
|
||||
use rustc_span::{DesugaringKind, Ident, Span, kw};
|
||||
|
||||
use super::errors::{
|
||||
ArbitraryExpressionInPattern, ExtraDoubleDot, MisplacedDoubleDot, SubTupleBinding,
|
||||
@ -430,22 +430,124 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
self.arena.alloc(hir::PatExpr { hir_id: self.lower_node_id(expr.id), span, kind })
|
||||
}
|
||||
|
||||
pub(crate) fn lower_ty_pat(&mut self, pattern: &TyPat) -> &'hir hir::TyPat<'hir> {
|
||||
self.arena.alloc(self.lower_ty_pat_mut(pattern))
|
||||
pub(crate) fn lower_ty_pat(
|
||||
&mut self,
|
||||
pattern: &TyPat,
|
||||
base_type: Span,
|
||||
) -> &'hir hir::TyPat<'hir> {
|
||||
self.arena.alloc(self.lower_ty_pat_mut(pattern, base_type))
|
||||
}
|
||||
|
||||
fn lower_ty_pat_mut(&mut self, pattern: &TyPat) -> hir::TyPat<'hir> {
|
||||
fn lower_ty_pat_mut(&mut self, pattern: &TyPat, base_type: Span) -> hir::TyPat<'hir> {
|
||||
// loop here to avoid recursion
|
||||
let pat_hir_id = self.lower_node_id(pattern.id);
|
||||
let node = match &pattern.kind {
|
||||
TyPatKind::Range(e1, e2, Spanned { node: end, .. }) => hir::TyPatKind::Range(
|
||||
e1.as_deref().map(|e| self.lower_anon_const_to_const_arg(e)),
|
||||
e2.as_deref().map(|e| self.lower_anon_const_to_const_arg(e)),
|
||||
self.lower_range_end(end, e2.is_some()),
|
||||
TyPatKind::Range(e1, e2, Spanned { node: end, span }) => hir::TyPatKind::Range(
|
||||
e1.as_deref().map(|e| self.lower_anon_const_to_const_arg(e)).unwrap_or_else(|| {
|
||||
self.lower_ty_pat_range_end(
|
||||
hir::LangItem::RangeMin,
|
||||
span.shrink_to_lo(),
|
||||
base_type,
|
||||
)
|
||||
}),
|
||||
e2.as_deref()
|
||||
.map(|e| match end {
|
||||
RangeEnd::Included(..) => self.lower_anon_const_to_const_arg(e),
|
||||
RangeEnd::Excluded => self.lower_excluded_range_end(e),
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
self.lower_ty_pat_range_end(
|
||||
hir::LangItem::RangeMax,
|
||||
span.shrink_to_hi(),
|
||||
base_type,
|
||||
)
|
||||
}),
|
||||
),
|
||||
TyPatKind::Err(guar) => hir::TyPatKind::Err(*guar),
|
||||
};
|
||||
|
||||
hir::TyPat { hir_id: pat_hir_id, kind: node, span: self.lower_span(pattern.span) }
|
||||
}
|
||||
|
||||
/// Lowers the range end of an exclusive range (`2..5`) to an inclusive range 2..=(5 - 1).
|
||||
/// This way the type system doesn't have to handle the distinction between inclusive/exclusive ranges.
|
||||
fn lower_excluded_range_end(&mut self, e: &AnonConst) -> &'hir hir::ConstArg<'hir> {
|
||||
let span = self.lower_span(e.value.span);
|
||||
let unstable_span = self.mark_span_with_reason(
|
||||
DesugaringKind::PatTyRange,
|
||||
span,
|
||||
Some(Arc::clone(&self.allow_pattern_type)),
|
||||
);
|
||||
let anon_const = self.with_new_scopes(span, |this| {
|
||||
let def_id = this.local_def_id(e.id);
|
||||
let hir_id = this.lower_node_id(e.id);
|
||||
let body = this.lower_body(|this| {
|
||||
// Need to use a custom function as we can't just subtract `1` from a `char`.
|
||||
let kind = hir::ExprKind::Path(this.make_lang_item_qpath(
|
||||
hir::LangItem::RangeSub,
|
||||
unstable_span,
|
||||
None,
|
||||
));
|
||||
let fn_def = this.arena.alloc(hir::Expr { hir_id: this.next_id(), kind, span });
|
||||
let args = this.arena.alloc([this.lower_expr_mut(&e.value)]);
|
||||
(
|
||||
&[],
|
||||
hir::Expr {
|
||||
hir_id: this.next_id(),
|
||||
kind: hir::ExprKind::Call(fn_def, args),
|
||||
span,
|
||||
},
|
||||
)
|
||||
});
|
||||
hir::AnonConst { def_id, hir_id, body, span }
|
||||
});
|
||||
self.arena.alloc(hir::ConstArg {
|
||||
hir_id: self.next_id(),
|
||||
kind: hir::ConstArgKind::Anon(self.arena.alloc(anon_const)),
|
||||
})
|
||||
}
|
||||
|
||||
/// When a range has no end specified (`1..` or `1..=`) or no start specified (`..5` or `..=5`),
|
||||
/// we instead use a constant of the MAX/MIN of the type.
|
||||
/// This way the type system does not have to handle the lack of a start/end.
|
||||
fn lower_ty_pat_range_end(
|
||||
&mut self,
|
||||
lang_item: LangItem,
|
||||
span: Span,
|
||||
base_type: Span,
|
||||
) -> &'hir hir::ConstArg<'hir> {
|
||||
let parent_def_id = self.current_hir_id_owner.def_id;
|
||||
let node_id = self.next_node_id();
|
||||
|
||||
// Add a definition for the in-band const def.
|
||||
// We're generating a range end that didn't exist in the AST,
|
||||
// so the def collector didn't create the def ahead of time. That's why we have to do
|
||||
// it here.
|
||||
let def_id = self.create_def(parent_def_id, node_id, kw::Empty, DefKind::AnonConst, span);
|
||||
let hir_id = self.lower_node_id(node_id);
|
||||
|
||||
let unstable_span = self.mark_span_with_reason(
|
||||
DesugaringKind::PatTyRange,
|
||||
self.lower_span(span),
|
||||
Some(Arc::clone(&self.allow_pattern_type)),
|
||||
);
|
||||
let span = self.lower_span(base_type);
|
||||
|
||||
let path_expr = hir::Expr {
|
||||
hir_id: self.next_id(),
|
||||
kind: hir::ExprKind::Path(self.make_lang_item_qpath(lang_item, unstable_span, None)),
|
||||
span,
|
||||
};
|
||||
|
||||
let ct = self.with_new_scopes(span, |this| {
|
||||
self.arena.alloc(hir::AnonConst {
|
||||
def_id,
|
||||
hir_id,
|
||||
body: this.lower_body(|_this| (&[], path_expr)),
|
||||
span,
|
||||
})
|
||||
});
|
||||
let hir_id = self.next_id();
|
||||
self.arena.alloc(hir::ConstArg { kind: hir::ConstArgKind::Anon(ct), hir_id })
|
||||
}
|
||||
}
|
||||
|
@ -1600,7 +1600,7 @@ pub struct PatField<'hir> {
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Debug, HashStable_Generic)]
|
||||
#[derive(Copy, Clone, PartialEq, Debug, HashStable_Generic, Hash, Eq, Encodable, Decodable)]
|
||||
pub enum RangeEnd {
|
||||
Included,
|
||||
Excluded,
|
||||
@ -1668,7 +1668,7 @@ pub enum PatExprKind<'hir> {
|
||||
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
||||
pub enum TyPatKind<'hir> {
|
||||
/// A range pattern (e.g., `1..=2` or `1..2`).
|
||||
Range(Option<&'hir ConstArg<'hir>>, Option<&'hir ConstArg<'hir>>, RangeEnd),
|
||||
Range(&'hir ConstArg<'hir>, &'hir ConstArg<'hir>),
|
||||
|
||||
/// A placeholder for a pattern that wasn't well formed in some way.
|
||||
Err(ErrorGuaranteed),
|
||||
|
@ -708,9 +708,9 @@ pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm<'v>) -> V::Res
|
||||
pub fn walk_ty_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v TyPat<'v>) -> V::Result {
|
||||
try_visit!(visitor.visit_id(pattern.hir_id));
|
||||
match pattern.kind {
|
||||
TyPatKind::Range(lower_bound, upper_bound, _) => {
|
||||
visit_opt!(visitor, visit_const_arg_unambig, lower_bound);
|
||||
visit_opt!(visitor, visit_const_arg_unambig, upper_bound);
|
||||
TyPatKind::Range(lower_bound, upper_bound) => {
|
||||
try_visit!(visitor.visit_const_arg_unambig(lower_bound));
|
||||
try_visit!(visitor.visit_const_arg_unambig(upper_bound));
|
||||
}
|
||||
TyPatKind::Err(_) => (),
|
||||
}
|
||||
|
@ -418,6 +418,9 @@ language_item_table! {
|
||||
Range, sym::Range, range_struct, Target::Struct, GenericRequirement::None;
|
||||
RangeToInclusive, sym::RangeToInclusive, range_to_inclusive_struct, Target::Struct, GenericRequirement::None;
|
||||
RangeTo, sym::RangeTo, range_to_struct, Target::Struct, GenericRequirement::None;
|
||||
RangeMax, sym::RangeMax, range_max, Target::AssocConst, GenericRequirement::Exact(0);
|
||||
RangeMin, sym::RangeMin, range_min, Target::AssocConst, GenericRequirement::Exact(0);
|
||||
RangeSub, sym::RangeSub, range_sub, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::Exact(0);
|
||||
|
||||
// `new_range` types that are `Copy + IntoIterator`
|
||||
RangeFromCopy, sym::RangeFromCopy, range_from_copy_struct, Target::Struct, GenericRequirement::None;
|
||||
|
@ -244,9 +244,6 @@ hir_analysis_inherent_ty_outside_relevant = cannot define inherent `impl` for a
|
||||
.help = consider moving this inherent impl into the crate defining the type if possible
|
||||
.span_help = alternatively add `#[rustc_allow_incoherent_impl]` to the relevant impl items
|
||||
|
||||
hir_analysis_invalid_base_type = `{$ty}` is not a valid base type for range patterns
|
||||
.note = range patterns only support integers
|
||||
|
||||
hir_analysis_invalid_generic_receiver_ty = invalid generic `self` parameter type: `{$receiver_ty}`
|
||||
.note = type of `self` must not be a method generic parameter type
|
||||
|
||||
|
@ -11,8 +11,6 @@ use rustc_middle::ty::Ty;
|
||||
use rustc_span::{Ident, Span, Symbol};
|
||||
|
||||
use crate::fluent_generated as fluent;
|
||||
mod pattern_types;
|
||||
pub(crate) use pattern_types::*;
|
||||
pub(crate) mod wrong_number_of_generic_args;
|
||||
|
||||
mod precise_captures;
|
||||
|
@ -1,14 +0,0 @@
|
||||
use rustc_macros::Diagnostic;
|
||||
use rustc_middle::ty::Ty;
|
||||
use rustc_span::Span;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_invalid_base_type)]
|
||||
pub(crate) struct InvalidBaseType<'tcx> {
|
||||
pub ty: Ty<'tcx>,
|
||||
#[primary_span]
|
||||
pub ty_span: Span,
|
||||
pub pat: &'static str,
|
||||
#[note]
|
||||
pub pat_span: Span,
|
||||
}
|
@ -55,9 +55,7 @@ use tracing::{debug, instrument};
|
||||
|
||||
use self::errors::assoc_kind_str;
|
||||
use crate::check::check_abi_fn_ptr;
|
||||
use crate::errors::{
|
||||
AmbiguousLifetimeBound, BadReturnTypeNotation, InvalidBaseType, NoVariantNamed,
|
||||
};
|
||||
use crate::errors::{AmbiguousLifetimeBound, BadReturnTypeNotation, NoVariantNamed};
|
||||
use crate::hir_ty_lowering::errors::{GenericsArgsErrExtend, prohibit_assoc_item_constraint};
|
||||
use crate::hir_ty_lowering::generics::{check_generic_arg_count, lower_generic_args};
|
||||
use crate::middle::resolve_bound_vars as rbv;
|
||||
@ -2692,28 +2690,26 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
let ty_span = ty.span;
|
||||
let ty = self.lower_ty(ty);
|
||||
let pat_ty = match pat.kind {
|
||||
hir::TyPatKind::Range(start, end, include_end) => {
|
||||
let ty = match ty.kind() {
|
||||
ty::Int(_) | ty::Uint(_) | ty::Char => ty,
|
||||
_ => Ty::new_error(
|
||||
tcx,
|
||||
self.dcx().emit_err(InvalidBaseType {
|
||||
ty,
|
||||
pat: "range",
|
||||
hir::TyPatKind::Range(start, end) => {
|
||||
let (ty, start, end) = match ty.kind() {
|
||||
// Keep this list of types in sync with the list of types that
|
||||
// the `RangePattern` trait is implemented for.
|
||||
ty::Int(_) | ty::Uint(_) | ty::Char => {
|
||||
let start = self.lower_const_arg(start, FeedConstTy::No);
|
||||
let end = self.lower_const_arg(end, FeedConstTy::No);
|
||||
(ty, start, end)
|
||||
}
|
||||
_ => {
|
||||
let guar = self.dcx().span_delayed_bug(
|
||||
ty_span,
|
||||
pat_span: pat.span,
|
||||
}),
|
||||
),
|
||||
};
|
||||
let start = start.map(|expr| self.lower_const_arg(expr, FeedConstTy::No));
|
||||
let end = end.map(|expr| self.lower_const_arg(expr, FeedConstTy::No));
|
||||
|
||||
let include_end = match include_end {
|
||||
hir::RangeEnd::Included => true,
|
||||
hir::RangeEnd::Excluded => false,
|
||||
"invalid base type for range pattern",
|
||||
);
|
||||
let errc = ty::Const::new_error(tcx, guar);
|
||||
(Ty::new_error(tcx, guar), errc, errc)
|
||||
}
|
||||
};
|
||||
|
||||
let pat = tcx.mk_pat(ty::PatternKind::Range { start, end, include_end });
|
||||
let pat = tcx.mk_pat(ty::PatternKind::Range { start, end });
|
||||
Ty::new_pat(tcx, ty, pat)
|
||||
}
|
||||
hir::TyPatKind::Err(e) => Ty::new_error(tcx, e),
|
||||
|
@ -252,13 +252,9 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
|
||||
|
||||
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);
|
||||
}
|
||||
ty::PatternKind::Range { start, end } => {
|
||||
self.add_constraints_from_const(current, start, variance);
|
||||
self.add_constraints_from_const(current, end, variance);
|
||||
}
|
||||
}
|
||||
self.add_constraints_from_ty(current, typ, variance);
|
||||
|
@ -1943,17 +1943,10 @@ impl<'a> State<'a> {
|
||||
// Pat isn't normalized, but the beauty of it
|
||||
// is that it doesn't matter
|
||||
match pat.kind {
|
||||
TyPatKind::Range(begin, end, end_kind) => {
|
||||
if let Some(expr) = begin {
|
||||
self.print_const_arg(expr);
|
||||
}
|
||||
match end_kind {
|
||||
RangeEnd::Included => self.word("..."),
|
||||
RangeEnd::Excluded => self.word(".."),
|
||||
}
|
||||
if let Some(expr) = end {
|
||||
self.print_const_arg(expr);
|
||||
}
|
||||
TyPatKind::Range(begin, end) => {
|
||||
self.print_const_arg(begin);
|
||||
self.word("..=");
|
||||
self.print_const_arg(end);
|
||||
}
|
||||
TyPatKind::Err(_) => {
|
||||
self.popen();
|
||||
|
@ -882,27 +882,13 @@ fn ty_is_known_nonnull<'tcx>(
|
||||
|| Option::unwrap_or_default(
|
||||
try {
|
||||
match **pat {
|
||||
ty::PatternKind::Range { start, end, include_end } => {
|
||||
match (start, end) {
|
||||
(Some(start), None) => {
|
||||
start.try_to_value()?.try_to_bits(tcx, typing_env)? > 0
|
||||
}
|
||||
(Some(start), Some(end)) => {
|
||||
let start =
|
||||
start.try_to_value()?.try_to_bits(tcx, typing_env)?;
|
||||
let end =
|
||||
end.try_to_value()?.try_to_bits(tcx, typing_env)?;
|
||||
ty::PatternKind::Range { start, end } => {
|
||||
let start = start.try_to_value()?.try_to_bits(tcx, typing_env)?;
|
||||
let end = end.try_to_value()?.try_to_bits(tcx, typing_env)?;
|
||||
|
||||
if include_end {
|
||||
// This also works for negative numbers, as we just need
|
||||
// to ensure we aren't wrapping over zero.
|
||||
start > 0 && end >= start
|
||||
} else {
|
||||
start > 0 && end > start
|
||||
}
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
// This also works for negative numbers, as we just need
|
||||
// to ensure we aren't wrapping over zero.
|
||||
start > 0 && end >= start
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -220,13 +220,9 @@ impl FlagComputation {
|
||||
&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::PatternKind::Range { start, end } => {
|
||||
self.add_const(start);
|
||||
self.add_const(end);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,18 +26,30 @@ impl<'tcx> fmt::Debug for Pattern<'tcx> {
|
||||
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}")?;
|
||||
PatternKind::Range { start, end } => {
|
||||
write!(f, "{start}")?;
|
||||
|
||||
if let Some(c) = end.try_to_value() {
|
||||
let end = c.valtree.unwrap_leaf();
|
||||
let size = end.size();
|
||||
let max = match c.ty.kind() {
|
||||
ty::Int(_) => {
|
||||
Some(ty::ScalarInt::truncate_from_int(size.signed_int_max(), size))
|
||||
}
|
||||
ty::Uint(_) => {
|
||||
Some(ty::ScalarInt::truncate_from_uint(size.unsigned_int_max(), size))
|
||||
}
|
||||
ty::Char => Some(ty::ScalarInt::truncate_from_uint(char::MAX, size)),
|
||||
_ => None,
|
||||
};
|
||||
if let Some((max, _)) = max
|
||||
&& end == max
|
||||
{
|
||||
return write!(f, "..");
|
||||
}
|
||||
}
|
||||
write!(f, "..")?;
|
||||
if include_end {
|
||||
write!(f, "=")?;
|
||||
}
|
||||
if let Some(end) = end {
|
||||
write!(f, "{end}")?;
|
||||
}
|
||||
Ok(())
|
||||
|
||||
write!(f, "..={end}")
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -46,5 +58,5 @@ impl<'tcx> fmt::Debug for PatternKind<'tcx> {
|
||||
#[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 },
|
||||
Range { start: ty::Const<'tcx>, end: ty::Const<'tcx> },
|
||||
}
|
||||
|
@ -51,22 +51,12 @@ impl<'tcx> Relate<TyCtxt<'tcx>> for ty::Pattern<'tcx> {
|
||||
) -> 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 },
|
||||
&ty::PatternKind::Range { start: start_a, end: end_a },
|
||||
&ty::PatternKind::Range { start: start_b, end: end_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.cx().mk_pat(ty::PatternKind::Range { start, end, include_end: inc_a }))
|
||||
let start = relation.relate(start_a, start_b)?;
|
||||
let end = relation.relate(end_a, end_b)?;
|
||||
Ok(relation.cx().mk_pat(ty::PatternKind::Range { start, end }))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -284,6 +284,7 @@ TrivialTypeTraversalImpls! {
|
||||
rustc_hir::def_id::LocalDefId,
|
||||
rustc_hir::HirId,
|
||||
rustc_hir::MatchSource,
|
||||
rustc_hir::RangeEnd,
|
||||
rustc_span::Ident,
|
||||
rustc_span::Span,
|
||||
rustc_span::Symbol,
|
||||
|
@ -137,9 +137,9 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>)
|
||||
|
||||
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));
|
||||
ty::PatternKind::Range { start, end } => {
|
||||
stack.push(end.into());
|
||||
stack.push(start.into());
|
||||
}
|
||||
}
|
||||
stack.push(ty.into());
|
||||
|
@ -88,10 +88,9 @@ 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| c.internal(tables, tcx)),
|
||||
end: end.as_ref().map(|c| c.internal(tables, tcx)),
|
||||
include_end: *include_end,
|
||||
Pattern::Range { start, end, include_end: _ } => rustc_ty::PatternKind::Range {
|
||||
start: start.as_ref().unwrap().internal(tables, tcx),
|
||||
end: end.as_ref().unwrap().internal(tables, tcx),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
@ -405,10 +405,11 @@ impl<'tcx> Stable<'tcx> for ty::Pattern<'tcx> {
|
||||
|
||||
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,
|
||||
ty::PatternKind::Range { start, end } => stable_mir::ty::Pattern::Range {
|
||||
// FIXME(SMIR): update data structures to not have an Option here anymore
|
||||
start: Some(start.stable(tables)),
|
||||
end: Some(end.stable(tables)),
|
||||
include_end: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -1173,6 +1173,8 @@ pub enum DesugaringKind {
|
||||
BoundModifier,
|
||||
/// Calls to contract checks (`#[requires]` to precond, `#[ensures]` to postcond)
|
||||
Contract,
|
||||
/// A pattern type range start/end
|
||||
PatTyRange,
|
||||
}
|
||||
|
||||
impl DesugaringKind {
|
||||
@ -1190,6 +1192,7 @@ impl DesugaringKind {
|
||||
DesugaringKind::WhileLoop => "`while` loop",
|
||||
DesugaringKind::BoundModifier => "trait bound modifier",
|
||||
DesugaringKind::Contract => "contract check",
|
||||
DesugaringKind::PatTyRange => "pattern type",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -308,6 +308,9 @@ symbols! {
|
||||
RangeFull,
|
||||
RangeInclusive,
|
||||
RangeInclusiveCopy,
|
||||
RangeMax,
|
||||
RangeMin,
|
||||
RangeSub,
|
||||
RangeTo,
|
||||
RangeToInclusive,
|
||||
Rc,
|
||||
@ -1522,6 +1525,7 @@ symbols! {
|
||||
pattern_complexity_limit,
|
||||
pattern_parentheses,
|
||||
pattern_type,
|
||||
pattern_type_range_trait,
|
||||
pattern_types,
|
||||
permissions_from_mode,
|
||||
phantom_data,
|
||||
|
@ -413,12 +413,8 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
|
||||
}
|
||||
|
||||
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),
|
||||
];
|
||||
ty::PatternKind::Range { start, end } => {
|
||||
let consts = [start, end];
|
||||
// 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");
|
||||
|
@ -708,7 +708,7 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
|
||||
ty::Pat(subty, pat) => {
|
||||
self.require_sized(subty, ObligationCauseCode::Misc);
|
||||
match *pat {
|
||||
ty::PatternKind::Range { start, end, include_end: _ } => {
|
||||
ty::PatternKind::Range { start, end } => {
|
||||
let mut check = |c| {
|
||||
let cause = self.cause(ObligationCauseCode::Misc);
|
||||
self.out.push(traits::Obligation::with_depth(
|
||||
@ -738,12 +738,8 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
};
|
||||
if let Some(start) = start {
|
||||
check(start)
|
||||
}
|
||||
if let Some(end) = end {
|
||||
check(end)
|
||||
}
|
||||
check(start);
|
||||
check(end);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -205,24 +205,17 @@ fn layout_of_uncached<'tcx>(
|
||||
let layout = cx.layout_of(ty)?.layout;
|
||||
let mut layout = LayoutData::clone(&layout.0);
|
||||
match *pat {
|
||||
ty::PatternKind::Range { start, end, include_end } => {
|
||||
ty::PatternKind::Range { start, end } => {
|
||||
if let BackendRepr::Scalar(scalar) | BackendRepr::ScalarPair(scalar, _) =
|
||||
&mut layout.backend_repr
|
||||
{
|
||||
if let Some(start) = start {
|
||||
scalar.valid_range_mut().start = extract_const_value(cx, ty, start)?
|
||||
.try_to_bits(tcx, cx.typing_env)
|
||||
.ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
|
||||
}
|
||||
if let Some(end) = end {
|
||||
let mut end = extract_const_value(cx, ty, end)?
|
||||
.try_to_bits(tcx, cx.typing_env)
|
||||
.ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
|
||||
if !include_end {
|
||||
end = end.wrapping_sub(1);
|
||||
}
|
||||
scalar.valid_range_mut().end = end;
|
||||
}
|
||||
scalar.valid_range_mut().start = extract_const_value(cx, ty, start)?
|
||||
.try_to_bits(tcx, cx.typing_env)
|
||||
.ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
|
||||
|
||||
scalar.valid_range_mut().end = extract_const_value(cx, ty, end)?
|
||||
.try_to_bits(tcx, cx.typing_env)
|
||||
.ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
|
||||
|
||||
let niche = Niche {
|
||||
offset: Size::ZERO,
|
||||
|
@ -12,3 +12,65 @@ macro_rules! pattern_type {
|
||||
/* compiler built-in */
|
||||
};
|
||||
}
|
||||
|
||||
/// A trait implemented for integer types and `char`.
|
||||
/// Useful in the future for generic pattern types, but
|
||||
/// used right now to simplify ast lowering of pattern type ranges.
|
||||
#[unstable(feature = "pattern_type_range_trait", issue = "123646")]
|
||||
#[rustc_const_unstable(feature = "pattern_type_range_trait", issue = "123646")]
|
||||
#[const_trait]
|
||||
#[diagnostic::on_unimplemented(
|
||||
message = "`{Self}` is not a valid base type for range patterns",
|
||||
label = "only integer types and `char` are supported"
|
||||
)]
|
||||
pub trait RangePattern {
|
||||
/// Trait version of the inherent `MIN` assoc const.
|
||||
#[cfg_attr(not(bootstrap), lang = "RangeMin")]
|
||||
const MIN: Self;
|
||||
|
||||
/// Trait version of the inherent `MIN` assoc const.
|
||||
#[cfg_attr(not(bootstrap), lang = "RangeMax")]
|
||||
const MAX: Self;
|
||||
|
||||
/// A compile-time helper to subtract 1 for exclusive ranges.
|
||||
#[cfg_attr(not(bootstrap), lang = "RangeSub")]
|
||||
#[track_caller]
|
||||
fn sub_one(self) -> Self;
|
||||
}
|
||||
|
||||
macro_rules! impl_range_pat {
|
||||
($($ty:ty,)*) => {
|
||||
$(
|
||||
#[rustc_const_unstable(feature = "pattern_type_range_trait", issue = "123646")]
|
||||
impl const RangePattern for $ty {
|
||||
const MIN: $ty = <$ty>::MIN;
|
||||
const MAX: $ty = <$ty>::MAX;
|
||||
fn sub_one(self) -> Self {
|
||||
match self.checked_sub(1) {
|
||||
Some(val) => val,
|
||||
None => panic!("exclusive range end at minimum value of type")
|
||||
}
|
||||
}
|
||||
}
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
impl_range_pat! {
|
||||
i8, i16, i32, i64, i128, isize,
|
||||
u8, u16, u32, u64, u128, usize,
|
||||
}
|
||||
|
||||
#[rustc_const_unstable(feature = "pattern_type_range_trait", issue = "123646")]
|
||||
impl const RangePattern for char {
|
||||
const MIN: Self = char::MIN;
|
||||
|
||||
const MAX: Self = char::MAX;
|
||||
|
||||
fn sub_one(self) -> Self {
|
||||
match char::from_u32(self as u32 - 1) {
|
||||
None => panic!("exclusive range to start of valid chars"),
|
||||
Some(val) => val,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1108,14 +1108,9 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
||||
pub fn hash_ty_pat(&mut self, pat: &TyPat<'_>) {
|
||||
std::mem::discriminant(&pat.kind).hash(&mut self.s);
|
||||
match pat.kind {
|
||||
TyPatKind::Range(s, e, i) => {
|
||||
if let Some(s) = s {
|
||||
self.hash_const_arg(s);
|
||||
}
|
||||
if let Some(e) = e {
|
||||
self.hash_const_arg(e);
|
||||
}
|
||||
std::mem::discriminant(&i).hash(&mut self.s);
|
||||
TyPatKind::Range(s, e) => {
|
||||
self.hash_const_arg(s);
|
||||
self.hash_const_arg(e);
|
||||
},
|
||||
TyPatKind::Err(_) => {},
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ pub fn bar() {
|
||||
// CHECK: call pattern_type_symbols::foo::<u32>
|
||||
// CHECK: call void @_RINvC[[CRATE_IDENT:[a-zA-Z0-9]{12}]]_20pattern_type_symbols3foomEB2_
|
||||
foo::<u32>();
|
||||
// CHECK: call pattern_type_symbols::foo::<(u32, [(); 0], [(); 999999999], [(); true])>
|
||||
// CHECK: call void @_RINvC[[CRATE_IDENT]]_20pattern_type_symbols3fooTmAum0_Aum3b9ac9ff_Aub1_EEB2_
|
||||
// CHECK: call pattern_type_symbols::foo::<(u32, [(); 0], [(); 999999999])>
|
||||
// CHECK: call void @_RINvC[[CRATE_IDENT]]_20pattern_type_symbols3fooTmAum0_Aum3b9ac9ff_EEB2_
|
||||
foo::<NanoU32>();
|
||||
}
|
||||
|
@ -3,9 +3,9 @@
|
||||
fn main() -> () {
|
||||
let mut _0: ();
|
||||
scope 1 {
|
||||
debug x => const 2_u32 is 1..=;
|
||||
debug x => const 2_u32 is 1..;
|
||||
scope 2 {
|
||||
debug y => const {transmute(0x00000000): (u32) is 1..=};
|
||||
debug y => const {transmute(0x00000000): (u32) is 1..};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,8 +5,8 @@ use std::pat::pattern_type;
|
||||
|
||||
// EMIT_MIR pattern_types.main.PreCodegen.after.mir
|
||||
fn main() {
|
||||
// CHECK: debug x => const 2_u32 is 1..=
|
||||
// CHECK: debug x => const 2_u32 is 1..
|
||||
let x: pattern_type!(u32 is 1..) = unsafe { std::mem::transmute(2) };
|
||||
// CHECK: debug y => const {transmute(0x00000000): (u32) is 1..=}
|
||||
// CHECK: debug y => const {transmute(0x00000000): (u32) is 1..}
|
||||
let y: pattern_type!(u32 is 1..) = unsafe { std::mem::transmute(0) };
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ LL | fn hidden_niche_unsafe_cell() -> Option<UnsafeCell<NonZero<usiz
|
||||
= help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
|
||||
= note: enum has no representation hint
|
||||
|
||||
warning: `extern` block uses type `Option<(usize) is 0..=>`, which is not FFI-safe
|
||||
warning: `extern` block uses type `Option<(usize) is 0..>`, which is not FFI-safe
|
||||
--> $DIR/clashing-extern-fn.rs:502:54
|
||||
|
|
||||
LL | fn pt_non_zero_usize_opt_full_range() -> Option<pattern_type!(usize is 0..)>;
|
||||
|
@ -18,10 +18,12 @@ const BAD_NESTING2: pattern_type!(pattern_type!(i32 is 1..) is ..=-1) = todo!();
|
||||
|
||||
const BAD_NESTING3: pattern_type!(pattern_type!(i32 is 1..) is ..0) = todo!();
|
||||
//~^ ERROR: not a valid base type for range patterns
|
||||
//~| ERROR: not a valid base type for range patterns
|
||||
//~| ERROR: mismatched types
|
||||
|
||||
const BAD_NESTING4: pattern_type!(() is ..0) = todo!();
|
||||
//~^ ERROR: not a valid base type for range patterns
|
||||
//~| ERROR: not a valid base type for range patterns
|
||||
//~| ERROR: mismatched types
|
||||
|
||||
const BAD_NESTING5: pattern_type!(f32 is 1.0 .. 2.0) = todo!();
|
||||
|
@ -1,96 +1,184 @@
|
||||
error: `(u32) is 1..=` is not a valid base type for range patterns
|
||||
--> $DIR/nested.rs:10:34
|
||||
|
|
||||
LL | const BAD_NESTING: pattern_type!(pattern_type!(u32 is 1..) is 0..) = todo!();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: range patterns only support integers
|
||||
--> $DIR/nested.rs:10:63
|
||||
|
|
||||
LL | const BAD_NESTING: pattern_type!(pattern_type!(u32 is 1..) is 0..) = todo!();
|
||||
| ^^^
|
||||
|
||||
error: `(i32) is 1..=` is not a valid base type for range patterns
|
||||
--> $DIR/nested.rs:15:35
|
||||
|
|
||||
LL | const BAD_NESTING2: pattern_type!(pattern_type!(i32 is 1..) is ..=-1) = todo!();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: range patterns only support integers
|
||||
--> $DIR/nested.rs:15:64
|
||||
|
|
||||
LL | const BAD_NESTING2: pattern_type!(pattern_type!(i32 is 1..) is ..=-1) = todo!();
|
||||
| ^^^^^
|
||||
|
||||
error: `(i32) is 1..=` is not a valid base type for range patterns
|
||||
--> $DIR/nested.rs:19:35
|
||||
|
|
||||
LL | const BAD_NESTING3: pattern_type!(pattern_type!(i32 is 1..) is ..0) = todo!();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: range patterns only support integers
|
||||
--> $DIR/nested.rs:19:64
|
||||
|
|
||||
LL | const BAD_NESTING3: pattern_type!(pattern_type!(i32 is 1..) is ..0) = todo!();
|
||||
| ^^^
|
||||
|
||||
error: `()` is not a valid base type for range patterns
|
||||
--> $DIR/nested.rs:23:35
|
||||
|
|
||||
LL | const BAD_NESTING4: pattern_type!(() is ..0) = todo!();
|
||||
| ^^
|
||||
|
|
||||
note: range patterns only support integers
|
||||
--> $DIR/nested.rs:23:41
|
||||
|
|
||||
LL | const BAD_NESTING4: pattern_type!(() is ..0) = todo!();
|
||||
| ^^^
|
||||
|
||||
error: `f32` is not a valid base type for range patterns
|
||||
--> $DIR/nested.rs:27:35
|
||||
|
|
||||
LL | const BAD_NESTING5: pattern_type!(f32 is 1.0 .. 2.0) = todo!();
|
||||
| ^^^
|
||||
|
|
||||
note: range patterns only support integers
|
||||
--> $DIR/nested.rs:27:42
|
||||
|
|
||||
LL | const BAD_NESTING5: pattern_type!(f32 is 1.0 .. 2.0) = todo!();
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/nested.rs:10:63
|
||||
|
|
||||
LL | const BAD_NESTING: pattern_type!(pattern_type!(u32 is 1..) is 0..) = todo!();
|
||||
| ^ expected `(u32) is 1..=`, found integer
|
||||
| ^ expected `(u32) is 1..`, found integer
|
||||
|
|
||||
= note: expected pattern type `(u32) is 1..=`
|
||||
= note: expected pattern type `(u32) is 1..`
|
||||
found type `{integer}`
|
||||
|
||||
error[E0277]: `(u32) is 1..` is not a valid base type for range patterns
|
||||
--> $DIR/nested.rs:10:34
|
||||
|
|
||||
LL | const BAD_NESTING: pattern_type!(pattern_type!(u32 is 1..) is 0..) = todo!();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ only integer types and `char` are supported
|
||||
|
|
||||
= help: the trait `core::pat::RangePattern` is not implemented for `(u32) is 1..`
|
||||
= help: the following other types implement trait `core::pat::RangePattern`:
|
||||
char
|
||||
i128
|
||||
i16
|
||||
i32
|
||||
i64
|
||||
i8
|
||||
isize
|
||||
u128
|
||||
and 5 others
|
||||
|
||||
error[E0277]: `(i32) is 1..` is not a valid base type for range patterns
|
||||
--> $DIR/nested.rs:15:35
|
||||
|
|
||||
LL | const BAD_NESTING2: pattern_type!(pattern_type!(i32 is 1..) is ..=-1) = todo!();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ only integer types and `char` are supported
|
||||
|
|
||||
= help: the trait `core::pat::RangePattern` is not implemented for `(i32) is 1..`
|
||||
= help: the following other types implement trait `core::pat::RangePattern`:
|
||||
char
|
||||
i128
|
||||
i16
|
||||
i32
|
||||
i64
|
||||
i8
|
||||
isize
|
||||
u128
|
||||
and 5 others
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/nested.rs:15:67
|
||||
|
|
||||
LL | const BAD_NESTING2: pattern_type!(pattern_type!(i32 is 1..) is ..=-1) = todo!();
|
||||
| ^^ expected `(i32) is 1..=`, found integer
|
||||
| ^^ expected `(i32) is 1..`, found integer
|
||||
|
|
||||
= note: expected pattern type `(i32) is 1..=`
|
||||
= note: expected pattern type `(i32) is 1..`
|
||||
found type `{integer}`
|
||||
|
||||
error[E0277]: `(i32) is 1..` is not a valid base type for range patterns
|
||||
--> $DIR/nested.rs:19:35
|
||||
|
|
||||
LL | const BAD_NESTING3: pattern_type!(pattern_type!(i32 is 1..) is ..0) = todo!();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ only integer types and `char` are supported
|
||||
|
|
||||
= help: the trait `core::pat::RangePattern` is not implemented for `(i32) is 1..`
|
||||
= help: the following other types implement trait `core::pat::RangePattern`:
|
||||
char
|
||||
i128
|
||||
i16
|
||||
i32
|
||||
i64
|
||||
i8
|
||||
isize
|
||||
u128
|
||||
and 5 others
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/nested.rs:19:66
|
||||
|
|
||||
LL | const BAD_NESTING3: pattern_type!(pattern_type!(i32 is 1..) is ..0) = todo!();
|
||||
| ^ expected `(i32) is 1..=`, found integer
|
||||
| ^
|
||||
| |
|
||||
| expected `(i32) is 1..`, found integer
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
= note: expected pattern type `(i32) is 1..=`
|
||||
= note: expected pattern type `(i32) is 1..`
|
||||
found type `{integer}`
|
||||
help: the return type of this call is `{integer}` due to the type of the argument passed
|
||||
--> $DIR/nested.rs:19:66
|
||||
|
|
||||
LL | const BAD_NESTING3: pattern_type!(pattern_type!(i32 is 1..) is ..0) = todo!();
|
||||
| ^ this argument influences the return type of `RangeSub`
|
||||
note: method defined here
|
||||
--> $SRC_DIR/core/src/pat.rs:LL:COL
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/nested.rs:23:43
|
||||
error[E0277]: `(i32) is 1..` is not a valid base type for range patterns
|
||||
--> $DIR/nested.rs:19:66
|
||||
|
|
||||
LL | const BAD_NESTING3: pattern_type!(pattern_type!(i32 is 1..) is ..0) = todo!();
|
||||
| ^ only integer types and `char` are supported
|
||||
|
|
||||
= help: the trait `core::pat::RangePattern` is not implemented for `(i32) is 1..`
|
||||
= help: the following other types implement trait `core::pat::RangePattern`:
|
||||
char
|
||||
i128
|
||||
i16
|
||||
i32
|
||||
i64
|
||||
i8
|
||||
isize
|
||||
u128
|
||||
and 5 others
|
||||
|
||||
error[E0277]: `()` is not a valid base type for range patterns
|
||||
--> $DIR/nested.rs:24:35
|
||||
|
|
||||
LL | const BAD_NESTING4: pattern_type!(() is ..0) = todo!();
|
||||
| ^ expected `()`, found integer
|
||||
| ^^ only integer types and `char` are supported
|
||||
|
|
||||
= help: the trait `core::pat::RangePattern` is not implemented for `()`
|
||||
= help: the following other types implement trait `core::pat::RangePattern`:
|
||||
char
|
||||
i128
|
||||
i16
|
||||
i32
|
||||
i64
|
||||
i8
|
||||
isize
|
||||
u128
|
||||
and 5 others
|
||||
|
||||
error: aborting due to 9 previous errors
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/nested.rs:24:43
|
||||
|
|
||||
LL | const BAD_NESTING4: pattern_type!(() is ..0) = todo!();
|
||||
| ^
|
||||
| |
|
||||
| expected `()`, found integer
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
help: the return type of this call is `{integer}` due to the type of the argument passed
|
||||
--> $DIR/nested.rs:24:43
|
||||
|
|
||||
LL | const BAD_NESTING4: pattern_type!(() is ..0) = todo!();
|
||||
| ^ this argument influences the return type of `RangeSub`
|
||||
note: method defined here
|
||||
--> $SRC_DIR/core/src/pat.rs:LL:COL
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
error[E0277]: `()` is not a valid base type for range patterns
|
||||
--> $DIR/nested.rs:24:43
|
||||
|
|
||||
LL | const BAD_NESTING4: pattern_type!(() is ..0) = todo!();
|
||||
| ^ only integer types and `char` are supported
|
||||
|
|
||||
= help: the trait `core::pat::RangePattern` is not implemented for `()`
|
||||
= help: the following other types implement trait `core::pat::RangePattern`:
|
||||
char
|
||||
i128
|
||||
i16
|
||||
i32
|
||||
i64
|
||||
i8
|
||||
isize
|
||||
u128
|
||||
and 5 others
|
||||
|
||||
error[E0277]: `f32` is not a valid base type for range patterns
|
||||
--> $DIR/nested.rs:29:49
|
||||
|
|
||||
LL | const BAD_NESTING5: pattern_type!(f32 is 1.0 .. 2.0) = todo!();
|
||||
| ^^^ only integer types and `char` are supported
|
||||
|
|
||||
= help: the trait `core::pat::RangePattern` is not implemented for `f32`
|
||||
= help: the following other types implement trait `core::pat::RangePattern`:
|
||||
i128
|
||||
i16
|
||||
i32
|
||||
i64
|
||||
i8
|
||||
isize
|
||||
u128
|
||||
u16
|
||||
and 4 others
|
||||
|
||||
error: aborting due to 11 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0277, E0308.
|
||||
For more information about an error, try `rustc --explain E0277`.
|
||||
|
@ -44,7 +44,7 @@ error: layout_of(NonZero<u32>) = Layout {
|
||||
LL | type X = std::num::NonZeroU32;
|
||||
| ^^^^^^
|
||||
|
||||
error: layout_of((u32) is 1..=) = Layout {
|
||||
error: layout_of((u32) is 1..) = Layout {
|
||||
size: Size(4 bytes),
|
||||
align: AbiAndPrefAlign {
|
||||
abi: Align(4 bytes),
|
||||
@ -83,7 +83,7 @@ error: layout_of((u32) is 1..=) = Layout {
|
||||
LL | type Y = pattern_type!(u32 is 1..);
|
||||
| ^^^^^^
|
||||
|
||||
error: layout_of(Option<(u32) is 1..=>) = Layout {
|
||||
error: layout_of(Option<(u32) is 1..>) = Layout {
|
||||
size: Size(4 bytes),
|
||||
align: AbiAndPrefAlign {
|
||||
abi: Align(4 bytes),
|
||||
|
@ -4,7 +4,7 @@ error[E0512]: cannot transmute between types of different sizes, or dependently-
|
||||
LL | let _: Option<u32> = unsafe { std::mem::transmute(z) };
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: source type: `Option<(u32) is 1..=>` (32 bits)
|
||||
= note: source type: `Option<(u32) is 1..>` (32 bits)
|
||||
= note: target type: `Option<u32>` (64 bits)
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
@ -11,5 +11,5 @@ type Z = Option<pattern_type!(u32 is 1..)>;
|
||||
|
||||
fn main() {
|
||||
let x: Y = unsafe { std::mem::transmute(42_u32) };
|
||||
let x = x + 1_u32; //~ ERROR cannot add `u32` to `(u32) is 1..=`
|
||||
let x = x + 1_u32; //~ ERROR cannot add `u32` to `(u32) is 1..`
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
error[E0369]: cannot add `u32` to `(u32) is 1..=`
|
||||
error[E0369]: cannot add `u32` to `(u32) is 1..`
|
||||
--> $DIR/range_patterns_unusable_math.rs:14:15
|
||||
|
|
||||
LL | let x = x + 1_u32;
|
||||
| - ^ ----- u32
|
||||
| |
|
||||
| (u32) is 1..=
|
||||
| (u32) is 1..
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -1,14 +1,11 @@
|
||||
//! Check that the range start must be smaller than the range end
|
||||
//@ known-bug: unknown
|
||||
//@ failure-status: 101
|
||||
//@ normalize-stderr: "note: .*\n\n" -> ""
|
||||
//@ normalize-stderr: "thread 'rustc' panicked.*\n" -> ""
|
||||
//@ normalize-stderr: "(error: internal compiler error: [^:]+):\d+:\d+: " -> "$1:LL:CC: "
|
||||
//@ rustc-env:RUST_BACKTRACE=0
|
||||
|
||||
#![feature(pattern_types)]
|
||||
#![feature(pattern_types, const_trait_impl, pattern_type_range_trait)]
|
||||
#![feature(pattern_type_macro)]
|
||||
|
||||
use std::pat::pattern_type;
|
||||
|
||||
const NONE: pattern_type!(u8 is 1..0) = unsafe { std::mem::transmute(3_u8) };
|
||||
//~^ NOTE: exclusive range end at minimum value of type
|
||||
//~| ERROR: evaluation of constant value failed
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,17 +1,9 @@
|
||||
error[E0601]: `main` function not found in crate `reverse_range`
|
||||
--> $DIR/reverse_range.rs:14:78
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/reverse_range.rs:7:36
|
||||
|
|
||||
LL | const NONE: pattern_type!(u8 is 1..0) = unsafe { std::mem::transmute(3_u8) };
|
||||
| ^ consider adding a `main` function to `$DIR/reverse_range.rs`
|
||||
| ^ evaluation panicked: exclusive range end at minimum value of type
|
||||
|
||||
|
||||
assertion failed: end <= max_value
|
||||
error: the compiler unexpectedly panicked. this is a bug.
|
||||
|
||||
query stack during panic:
|
||||
#0 [eval_to_allocation_raw] const-evaluating + checking `NONE`
|
||||
#1 [eval_to_const_value_raw] simplifying constant for the type system `NONE`
|
||||
... and 1 other queries... use `env RUST_BACKTRACE=1` to see the full query stack
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0601`.
|
||||
For more information about this error, try `rustc --explain E0080`.
|
||||
|
@ -1,6 +1,6 @@
|
||||
//! Check that pattern types have their validity checked
|
||||
|
||||
#![feature(pattern_types)]
|
||||
#![feature(pattern_types, const_trait_impl, pattern_type_range_trait)]
|
||||
#![feature(pattern_type_macro)]
|
||||
|
||||
use std::pat::pattern_type;
|
||||
|
Loading…
Reference in New Issue
Block a user