Add not-null pointer patterns to pattern types
This commit is contained in:
@@ -2579,6 +2579,9 @@ pub enum TyPatKind {
|
|||||||
/// A range pattern (e.g., `1...2`, `1..2`, `1..`, `..2`, `1..=2`, `..=2`).
|
/// A range pattern (e.g., `1...2`, `1..2`, `1..`, `..2`, `1..=2`, `..=2`).
|
||||||
Range(Option<Box<AnonConst>>, Option<Box<AnonConst>>, Spanned<RangeEnd>),
|
Range(Option<Box<AnonConst>>, Option<Box<AnonConst>>, Spanned<RangeEnd>),
|
||||||
|
|
||||||
|
/// A `!null` pattern for raw pointers.
|
||||||
|
NotNull,
|
||||||
|
|
||||||
Or(ThinVec<TyPat>),
|
Or(ThinVec<TyPat>),
|
||||||
|
|
||||||
/// Placeholder for a pattern that wasn't syntactically well formed in some way.
|
/// Placeholder for a pattern that wasn't syntactically well formed in some way.
|
||||||
|
|||||||
@@ -143,7 +143,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
}
|
}
|
||||||
// return inner to be processed in next loop
|
// return inner to be processed in next loop
|
||||||
PatKind::Paren(inner) => pattern = inner,
|
PatKind::Paren(inner) => pattern = inner,
|
||||||
PatKind::MacCall(_) => panic!("{:?} shouldn't exist here", pattern.span),
|
PatKind::MacCall(_) => {
|
||||||
|
panic!("{pattern:#?} shouldn't exist here")
|
||||||
|
}
|
||||||
PatKind::Err(guar) => break hir::PatKind::Err(*guar),
|
PatKind::Err(guar) => break hir::PatKind::Err(*guar),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -460,6 +462,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
|
TyPatKind::NotNull => hir::TyPatKind::NotNull,
|
||||||
TyPatKind::Or(variants) => {
|
TyPatKind::Or(variants) => {
|
||||||
hir::TyPatKind::Or(self.arena.alloc_from_iter(
|
hir::TyPatKind::Or(self.arena.alloc_from_iter(
|
||||||
variants.iter().map(|pat| self.lower_ty_pat_mut(pat, base_type)),
|
variants.iter().map(|pat| self.lower_ty_pat_mut(pat, base_type)),
|
||||||
|
|||||||
@@ -1232,6 +1232,7 @@ impl<'a> State<'a> {
|
|||||||
self.print_expr_anon_const(end, &[]);
|
self.print_expr_anon_const(end, &[]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
rustc_ast::TyPatKind::NotNull => self.word("!null"),
|
||||||
rustc_ast::TyPatKind::Or(variants) => {
|
rustc_ast::TyPatKind::Or(variants) => {
|
||||||
let mut first = true;
|
let mut first = true;
|
||||||
for pat in variants {
|
for pat in variants {
|
||||||
|
|||||||
@@ -30,15 +30,21 @@ fn parse_pat_ty<'a>(
|
|||||||
let ty = parser.parse_ty()?;
|
let ty = parser.parse_ty()?;
|
||||||
parser.expect_keyword(exp!(Is))?;
|
parser.expect_keyword(exp!(Is))?;
|
||||||
|
|
||||||
let pat = pat_to_ty_pat(
|
let start = parser.token.span;
|
||||||
cx,
|
let pat = if parser.eat(exp!(Bang)) {
|
||||||
parser.parse_pat_no_top_guard(
|
parser.expect_keyword(exp!(Null))?;
|
||||||
None,
|
ty_pat(TyPatKind::NotNull, start.to(parser.token.span))
|
||||||
RecoverComma::No,
|
} else {
|
||||||
RecoverColon::No,
|
pat_to_ty_pat(
|
||||||
CommaRecoveryMode::EitherTupleOrPipe,
|
cx,
|
||||||
)?,
|
parser.parse_pat_no_top_guard(
|
||||||
);
|
None,
|
||||||
|
RecoverComma::No,
|
||||||
|
RecoverColon::No,
|
||||||
|
CommaRecoveryMode::EitherTupleOrPipe,
|
||||||
|
)?,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
if parser.token != token::Eof {
|
if parser.token != token::Eof {
|
||||||
parser.unexpected()?;
|
parser.unexpected()?;
|
||||||
|
|||||||
@@ -1261,9 +1261,10 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
|
|||||||
// When you extend this match, make sure to also add tests to
|
// When you extend this match, make sure to also add tests to
|
||||||
// tests/ui/type/pattern_types/validity.rs((
|
// tests/ui/type/pattern_types/validity.rs((
|
||||||
match **pat {
|
match **pat {
|
||||||
// Range patterns are precisely reflected into `valid_range` and thus
|
// Range and non-null patterns are precisely reflected into `valid_range` and thus
|
||||||
// handled fully by `visit_scalar` (called below).
|
// handled fully by `visit_scalar` (called below).
|
||||||
ty::PatternKind::Range { .. } => {},
|
ty::PatternKind::Range { .. } => {},
|
||||||
|
ty::PatternKind::NotNull => {},
|
||||||
|
|
||||||
// FIXME(pattern_types): check that the value is covered by one of the variants.
|
// FIXME(pattern_types): check that the value is covered by one of the variants.
|
||||||
// For now, we rely on layout computation setting the scalar's `valid_range` to
|
// For now, we rely on layout computation setting the scalar's `valid_range` to
|
||||||
|
|||||||
@@ -1854,6 +1854,9 @@ pub enum TyPatKind<'hir> {
|
|||||||
/// A range pattern (e.g., `1..=2` or `1..2`).
|
/// A range pattern (e.g., `1..=2` or `1..2`).
|
||||||
Range(&'hir ConstArg<'hir>, &'hir ConstArg<'hir>),
|
Range(&'hir ConstArg<'hir>, &'hir ConstArg<'hir>),
|
||||||
|
|
||||||
|
/// A pattern that excludes null pointers
|
||||||
|
NotNull,
|
||||||
|
|
||||||
/// A list of patterns where only one needs to be satisfied
|
/// A list of patterns where only one needs to be satisfied
|
||||||
Or(&'hir [TyPat<'hir>]),
|
Or(&'hir [TyPat<'hir>]),
|
||||||
|
|
||||||
|
|||||||
@@ -725,7 +725,7 @@ pub fn walk_ty_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v TyPat<'v>)
|
|||||||
try_visit!(visitor.visit_const_arg_unambig(upper_bound));
|
try_visit!(visitor.visit_const_arg_unambig(upper_bound));
|
||||||
}
|
}
|
||||||
TyPatKind::Or(patterns) => walk_list!(visitor, visit_pattern_type_pattern, patterns),
|
TyPatKind::Or(patterns) => walk_list!(visitor, visit_pattern_type_pattern, patterns),
|
||||||
TyPatKind::Err(_) => (),
|
TyPatKind::NotNull | TyPatKind::Err(_) => (),
|
||||||
}
|
}
|
||||||
V::Result::output()
|
V::Result::output()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2611,6 +2611,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||||||
.span_delayed_bug(ty_span, "invalid base type for range pattern")),
|
.span_delayed_bug(ty_span, "invalid base type for range pattern")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
hir::TyPatKind::NotNull => Ok(ty::PatternKind::NotNull),
|
||||||
hir::TyPatKind::Or(patterns) => {
|
hir::TyPatKind::Or(patterns) => {
|
||||||
self.tcx()
|
self.tcx()
|
||||||
.mk_patterns_from_iter(patterns.iter().map(|pat| {
|
.mk_patterns_from_iter(patterns.iter().map(|pat| {
|
||||||
|
|||||||
@@ -340,6 +340,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
|
|||||||
self.add_constraints_from_const(current, start, variance);
|
self.add_constraints_from_const(current, start, variance);
|
||||||
self.add_constraints_from_const(current, end, variance);
|
self.add_constraints_from_const(current, end, variance);
|
||||||
}
|
}
|
||||||
|
ty::PatternKind::NotNull => {}
|
||||||
ty::PatternKind::Or(patterns) => {
|
ty::PatternKind::Or(patterns) => {
|
||||||
for pat in patterns {
|
for pat in patterns {
|
||||||
self.add_constraints_from_pat(current, variance, pat)
|
self.add_constraints_from_pat(current, variance, pat)
|
||||||
|
|||||||
@@ -1888,6 +1888,10 @@ impl<'a> State<'a> {
|
|||||||
self.word("..=");
|
self.word("..=");
|
||||||
self.print_const_arg(end);
|
self.print_const_arg(end);
|
||||||
}
|
}
|
||||||
|
TyPatKind::NotNull => {
|
||||||
|
self.word_space("not");
|
||||||
|
self.word("null");
|
||||||
|
}
|
||||||
TyPatKind::Or(patterns) => {
|
TyPatKind::Or(patterns) => {
|
||||||
self.popen();
|
self.popen();
|
||||||
let mut first = true;
|
let mut first = true;
|
||||||
|
|||||||
@@ -758,6 +758,7 @@ fn pat_ty_is_known_nonnull<'tcx>(
|
|||||||
// to ensure we aren't wrapping over zero.
|
// to ensure we aren't wrapping over zero.
|
||||||
start > 0 && end >= start
|
start > 0 && end >= start
|
||||||
}
|
}
|
||||||
|
ty::PatternKind::NotNull => true,
|
||||||
ty::PatternKind::Or(patterns) => {
|
ty::PatternKind::Or(patterns) => {
|
||||||
patterns.iter().all(|pat| pat_ty_is_known_nonnull(tcx, typing_env, pat))
|
patterns.iter().all(|pat| pat_ty_is_known_nonnull(tcx, typing_env, pat))
|
||||||
}
|
}
|
||||||
@@ -918,7 +919,9 @@ fn get_nullable_type_from_pat<'tcx>(
|
|||||||
pat: ty::Pattern<'tcx>,
|
pat: ty::Pattern<'tcx>,
|
||||||
) -> Option<Ty<'tcx>> {
|
) -> Option<Ty<'tcx>> {
|
||||||
match *pat {
|
match *pat {
|
||||||
ty::PatternKind::Range { .. } => get_nullable_type(tcx, typing_env, base),
|
ty::PatternKind::NotNull | ty::PatternKind::Range { .. } => {
|
||||||
|
get_nullable_type(tcx, typing_env, base)
|
||||||
|
}
|
||||||
ty::PatternKind::Or(patterns) => {
|
ty::PatternKind::Or(patterns) => {
|
||||||
let first = get_nullable_type_from_pat(tcx, typing_env, base, patterns[0])?;
|
let first = get_nullable_type_from_pat(tcx, typing_env, base, patterns[0])?;
|
||||||
for &pat in &patterns[1..] {
|
for &pat in &patterns[1..] {
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ impl<'tcx> Flags for Pattern<'tcx> {
|
|||||||
}
|
}
|
||||||
flags
|
flags
|
||||||
}
|
}
|
||||||
|
ty::PatternKind::NotNull => rustc_type_ir::TypeFlags::empty(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,6 +46,7 @@ impl<'tcx> Flags for Pattern<'tcx> {
|
|||||||
}
|
}
|
||||||
idx
|
idx
|
||||||
}
|
}
|
||||||
|
ty::PatternKind::NotNull => rustc_type_ir::INNERMOST,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -91,6 +93,7 @@ impl<'tcx> IrPrint<PatternKind<'tcx>> for TyCtxt<'tcx> {
|
|||||||
|
|
||||||
write!(f, "..={end}")
|
write!(f, "..={end}")
|
||||||
}
|
}
|
||||||
|
PatternKind::NotNull => write!(f, "!null"),
|
||||||
PatternKind::Or(patterns) => {
|
PatternKind::Or(patterns) => {
|
||||||
write!(f, "(")?;
|
write!(f, "(")?;
|
||||||
let mut first = true;
|
let mut first = true;
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ impl<'tcx> Relate<TyCtxt<'tcx>> for ty::Pattern<'tcx> {
|
|||||||
let end = relation.relate(end_a, end_b)?;
|
let end = relation.relate(end_a, end_b)?;
|
||||||
Ok(tcx.mk_pat(ty::PatternKind::Range { start, end }))
|
Ok(tcx.mk_pat(ty::PatternKind::Range { start, end }))
|
||||||
}
|
}
|
||||||
|
(ty::PatternKind::NotNull, ty::PatternKind::NotNull) => Ok(a),
|
||||||
(&ty::PatternKind::Or(a), &ty::PatternKind::Or(b)) => {
|
(&ty::PatternKind::Or(a), &ty::PatternKind::Or(b)) => {
|
||||||
if a.len() != b.len() {
|
if a.len() != b.len() {
|
||||||
return Err(TypeError::Mismatch);
|
return Err(TypeError::Mismatch);
|
||||||
@@ -43,7 +44,10 @@ impl<'tcx> Relate<TyCtxt<'tcx>> for ty::Pattern<'tcx> {
|
|||||||
let patterns = tcx.mk_patterns_from_iter(v)?;
|
let patterns = tcx.mk_patterns_from_iter(v)?;
|
||||||
Ok(tcx.mk_pat(ty::PatternKind::Or(patterns)))
|
Ok(tcx.mk_pat(ty::PatternKind::Or(patterns)))
|
||||||
}
|
}
|
||||||
(ty::PatternKind::Range { .. } | ty::PatternKind::Or(_), _) => Err(TypeError::Mismatch),
|
(
|
||||||
|
ty::PatternKind::NotNull | ty::PatternKind::Range { .. } | ty::PatternKind::Or(_),
|
||||||
|
_,
|
||||||
|
) => Err(TypeError::Mismatch),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -139,6 +139,7 @@ pub enum TokenType {
|
|||||||
SymNomem,
|
SymNomem,
|
||||||
SymNoreturn,
|
SymNoreturn,
|
||||||
SymNostack,
|
SymNostack,
|
||||||
|
SymNull,
|
||||||
SymOptions,
|
SymOptions,
|
||||||
SymOut,
|
SymOut,
|
||||||
SymPreservesFlags,
|
SymPreservesFlags,
|
||||||
@@ -273,6 +274,7 @@ impl TokenType {
|
|||||||
SymNomem,
|
SymNomem,
|
||||||
SymNoreturn,
|
SymNoreturn,
|
||||||
SymNostack,
|
SymNostack,
|
||||||
|
SymNull,
|
||||||
SymOptions,
|
SymOptions,
|
||||||
SymOut,
|
SymOut,
|
||||||
SymPreservesFlags,
|
SymPreservesFlags,
|
||||||
@@ -348,6 +350,7 @@ impl TokenType {
|
|||||||
TokenType::SymNomem => Some(sym::nomem),
|
TokenType::SymNomem => Some(sym::nomem),
|
||||||
TokenType::SymNoreturn => Some(sym::noreturn),
|
TokenType::SymNoreturn => Some(sym::noreturn),
|
||||||
TokenType::SymNostack => Some(sym::nostack),
|
TokenType::SymNostack => Some(sym::nostack),
|
||||||
|
TokenType::SymNull => Some(sym::null),
|
||||||
TokenType::SymOptions => Some(sym::options),
|
TokenType::SymOptions => Some(sym::options),
|
||||||
TokenType::SymOut => Some(sym::out),
|
TokenType::SymOut => Some(sym::out),
|
||||||
TokenType::SymPreservesFlags => Some(sym::preserves_flags),
|
TokenType::SymPreservesFlags => Some(sym::preserves_flags),
|
||||||
@@ -562,6 +565,7 @@ macro_rules! exp {
|
|||||||
(Nomem) => { exp!(@sym, nomem, SymNomem) };
|
(Nomem) => { exp!(@sym, nomem, SymNomem) };
|
||||||
(Noreturn) => { exp!(@sym, noreturn, SymNoreturn) };
|
(Noreturn) => { exp!(@sym, noreturn, SymNoreturn) };
|
||||||
(Nostack) => { exp!(@sym, nostack, SymNostack) };
|
(Nostack) => { exp!(@sym, nostack, SymNostack) };
|
||||||
|
(Null) => { exp!(@sym, null, SymNull) };
|
||||||
(Options) => { exp!(@sym, options, SymOptions) };
|
(Options) => { exp!(@sym, options, SymOptions) };
|
||||||
(Out) => { exp!(@sym, out, SymOut) };
|
(Out) => { exp!(@sym, out, SymOut) };
|
||||||
(PreservesFlags) => { exp!(@sym, preserves_flags, SymPreservesFlags) };
|
(PreservesFlags) => { exp!(@sym, preserves_flags, SymPreservesFlags) };
|
||||||
|
|||||||
@@ -485,6 +485,7 @@ impl<'tcx> Stable<'tcx> for ty::Pattern<'tcx> {
|
|||||||
end: Some(end.stable(tables, cx)),
|
end: Some(end.stable(tables, cx)),
|
||||||
include_end: true,
|
include_end: true,
|
||||||
},
|
},
|
||||||
|
ty::PatternKind::NotNull => todo!(),
|
||||||
ty::PatternKind::Or(_) => todo!(),
|
ty::PatternKind::Or(_) => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -968,7 +968,7 @@ impl<'ast, 'ra, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tc
|
|||||||
self.visit_ty_pat(pat)
|
self.visit_ty_pat(pat)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TyPatKind::Err(_) => {}
|
TyPatKind::NotNull | TyPatKind::Err(_) => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1554,6 +1554,7 @@ symbols! {
|
|||||||
not,
|
not,
|
||||||
notable_trait,
|
notable_trait,
|
||||||
note,
|
note,
|
||||||
|
null,
|
||||||
nvptx_target_feature,
|
nvptx_target_feature,
|
||||||
object_safe_for_dispatch,
|
object_safe_for_dispatch,
|
||||||
of,
|
of,
|
||||||
|
|||||||
@@ -266,6 +266,9 @@ impl<'tcx> V0SymbolMangler<'tcx> {
|
|||||||
self.print_const(start)?;
|
self.print_const(start)?;
|
||||||
self.print_const(end)?;
|
self.print_const(end)?;
|
||||||
}
|
}
|
||||||
|
ty::PatternKind::NotNull => {
|
||||||
|
self.tcx.types.unit.print(self)?;
|
||||||
|
}
|
||||||
ty::PatternKind::Or(patterns) => {
|
ty::PatternKind::Or(patterns) => {
|
||||||
self.push("O");
|
self.push("O");
|
||||||
for pat in patterns {
|
for pat in patterns {
|
||||||
|
|||||||
@@ -705,6 +705,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
|
|||||||
check(start);
|
check(start);
|
||||||
check(end);
|
check(end);
|
||||||
}
|
}
|
||||||
|
ty::PatternKind::NotNull => {}
|
||||||
ty::PatternKind::Or(patterns) => {
|
ty::PatternKind::Or(patterns) => {
|
||||||
for pat in patterns {
|
for pat in patterns {
|
||||||
self.add_wf_preds_for_pat_ty(base_ty, pat)
|
self.add_wf_preds_for_pat_ty(base_ty, pat)
|
||||||
|
|||||||
@@ -216,9 +216,7 @@ fn layout_of_uncached<'tcx>(
|
|||||||
let mut layout = LayoutData::clone(&layout.0);
|
let mut layout = LayoutData::clone(&layout.0);
|
||||||
match *pat {
|
match *pat {
|
||||||
ty::PatternKind::Range { start, end } => {
|
ty::PatternKind::Range { start, end } => {
|
||||||
if let BackendRepr::Scalar(scalar) | BackendRepr::ScalarPair(scalar, _) =
|
if let BackendRepr::Scalar(scalar) = &mut layout.backend_repr {
|
||||||
&mut layout.backend_repr
|
|
||||||
{
|
|
||||||
scalar.valid_range_mut().start = extract_const_value(cx, ty, start)?
|
scalar.valid_range_mut().start = extract_const_value(cx, ty, start)?
|
||||||
.try_to_bits(tcx, cx.typing_env)
|
.try_to_bits(tcx, cx.typing_env)
|
||||||
.ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
|
.ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
|
||||||
@@ -266,6 +264,25 @@ fn layout_of_uncached<'tcx>(
|
|||||||
bug!("pattern type with range but not scalar layout: {ty:?}, {layout:?}")
|
bug!("pattern type with range but not scalar layout: {ty:?}, {layout:?}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ty::PatternKind::NotNull => {
|
||||||
|
if let BackendRepr::Scalar(scalar) | BackendRepr::ScalarPair(scalar, _) =
|
||||||
|
&mut layout.backend_repr
|
||||||
|
{
|
||||||
|
scalar.valid_range_mut().start = 1;
|
||||||
|
let niche = Niche {
|
||||||
|
offset: Size::ZERO,
|
||||||
|
value: scalar.primitive(),
|
||||||
|
valid_range: scalar.valid_range(cx),
|
||||||
|
};
|
||||||
|
|
||||||
|
layout.largest_niche = Some(niche);
|
||||||
|
} else {
|
||||||
|
bug!(
|
||||||
|
"pattern type with `!null` pattern but not scalar/pair layout: {ty:?}, {layout:?}"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ty::PatternKind::Or(variants) => match *variants[0] {
|
ty::PatternKind::Or(variants) => match *variants[0] {
|
||||||
ty::PatternKind::Range { .. } => {
|
ty::PatternKind::Range { .. } => {
|
||||||
if let BackendRepr::Scalar(scalar) = &mut layout.backend_repr {
|
if let BackendRepr::Scalar(scalar) = &mut layout.backend_repr {
|
||||||
@@ -282,7 +299,7 @@ fn layout_of_uncached<'tcx>(
|
|||||||
.try_to_bits(tcx, cx.typing_env)
|
.try_to_bits(tcx, cx.typing_env)
|
||||||
.ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?,
|
.ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?,
|
||||||
)),
|
)),
|
||||||
ty::PatternKind::Or(_) => {
|
ty::PatternKind::NotNull | ty::PatternKind::Or(_) => {
|
||||||
unreachable!("mixed or patterns are not allowed")
|
unreachable!("mixed or patterns are not allowed")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -347,6 +364,7 @@ fn layout_of_uncached<'tcx>(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ty::PatternKind::NotNull => bug!("or patterns can't contain `!null` patterns"),
|
||||||
ty::PatternKind::Or(..) => bug!("patterns cannot have nested or patterns"),
|
ty::PatternKind::Or(..) => bug!("patterns cannot have nested or patterns"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ use crate::Interner;
|
|||||||
pub enum PatternKind<I: Interner> {
|
pub enum PatternKind<I: Interner> {
|
||||||
Range { start: I::Const, end: I::Const },
|
Range { start: I::Const, end: I::Const },
|
||||||
Or(I::PatList),
|
Or(I::PatList),
|
||||||
|
NotNull,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I: Interner> Eq for PatternKind<I> {}
|
impl<I: Interner> Eq for PatternKind<I> {}
|
||||||
|
|||||||
@@ -178,5 +178,6 @@ fn push_ty_pat<I: Interner>(stack: &mut TypeWalkerStack<I>, pat: I::Pat) {
|
|||||||
push_ty_pat::<I>(stack, pat)
|
push_ty_pat::<I>(stack, pat)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ty::PatternKind::NotNull => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1123,7 +1123,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
|||||||
self.hash_ty_pat(variant);
|
self.hash_ty_pat(variant);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
TyPatKind::Err(_) => {},
|
TyPatKind::NotNull | TyPatKind::Err(_) => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1099,7 +1099,7 @@ impl Rewrite for ast::TyPat {
|
|||||||
}
|
}
|
||||||
Ok(s)
|
Ok(s)
|
||||||
}
|
}
|
||||||
ast::TyPatKind::Err(_) => Err(RewriteError::Unknown),
|
ast::TyPatKind::NotNull | ast::TyPatKind::Err(_) => Err(RewriteError::Unknown),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,4 +10,15 @@ type Positive2 = pattern_type!(i32 is 0..=);
|
|||||||
type Wild = pattern_type!(() is _);
|
type Wild = pattern_type!(() is _);
|
||||||
//~^ ERROR: pattern not supported in pattern types
|
//~^ ERROR: pattern not supported in pattern types
|
||||||
|
|
||||||
|
// FIXME: confusing diagnostic because `not` can be a binding
|
||||||
|
type NonNull = pattern_type!(*const () is not null);
|
||||||
|
//~^ ERROR: expected one of `@` or `|`, found `null`
|
||||||
|
//~| ERROR: pattern not supported in pattern types
|
||||||
|
|
||||||
|
type NonNull2 = pattern_type!(*const () is !nil);
|
||||||
|
//~^ ERROR: expected `null`, found `nil`
|
||||||
|
|
||||||
|
// FIXME: reject with a type mismatch
|
||||||
|
type Mismatch2 = pattern_type!(() is !null);
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|||||||
@@ -30,6 +30,24 @@ error: pattern not supported in pattern types
|
|||||||
LL | type Wild = pattern_type!(() is _);
|
LL | type Wild = pattern_type!(() is _);
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error: pattern not supported in pattern types
|
||||||
|
--> $DIR/bad_pat.rs:14:43
|
||||||
|
|
|
||||||
|
LL | type NonNull = pattern_type!(*const () is not null);
|
||||||
|
| ^^^
|
||||||
|
|
||||||
|
error: expected one of `@` or `|`, found `null`
|
||||||
|
--> $DIR/bad_pat.rs:14:47
|
||||||
|
|
|
||||||
|
LL | type NonNull = pattern_type!(*const () is not null);
|
||||||
|
| ^^^^ expected one of `@` or `|`
|
||||||
|
|
||||||
|
error: expected `null`, found `nil`
|
||||||
|
--> $DIR/bad_pat.rs:18:45
|
||||||
|
|
|
||||||
|
LL | type NonNull2 = pattern_type!(*const () is !nil);
|
||||||
|
| ^^^ expected `null`
|
||||||
|
|
||||||
|
error: aborting due to 6 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0586`.
|
For more information about this error, try `rustc --explain E0586`.
|
||||||
|
|||||||
21
tests/ui/type/pattern_types/non_null.rs
Normal file
21
tests/ui/type/pattern_types/non_null.rs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
//! Show that pattern-types non-null is the same as libstd's
|
||||||
|
|
||||||
|
//@ normalize-stderr: "randomization_seed: \d+" -> "randomization_seed: $$SEED"
|
||||||
|
//@ only-64bit
|
||||||
|
|
||||||
|
#![feature(pattern_type_macro, pattern_types, rustc_attrs)]
|
||||||
|
|
||||||
|
use std::pat::pattern_type;
|
||||||
|
|
||||||
|
#[rustc_layout(debug)]
|
||||||
|
type NonNull<T> = pattern_type!(*const T is !null); //~ ERROR layout_of
|
||||||
|
|
||||||
|
#[rustc_layout(debug)]
|
||||||
|
type Test = Option<NonNull<()>>; //~ ERROR layout_of
|
||||||
|
|
||||||
|
#[rustc_layout(debug)]
|
||||||
|
type Wide = pattern_type!(*const [u8] is !null); //~ ERROR layout_of
|
||||||
|
|
||||||
|
const _: () = assert!(size_of::<NonNull<()>>() == size_of::<Option<NonNull<()>>>());
|
||||||
|
|
||||||
|
fn main() {}
|
||||||
218
tests/ui/type/pattern_types/non_null.stderr
Normal file
218
tests/ui/type/pattern_types/non_null.stderr
Normal file
@@ -0,0 +1,218 @@
|
|||||||
|
error: layout_of((*const T) is !null) = Layout {
|
||||||
|
size: Size(8 bytes),
|
||||||
|
align: AbiAlign {
|
||||||
|
abi: Align(8 bytes),
|
||||||
|
},
|
||||||
|
backend_repr: Scalar(
|
||||||
|
Initialized {
|
||||||
|
value: Pointer(
|
||||||
|
AddressSpace(
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
valid_range: 1..=18446744073709551615,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
fields: Arbitrary {
|
||||||
|
offsets: [
|
||||||
|
Size(0 bytes),
|
||||||
|
],
|
||||||
|
memory_index: [
|
||||||
|
0,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
largest_niche: Some(
|
||||||
|
Niche {
|
||||||
|
offset: Size(0 bytes),
|
||||||
|
value: Pointer(
|
||||||
|
AddressSpace(
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
valid_range: 1..=18446744073709551615,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
uninhabited: false,
|
||||||
|
variants: Single {
|
||||||
|
index: 0,
|
||||||
|
},
|
||||||
|
max_repr_align: None,
|
||||||
|
unadjusted_abi_align: Align(8 bytes),
|
||||||
|
randomization_seed: $SEED,
|
||||||
|
}
|
||||||
|
--> $DIR/non_null.rs:11:1
|
||||||
|
|
|
||||||
|
LL | type NonNull<T> = pattern_type!(*const T is !null);
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: layout_of(Option<(*const ()) is !null>) = Layout {
|
||||||
|
size: Size(8 bytes),
|
||||||
|
align: AbiAlign {
|
||||||
|
abi: Align(8 bytes),
|
||||||
|
},
|
||||||
|
backend_repr: Scalar(
|
||||||
|
Initialized {
|
||||||
|
value: Pointer(
|
||||||
|
AddressSpace(
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
valid_range: (..=0) | (1..),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
fields: Arbitrary {
|
||||||
|
offsets: [
|
||||||
|
Size(0 bytes),
|
||||||
|
],
|
||||||
|
memory_index: [
|
||||||
|
0,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
largest_niche: None,
|
||||||
|
uninhabited: false,
|
||||||
|
variants: Multiple {
|
||||||
|
tag: Initialized {
|
||||||
|
value: Pointer(
|
||||||
|
AddressSpace(
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
valid_range: (..=0) | (1..),
|
||||||
|
},
|
||||||
|
tag_encoding: Niche {
|
||||||
|
untagged_variant: 1,
|
||||||
|
niche_variants: 0..=0,
|
||||||
|
niche_start: 0,
|
||||||
|
},
|
||||||
|
tag_field: 0,
|
||||||
|
variants: [
|
||||||
|
Layout {
|
||||||
|
size: Size(0 bytes),
|
||||||
|
align: AbiAlign {
|
||||||
|
abi: Align(1 bytes),
|
||||||
|
},
|
||||||
|
backend_repr: Memory {
|
||||||
|
sized: true,
|
||||||
|
},
|
||||||
|
fields: Arbitrary {
|
||||||
|
offsets: [],
|
||||||
|
memory_index: [],
|
||||||
|
},
|
||||||
|
largest_niche: None,
|
||||||
|
uninhabited: false,
|
||||||
|
variants: Single {
|
||||||
|
index: 0,
|
||||||
|
},
|
||||||
|
max_repr_align: None,
|
||||||
|
unadjusted_abi_align: Align(1 bytes),
|
||||||
|
randomization_seed: $SEED,
|
||||||
|
},
|
||||||
|
Layout {
|
||||||
|
size: Size(8 bytes),
|
||||||
|
align: AbiAlign {
|
||||||
|
abi: Align(8 bytes),
|
||||||
|
},
|
||||||
|
backend_repr: Scalar(
|
||||||
|
Initialized {
|
||||||
|
value: Pointer(
|
||||||
|
AddressSpace(
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
valid_range: 1..=18446744073709551615,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
fields: Arbitrary {
|
||||||
|
offsets: [
|
||||||
|
Size(0 bytes),
|
||||||
|
],
|
||||||
|
memory_index: [
|
||||||
|
0,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
largest_niche: Some(
|
||||||
|
Niche {
|
||||||
|
offset: Size(0 bytes),
|
||||||
|
value: Pointer(
|
||||||
|
AddressSpace(
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
valid_range: 1..=18446744073709551615,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
uninhabited: false,
|
||||||
|
variants: Single {
|
||||||
|
index: 1,
|
||||||
|
},
|
||||||
|
max_repr_align: None,
|
||||||
|
unadjusted_abi_align: Align(8 bytes),
|
||||||
|
randomization_seed: $SEED,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
max_repr_align: None,
|
||||||
|
unadjusted_abi_align: Align(8 bytes),
|
||||||
|
randomization_seed: $SEED,
|
||||||
|
}
|
||||||
|
--> $DIR/non_null.rs:14:1
|
||||||
|
|
|
||||||
|
LL | type Test = Option<NonNull<()>>;
|
||||||
|
| ^^^^^^^^^
|
||||||
|
|
||||||
|
error: layout_of((*const [u8]) is !null) = Layout {
|
||||||
|
size: Size(16 bytes),
|
||||||
|
align: AbiAlign {
|
||||||
|
abi: Align(8 bytes),
|
||||||
|
},
|
||||||
|
backend_repr: ScalarPair(
|
||||||
|
Initialized {
|
||||||
|
value: Pointer(
|
||||||
|
AddressSpace(
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
valid_range: 1..=18446744073709551615,
|
||||||
|
},
|
||||||
|
Initialized {
|
||||||
|
value: Int(
|
||||||
|
I64,
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
valid_range: 0..=18446744073709551615,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
fields: Arbitrary {
|
||||||
|
offsets: [
|
||||||
|
Size(0 bytes),
|
||||||
|
],
|
||||||
|
memory_index: [
|
||||||
|
0,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
largest_niche: Some(
|
||||||
|
Niche {
|
||||||
|
offset: Size(0 bytes),
|
||||||
|
value: Pointer(
|
||||||
|
AddressSpace(
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
valid_range: 1..=18446744073709551615,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
uninhabited: false,
|
||||||
|
variants: Single {
|
||||||
|
index: 0,
|
||||||
|
},
|
||||||
|
max_repr_align: None,
|
||||||
|
unadjusted_abi_align: Align(8 bytes),
|
||||||
|
randomization_seed: $SEED,
|
||||||
|
}
|
||||||
|
--> $DIR/non_null.rs:17:1
|
||||||
|
|
|
||||||
|
LL | type Wide = pattern_type!(*const [u8] is !null);
|
||||||
|
| ^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
Reference in New Issue
Block a user