mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-04 19:29:07 +00:00
Auto merge of #131320 - matthiaskrgr:rollup-tom15b3, r=matthiaskrgr
Rollup of 5 pull requests Successful merges: - #129392 (Do not consider match/let/ref of place that evaluates to `!` to diverge, disallow coercions from them too) - #131279 (update "build/host" symlink comment) - #131312 (On function and method calls in patterns, link to the book) - #131315 (bootstrap: add `std_features` config) - #131316 (Fix typo in primitive_docs.rs) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
96d9d8aa7d
@ -82,6 +82,11 @@ struct Coerce<'a, 'tcx> {
|
|||||||
/// See #47489 and #48598
|
/// See #47489 and #48598
|
||||||
/// See docs on the "AllowTwoPhase" type for a more detailed discussion
|
/// See docs on the "AllowTwoPhase" type for a more detailed discussion
|
||||||
allow_two_phase: AllowTwoPhase,
|
allow_two_phase: AllowTwoPhase,
|
||||||
|
/// Whether we allow `NeverToAny` coercions. This is unsound if we're
|
||||||
|
/// coercing a place expression without it counting as a read in the MIR.
|
||||||
|
/// This is a side-effect of HIR not really having a great distinction
|
||||||
|
/// between places and values.
|
||||||
|
coerce_never: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> Deref for Coerce<'a, 'tcx> {
|
impl<'a, 'tcx> Deref for Coerce<'a, 'tcx> {
|
||||||
@ -125,8 +130,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
|||||||
fcx: &'f FnCtxt<'f, 'tcx>,
|
fcx: &'f FnCtxt<'f, 'tcx>,
|
||||||
cause: ObligationCause<'tcx>,
|
cause: ObligationCause<'tcx>,
|
||||||
allow_two_phase: AllowTwoPhase,
|
allow_two_phase: AllowTwoPhase,
|
||||||
|
coerce_never: bool,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Coerce { fcx, cause, allow_two_phase, use_lub: false }
|
Coerce { fcx, cause, allow_two_phase, use_lub: false, coerce_never }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unify(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> InferResult<'tcx, Ty<'tcx>> {
|
fn unify(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> InferResult<'tcx, Ty<'tcx>> {
|
||||||
@ -177,7 +183,12 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
|||||||
|
|
||||||
// Coercing from `!` to any type is allowed:
|
// Coercing from `!` to any type is allowed:
|
||||||
if a.is_never() {
|
if a.is_never() {
|
||||||
return success(simple(Adjust::NeverToAny)(b), b, vec![]);
|
if self.coerce_never {
|
||||||
|
return success(simple(Adjust::NeverToAny)(b), b, vec![]);
|
||||||
|
} else {
|
||||||
|
// Otherwise the only coercion we can do is unification.
|
||||||
|
return self.unify_and(a, b, identity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Coercing *from* an unresolved inference variable means that
|
// Coercing *from* an unresolved inference variable means that
|
||||||
@ -1038,7 +1049,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
/// The expressions *must not* have any preexisting adjustments.
|
/// The expressions *must not* have any preexisting adjustments.
|
||||||
pub(crate) fn coerce(
|
pub(crate) fn coerce(
|
||||||
&self,
|
&self,
|
||||||
expr: &hir::Expr<'_>,
|
expr: &'tcx hir::Expr<'tcx>,
|
||||||
expr_ty: Ty<'tcx>,
|
expr_ty: Ty<'tcx>,
|
||||||
mut target: Ty<'tcx>,
|
mut target: Ty<'tcx>,
|
||||||
allow_two_phase: AllowTwoPhase,
|
allow_two_phase: AllowTwoPhase,
|
||||||
@ -1055,7 +1066,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
|
|
||||||
let cause =
|
let cause =
|
||||||
cause.unwrap_or_else(|| self.cause(expr.span, ObligationCauseCode::ExprAssignable));
|
cause.unwrap_or_else(|| self.cause(expr.span, ObligationCauseCode::ExprAssignable));
|
||||||
let coerce = Coerce::new(self, cause, allow_two_phase);
|
let coerce = Coerce::new(
|
||||||
|
self,
|
||||||
|
cause,
|
||||||
|
allow_two_phase,
|
||||||
|
self.expr_guaranteed_to_constitute_read_for_never(expr),
|
||||||
|
);
|
||||||
let ok = self.commit_if_ok(|_| coerce.coerce(source, target))?;
|
let ok = self.commit_if_ok(|_| coerce.coerce(source, target))?;
|
||||||
|
|
||||||
let (adjustments, _) = self.register_infer_ok_obligations(ok);
|
let (adjustments, _) = self.register_infer_ok_obligations(ok);
|
||||||
@ -1077,8 +1093,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
debug!("coercion::can_with_predicates({:?} -> {:?})", source, target);
|
debug!("coercion::can_with_predicates({:?} -> {:?})", source, target);
|
||||||
|
|
||||||
let cause = self.cause(DUMMY_SP, ObligationCauseCode::ExprAssignable);
|
let cause = self.cause(DUMMY_SP, ObligationCauseCode::ExprAssignable);
|
||||||
// We don't ever need two-phase here since we throw out the result of the coercion
|
// We don't ever need two-phase here since we throw out the result of the coercion.
|
||||||
let coerce = Coerce::new(self, cause, AllowTwoPhase::No);
|
// We also just always set `coerce_never` to true, since this is a heuristic.
|
||||||
|
let coerce = Coerce::new(self, cause, AllowTwoPhase::No, true);
|
||||||
self.probe(|_| {
|
self.probe(|_| {
|
||||||
let Ok(ok) = coerce.coerce(source, target) else {
|
let Ok(ok) = coerce.coerce(source, target) else {
|
||||||
return false;
|
return false;
|
||||||
@ -1090,12 +1107,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Given a type and a target type, this function will calculate and return
|
/// Given a type and a target type, this function will calculate and return
|
||||||
/// how many dereference steps needed to achieve `expr_ty <: target`. If
|
/// how many dereference steps needed to coerce `expr_ty` to `target`. If
|
||||||
/// it's not possible, return `None`.
|
/// it's not possible, return `None`.
|
||||||
pub(crate) fn deref_steps(&self, expr_ty: Ty<'tcx>, target: Ty<'tcx>) -> Option<usize> {
|
pub(crate) fn deref_steps_for_suggestion(
|
||||||
|
&self,
|
||||||
|
expr_ty: Ty<'tcx>,
|
||||||
|
target: Ty<'tcx>,
|
||||||
|
) -> Option<usize> {
|
||||||
let cause = self.cause(DUMMY_SP, ObligationCauseCode::ExprAssignable);
|
let cause = self.cause(DUMMY_SP, ObligationCauseCode::ExprAssignable);
|
||||||
// We don't ever need two-phase here since we throw out the result of the coercion
|
// We don't ever need two-phase here since we throw out the result of the coercion.
|
||||||
let coerce = Coerce::new(self, cause, AllowTwoPhase::No);
|
let coerce = Coerce::new(self, cause, AllowTwoPhase::No, true);
|
||||||
coerce
|
coerce
|
||||||
.autoderef(DUMMY_SP, expr_ty)
|
.autoderef(DUMMY_SP, expr_ty)
|
||||||
.find_map(|(ty, steps)| self.probe(|_| coerce.unify(ty, target)).ok().map(|_| steps))
|
.find_map(|(ty, steps)| self.probe(|_| coerce.unify(ty, target)).ok().map(|_| steps))
|
||||||
@ -1252,7 +1273,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
// probably aren't processing function arguments here and even if we were,
|
// probably aren't processing function arguments here and even if we were,
|
||||||
// they're going to get autorefed again anyway and we can apply 2-phase borrows
|
// they're going to get autorefed again anyway and we can apply 2-phase borrows
|
||||||
// at that time.
|
// at that time.
|
||||||
let mut coerce = Coerce::new(self, cause.clone(), AllowTwoPhase::No);
|
//
|
||||||
|
// NOTE: we set `coerce_never` to `true` here because coercion LUBs only
|
||||||
|
// operate on values and not places, so a never coercion is valid.
|
||||||
|
let mut coerce = Coerce::new(self, cause.clone(), AllowTwoPhase::No, true);
|
||||||
coerce.use_lub = true;
|
coerce.use_lub = true;
|
||||||
|
|
||||||
// First try to coerce the new expression to the type of the previous ones,
|
// First try to coerce the new expression to the type of the previous ones,
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
// ignore-tidy-filelength
|
||||||
|
// FIXME: we should move the field error reporting code somewhere else.
|
||||||
|
|
||||||
//! Type checking expressions.
|
//! Type checking expressions.
|
||||||
//!
|
//!
|
||||||
//! See [`rustc_hir_analysis::check`] for more context on type checking in general.
|
//! See [`rustc_hir_analysis::check`] for more context on type checking in general.
|
||||||
@ -62,7 +65,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
|
|
||||||
// While we don't allow *arbitrary* coercions here, we *do* allow
|
// While we don't allow *arbitrary* coercions here, we *do* allow
|
||||||
// coercions from ! to `expected`.
|
// coercions from ! to `expected`.
|
||||||
if ty.is_never() {
|
if ty.is_never() && self.expr_guaranteed_to_constitute_read_for_never(expr) {
|
||||||
if let Some(_) = self.typeck_results.borrow().adjustments().get(expr.hir_id) {
|
if let Some(_) = self.typeck_results.borrow().adjustments().get(expr.hir_id) {
|
||||||
let reported = self.dcx().span_delayed_bug(
|
let reported = self.dcx().span_delayed_bug(
|
||||||
expr.span,
|
expr.span,
|
||||||
@ -238,8 +241,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
_ => self.warn_if_unreachable(expr.hir_id, expr.span, "expression"),
|
_ => self.warn_if_unreachable(expr.hir_id, expr.span, "expression"),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Any expression that produces a value of type `!` must have diverged
|
// Any expression that produces a value of type `!` must have diverged,
|
||||||
if ty.is_never() {
|
// unless it's a place expression that isn't being read from, in which case
|
||||||
|
// diverging would be unsound since we may never actually read the `!`.
|
||||||
|
// e.g. `let _ = *never_ptr;` with `never_ptr: *const !`.
|
||||||
|
if ty.is_never() && self.expr_guaranteed_to_constitute_read_for_never(expr) {
|
||||||
self.diverges.set(self.diverges.get() | Diverges::always(expr.span));
|
self.diverges.set(self.diverges.get() | Diverges::always(expr.span));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -257,6 +263,185 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
ty
|
ty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whether this expression constitutes a read of value of the type that
|
||||||
|
/// it evaluates to.
|
||||||
|
///
|
||||||
|
/// This is used to determine if we should consider the block to diverge
|
||||||
|
/// if the expression evaluates to `!`, and if we should insert a `NeverToAny`
|
||||||
|
/// coercion for values of type `!`.
|
||||||
|
///
|
||||||
|
/// This function generally returns `false` if the expression is a place
|
||||||
|
/// expression and the *parent* expression is the scrutinee of a match or
|
||||||
|
/// the pointee of an `&` addr-of expression, since both of those parent
|
||||||
|
/// expressions take a *place* and not a value.
|
||||||
|
pub(super) fn expr_guaranteed_to_constitute_read_for_never(
|
||||||
|
&self,
|
||||||
|
expr: &'tcx hir::Expr<'tcx>,
|
||||||
|
) -> bool {
|
||||||
|
// We only care about place exprs. Anything else returns an immediate
|
||||||
|
// which would constitute a read. We don't care about distinguishing
|
||||||
|
// "syntactic" place exprs since if the base of a field projection is
|
||||||
|
// not a place then it would've been UB to read from it anyways since
|
||||||
|
// that constitutes a read.
|
||||||
|
if !expr.is_syntactic_place_expr() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
let parent_node = self.tcx.parent_hir_node(expr.hir_id);
|
||||||
|
match parent_node {
|
||||||
|
hir::Node::Expr(parent_expr) => {
|
||||||
|
match parent_expr.kind {
|
||||||
|
// Addr-of, field projections, and LHS of assignment don't constitute reads.
|
||||||
|
// Assignment does call `drop_in_place`, though, but its safety
|
||||||
|
// requirements are not the same.
|
||||||
|
ExprKind::AddrOf(..) | hir::ExprKind::Field(..) => false,
|
||||||
|
ExprKind::Assign(lhs, _, _) => {
|
||||||
|
// Only the LHS does not constitute a read
|
||||||
|
expr.hir_id != lhs.hir_id
|
||||||
|
}
|
||||||
|
|
||||||
|
// See note on `PatKind::Or` below for why this is `all`.
|
||||||
|
ExprKind::Match(scrutinee, arms, _) => {
|
||||||
|
assert_eq!(scrutinee.hir_id, expr.hir_id);
|
||||||
|
arms.iter()
|
||||||
|
.all(|arm| self.pat_guaranteed_to_constitute_read_for_never(arm.pat))
|
||||||
|
}
|
||||||
|
ExprKind::Let(hir::LetExpr { init, pat, .. }) => {
|
||||||
|
assert_eq!(init.hir_id, expr.hir_id);
|
||||||
|
self.pat_guaranteed_to_constitute_read_for_never(*pat)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Any expression child of these expressions constitute reads.
|
||||||
|
ExprKind::Array(_)
|
||||||
|
| ExprKind::Call(_, _)
|
||||||
|
| ExprKind::MethodCall(_, _, _, _)
|
||||||
|
| ExprKind::Tup(_)
|
||||||
|
| ExprKind::Binary(_, _, _)
|
||||||
|
| ExprKind::Unary(_, _)
|
||||||
|
| ExprKind::Cast(_, _)
|
||||||
|
| ExprKind::Type(_, _)
|
||||||
|
| ExprKind::DropTemps(_)
|
||||||
|
| ExprKind::If(_, _, _)
|
||||||
|
| ExprKind::Closure(_)
|
||||||
|
| ExprKind::Block(_, _)
|
||||||
|
| ExprKind::AssignOp(_, _, _)
|
||||||
|
| ExprKind::Index(_, _, _)
|
||||||
|
| ExprKind::Break(_, _)
|
||||||
|
| ExprKind::Ret(_)
|
||||||
|
| ExprKind::Become(_)
|
||||||
|
| ExprKind::InlineAsm(_)
|
||||||
|
| ExprKind::Struct(_, _, _)
|
||||||
|
| ExprKind::Repeat(_, _)
|
||||||
|
| ExprKind::Yield(_, _) => true,
|
||||||
|
|
||||||
|
// These expressions have no (direct) sub-exprs.
|
||||||
|
ExprKind::ConstBlock(_)
|
||||||
|
| ExprKind::Loop(_, _, _, _)
|
||||||
|
| ExprKind::Lit(_)
|
||||||
|
| ExprKind::Path(_)
|
||||||
|
| ExprKind::Continue(_)
|
||||||
|
| ExprKind::OffsetOf(_, _)
|
||||||
|
| ExprKind::Err(_) => unreachable!("no sub-expr expected for {:?}", expr.kind),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have a subpattern that performs a read, we want to consider this
|
||||||
|
// to diverge for compatibility to support something like `let x: () = *never_ptr;`.
|
||||||
|
hir::Node::LetStmt(hir::LetStmt { init: Some(target), pat, .. }) => {
|
||||||
|
assert_eq!(target.hir_id, expr.hir_id);
|
||||||
|
self.pat_guaranteed_to_constitute_read_for_never(*pat)
|
||||||
|
}
|
||||||
|
|
||||||
|
// These nodes (if they have a sub-expr) do constitute a read.
|
||||||
|
hir::Node::Block(_)
|
||||||
|
| hir::Node::Arm(_)
|
||||||
|
| hir::Node::ExprField(_)
|
||||||
|
| hir::Node::AnonConst(_)
|
||||||
|
| hir::Node::ConstBlock(_)
|
||||||
|
| hir::Node::ConstArg(_)
|
||||||
|
| hir::Node::Stmt(_)
|
||||||
|
| hir::Node::Item(hir::Item {
|
||||||
|
kind: hir::ItemKind::Const(..) | hir::ItemKind::Static(..),
|
||||||
|
..
|
||||||
|
})
|
||||||
|
| hir::Node::TraitItem(hir::TraitItem {
|
||||||
|
kind: hir::TraitItemKind::Const(..), ..
|
||||||
|
})
|
||||||
|
| hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. }) => true,
|
||||||
|
|
||||||
|
// These nodes do not have direct sub-exprs.
|
||||||
|
hir::Node::Param(_)
|
||||||
|
| hir::Node::Item(_)
|
||||||
|
| hir::Node::ForeignItem(_)
|
||||||
|
| hir::Node::TraitItem(_)
|
||||||
|
| hir::Node::ImplItem(_)
|
||||||
|
| hir::Node::Variant(_)
|
||||||
|
| hir::Node::Field(_)
|
||||||
|
| hir::Node::PathSegment(_)
|
||||||
|
| hir::Node::Ty(_)
|
||||||
|
| hir::Node::AssocItemConstraint(_)
|
||||||
|
| hir::Node::TraitRef(_)
|
||||||
|
| hir::Node::Pat(_)
|
||||||
|
| hir::Node::PatField(_)
|
||||||
|
| hir::Node::LetStmt(_)
|
||||||
|
| hir::Node::Synthetic
|
||||||
|
| hir::Node::Err(_)
|
||||||
|
| hir::Node::Ctor(_)
|
||||||
|
| hir::Node::Lifetime(_)
|
||||||
|
| hir::Node::GenericParam(_)
|
||||||
|
| hir::Node::Crate(_)
|
||||||
|
| hir::Node::Infer(_)
|
||||||
|
| hir::Node::WhereBoundPredicate(_)
|
||||||
|
| hir::Node::ArrayLenInfer(_)
|
||||||
|
| hir::Node::PreciseCapturingNonLifetimeArg(_)
|
||||||
|
| hir::Node::OpaqueTy(_) => {
|
||||||
|
unreachable!("no sub-expr expected for {parent_node:?}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Whether this pattern constitutes a read of value of the scrutinee that
|
||||||
|
/// it is matching against. This is used to determine whether we should
|
||||||
|
/// perform `NeverToAny` coercions.
|
||||||
|
///
|
||||||
|
/// See above for the nuances of what happens when this returns true.
|
||||||
|
pub(super) fn pat_guaranteed_to_constitute_read_for_never(&self, pat: &hir::Pat<'_>) -> bool {
|
||||||
|
match pat.kind {
|
||||||
|
// Does not constitute a read.
|
||||||
|
hir::PatKind::Wild => false,
|
||||||
|
|
||||||
|
// This is unnecessarily restrictive when the pattern that doesn't
|
||||||
|
// constitute a read is unreachable.
|
||||||
|
//
|
||||||
|
// For example `match *never_ptr { value => {}, _ => {} }` or
|
||||||
|
// `match *never_ptr { _ if false => {}, value => {} }`.
|
||||||
|
//
|
||||||
|
// It is however fine to be restrictive here; only returning `true`
|
||||||
|
// can lead to unsoundness.
|
||||||
|
hir::PatKind::Or(subpats) => {
|
||||||
|
subpats.iter().all(|pat| self.pat_guaranteed_to_constitute_read_for_never(pat))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Does constitute a read, since it is equivalent to a discriminant read.
|
||||||
|
hir::PatKind::Never => true,
|
||||||
|
|
||||||
|
// All of these constitute a read, or match on something that isn't `!`,
|
||||||
|
// which would require a `NeverToAny` coercion.
|
||||||
|
hir::PatKind::Binding(_, _, _, _)
|
||||||
|
| hir::PatKind::Struct(_, _, _)
|
||||||
|
| hir::PatKind::TupleStruct(_, _, _)
|
||||||
|
| hir::PatKind::Path(_)
|
||||||
|
| hir::PatKind::Tuple(_, _)
|
||||||
|
| hir::PatKind::Box(_)
|
||||||
|
| hir::PatKind::Ref(_, _)
|
||||||
|
| hir::PatKind::Deref(_)
|
||||||
|
| hir::PatKind::Lit(_)
|
||||||
|
| hir::PatKind::Range(_, _, _)
|
||||||
|
| hir::PatKind::Slice(_, _, _)
|
||||||
|
| hir::PatKind::Err(_) => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[instrument(skip(self, expr), level = "debug")]
|
#[instrument(skip(self, expr), level = "debug")]
|
||||||
fn check_expr_kind(
|
fn check_expr_kind(
|
||||||
&self,
|
&self,
|
||||||
|
@ -2608,7 +2608,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let hir::ExprKind::Unary(hir::UnOp::Deref, inner) = expr.kind
|
if let hir::ExprKind::Unary(hir::UnOp::Deref, inner) = expr.kind
|
||||||
&& let Some(1) = self.deref_steps(expected, checked_ty)
|
&& let Some(1) = self.deref_steps_for_suggestion(expected, checked_ty)
|
||||||
{
|
{
|
||||||
// We have `*&T`, check if what was expected was `&T`.
|
// We have `*&T`, check if what was expected was `&T`.
|
||||||
// If so, we may want to suggest removing a `*`.
|
// If so, we may want to suggest removing a `*`.
|
||||||
@ -2738,7 +2738,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
(_, &ty::RawPtr(ty_b, mutbl_b), &ty::Ref(_, ty_a, mutbl_a)) => {
|
(_, &ty::RawPtr(ty_b, mutbl_b), &ty::Ref(_, ty_a, mutbl_a)) => {
|
||||||
if let Some(steps) = self.deref_steps(ty_a, ty_b)
|
if let Some(steps) = self.deref_steps_for_suggestion(ty_a, ty_b)
|
||||||
// Only suggest valid if dereferencing needed.
|
// Only suggest valid if dereferencing needed.
|
||||||
&& steps > 0
|
&& steps > 0
|
||||||
// The pointer type implements `Copy` trait so the suggestion is always valid.
|
// The pointer type implements `Copy` trait so the suggestion is always valid.
|
||||||
@ -2782,7 +2782,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ if sp == expr.span => {
|
_ if sp == expr.span => {
|
||||||
if let Some(mut steps) = self.deref_steps(checked_ty, expected) {
|
if let Some(mut steps) = self.deref_steps_for_suggestion(checked_ty, expected) {
|
||||||
let mut expr = expr.peel_blocks();
|
let mut expr = expr.peel_blocks();
|
||||||
let mut prefix_span = expr.span.shrink_to_lo();
|
let mut prefix_span = expr.span.shrink_to_lo();
|
||||||
let mut remove = String::new();
|
let mut remove = String::new();
|
||||||
|
@ -812,7 +812,8 @@ parse_unexpected_expr_in_pat =
|
|||||||
*[false] a pattern
|
*[false] a pattern
|
||||||
}, found an expression
|
}, found an expression
|
||||||
|
|
||||||
.label = arbitrary expressions are not allowed in patterns
|
.label = not a pattern
|
||||||
|
.note = arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
|
|
||||||
parse_unexpected_expr_in_pat_const_sugg = consider extracting the expression into a `const`
|
parse_unexpected_expr_in_pat_const_sugg = consider extracting the expression into a `const`
|
||||||
|
|
||||||
|
@ -2608,6 +2608,7 @@ pub(crate) struct ExpectedCommaAfterPatternField {
|
|||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(parse_unexpected_expr_in_pat)]
|
#[diag(parse_unexpected_expr_in_pat)]
|
||||||
|
#[note]
|
||||||
pub(crate) struct UnexpectedExpressionInPattern {
|
pub(crate) struct UnexpectedExpressionInPattern {
|
||||||
/// The unexpected expr's span.
|
/// The unexpected expr's span.
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
|
@ -443,6 +443,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
|
|||||||
|
|
||||||
self.suggest_bare_struct_literal(&mut err);
|
self.suggest_bare_struct_literal(&mut err);
|
||||||
self.suggest_changing_type_to_const_param(&mut err, res, source, span);
|
self.suggest_changing_type_to_const_param(&mut err, res, source, span);
|
||||||
|
self.explain_functions_in_pattern(&mut err, res, source);
|
||||||
|
|
||||||
if self.suggest_pattern_match_with_let(&mut err, source, span) {
|
if self.suggest_pattern_match_with_let(&mut err, source, span) {
|
||||||
// Fallback label.
|
// Fallback label.
|
||||||
@ -1166,6 +1167,18 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn explain_functions_in_pattern(
|
||||||
|
&mut self,
|
||||||
|
err: &mut Diag<'_>,
|
||||||
|
res: Option<Res>,
|
||||||
|
source: PathSource<'_>,
|
||||||
|
) {
|
||||||
|
let PathSource::TupleStruct(_, _) = source else { return };
|
||||||
|
let Some(Res::Def(DefKind::Fn, _)) = res else { return };
|
||||||
|
err.primary_message("expected a pattern, found a function call");
|
||||||
|
err.note("function calls are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>");
|
||||||
|
}
|
||||||
|
|
||||||
fn suggest_changing_type_to_const_param(
|
fn suggest_changing_type_to_const_param(
|
||||||
&mut self,
|
&mut self,
|
||||||
err: &mut Diag<'_>,
|
err: &mut Diag<'_>,
|
||||||
|
@ -759,6 +759,16 @@
|
|||||||
# Build compiler with the optimization enabled and -Zvalidate-mir, currently only for `std`
|
# Build compiler with the optimization enabled and -Zvalidate-mir, currently only for `std`
|
||||||
#validate-mir-opts = 3
|
#validate-mir-opts = 3
|
||||||
|
|
||||||
|
# Configure `std` features used during bootstrap.
|
||||||
|
# Default features will be expanded in the following cases:
|
||||||
|
# - If `rust.llvm-libunwind` or `target.llvm-libunwind` is enabled:
|
||||||
|
# - "llvm-libunwind" will be added for in-tree LLVM builds.
|
||||||
|
# - "system-llvm-libunwind" will be added for system LLVM builds.
|
||||||
|
# - If `rust.backtrace` is enabled, "backtrace" will be added.
|
||||||
|
# - If `rust.profiler` or `target.profiler` is enabled, "profiler" will be added.
|
||||||
|
# - If building for a zkvm target, "compiler-builtins-mem" will be added.
|
||||||
|
#std-features = ["panic_unwind"]
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# Options for specific targets
|
# Options for specific targets
|
||||||
#
|
#
|
||||||
|
@ -1251,7 +1251,7 @@ mod prim_f16 {}
|
|||||||
/// - **Unchanged NaN propagation**: The quiet bit and payload are copied from any input operand
|
/// - **Unchanged NaN propagation**: The quiet bit and payload are copied from any input operand
|
||||||
/// that is a NaN. If the inputs and outputs do not have the same size (i.e., for `as` casts), the
|
/// that is a NaN. If the inputs and outputs do not have the same size (i.e., for `as` casts), the
|
||||||
/// same rules as for "quieting NaN propagation" apply, with one caveat: if the output is smaller
|
/// same rules as for "quieting NaN propagation" apply, with one caveat: if the output is smaller
|
||||||
/// than the input, droppig the low-order bits may result in a payload of 0; a payload of 0 is not
|
/// than the input, dropping the low-order bits may result in a payload of 0; a payload of 0 is not
|
||||||
/// possible with a signaling NaN (the all-0 significand encodes an infinity) so unchanged NaN
|
/// possible with a signaling NaN (the all-0 significand encodes an infinity) so unchanged NaN
|
||||||
/// propagation cannot occur with some inputs.
|
/// propagation cannot occur with some inputs.
|
||||||
/// - **Target-specific NaN**: The quiet bit is set and the payload is picked from a target-specific
|
/// - **Target-specific NaN**: The quiet bit is set and the payload is picked from a target-specific
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
//! how the build runs.
|
//! how the build runs.
|
||||||
|
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, RefCell};
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{BTreeSet, HashMap, HashSet};
|
||||||
use std::fmt::{self, Display};
|
use std::fmt::{self, Display};
|
||||||
use std::io::IsTerminal;
|
use std::io::IsTerminal;
|
||||||
use std::path::{Path, PathBuf, absolute};
|
use std::path::{Path, PathBuf, absolute};
|
||||||
@ -287,6 +287,7 @@ pub struct Config {
|
|||||||
pub rust_profile_generate: Option<String>,
|
pub rust_profile_generate: Option<String>,
|
||||||
pub rust_lto: RustcLto,
|
pub rust_lto: RustcLto,
|
||||||
pub rust_validate_mir_opts: Option<u32>,
|
pub rust_validate_mir_opts: Option<u32>,
|
||||||
|
pub rust_std_features: BTreeSet<String>,
|
||||||
pub llvm_profile_use: Option<String>,
|
pub llvm_profile_use: Option<String>,
|
||||||
pub llvm_profile_generate: bool,
|
pub llvm_profile_generate: bool,
|
||||||
pub llvm_libunwind_default: Option<LlvmLibunwind>,
|
pub llvm_libunwind_default: Option<LlvmLibunwind>,
|
||||||
@ -1152,6 +1153,7 @@ define_config! {
|
|||||||
download_rustc: Option<StringOrBool> = "download-rustc",
|
download_rustc: Option<StringOrBool> = "download-rustc",
|
||||||
lto: Option<String> = "lto",
|
lto: Option<String> = "lto",
|
||||||
validate_mir_opts: Option<u32> = "validate-mir-opts",
|
validate_mir_opts: Option<u32> = "validate-mir-opts",
|
||||||
|
std_features: Option<BTreeSet<String>> = "std-features",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1645,6 +1647,7 @@ impl Config {
|
|||||||
let mut optimize = None;
|
let mut optimize = None;
|
||||||
let mut omit_git_hash = None;
|
let mut omit_git_hash = None;
|
||||||
let mut lld_enabled = None;
|
let mut lld_enabled = None;
|
||||||
|
let mut std_features = None;
|
||||||
|
|
||||||
let mut is_user_configured_rust_channel = false;
|
let mut is_user_configured_rust_channel = false;
|
||||||
|
|
||||||
@ -1703,6 +1706,7 @@ impl Config {
|
|||||||
stack_protector,
|
stack_protector,
|
||||||
strip,
|
strip,
|
||||||
lld_mode,
|
lld_mode,
|
||||||
|
std_features: std_features_toml,
|
||||||
} = rust;
|
} = rust;
|
||||||
|
|
||||||
is_user_configured_rust_channel = channel.is_some();
|
is_user_configured_rust_channel = channel.is_some();
|
||||||
@ -1722,6 +1726,7 @@ impl Config {
|
|||||||
debuginfo_level_tools = debuginfo_level_tools_toml;
|
debuginfo_level_tools = debuginfo_level_tools_toml;
|
||||||
debuginfo_level_tests = debuginfo_level_tests_toml;
|
debuginfo_level_tests = debuginfo_level_tests_toml;
|
||||||
lld_enabled = lld_enabled_toml;
|
lld_enabled = lld_enabled_toml;
|
||||||
|
std_features = std_features_toml;
|
||||||
|
|
||||||
optimize = optimize_toml;
|
optimize = optimize_toml;
|
||||||
omit_git_hash = omit_git_hash_toml;
|
omit_git_hash = omit_git_hash_toml;
|
||||||
@ -2118,6 +2123,9 @@ impl Config {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let default_std_features = BTreeSet::from([String::from("panic-unwind")]);
|
||||||
|
config.rust_std_features = std_features.unwrap_or(default_std_features);
|
||||||
|
|
||||||
let default = debug == Some(true);
|
let default = debug == Some(true);
|
||||||
config.rust_debug_assertions = debug_assertions.unwrap_or(default);
|
config.rust_debug_assertions = debug_assertions.unwrap_or(default);
|
||||||
config.rust_debug_assertions_std =
|
config.rust_debug_assertions_std =
|
||||||
@ -3016,6 +3024,7 @@ fn check_incompatible_options_for_ci_rustc(
|
|||||||
description,
|
description,
|
||||||
incremental,
|
incremental,
|
||||||
default_linker,
|
default_linker,
|
||||||
|
std_features,
|
||||||
|
|
||||||
// Rest of the options can simply be ignored.
|
// Rest of the options can simply be ignored.
|
||||||
debug: _,
|
debug: _,
|
||||||
@ -3077,6 +3086,7 @@ fn check_incompatible_options_for_ci_rustc(
|
|||||||
err!(current_rust_config.default_linker, default_linker);
|
err!(current_rust_config.default_linker, default_linker);
|
||||||
err!(current_rust_config.stack_protector, stack_protector);
|
err!(current_rust_config.stack_protector, stack_protector);
|
||||||
err!(current_rust_config.lto, lto);
|
err!(current_rust_config.lto, lto);
|
||||||
|
err!(current_rust_config.std_features, std_features);
|
||||||
|
|
||||||
warn!(current_rust_config.channel, channel);
|
warn!(current_rust_config.channel, channel);
|
||||||
warn!(current_rust_config.description, description);
|
warn!(current_rust_config.description, description);
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use std::collections::BTreeSet;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::fs::{File, remove_file};
|
use std::fs::{File, remove_file};
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
@ -326,3 +327,24 @@ fn verbose_tests_default_value() {
|
|||||||
let config = Config::parse(Flags::parse(&["build".into(), "compiler".into(), "-v".into()]));
|
let config = Config::parse(Flags::parse(&["build".into(), "compiler".into(), "-v".into()]));
|
||||||
assert_eq!(config.verbose_tests, true);
|
assert_eq!(config.verbose_tests, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_rust_std_features() {
|
||||||
|
let config = parse("rust.std-features = [\"panic-unwind\", \"backtrace\"]");
|
||||||
|
let expected_features: BTreeSet<String> =
|
||||||
|
["panic-unwind", "backtrace"].into_iter().map(|s| s.to_string()).collect();
|
||||||
|
assert_eq!(config.rust_std_features, expected_features);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_rust_std_features_empty() {
|
||||||
|
let config = parse("rust.std-features = []");
|
||||||
|
let expected_features: BTreeSet<String> = BTreeSet::new();
|
||||||
|
assert_eq!(config.rust_std_features, expected_features);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic]
|
||||||
|
fn parse_rust_std_features_invalid() {
|
||||||
|
parse("rust.std-features = \"backtrace\"");
|
||||||
|
}
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
//! also check out the `src/bootstrap/README.md` file for more information.
|
//! also check out the `src/bootstrap/README.md` file for more information.
|
||||||
|
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, RefCell};
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{BTreeSet, HashMap, HashSet};
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
use std::fs::{self, File};
|
use std::fs::{self, File};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
@ -470,7 +470,7 @@ impl Build {
|
|||||||
crate::core::metadata::build(&mut build);
|
crate::core::metadata::build(&mut build);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make a symbolic link so we can use a consistent directory in the documentation.
|
// Create symbolic link to use host sysroot from a consistent path (e.g., in the rust-analyzer config file).
|
||||||
let build_triple = build.out.join(build.build);
|
let build_triple = build.out.join(build.build);
|
||||||
t!(fs::create_dir_all(&build_triple));
|
t!(fs::create_dir_all(&build_triple));
|
||||||
let host = build.out.join("host");
|
let host = build.out.join("host");
|
||||||
@ -645,28 +645,31 @@ impl Build {
|
|||||||
&self.config.rust_info
|
&self.config.rust_info
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the space-separated set of activated features for the standard
|
/// Gets the space-separated set of activated features for the standard library.
|
||||||
/// library.
|
/// This can be configured with the `std-features` key in config.toml.
|
||||||
fn std_features(&self, target: TargetSelection) -> String {
|
fn std_features(&self, target: TargetSelection) -> String {
|
||||||
let mut features = " panic-unwind".to_string();
|
let mut features: BTreeSet<&str> =
|
||||||
|
self.config.rust_std_features.iter().map(|s| s.as_str()).collect();
|
||||||
|
|
||||||
match self.config.llvm_libunwind(target) {
|
match self.config.llvm_libunwind(target) {
|
||||||
LlvmLibunwind::InTree => features.push_str(" llvm-libunwind"),
|
LlvmLibunwind::InTree => features.insert("llvm-libunwind"),
|
||||||
LlvmLibunwind::System => features.push_str(" system-llvm-libunwind"),
|
LlvmLibunwind::System => features.insert("system-llvm-libunwind"),
|
||||||
LlvmLibunwind::No => {}
|
LlvmLibunwind::No => false,
|
||||||
}
|
};
|
||||||
|
|
||||||
if self.config.backtrace {
|
if self.config.backtrace {
|
||||||
features.push_str(" backtrace");
|
features.insert("backtrace");
|
||||||
}
|
}
|
||||||
if self.config.profiler_enabled(target) {
|
if self.config.profiler_enabled(target) {
|
||||||
features.push_str(" profiler");
|
features.insert("profiler");
|
||||||
}
|
}
|
||||||
// Generate memcpy, etc. FIXME: Remove this once compiler-builtins
|
// Generate memcpy, etc. FIXME: Remove this once compiler-builtins
|
||||||
// automatically detects this target.
|
// automatically detects this target.
|
||||||
if target.contains("zkvm") {
|
if target.contains("zkvm") {
|
||||||
features.push_str(" compiler-builtins-mem");
|
features.insert("compiler-builtins-mem");
|
||||||
}
|
}
|
||||||
features
|
|
||||||
|
features.into_iter().collect::<Vec<_>>().join(" ")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the space-separated set of activated features for the compiler.
|
/// Gets the space-separated set of activated features for the compiler.
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
// Various tests ensuring that underscore patterns really just construct the place, but don't check its contents.
|
// Various tests ensuring that underscore patterns really just construct the place, but don't check its contents.
|
||||||
#![feature(strict_provenance)]
|
#![feature(strict_provenance)]
|
||||||
|
#![feature(never_type)]
|
||||||
|
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
@ -9,6 +11,7 @@ fn main() {
|
|||||||
invalid_let();
|
invalid_let();
|
||||||
dangling_let_type_annotation();
|
dangling_let_type_annotation();
|
||||||
invalid_let_type_annotation();
|
invalid_let_type_annotation();
|
||||||
|
never();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dangling_match() {
|
fn dangling_match() {
|
||||||
@ -34,6 +37,13 @@ fn invalid_match() {
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let x: Uninit<!> = Uninit { uninit: () };
|
||||||
|
match x.value {
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dangling_let() {
|
fn dangling_let() {
|
||||||
@ -41,6 +51,11 @@ fn dangling_let() {
|
|||||||
let ptr = ptr::without_provenance::<bool>(0x40);
|
let ptr = ptr::without_provenance::<bool>(0x40);
|
||||||
let _ = *ptr;
|
let _ = *ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let ptr = ptr::without_provenance::<!>(0x40);
|
||||||
|
let _ = *ptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn invalid_let() {
|
fn invalid_let() {
|
||||||
@ -49,6 +64,12 @@ fn invalid_let() {
|
|||||||
let ptr = ptr::addr_of!(val).cast::<bool>();
|
let ptr = ptr::addr_of!(val).cast::<bool>();
|
||||||
let _ = *ptr;
|
let _ = *ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let val = 3u8;
|
||||||
|
let ptr = ptr::addr_of!(val).cast::<!>();
|
||||||
|
let _ = *ptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adding a type annotation used to change how MIR is generated, make sure we cover both cases.
|
// Adding a type annotation used to change how MIR is generated, make sure we cover both cases.
|
||||||
@ -57,6 +78,11 @@ fn dangling_let_type_annotation() {
|
|||||||
let ptr = ptr::without_provenance::<bool>(0x40);
|
let ptr = ptr::without_provenance::<bool>(0x40);
|
||||||
let _: bool = *ptr;
|
let _: bool = *ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let ptr = ptr::without_provenance::<!>(0x40);
|
||||||
|
let _: ! = *ptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn invalid_let_type_annotation() {
|
fn invalid_let_type_annotation() {
|
||||||
@ -65,7 +91,28 @@ fn invalid_let_type_annotation() {
|
|||||||
let ptr = ptr::addr_of!(val).cast::<bool>();
|
let ptr = ptr::addr_of!(val).cast::<bool>();
|
||||||
let _: bool = *ptr;
|
let _: bool = *ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let val = 3u8;
|
||||||
|
let ptr = ptr::addr_of!(val).cast::<!>();
|
||||||
|
let _: ! = *ptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: we should also test `!`, not just `bool` -- but that s currently buggy:
|
// Regression test from <https://github.com/rust-lang/rust/issues/117288>.
|
||||||
// https://github.com/rust-lang/rust/issues/117288
|
fn never() {
|
||||||
|
unsafe {
|
||||||
|
let x = 3u8;
|
||||||
|
let x: *const ! = &x as *const u8 as *const _;
|
||||||
|
let _: ! = *x;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Without a type annotation, make sure we don't implicitly coerce `!` to `()`
|
||||||
|
// when we do the noop `*x` (as that would require a `!` *value*, creating
|
||||||
|
// which is UB).
|
||||||
|
unsafe {
|
||||||
|
let x = 3u8;
|
||||||
|
let x: *const ! = &x as *const u8 as *const _;
|
||||||
|
let _ = *x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -3,9 +3,8 @@
|
|||||||
fn process_never(_1: *const !) -> () {
|
fn process_never(_1: *const !) -> () {
|
||||||
debug input => _1;
|
debug input => _1;
|
||||||
let mut _0: ();
|
let mut _0: ();
|
||||||
let _2: &!;
|
|
||||||
scope 1 {
|
scope 1 {
|
||||||
debug _input => _2;
|
debug _input => const ();
|
||||||
}
|
}
|
||||||
|
|
||||||
bb0: {
|
bb0: {
|
||||||
|
@ -4,7 +4,7 @@ fn process_void(_1: *const Void) -> () {
|
|||||||
debug input => _1;
|
debug input => _1;
|
||||||
let mut _0: ();
|
let mut _0: ();
|
||||||
scope 1 {
|
scope 1 {
|
||||||
debug _input => _1;
|
debug _input => const ZeroSized: Void;
|
||||||
}
|
}
|
||||||
|
|
||||||
bb0: {
|
bb0: {
|
||||||
|
@ -1,18 +1,19 @@
|
|||||||
// skip-filecheck
|
// skip-filecheck
|
||||||
#![feature(never_type)]
|
#![feature(never_type)]
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
pub enum Void {}
|
pub enum Void {}
|
||||||
|
|
||||||
// EMIT_MIR uninhabited_enum.process_never.SimplifyLocals-final.after.mir
|
// EMIT_MIR uninhabited_enum.process_never.SimplifyLocals-final.after.mir
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn process_never(input: *const !) {
|
pub fn process_never(input: *const !) {
|
||||||
let _input = unsafe { &*input };
|
let _input = unsafe { *input };
|
||||||
}
|
}
|
||||||
|
|
||||||
// EMIT_MIR uninhabited_enum.process_void.SimplifyLocals-final.after.mir
|
// EMIT_MIR uninhabited_enum.process_void.SimplifyLocals-final.after.mir
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn process_void(input: *const Void) {
|
pub fn process_void(input: *const Void) {
|
||||||
let _input = unsafe { &*input };
|
let _input = unsafe { *input };
|
||||||
// In the future, this should end with `unreachable`, but we currently only do
|
// In the future, this should end with `unreachable`, but we currently only do
|
||||||
// unreachability analysis for `!`.
|
// unreachability analysis for `!`.
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,49 @@
|
|||||||
|
// MIR for `main` after SimplifyLocals-final
|
||||||
|
|
||||||
|
fn main() -> () {
|
||||||
|
let mut _0: ();
|
||||||
|
let _1: u8;
|
||||||
|
let mut _2: *const !;
|
||||||
|
let mut _3: *const u8;
|
||||||
|
let _4: u8;
|
||||||
|
let mut _5: *const !;
|
||||||
|
let mut _6: *const u8;
|
||||||
|
scope 1 {
|
||||||
|
debug x => _1;
|
||||||
|
scope 2 {
|
||||||
|
debug x => _2;
|
||||||
|
scope 3 {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scope 4 {
|
||||||
|
debug x => _4;
|
||||||
|
scope 5 {
|
||||||
|
debug x => _5;
|
||||||
|
scope 6 {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bb0: {
|
||||||
|
StorageLive(_1);
|
||||||
|
_1 = const 3_u8;
|
||||||
|
StorageLive(_2);
|
||||||
|
StorageLive(_3);
|
||||||
|
_3 = &raw const _1;
|
||||||
|
_2 = move _3 as *const ! (PtrToPtr);
|
||||||
|
StorageDead(_3);
|
||||||
|
StorageDead(_2);
|
||||||
|
StorageDead(_1);
|
||||||
|
StorageLive(_4);
|
||||||
|
_4 = const 3_u8;
|
||||||
|
StorageLive(_5);
|
||||||
|
StorageLive(_6);
|
||||||
|
_6 = &raw const _4;
|
||||||
|
_5 = move _6 as *const ! (PtrToPtr);
|
||||||
|
StorageDead(_6);
|
||||||
|
StorageDead(_5);
|
||||||
|
StorageDead(_4);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
26
tests/mir-opt/uninhabited_not_read.rs
Normal file
26
tests/mir-opt/uninhabited_not_read.rs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// skip-filecheck
|
||||||
|
|
||||||
|
//@ edition: 2021
|
||||||
|
// In ed 2021 and below, we don't fallback `!` to `()`.
|
||||||
|
// This would introduce a `! -> ()` coercion which would
|
||||||
|
// be UB if we didn't disallow this explicitly.
|
||||||
|
|
||||||
|
#![feature(never_type)]
|
||||||
|
|
||||||
|
// EMIT_MIR uninhabited_not_read.main.SimplifyLocals-final.after.mir
|
||||||
|
fn main() {
|
||||||
|
// With a type annotation
|
||||||
|
unsafe {
|
||||||
|
let x = 3u8;
|
||||||
|
let x: *const ! = &x as *const u8 as *const _;
|
||||||
|
let _: ! = *x;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Without a type annotation, make sure we don't implicitly coerce `!` to `()`
|
||||||
|
// when we do the noop `*x`.
|
||||||
|
unsafe {
|
||||||
|
let x = 3u8;
|
||||||
|
let x: *const ! = &x as *const u8 as *const _;
|
||||||
|
let _ = *x;
|
||||||
|
}
|
||||||
|
}
|
@ -7,14 +7,12 @@ LL | let c1 = || match x { };
|
|||||||
| ^ `x` used here but it isn't initialized
|
| ^ `x` used here but it isn't initialized
|
||||||
|
|
||||||
error[E0381]: used binding `x` isn't initialized
|
error[E0381]: used binding `x` isn't initialized
|
||||||
--> $DIR/pattern-matching-should-fail.rs:15:14
|
--> $DIR/pattern-matching-should-fail.rs:15:23
|
||||||
|
|
|
|
||||||
LL | let x: !;
|
LL | let x: !;
|
||||||
| - binding declared here but left uninitialized
|
| - binding declared here but left uninitialized
|
||||||
LL | let c2 = || match x { _ => () };
|
LL | let c2 = || match x { _ => () };
|
||||||
| ^^ - borrow occurs due to use in closure
|
| ^ `x` used here but it isn't initialized
|
||||||
| |
|
|
||||||
| `x` used here but it isn't initialized
|
|
||||||
|
|
||||||
error[E0381]: used binding `variant` isn't initialized
|
error[E0381]: used binding `variant` isn't initialized
|
||||||
--> $DIR/pattern-matching-should-fail.rs:27:13
|
--> $DIR/pattern-matching-should-fail.rs:27:13
|
||||||
|
@ -2,8 +2,9 @@ error: expected a pattern range bound, found an expression
|
|||||||
--> $DIR/range_pat_interactions1.rs:17:16
|
--> $DIR/range_pat_interactions1.rs:17:16
|
||||||
|
|
|
|
||||||
LL | 0..5+1 => errors_only.push(x),
|
LL | 0..5+1 => errors_only.push(x),
|
||||||
| ^^^ arbitrary expressions are not allowed in patterns
|
| ^^^ not a pattern
|
||||||
|
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
help: consider extracting the expression into a `const`
|
help: consider extracting the expression into a `const`
|
||||||
|
|
|
|
||||||
LL + const VAL: /* Type */ = 5+1;
|
LL + const VAL: /* Type */ = 5+1;
|
||||||
|
@ -14,8 +14,9 @@ error: expected a pattern range bound, found an expression
|
|||||||
--> $DIR/range_pat_interactions2.rs:10:18
|
--> $DIR/range_pat_interactions2.rs:10:18
|
||||||
|
|
|
|
||||||
LL | 0..=(5+1) => errors_only.push(x),
|
LL | 0..=(5+1) => errors_only.push(x),
|
||||||
| ^^^ arbitrary expressions are not allowed in patterns
|
| ^^^ not a pattern
|
||||||
|
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
help: consider extracting the expression into a `const`
|
help: consider extracting the expression into a `const`
|
||||||
|
|
|
|
||||||
LL + const VAL: /* Type */ = 5+1;
|
LL + const VAL: /* Type */ = 5+1;
|
||||||
|
74
tests/ui/never_type/diverging-place-match.rs
Normal file
74
tests/ui/never_type/diverging-place-match.rs
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
#![feature(never_type)]
|
||||||
|
|
||||||
|
fn not_a_read() -> ! {
|
||||||
|
unsafe {
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
let x: *const ! = 0 as _;
|
||||||
|
let _: ! = *x;
|
||||||
|
// Since `*x` "diverges" in HIR, but doesn't count as a read in MIR, this
|
||||||
|
// is unsound since we act as if it diverges but it doesn't.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn not_a_read_implicit() -> ! {
|
||||||
|
unsafe {
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
let x: *const ! = 0 as _;
|
||||||
|
let _ = *x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn not_a_read_guide_coercion() -> ! {
|
||||||
|
unsafe {
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
let x: *const ! = 0 as _;
|
||||||
|
let _: () = *x;
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn empty_match() -> ! {
|
||||||
|
unsafe {
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
let x: *const ! = 0 as _;
|
||||||
|
match *x { _ => {} };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn field_projection() -> ! {
|
||||||
|
unsafe {
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
let x: *const (!, ()) = 0 as _;
|
||||||
|
let _ = (*x).0;
|
||||||
|
// ^ I think this is still UB, but because of the inbounds projection.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn covered_arm() -> ! {
|
||||||
|
unsafe {
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
let x: *const ! = 0 as _;
|
||||||
|
let (_ | 1i32) = *x;
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: This *could* be considered a read of `!`, but we're not that sophisticated..
|
||||||
|
fn uncovered_arm() -> ! {
|
||||||
|
unsafe {
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
let x: *const ! = 0 as _;
|
||||||
|
let (1i32 | _) = *x;
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn coerce_ref_binding() -> ! {
|
||||||
|
unsafe {
|
||||||
|
let x: *const ! = 0 as _;
|
||||||
|
let ref _x: () = *x;
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
142
tests/ui/never_type/diverging-place-match.stderr
Normal file
142
tests/ui/never_type/diverging-place-match.stderr
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/diverging-place-match.rs:4:5
|
||||||
|
|
|
||||||
|
LL | / unsafe {
|
||||||
|
LL | |
|
||||||
|
LL | | let x: *const ! = 0 as _;
|
||||||
|
LL | | let _: ! = *x;
|
||||||
|
LL | | // Since `*x` "diverges" in HIR, but doesn't count as a read in MIR, this
|
||||||
|
LL | | // is unsound since we act as if it diverges but it doesn't.
|
||||||
|
LL | | }
|
||||||
|
| |_____^ expected `!`, found `()`
|
||||||
|
|
|
||||||
|
= note: expected type `!`
|
||||||
|
found unit type `()`
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/diverging-place-match.rs:14:5
|
||||||
|
|
|
||||||
|
LL | / unsafe {
|
||||||
|
LL | |
|
||||||
|
LL | | let x: *const ! = 0 as _;
|
||||||
|
LL | | let _ = *x;
|
||||||
|
LL | | }
|
||||||
|
| |_____^ expected `!`, found `()`
|
||||||
|
|
|
||||||
|
= note: expected type `!`
|
||||||
|
found unit type `()`
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/diverging-place-match.rs:25:21
|
||||||
|
|
|
||||||
|
LL | let _: () = *x;
|
||||||
|
| -- ^^ expected `()`, found `!`
|
||||||
|
| |
|
||||||
|
| expected due to this
|
||||||
|
|
|
||||||
|
= note: expected unit type `()`
|
||||||
|
found type `!`
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/diverging-place-match.rs:22:5
|
||||||
|
|
|
||||||
|
LL | / unsafe {
|
||||||
|
LL | |
|
||||||
|
LL | | let x: *const ! = 0 as _;
|
||||||
|
LL | | let _: () = *x;
|
||||||
|
LL | |
|
||||||
|
LL | | }
|
||||||
|
| |_____^ expected `!`, found `()`
|
||||||
|
|
|
||||||
|
= note: expected type `!`
|
||||||
|
found unit type `()`
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/diverging-place-match.rs:31:5
|
||||||
|
|
|
||||||
|
LL | / unsafe {
|
||||||
|
LL | |
|
||||||
|
LL | | let x: *const ! = 0 as _;
|
||||||
|
LL | | match *x { _ => {} };
|
||||||
|
LL | | }
|
||||||
|
| |_____^ expected `!`, found `()`
|
||||||
|
|
|
||||||
|
= note: expected type `!`
|
||||||
|
found unit type `()`
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/diverging-place-match.rs:39:5
|
||||||
|
|
|
||||||
|
LL | / unsafe {
|
||||||
|
LL | |
|
||||||
|
LL | | let x: *const (!, ()) = 0 as _;
|
||||||
|
LL | | let _ = (*x).0;
|
||||||
|
LL | | // ^ I think this is still UB, but because of the inbounds projection.
|
||||||
|
LL | | }
|
||||||
|
| |_____^ expected `!`, found `()`
|
||||||
|
|
|
||||||
|
= note: expected type `!`
|
||||||
|
found unit type `()`
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/diverging-place-match.rs:51:18
|
||||||
|
|
|
||||||
|
LL | let (_ | 1i32) = *x;
|
||||||
|
| ^^^^ -- this expression has type `!`
|
||||||
|
| |
|
||||||
|
| expected `!`, found `i32`
|
||||||
|
|
|
||||||
|
= note: expected type `!`
|
||||||
|
found type `i32`
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/diverging-place-match.rs:48:5
|
||||||
|
|
|
||||||
|
LL | / unsafe {
|
||||||
|
LL | |
|
||||||
|
LL | | let x: *const ! = 0 as _;
|
||||||
|
LL | | let (_ | 1i32) = *x;
|
||||||
|
LL | |
|
||||||
|
LL | | }
|
||||||
|
| |_____^ expected `!`, found `()`
|
||||||
|
|
|
||||||
|
= note: expected type `!`
|
||||||
|
found unit type `()`
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/diverging-place-match.rs:61:14
|
||||||
|
|
|
||||||
|
LL | let (1i32 | _) = *x;
|
||||||
|
| ^^^^ -- this expression has type `!`
|
||||||
|
| |
|
||||||
|
| expected `!`, found `i32`
|
||||||
|
|
|
||||||
|
= note: expected type `!`
|
||||||
|
found type `i32`
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/diverging-place-match.rs:58:5
|
||||||
|
|
|
||||||
|
LL | / unsafe {
|
||||||
|
LL | |
|
||||||
|
LL | | let x: *const ! = 0 as _;
|
||||||
|
LL | | let (1i32 | _) = *x;
|
||||||
|
LL | |
|
||||||
|
LL | | }
|
||||||
|
| |_____^ expected `!`, found `()`
|
||||||
|
|
|
||||||
|
= note: expected type `!`
|
||||||
|
found unit type `()`
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/diverging-place-match.rs:69:26
|
||||||
|
|
|
||||||
|
LL | let ref _x: () = *x;
|
||||||
|
| ^^ expected `()`, found `!`
|
||||||
|
|
|
||||||
|
= note: expected unit type `()`
|
||||||
|
found type `!`
|
||||||
|
|
||||||
|
error: aborting due to 11 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0308`.
|
@ -8,7 +8,9 @@ error: expected a pattern, found an expression
|
|||||||
--> $DIR/bad-name.rs:2:7
|
--> $DIR/bad-name.rs:2:7
|
||||||
|
|
|
|
||||||
LL | let x.y::<isize>.z foo;
|
LL | let x.y::<isize>.z foo;
|
||||||
| ^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^^^^^^^^^^ not a pattern
|
||||||
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
|
|
||||||
error: expected one of `(`, `.`, `::`, `:`, `;`, `=`, `?`, `|`, or an operator, found `foo`
|
error: expected one of `(`, `.`, `::`, `:`, `;`, `=`, `?`, `|`, or an operator, found `foo`
|
||||||
--> $DIR/bad-name.rs:2:22
|
--> $DIR/bad-name.rs:2:22
|
||||||
|
@ -2,7 +2,9 @@ error: expected a pattern, found an expression
|
|||||||
--> $DIR/issue-24197.rs:2:9
|
--> $DIR/issue-24197.rs:2:9
|
||||||
|
|
|
|
||||||
LL | let buf[0] = 0;
|
LL | let buf[0] = 0;
|
||||||
| ^^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^^ not a pattern
|
||||||
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
@ -2,8 +2,9 @@ error: expected a pattern, found an expression
|
|||||||
--> $DIR/issue-24375.rs:6:9
|
--> $DIR/issue-24375.rs:6:9
|
||||||
|
|
|
|
||||||
LL | tmp[0] => {}
|
LL | tmp[0] => {}
|
||||||
| ^^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^^ not a pattern
|
||||||
|
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
help: consider moving the expression to a match arm guard
|
help: consider moving the expression to a match arm guard
|
||||||
|
|
|
|
||||||
LL | val if val == tmp[0] => {}
|
LL | val if val == tmp[0] => {}
|
||||||
|
@ -2,7 +2,9 @@ error: expected a pattern, found an expression
|
|||||||
--> $DIR/pat-lt-bracket-5.rs:2:9
|
--> $DIR/pat-lt-bracket-5.rs:2:9
|
||||||
|
|
|
|
||||||
LL | let v[0] = v[1];
|
LL | let v[0] = v[1];
|
||||||
| ^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^ not a pattern
|
||||||
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
|
|
||||||
error[E0425]: cannot find value `v` in this scope
|
error[E0425]: cannot find value `v` in this scope
|
||||||
--> $DIR/pat-lt-bracket-5.rs:2:16
|
--> $DIR/pat-lt-bracket-5.rs:2:16
|
||||||
|
@ -2,7 +2,9 @@ error: expected a pattern, found an expression
|
|||||||
--> $DIR/pat-lt-bracket-6.rs:5:14
|
--> $DIR/pat-lt-bracket-6.rs:5:14
|
||||||
|
|
|
|
||||||
LL | let Test(&desc[..]) = x;
|
LL | let Test(&desc[..]) = x;
|
||||||
| ^^^^^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^^^^^ not a pattern
|
||||||
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/pat-lt-bracket-6.rs:10:30
|
--> $DIR/pat-lt-bracket-6.rs:10:30
|
||||||
|
@ -2,13 +2,17 @@ error: expected a pattern range bound, found an expression
|
|||||||
--> $DIR/pat-ranges-3.rs:4:16
|
--> $DIR/pat-ranges-3.rs:4:16
|
||||||
|
|
|
|
||||||
LL | let 10 ..= 10 + 3 = 12;
|
LL | let 10 ..= 10 + 3 = 12;
|
||||||
| ^^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^^ not a pattern
|
||||||
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
|
|
||||||
error: expected a pattern range bound, found an expression
|
error: expected a pattern range bound, found an expression
|
||||||
--> $DIR/pat-ranges-3.rs:7:9
|
--> $DIR/pat-ranges-3.rs:7:9
|
||||||
|
|
|
|
||||||
LL | let 10 - 3 ..= 10 = 8;
|
LL | let 10 - 3 ..= 10 = 8;
|
||||||
| ^^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^^ not a pattern
|
||||||
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
@ -2,8 +2,9 @@ error: expected a pattern, found an expression
|
|||||||
--> $DIR/recover-pat-exprs.rs:5:9
|
--> $DIR/recover-pat-exprs.rs:5:9
|
||||||
|
|
|
|
||||||
LL | x.y => (),
|
LL | x.y => (),
|
||||||
| ^^^ arbitrary expressions are not allowed in patterns
|
| ^^^ not a pattern
|
||||||
|
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
help: consider moving the expression to a match arm guard
|
help: consider moving the expression to a match arm guard
|
||||||
|
|
|
|
||||||
LL | val if val == x.y => (),
|
LL | val if val == x.y => (),
|
||||||
@ -24,8 +25,9 @@ error: expected a pattern, found an expression
|
|||||||
--> $DIR/recover-pat-exprs.rs:6:9
|
--> $DIR/recover-pat-exprs.rs:6:9
|
||||||
|
|
|
|
||||||
LL | x.0 => (),
|
LL | x.0 => (),
|
||||||
| ^^^ arbitrary expressions are not allowed in patterns
|
| ^^^ not a pattern
|
||||||
|
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
help: consider moving the expression to a match arm guard
|
help: consider moving the expression to a match arm guard
|
||||||
|
|
|
|
||||||
LL | val if val == x.0 => (),
|
LL | val if val == x.0 => (),
|
||||||
@ -47,8 +49,9 @@ error: expected a pattern, found an expression
|
|||||||
--> $DIR/recover-pat-exprs.rs:7:9
|
--> $DIR/recover-pat-exprs.rs:7:9
|
||||||
|
|
|
|
||||||
LL | x._0 => (),
|
LL | x._0 => (),
|
||||||
| ^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^ not a pattern
|
||||||
|
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
help: consider moving the expression to a match arm guard
|
help: consider moving the expression to a match arm guard
|
||||||
|
|
|
|
||||||
LL | val if val == x._0 => (),
|
LL | val if val == x._0 => (),
|
||||||
@ -71,8 +74,9 @@ error: expected a pattern, found an expression
|
|||||||
--> $DIR/recover-pat-exprs.rs:8:9
|
--> $DIR/recover-pat-exprs.rs:8:9
|
||||||
|
|
|
|
||||||
LL | x.0.1 => (),
|
LL | x.0.1 => (),
|
||||||
| ^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^ not a pattern
|
||||||
|
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
help: consider moving the expression to a match arm guard
|
help: consider moving the expression to a match arm guard
|
||||||
|
|
|
|
||||||
LL | val if val == x.0.1 => (),
|
LL | val if val == x.0.1 => (),
|
||||||
@ -95,8 +99,9 @@ error: expected a pattern, found an expression
|
|||||||
--> $DIR/recover-pat-exprs.rs:9:9
|
--> $DIR/recover-pat-exprs.rs:9:9
|
||||||
|
|
|
|
||||||
LL | x.4.y.17.__z => (),
|
LL | x.4.y.17.__z => (),
|
||||||
| ^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^^^^^^^^ not a pattern
|
||||||
|
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
help: consider moving the expression to a match arm guard
|
help: consider moving the expression to a match arm guard
|
||||||
|
|
|
|
||||||
LL | val if val == x.4.y.17.__z => (),
|
LL | val if val == x.4.y.17.__z => (),
|
||||||
@ -149,8 +154,9 @@ error: expected a pattern, found an expression
|
|||||||
--> $DIR/recover-pat-exprs.rs:23:9
|
--> $DIR/recover-pat-exprs.rs:23:9
|
||||||
|
|
|
|
||||||
LL | x[0] => (),
|
LL | x[0] => (),
|
||||||
| ^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^ not a pattern
|
||||||
|
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
help: consider moving the expression to a match arm guard
|
help: consider moving the expression to a match arm guard
|
||||||
|
|
|
|
||||||
LL | val if val == x[0] => (),
|
LL | val if val == x[0] => (),
|
||||||
@ -170,8 +176,9 @@ error: expected a pattern, found an expression
|
|||||||
--> $DIR/recover-pat-exprs.rs:24:9
|
--> $DIR/recover-pat-exprs.rs:24:9
|
||||||
|
|
|
|
||||||
LL | x[..] => (),
|
LL | x[..] => (),
|
||||||
| ^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^ not a pattern
|
||||||
|
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
help: consider moving the expression to a match arm guard
|
help: consider moving the expression to a match arm guard
|
||||||
|
|
|
|
||||||
LL | val if val == x[..] => (),
|
LL | val if val == x[..] => (),
|
||||||
@ -219,8 +226,9 @@ error: expected a pattern, found an expression
|
|||||||
--> $DIR/recover-pat-exprs.rs:37:9
|
--> $DIR/recover-pat-exprs.rs:37:9
|
||||||
|
|
|
|
||||||
LL | x.f() => (),
|
LL | x.f() => (),
|
||||||
| ^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^ not a pattern
|
||||||
|
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
help: consider moving the expression to a match arm guard
|
help: consider moving the expression to a match arm guard
|
||||||
|
|
|
|
||||||
LL | val if val == x.f() => (),
|
LL | val if val == x.f() => (),
|
||||||
@ -240,8 +248,9 @@ error: expected a pattern, found an expression
|
|||||||
--> $DIR/recover-pat-exprs.rs:38:9
|
--> $DIR/recover-pat-exprs.rs:38:9
|
||||||
|
|
|
|
||||||
LL | x._f() => (),
|
LL | x._f() => (),
|
||||||
| ^^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^^ not a pattern
|
||||||
|
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
help: consider moving the expression to a match arm guard
|
help: consider moving the expression to a match arm guard
|
||||||
|
|
|
|
||||||
LL | val if val == x._f() => (),
|
LL | val if val == x._f() => (),
|
||||||
@ -262,8 +271,9 @@ error: expected a pattern, found an expression
|
|||||||
--> $DIR/recover-pat-exprs.rs:39:9
|
--> $DIR/recover-pat-exprs.rs:39:9
|
||||||
|
|
|
|
||||||
LL | x? => (),
|
LL | x? => (),
|
||||||
| ^^ arbitrary expressions are not allowed in patterns
|
| ^^ not a pattern
|
||||||
|
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
help: consider moving the expression to a match arm guard
|
help: consider moving the expression to a match arm guard
|
||||||
|
|
|
|
||||||
LL | val if val == x? => (),
|
LL | val if val == x? => (),
|
||||||
@ -285,8 +295,9 @@ error: expected a pattern, found an expression
|
|||||||
--> $DIR/recover-pat-exprs.rs:40:9
|
--> $DIR/recover-pat-exprs.rs:40:9
|
||||||
|
|
|
|
||||||
LL | ().f() => (),
|
LL | ().f() => (),
|
||||||
| ^^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^^ not a pattern
|
||||||
|
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
help: consider moving the expression to a match arm guard
|
help: consider moving the expression to a match arm guard
|
||||||
|
|
|
|
||||||
LL | val if val == ().f() => (),
|
LL | val if val == ().f() => (),
|
||||||
@ -309,8 +320,9 @@ error: expected a pattern, found an expression
|
|||||||
--> $DIR/recover-pat-exprs.rs:41:9
|
--> $DIR/recover-pat-exprs.rs:41:9
|
||||||
|
|
|
|
||||||
LL | (0, x)?.f() => (),
|
LL | (0, x)?.f() => (),
|
||||||
| ^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^^^^^^^ not a pattern
|
||||||
|
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
help: consider moving the expression to a match arm guard
|
help: consider moving the expression to a match arm guard
|
||||||
|
|
|
|
||||||
LL | val if val == (0, x)?.f() => (),
|
LL | val if val == (0, x)?.f() => (),
|
||||||
@ -333,8 +345,9 @@ error: expected a pattern, found an expression
|
|||||||
--> $DIR/recover-pat-exprs.rs:42:9
|
--> $DIR/recover-pat-exprs.rs:42:9
|
||||||
|
|
|
|
||||||
LL | x.f().g() => (),
|
LL | x.f().g() => (),
|
||||||
| ^^^^^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^^^^^ not a pattern
|
||||||
|
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
help: consider moving the expression to a match arm guard
|
help: consider moving the expression to a match arm guard
|
||||||
|
|
|
|
||||||
LL | val if val == x.f().g() => (),
|
LL | val if val == x.f().g() => (),
|
||||||
@ -357,8 +370,9 @@ error: expected a pattern, found an expression
|
|||||||
--> $DIR/recover-pat-exprs.rs:43:9
|
--> $DIR/recover-pat-exprs.rs:43:9
|
||||||
|
|
|
|
||||||
LL | 0.f()?.g()?? => (),
|
LL | 0.f()?.g()?? => (),
|
||||||
| ^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^^^^^^^^ not a pattern
|
||||||
|
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
help: consider moving the expression to a match arm guard
|
help: consider moving the expression to a match arm guard
|
||||||
|
|
|
|
||||||
LL | val if val == 0.f()?.g()?? => (),
|
LL | val if val == 0.f()?.g()?? => (),
|
||||||
@ -381,8 +395,9 @@ error: expected a pattern, found an expression
|
|||||||
--> $DIR/recover-pat-exprs.rs:50:9
|
--> $DIR/recover-pat-exprs.rs:50:9
|
||||||
|
|
|
|
||||||
LL | x as usize => (),
|
LL | x as usize => (),
|
||||||
| ^^^^^^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^^^^^^ not a pattern
|
||||||
|
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
help: consider moving the expression to a match arm guard
|
help: consider moving the expression to a match arm guard
|
||||||
|
|
|
|
||||||
LL | val if val == x as usize => (),
|
LL | val if val == x as usize => (),
|
||||||
@ -402,8 +417,9 @@ error: expected a pattern, found an expression
|
|||||||
--> $DIR/recover-pat-exprs.rs:51:9
|
--> $DIR/recover-pat-exprs.rs:51:9
|
||||||
|
|
|
|
||||||
LL | 0 as usize => (),
|
LL | 0 as usize => (),
|
||||||
| ^^^^^^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^^^^^^ not a pattern
|
||||||
|
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
help: consider moving the expression to a match arm guard
|
help: consider moving the expression to a match arm guard
|
||||||
|
|
|
|
||||||
LL | val if val == 0 as usize => (),
|
LL | val if val == 0 as usize => (),
|
||||||
@ -424,8 +440,9 @@ error: expected a pattern, found an expression
|
|||||||
--> $DIR/recover-pat-exprs.rs:52:9
|
--> $DIR/recover-pat-exprs.rs:52:9
|
||||||
|
|
|
|
||||||
LL | x.f().0.4 as f32 => (),
|
LL | x.f().0.4 as f32 => (),
|
||||||
| ^^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^^^^^^^^^^^^ not a pattern
|
||||||
|
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
help: consider moving the expression to a match arm guard
|
help: consider moving the expression to a match arm guard
|
||||||
|
|
|
|
||||||
LL | val if val == x.f().0.4 as f32 => (),
|
LL | val if val == x.f().0.4 as f32 => (),
|
||||||
@ -447,8 +464,9 @@ error: expected a pattern, found an expression
|
|||||||
--> $DIR/recover-pat-exprs.rs:59:9
|
--> $DIR/recover-pat-exprs.rs:59:9
|
||||||
|
|
|
|
||||||
LL | 1 + 1 => (),
|
LL | 1 + 1 => (),
|
||||||
| ^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^ not a pattern
|
||||||
|
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
help: consider moving the expression to a match arm guard
|
help: consider moving the expression to a match arm guard
|
||||||
|
|
|
|
||||||
LL | val if val == 1 + 1 => (),
|
LL | val if val == 1 + 1 => (),
|
||||||
@ -468,8 +486,9 @@ error: expected a pattern, found an expression
|
|||||||
--> $DIR/recover-pat-exprs.rs:60:9
|
--> $DIR/recover-pat-exprs.rs:60:9
|
||||||
|
|
|
|
||||||
LL | (1 + 2) * 3 => (),
|
LL | (1 + 2) * 3 => (),
|
||||||
| ^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^^^^^^^ not a pattern
|
||||||
|
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
help: consider moving the expression to a match arm guard
|
help: consider moving the expression to a match arm guard
|
||||||
|
|
|
|
||||||
LL | val if val == (1 + 2) * 3 => (),
|
LL | val if val == (1 + 2) * 3 => (),
|
||||||
@ -490,8 +509,9 @@ error: expected a pattern, found an expression
|
|||||||
--> $DIR/recover-pat-exprs.rs:63:9
|
--> $DIR/recover-pat-exprs.rs:63:9
|
||||||
|
|
|
|
||||||
LL | x.0 > 2 => (),
|
LL | x.0 > 2 => (),
|
||||||
| ^^^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^^^ not a pattern
|
||||||
|
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
help: consider moving the expression to a match arm guard
|
help: consider moving the expression to a match arm guard
|
||||||
|
|
|
|
||||||
LL | val if val == (x.0 > 2) => (),
|
LL | val if val == (x.0 > 2) => (),
|
||||||
@ -514,8 +534,9 @@ error: expected a pattern, found an expression
|
|||||||
--> $DIR/recover-pat-exprs.rs:64:9
|
--> $DIR/recover-pat-exprs.rs:64:9
|
||||||
|
|
|
|
||||||
LL | x.0 == 2 => (),
|
LL | x.0 == 2 => (),
|
||||||
| ^^^^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^^^^ not a pattern
|
||||||
|
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
help: consider moving the expression to a match arm guard
|
help: consider moving the expression to a match arm guard
|
||||||
|
|
|
|
||||||
LL | val if val == (x.0 == 2) => (),
|
LL | val if val == (x.0 == 2) => (),
|
||||||
@ -538,8 +559,9 @@ error: expected a pattern, found an expression
|
|||||||
--> $DIR/recover-pat-exprs.rs:69:13
|
--> $DIR/recover-pat-exprs.rs:69:13
|
||||||
|
|
|
|
||||||
LL | (x, y.0 > 2) if x != 0 => (),
|
LL | (x, y.0 > 2) if x != 0 => (),
|
||||||
| ^^^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^^^ not a pattern
|
||||||
|
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
help: consider moving the expression to the match arm guard
|
help: consider moving the expression to the match arm guard
|
||||||
|
|
|
|
||||||
LL | (x, val) if x != 0 && val == (y.0 > 2) => (),
|
LL | (x, val) if x != 0 && val == (y.0 > 2) => (),
|
||||||
@ -559,8 +581,9 @@ error: expected a pattern, found an expression
|
|||||||
--> $DIR/recover-pat-exprs.rs:70:13
|
--> $DIR/recover-pat-exprs.rs:70:13
|
||||||
|
|
|
|
||||||
LL | (x, y.0 > 2) if x != 0 || x != 1 => (),
|
LL | (x, y.0 > 2) if x != 0 || x != 1 => (),
|
||||||
| ^^^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^^^ not a pattern
|
||||||
|
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
help: consider moving the expression to the match arm guard
|
help: consider moving the expression to the match arm guard
|
||||||
|
|
|
|
||||||
LL | (x, val) if (x != 0 || x != 1) && val == (y.0 > 2) => (),
|
LL | (x, val) if (x != 0 || x != 1) && val == (y.0 > 2) => (),
|
||||||
@ -598,8 +621,9 @@ error: expected a pattern, found an expression
|
|||||||
--> $DIR/recover-pat-exprs.rs:81:9
|
--> $DIR/recover-pat-exprs.rs:81:9
|
||||||
|
|
|
|
||||||
LL | u8::MAX.abs() => (),
|
LL | u8::MAX.abs() => (),
|
||||||
| ^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^^^^^^^^^ not a pattern
|
||||||
|
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
help: consider moving the expression to a match arm guard
|
help: consider moving the expression to a match arm guard
|
||||||
|
|
|
|
||||||
LL | val if val == u8::MAX.abs() => (),
|
LL | val if val == u8::MAX.abs() => (),
|
||||||
@ -619,8 +643,9 @@ error: expected a pattern, found an expression
|
|||||||
--> $DIR/recover-pat-exprs.rs:86:17
|
--> $DIR/recover-pat-exprs.rs:86:17
|
||||||
|
|
|
|
||||||
LL | z @ w @ v.u() => (),
|
LL | z @ w @ v.u() => (),
|
||||||
| ^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^ not a pattern
|
||||||
|
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
help: consider moving the expression to a match arm guard
|
help: consider moving the expression to a match arm guard
|
||||||
|
|
|
|
||||||
LL | z @ w @ val if val == v.u() => (),
|
LL | z @ w @ val if val == v.u() => (),
|
||||||
@ -643,8 +668,9 @@ error: expected a pattern, found an expression
|
|||||||
--> $DIR/recover-pat-exprs.rs:88:9
|
--> $DIR/recover-pat-exprs.rs:88:9
|
||||||
|
|
|
|
||||||
LL | y.ilog(3) => (),
|
LL | y.ilog(3) => (),
|
||||||
| ^^^^^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^^^^^ not a pattern
|
||||||
|
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
help: consider moving the expression to a match arm guard
|
help: consider moving the expression to a match arm guard
|
||||||
|
|
|
|
||||||
LL | val if val == y.ilog(3) => (),
|
LL | val if val == y.ilog(3) => (),
|
||||||
@ -667,8 +693,9 @@ error: expected a pattern, found an expression
|
|||||||
--> $DIR/recover-pat-exprs.rs:90:9
|
--> $DIR/recover-pat-exprs.rs:90:9
|
||||||
|
|
|
|
||||||
LL | n + 1 => (),
|
LL | n + 1 => (),
|
||||||
| ^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^ not a pattern
|
||||||
|
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
help: consider moving the expression to a match arm guard
|
help: consider moving the expression to a match arm guard
|
||||||
|
|
|
|
||||||
LL | val if val == n + 1 => (),
|
LL | val if val == n + 1 => (),
|
||||||
@ -691,8 +718,9 @@ error: expected a pattern, found an expression
|
|||||||
--> $DIR/recover-pat-exprs.rs:92:10
|
--> $DIR/recover-pat-exprs.rs:92:10
|
||||||
|
|
|
|
||||||
LL | ("".f() + 14 * 8) => (),
|
LL | ("".f() + 14 * 8) => (),
|
||||||
| ^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^^^^^^^^^^^ not a pattern
|
||||||
|
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
help: consider moving the expression to a match arm guard
|
help: consider moving the expression to a match arm guard
|
||||||
|
|
|
|
||||||
LL | (val) if val == "".f() + 14 * 8 => (),
|
LL | (val) if val == "".f() + 14 * 8 => (),
|
||||||
@ -715,8 +743,9 @@ error: expected a pattern, found an expression
|
|||||||
--> $DIR/recover-pat-exprs.rs:95:9
|
--> $DIR/recover-pat-exprs.rs:95:9
|
||||||
|
|
|
|
||||||
LL | f?() => (),
|
LL | f?() => (),
|
||||||
| ^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^ not a pattern
|
||||||
|
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
help: consider moving the expression to a match arm guard
|
help: consider moving the expression to a match arm guard
|
||||||
|
|
|
|
||||||
LL | val if val == f?() => (),
|
LL | val if val == f?() => (),
|
||||||
@ -739,7 +768,9 @@ error: expected a pattern, found an expression
|
|||||||
--> $DIR/recover-pat-exprs.rs:101:9
|
--> $DIR/recover-pat-exprs.rs:101:9
|
||||||
|
|
|
|
||||||
LL | let 1 + 1 = 2;
|
LL | let 1 + 1 = 2;
|
||||||
| ^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^ not a pattern
|
||||||
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
|
|
||||||
error: expected one of `)`, `,`, `@`, or `|`, found `*`
|
error: expected one of `)`, `,`, `@`, or `|`, found `*`
|
||||||
--> $DIR/recover-pat-exprs.rs:104:28
|
--> $DIR/recover-pat-exprs.rs:104:28
|
||||||
@ -754,19 +785,25 @@ error: expected a pattern, found an expression
|
|||||||
--> $DIR/recover-pat-exprs.rs:60:10
|
--> $DIR/recover-pat-exprs.rs:60:10
|
||||||
|
|
|
|
||||||
LL | (1 + 2) * 3 => (),
|
LL | (1 + 2) * 3 => (),
|
||||||
| ^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^ not a pattern
|
||||||
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
|
|
||||||
error: expected a pattern, found an expression
|
error: expected a pattern, found an expression
|
||||||
--> $DIR/recover-pat-exprs.rs:75:5
|
--> $DIR/recover-pat-exprs.rs:75:5
|
||||||
|
|
|
|
||||||
LL | 1 + 2 * PI.cos() => 2,
|
LL | 1 + 2 * PI.cos() => 2,
|
||||||
| ^^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^^^^^^^^^^^^ not a pattern
|
||||||
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
|
|
||||||
error: expected a pattern, found an expression
|
error: expected a pattern, found an expression
|
||||||
--> $DIR/recover-pat-exprs.rs:83:9
|
--> $DIR/recover-pat-exprs.rs:83:9
|
||||||
|
|
|
|
||||||
LL | x.sqrt() @ .. => (),
|
LL | x.sqrt() @ .. => (),
|
||||||
| ^^^^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^^^^ not a pattern
|
||||||
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
|
|
||||||
error: aborting due to 45 previous errors
|
error: aborting due to 45 previous errors
|
||||||
|
|
||||||
|
@ -2,8 +2,9 @@ error: expected a pattern, found an expression
|
|||||||
--> $DIR/recover-pat-issues.rs:6:13
|
--> $DIR/recover-pat-issues.rs:6:13
|
||||||
|
|
|
|
||||||
LL | Foo("hi".to_owned()) => true,
|
LL | Foo("hi".to_owned()) => true,
|
||||||
| ^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^^^^^^^^^^^ not a pattern
|
||||||
|
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
help: consider moving the expression to a match arm guard
|
help: consider moving the expression to a match arm guard
|
||||||
|
|
|
|
||||||
LL | Foo(val) if val == "hi".to_owned() => true,
|
LL | Foo(val) if val == "hi".to_owned() => true,
|
||||||
@ -23,8 +24,9 @@ error: expected a pattern, found an expression
|
|||||||
--> $DIR/recover-pat-issues.rs:14:20
|
--> $DIR/recover-pat-issues.rs:14:20
|
||||||
|
|
|
|
||||||
LL | Bar { baz: "hi".to_owned() } => true,
|
LL | Bar { baz: "hi".to_owned() } => true,
|
||||||
| ^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^^^^^^^^^^^ not a pattern
|
||||||
|
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
help: consider moving the expression to a match arm guard
|
help: consider moving the expression to a match arm guard
|
||||||
|
|
|
|
||||||
LL | Bar { baz } if baz == "hi".to_owned() => true,
|
LL | Bar { baz } if baz == "hi".to_owned() => true,
|
||||||
@ -44,8 +46,9 @@ error: expected a pattern, found an expression
|
|||||||
--> $DIR/recover-pat-issues.rs:25:11
|
--> $DIR/recover-pat-issues.rs:25:11
|
||||||
|
|
|
|
||||||
LL | &["foo".to_string()] => {}
|
LL | &["foo".to_string()] => {}
|
||||||
| ^^^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^^^^^^^^^^^^^ not a pattern
|
||||||
|
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
help: consider moving the expression to a match arm guard
|
help: consider moving the expression to a match arm guard
|
||||||
|
|
|
|
||||||
LL | &[val] if val == "foo".to_string() => {}
|
LL | &[val] if val == "foo".to_string() => {}
|
||||||
@ -65,8 +68,9 @@ error: expected a pattern, found an expression
|
|||||||
--> $DIR/recover-pat-issues.rs:36:17
|
--> $DIR/recover-pat-issues.rs:36:17
|
||||||
|
|
|
|
||||||
LL | if let Some(MAGIC.0 as usize) = None::<usize> {}
|
LL | if let Some(MAGIC.0 as usize) = None::<usize> {}
|
||||||
| ^^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^^^^^^^^^^^^ not a pattern
|
||||||
|
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
help: consider extracting the expression into a `const`
|
help: consider extracting the expression into a `const`
|
||||||
|
|
|
|
||||||
LL + const VAL: /* Type */ = MAGIC.0 as usize;
|
LL + const VAL: /* Type */ = MAGIC.0 as usize;
|
||||||
@ -81,8 +85,9 @@ error: expected a pattern, found an expression
|
|||||||
--> $DIR/recover-pat-issues.rs:41:13
|
--> $DIR/recover-pat-issues.rs:41:13
|
||||||
|
|
|
|
||||||
LL | if let (-1.some(4)) = (0, Some(4)) {}
|
LL | if let (-1.some(4)) = (0, Some(4)) {}
|
||||||
| ^^^^^^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^^^^^^ not a pattern
|
||||||
|
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
help: consider extracting the expression into a `const`
|
help: consider extracting the expression into a `const`
|
||||||
|
|
|
|
||||||
LL + const VAL: /* Type */ = -1.some(4);
|
LL + const VAL: /* Type */ = -1.some(4);
|
||||||
@ -97,8 +102,9 @@ error: expected a pattern, found an expression
|
|||||||
--> $DIR/recover-pat-issues.rs:44:13
|
--> $DIR/recover-pat-issues.rs:44:13
|
||||||
|
|
|
|
||||||
LL | if let (-1.Some(4)) = (0, Some(4)) {}
|
LL | if let (-1.Some(4)) = (0, Some(4)) {}
|
||||||
| ^^^^^^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^^^^^^ not a pattern
|
||||||
|
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
help: consider extracting the expression into a `const`
|
help: consider extracting the expression into a `const`
|
||||||
|
|
|
|
||||||
LL + const VAL: /* Type */ = -1.Some(4);
|
LL + const VAL: /* Type */ = -1.Some(4);
|
||||||
|
@ -2,26 +2,33 @@ error: expected a pattern, found an expression
|
|||||||
--> $DIR/recover-pat-lets.rs:4:9
|
--> $DIR/recover-pat-lets.rs:4:9
|
||||||
|
|
|
|
||||||
LL | let x.expect("foo");
|
LL | let x.expect("foo");
|
||||||
| ^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^^^^^^^^^^^ not a pattern
|
||||||
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
|
|
||||||
error: expected a pattern, found an expression
|
error: expected a pattern, found an expression
|
||||||
--> $DIR/recover-pat-lets.rs:7:9
|
--> $DIR/recover-pat-lets.rs:7:9
|
||||||
|
|
|
|
||||||
LL | let x.unwrap(): u32;
|
LL | let x.unwrap(): u32;
|
||||||
| ^^^^^^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^^^^^^ not a pattern
|
||||||
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
|
|
||||||
error: expected a pattern, found an expression
|
error: expected a pattern, found an expression
|
||||||
--> $DIR/recover-pat-lets.rs:10:9
|
--> $DIR/recover-pat-lets.rs:10:9
|
||||||
|
|
|
|
||||||
LL | let x[0] = 1;
|
LL | let x[0] = 1;
|
||||||
| ^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^ not a pattern
|
||||||
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
|
|
||||||
error: expected a pattern, found an expression
|
error: expected a pattern, found an expression
|
||||||
--> $DIR/recover-pat-lets.rs:13:14
|
--> $DIR/recover-pat-lets.rs:13:14
|
||||||
|
|
|
|
||||||
LL | let Some(1 + 1) = x else {
|
LL | let Some(1 + 1) = x else {
|
||||||
| ^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^ not a pattern
|
||||||
|
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
help: consider extracting the expression into a `const`
|
help: consider extracting the expression into a `const`
|
||||||
|
|
|
|
||||||
LL + const VAL: /* Type */ = 1 + 1;
|
LL + const VAL: /* Type */ = 1 + 1;
|
||||||
@ -36,8 +43,9 @@ error: expected a pattern, found an expression
|
|||||||
--> $DIR/recover-pat-lets.rs:17:17
|
--> $DIR/recover-pat-lets.rs:17:17
|
||||||
|
|
|
|
||||||
LL | if let Some(1 + 1) = x {
|
LL | if let Some(1 + 1) = x {
|
||||||
| ^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^ not a pattern
|
||||||
|
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
help: consider extracting the expression into a `const`
|
help: consider extracting the expression into a `const`
|
||||||
|
|
|
|
||||||
LL + const VAL: /* Type */ = 1 + 1;
|
LL + const VAL: /* Type */ = 1 + 1;
|
||||||
|
@ -86,8 +86,9 @@ error: expected a pattern range bound, found an expression
|
|||||||
--> $DIR/recover-pat-ranges.rs:11:12
|
--> $DIR/recover-pat-ranges.rs:11:12
|
||||||
|
|
|
|
||||||
LL | ..=1 + 2 => (),
|
LL | ..=1 + 2 => (),
|
||||||
| ^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^ not a pattern
|
||||||
|
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
help: consider extracting the expression into a `const`
|
help: consider extracting the expression into a `const`
|
||||||
|
|
|
|
||||||
LL + const VAL: /* Type */ = 1 + 2;
|
LL + const VAL: /* Type */ = 1 + 2;
|
||||||
@ -106,8 +107,9 @@ error: expected a pattern range bound, found an expression
|
|||||||
--> $DIR/recover-pat-ranges.rs:15:10
|
--> $DIR/recover-pat-ranges.rs:15:10
|
||||||
|
|
|
|
||||||
LL | (-4 + 0).. => (),
|
LL | (-4 + 0).. => (),
|
||||||
| ^^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^^ not a pattern
|
||||||
|
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
help: consider extracting the expression into a `const`
|
help: consider extracting the expression into a `const`
|
||||||
|
|
|
|
||||||
LL + const VAL: /* Type */ = -4 + 0;
|
LL + const VAL: /* Type */ = -4 + 0;
|
||||||
@ -126,8 +128,9 @@ error: expected a pattern range bound, found an expression
|
|||||||
--> $DIR/recover-pat-ranges.rs:18:10
|
--> $DIR/recover-pat-ranges.rs:18:10
|
||||||
|
|
|
|
||||||
LL | (1 + 4)...1 * 2 => (),
|
LL | (1 + 4)...1 * 2 => (),
|
||||||
| ^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^ not a pattern
|
||||||
|
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
help: consider extracting the expression into a `const`
|
help: consider extracting the expression into a `const`
|
||||||
|
|
|
|
||||||
LL + const VAL: /* Type */ = 1 + 4;
|
LL + const VAL: /* Type */ = 1 + 4;
|
||||||
@ -146,8 +149,9 @@ error: expected a pattern range bound, found an expression
|
|||||||
--> $DIR/recover-pat-ranges.rs:18:19
|
--> $DIR/recover-pat-ranges.rs:18:19
|
||||||
|
|
|
|
||||||
LL | (1 + 4)...1 * 2 => (),
|
LL | (1 + 4)...1 * 2 => (),
|
||||||
| ^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^ not a pattern
|
||||||
|
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
help: consider extracting the expression into a `const`
|
help: consider extracting the expression into a `const`
|
||||||
|
|
|
|
||||||
LL + const VAL: /* Type */ = 1 * 2;
|
LL + const VAL: /* Type */ = 1 * 2;
|
||||||
@ -166,8 +170,9 @@ error: expected a pattern range bound, found an expression
|
|||||||
--> $DIR/recover-pat-ranges.rs:24:9
|
--> $DIR/recover-pat-ranges.rs:24:9
|
||||||
|
|
|
|
||||||
LL | 0.x()..="y".z() => (),
|
LL | 0.x()..="y".z() => (),
|
||||||
| ^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^ not a pattern
|
||||||
|
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
help: consider extracting the expression into a `const`
|
help: consider extracting the expression into a `const`
|
||||||
|
|
|
|
||||||
LL + const VAL: /* Type */ = 0.x();
|
LL + const VAL: /* Type */ = 0.x();
|
||||||
@ -186,8 +191,9 @@ error: expected a pattern range bound, found an expression
|
|||||||
--> $DIR/recover-pat-ranges.rs:24:17
|
--> $DIR/recover-pat-ranges.rs:24:17
|
||||||
|
|
|
|
||||||
LL | 0.x()..="y".z() => (),
|
LL | 0.x()..="y".z() => (),
|
||||||
| ^^^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^^^ not a pattern
|
||||||
|
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
help: consider extracting the expression into a `const`
|
help: consider extracting the expression into a `const`
|
||||||
|
|
|
|
||||||
LL + const VAL: /* Type */ = "y".z();
|
LL + const VAL: /* Type */ = "y".z();
|
||||||
|
@ -75,8 +75,9 @@ error: expected a pattern range bound, found an expression
|
|||||||
--> $DIR/recover-pat-wildcards.rs:55:14
|
--> $DIR/recover-pat-wildcards.rs:55:14
|
||||||
|
|
|
|
||||||
LL | 4..=(2 + _) => ()
|
LL | 4..=(2 + _) => ()
|
||||||
| ^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^ not a pattern
|
||||||
|
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
help: consider extracting the expression into a `const`
|
help: consider extracting the expression into a `const`
|
||||||
|
|
|
|
||||||
LL + const VAL: /* Type */ = 2 + _;
|
LL + const VAL: /* Type */ = 2 + _;
|
||||||
|
22
tests/ui/raw-ref-op/never-place-isnt-diverging.rs
Normal file
22
tests/ui/raw-ref-op/never-place-isnt-diverging.rs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#![feature(never_type)]
|
||||||
|
|
||||||
|
fn make_up_a_value<T>() -> T {
|
||||||
|
unsafe {
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
let x: *const ! = 0 as _;
|
||||||
|
&raw const *x;
|
||||||
|
// Since `*x` is `!`, HIR typeck used to think that it diverges
|
||||||
|
// and allowed the block to coerce to any value, leading to UB.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn make_up_a_pointer<T>() -> *const T {
|
||||||
|
unsafe {
|
||||||
|
let x: *const ! = 0 as _;
|
||||||
|
&raw const *x
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
34
tests/ui/raw-ref-op/never-place-isnt-diverging.stderr
Normal file
34
tests/ui/raw-ref-op/never-place-isnt-diverging.stderr
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/never-place-isnt-diverging.rs:4:5
|
||||||
|
|
|
||||||
|
LL | fn make_up_a_value<T>() -> T {
|
||||||
|
| - expected this type parameter
|
||||||
|
LL | / unsafe {
|
||||||
|
LL | |
|
||||||
|
LL | | let x: *const ! = 0 as _;
|
||||||
|
LL | | &raw const *x;
|
||||||
|
LL | | // Since `*x` is `!`, HIR typeck used to think that it diverges
|
||||||
|
LL | | // and allowed the block to coerce to any value, leading to UB.
|
||||||
|
LL | | }
|
||||||
|
| |_____^ expected type parameter `T`, found `()`
|
||||||
|
|
|
||||||
|
= note: expected type parameter `T`
|
||||||
|
found unit type `()`
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/never-place-isnt-diverging.rs:17:9
|
||||||
|
|
|
||||||
|
LL | fn make_up_a_pointer<T>() -> *const T {
|
||||||
|
| - -------- expected `*const T` because of return type
|
||||||
|
| |
|
||||||
|
| expected this type parameter
|
||||||
|
...
|
||||||
|
LL | &raw const *x
|
||||||
|
| ^^^^^^^^^^^^^ expected `*const T`, found `*const !`
|
||||||
|
|
|
||||||
|
= note: expected raw pointer `*const T`
|
||||||
|
found raw pointer `*const !`
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0308`.
|
@ -14,12 +14,13 @@ LL | #![deny(unreachable_code)]
|
|||||||
| ^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: unreachable expression
|
error: unreachable expression
|
||||||
--> $DIR/expr_assign.rs:20:14
|
--> $DIR/expr_assign.rs:20:9
|
||||||
|
|
|
|
||||||
LL | *p = return;
|
LL | *p = return;
|
||||||
| -- ^^^^^^ unreachable expression
|
| ^^^^^------
|
||||||
| |
|
| | |
|
||||||
| any code following this expression is unreachable
|
| | any code following this expression is unreachable
|
||||||
|
| unreachable expression
|
||||||
|
|
||||||
error: unreachable expression
|
error: unreachable expression
|
||||||
--> $DIR/expr_assign.rs:26:15
|
--> $DIR/expr_assign.rs:26:15
|
||||||
|
@ -3,7 +3,7 @@ fn foo(_: usize) -> Foo { Foo(false) }
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
match Foo(true) {
|
match Foo(true) {
|
||||||
foo(x) //~ ERROR expected tuple struct or tuple variant, found function `foo`
|
foo(x) //~ ERROR expected a pattern, found a function call
|
||||||
=> ()
|
=> ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
error[E0532]: expected tuple struct or tuple variant, found function `foo`
|
error[E0532]: expected a pattern, found a function call
|
||||||
--> $DIR/issue-10200.rs:6:9
|
--> $DIR/issue-10200.rs:6:9
|
||||||
|
|
|
|
||||||
LL | struct Foo(bool);
|
LL | struct Foo(bool);
|
||||||
@ -6,6 +6,8 @@ LL | struct Foo(bool);
|
|||||||
...
|
...
|
||||||
LL | foo(x)
|
LL | foo(x)
|
||||||
| ^^^ help: a tuple struct with a similar name exists (notice the capitalization): `Foo`
|
| ^^^ help: a tuple struct with a similar name exists (notice the capitalization): `Foo`
|
||||||
|
|
|
||||||
|
= note: function calls are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
@ -2,7 +2,9 @@ error: expected a pattern, found an expression
|
|||||||
--> $DIR/ensure-overriding-bindings-in-pattern-with-ty-err-doesnt-ice.rs:2:31
|
--> $DIR/ensure-overriding-bindings-in-pattern-with-ty-err-doesnt-ice.rs:2:31
|
||||||
|
|
|
|
||||||
LL | let str::<{fn str() { let str::T>>::as_bytes; }}, T>::as_bytes;
|
LL | let str::<{fn str() { let str::T>>::as_bytes; }}, T>::as_bytes;
|
||||||
| ^^^^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
|
| ^^^^^^^^^^^^^^^^^^ not a pattern
|
||||||
|
|
|
||||||
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
|
||||||
|
|
||||||
error[E0412]: cannot find type `T` in this scope
|
error[E0412]: cannot find type `T` in this scope
|
||||||
--> $DIR/ensure-overriding-bindings-in-pattern-with-ty-err-doesnt-ice.rs:2:55
|
--> $DIR/ensure-overriding-bindings-in-pattern-with-ty-err-doesnt-ice.rs:2:55
|
||||||
|
Loading…
Reference in New Issue
Block a user