Skip to content

Diverging tyvars #85558

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
@@ -1275,6 +1275,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}
}

/// Returns `false` if all non-auxiliary type variables unified with
/// `vid` is diverging. Returns `true` otherwise.
pub fn probe_ty_diverging(&self, vid: TyVid) -> bool {
let mut inner = self.inner.borrow_mut();
inner.type_variables().var_diverges_with_unification(vid)
}

/// Resolve any type variables found in `value` -- but only one
/// level. So, if the variable `?X` is bound to some type
/// `Foo<?Y>`, then this would return `Foo<?Y>` (but `?Y` may
108 changes: 100 additions & 8 deletions compiler/rustc_infer/src/infer/type_variable.rs
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@ use rustc_data_structures::undo_log::{Rollback, UndoLogs};
/// Represents a single undo-able action that affects a type inference variable.
pub(crate) enum UndoLog<'tcx> {
EqRelation(sv::UndoLog<ut::Delegate<TyVidEqKey<'tcx>>>),
SubRelation(sv::UndoLog<ut::Delegate<ty::TyVid>>),
SubRelation(sv::UndoLog<ut::Delegate<TyVidSubKey>>),
Values(sv::UndoLog<Delegate>),
}

@@ -28,8 +28,8 @@ impl<'tcx> From<sv::UndoLog<ut::Delegate<TyVidEqKey<'tcx>>>> for UndoLog<'tcx> {
}

/// Convert from a specific kind of undo to the more general UndoLog
impl<'tcx> From<sv::UndoLog<ut::Delegate<ty::TyVid>>> for UndoLog<'tcx> {
fn from(l: sv::UndoLog<ut::Delegate<ty::TyVid>>) -> Self {
impl<'tcx> From<sv::UndoLog<ut::Delegate<TyVidSubKey>>> for UndoLog<'tcx> {
fn from(l: sv::UndoLog<ut::Delegate<TyVidSubKey>>) -> Self {
UndoLog::SubRelation(l)
}
}
@@ -83,7 +83,7 @@ pub struct TypeVariableStorage<'tcx> {
/// This is reasonable because, in Rust, subtypes have the same
/// "skeleton" and hence there is no possible type such that
/// (e.g.) `Box<?3> <: ?3` for any `?3`.
sub_relations: ut::UnificationTableStorage<ty::TyVid>,
sub_relations: ut::UnificationTableStorage<TyVidSubKey>,
}

pub struct TypeVariableTable<'a, 'tcx> {
@@ -169,6 +169,16 @@ impl<'tcx> TypeVariableStorage<'tcx> {
}

impl<'tcx> TypeVariableTable<'_, 'tcx> {
/// Returns `false` if all non-auxiliary type variables unified with
/// `vid` is diverging. Returns `true` otherwise.
///
/// Precondition: `vid` should be unknown.
pub fn var_diverges_with_unification(&mut self, vid: ty::TyVid) -> bool {
debug_assert!(self.probe(vid).is_unknown());
let kind = self.sub_relations().inlined_probe_value(vid);
matches!(kind, TyVarUnifiedDiverging::Yes)
}

/// Returns the diverges flag given when `vid` was created.
///
/// Note that this function does not return care whether
@@ -243,8 +253,9 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
) -> ty::TyVid {
let eq_key = self.eq_relations().new_key(TypeVariableValue::Unknown { universe });

let sub_key = self.sub_relations().new_key(());
assert_eq!(eq_key.vid, sub_key);
let diverging_kind = TyVarUnifiedDiverging::from(diverging, origin.kind);
let sub_key = self.sub_relations().new_key(diverging_kind);
assert_eq!(eq_key.vid, sub_key.vid);

let index = self.values().push(TypeVariableData { origin, diverging });
assert_eq!(eq_key.vid.index, index as u32);
@@ -279,7 +290,7 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
///
/// exists X. (a <: X || X <: a) && (b <: X || X <: b)
pub fn sub_root_var(&mut self, vid: ty::TyVid) -> ty::TyVid {
self.sub_relations().find(vid)
self.sub_relations().find(vid).vid
}

/// Returns `true` if `a` and `b` have same "sub-root" (i.e., exists some
@@ -326,7 +337,7 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
}

#[inline]
fn sub_relations(&mut self) -> super::UnificationTable<'_, 'tcx, ty::TyVid> {
fn sub_relations(&mut self) -> super::UnificationTable<'_, 'tcx, TyVidSubKey> {
self.storage.sub_relations.with_log(self.undo_log)
}

@@ -443,3 +454,84 @@ impl<'tcx> ut::UnifyValue for TypeVariableValue<'tcx> {
}
}
}

///////////////////////////////////////////////////////////////////////////

/// These structs (a newtyped TyVid) are used as the unification key
/// for the `sub_relations`; they carry a `TyVarUnifiedDiverging`
/// along with them.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub(crate) struct TyVidSubKey {
vid: ty::TyVid,
}

/// This enum denotes whether unified type variables are all diverging
/// variables. Note auxiliary type variables (guessed with the help of
/// `TypeVariableOriginKind`) should be ignored.
#[derive(Copy, Clone, Debug)]
pub enum TyVarUnifiedDiverging {
/// All unified type variables are diverging.
Yes,
/// Some unified type variable are not diverging.
No,
/// We don't know the final result at all because we haven't seen
/// any non-auxiliary type variables yet.
Maybe,
}

impl From<ty::TyVid> for TyVidSubKey {
fn from(vid: ty::TyVid) -> Self {
TyVidSubKey { vid }
}
}

impl ut::UnifyKey for TyVidSubKey {
type Value = TyVarUnifiedDiverging;
fn index(&self) -> u32 {
self.vid.index
}
fn from_index(i: u32) -> Self {
TyVidSubKey::from(ty::TyVid { index: i })
}
fn tag() -> &'static str {
"TyVidSubKey"
}
}

impl ut::UnifyValue for TyVarUnifiedDiverging {
type Error = ut::NoError;

fn unify_values(value1: &Self, value2: &Self) -> Result<Self, ut::NoError> {
match (*value1, *value2) {
// Auxiliary type variables should be ignored.
(TyVarUnifiedDiverging::Maybe, other) => Ok(other),
(other, TyVarUnifiedDiverging::Maybe) => Ok(other),

// We've found some non-diverging type variables.
(TyVarUnifiedDiverging::No, _) => Ok(TyVarUnifiedDiverging::No),
(_, TyVarUnifiedDiverging::No) => Ok(TyVarUnifiedDiverging::No),

// All type variables are diverging yet.
(TyVarUnifiedDiverging::Yes, TyVarUnifiedDiverging::Yes) => {
Ok(TyVarUnifiedDiverging::Yes)
}
}
}
}

impl TyVarUnifiedDiverging {
#[inline]
fn from(diverging: bool, origin: TypeVariableOriginKind) -> Self {
if diverging {
return TyVarUnifiedDiverging::Yes;
}

// FIXME: Is it a complete list? Probably not.
match origin {
TypeVariableOriginKind::MiscVariable | TypeVariableOriginKind::LatticeVariable => {
TyVarUnifiedDiverging::Maybe
}
_ => TyVarUnifiedDiverging::No,
}
}
}
2 changes: 1 addition & 1 deletion compiler/rustc_infer/src/infer/undo_log.rs
Original file line number Diff line number Diff line change
@@ -46,7 +46,7 @@ impl_from! {
TypeVariables(type_variable::UndoLog<'tcx>),

TypeVariables(sv::UndoLog<ut::Delegate<type_variable::TyVidEqKey<'tcx>>>),
TypeVariables(sv::UndoLog<ut::Delegate<ty::TyVid>>),
TypeVariables(sv::UndoLog<ut::Delegate<type_variable::TyVidSubKey>>),
TypeVariables(sv::UndoLog<type_variable::Delegate>),
TypeVariables(type_variable::Instantiate),

6 changes: 5 additions & 1 deletion compiler/rustc_typeck/src/check/_match.rs
Original file line number Diff line number Diff line change
@@ -555,7 +555,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let Some(m) = contains_ref_bindings {
self.check_expr_with_needs(scrut, Needs::maybe_mut_place(m))
} else if no_arms {
self.check_expr(scrut)
// The hint for never type is a little hacky, but it will make
// `match never {}` work even without `never_type_fallback`.
// We can remove it once the feature `never_type_fallback` gets
// stabilized.
self.check_expr_with_hint(scrut, self.tcx.types.never)
} else {
// ...but otherwise we want to use any supertype of the
// scrutinee. This is sort of a workaround, see note (*) in
13 changes: 9 additions & 4 deletions compiler/rustc_typeck/src/check/coercion.rs
Original file line number Diff line number Diff line change
@@ -1022,8 +1022,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

// First try to coerce the new expression to the type of the previous ones,
// but only if the new expression has no coercion already applied to it.
let mut first_error = None;
if !self.typeck_results.borrow().adjustments().contains_key(new.hir_id) {
let first_try = match self.typeck_results.borrow().expr_adjustments(new) {
&[] | &[Adjustment { kind: Adjust::NeverToAny, .. }] => true,
_ => false,
};
let first_error = if first_try {
let result = self.commit_if_ok(|_| coerce.coerce(new_ty, prev_ty));
match result {
Ok(ok) => {
@@ -1035,9 +1038,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
return Ok(target);
}
Err(e) => first_error = Some(e),
Err(e) => Some(e),
}
}
} else {
None
};

// Then try to coerce the previous expressions to the type of the new one.
// This requires ensuring there are no coercions applied to *any* of the
58 changes: 38 additions & 20 deletions compiler/rustc_typeck/src/check/expr.rs
Original file line number Diff line number Diff line change
@@ -68,25 +68,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
extend_err: impl Fn(&mut DiagnosticBuilder<'_>),
) -> Ty<'tcx> {
let expected_ty = expected.to_option(&self).unwrap_or(self.tcx.types.bool);
let mut ty = self.check_expr_with_expectation(expr, expected);

// While we don't allow *arbitrary* coercions here, we *do* allow
// coercions from ! to `expected`.
if ty.is_never() {
assert!(
!self.typeck_results.borrow().adjustments().contains_key(expr.hir_id),
"expression with never type wound up being adjusted"
);
let adj_ty = self.next_diverging_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::AdjustmentType,
span: expr.span,
});
self.apply_adjustments(
expr,
vec![Adjustment { kind: Adjust::NeverToAny, target: adj_ty }],
);
ty = adj_ty;
}
let ty = self.check_expr_with_expectation(expr, expected);

if let Some(mut err) = self.demand_suptype_diag(expr.span, expected_ty, ty) {
let expr = expr.peel_drop_temps();
@@ -216,7 +198,43 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
debug!("type of {} is...", self.tcx.hir().node_to_string(expr.hir_id));
debug!("... {:?}, expected is {:?}", ty, expected);

ty
// Convert the never type to a diverging type variable.
// Overall it helps to improve the consistency. We expect that we can
// have the same behaviour for `return.foo()` and `{ return }.foo()`.
if ty.is_never() {
assert!(
!self.typeck_results.borrow().adjustments().contains_key(expr.hir_id),
"expression with never type wound up being adjusted"
);

let expected_ty = match expected {
ExpectHasType(target_ty) => Some(target_ty),
ExpectCastableToType(target_ty) => Some(target_ty),
_ => None,
};

// Mirco-optimization: No need to create a diverging type variable
// if the target type is known.
let target_ty = expected_ty
.map(|target_ty| self.infcx.shallow_resolve(target_ty))
.filter(|target_ty| !target_ty.is_ty_var())
.unwrap_or_else(|| {
self.next_diverging_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::AdjustmentType,
span: expr.span,
})
});
if !target_ty.is_never() {
self.apply_adjustments(
expr,
vec![Adjustment { kind: Adjust::NeverToAny, target: target_ty }],
);
}

target_ty
} else {
ty
}
}

fn check_expr_kind(
47 changes: 37 additions & 10 deletions compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
Original file line number Diff line number Diff line change
@@ -1567,17 +1567,44 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// Numeric inference variables may be left unresolved.
pub fn structurally_resolved_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
let ty = self.resolve_vars_with_obligations(ty);
if !ty.is_ty_var() {
ty
if let ty::Infer(ty::TyVar(vid)) = ty.kind() {
// If we get a type variable here, we may not want to issue "type
// annotations needed". For example, the code can be something like
// `panic!().foo()` or `{ return }.foo()`.
//
// However, we must issue the error message if we found the type
// variable is related to some non-auxiliary non-diverging ones.
//
// We'll issue the error message for this
// ```
// let a = return;
// { if true { a } else { return } }.foo();
// ```
// but we won't for this
// ```
// let a: ! = return;
// { if true { a } else { return } }.foo();
// ```

let new_ty = if self.infcx.probe_ty_diverging(*vid) {
if self.tcx.features().never_type_fallback {
self.tcx.types.never
} else {
self.tcx.types.unit
}
} else {
if !self.is_tainted_by_errors() {
self.emit_inference_failure_err((**self).body_id, sp, ty.into(), vec![], E0282)
.note("type must be known at this point")
.emit();
}
self.tcx.ty_error()
};

self.demand_suptype(sp, new_ty, ty);
new_ty
} else {
if !self.is_tainted_by_errors() {
self.emit_inference_failure_err((**self).body_id, sp, ty.into(), vec![], E0282)
.note("type must be known at this point")
.emit();
}
let err = self.tcx.ty_error();
self.demand_suptype(sp, err, ty);
err
ty
}
}

8 changes: 5 additions & 3 deletions src/test/mir-opt/inline/inline_diverging.f.Inline.diff
Original file line number Diff line number Diff line change
@@ -4,18 +4,20 @@
fn f() -> () {
let mut _0: (); // return place in scope 0 at $DIR/inline-diverging.rs:7:12: 7:12
let mut _1: !; // in scope 0 at $DIR/inline-diverging.rs:7:12: 9:2
let _2: !; // in scope 0 at $DIR/inline-diverging.rs:8:5: 8:12
+ let mut _3: !; // in scope 0 at $DIR/inline-diverging.rs:8:5: 8:12
let _2: (); // in scope 0 at $DIR/inline-diverging.rs:8:5: 8:12
let mut _3: !; // in scope 0 at $DIR/inline-diverging.rs:8:5: 8:12
+ let mut _4: !; // in scope 0 at $DIR/inline-diverging.rs:8:5: 8:12
+ scope 1 (inlined sleep) { // at $DIR/inline-diverging.rs:8:5: 8:12
+ }

bb0: {
StorageLive(_2); // scope 0 at $DIR/inline-diverging.rs:8:5: 8:12
StorageLive(_3); // scope 0 at $DIR/inline-diverging.rs:8:5: 8:12
- sleep(); // scope 0 at $DIR/inline-diverging.rs:8:5: 8:12
- // mir::Constant
- // + span: $DIR/inline-diverging.rs:8:5: 8:10
- // + literal: Const { ty: fn() -> ! {sleep}, val: Value(Scalar(<ZST>)) }
+ StorageLive(_3); // scope 0 at $DIR/inline-diverging.rs:8:5: 8:12
+ StorageLive(_4); // scope 0 at $DIR/inline-diverging.rs:8:5: 8:12
+ goto -> bb1; // scope 0 at $DIR/inline-diverging.rs:8:5: 8:12
+ }
+
8 changes: 5 additions & 3 deletions src/test/mir-opt/inline/inline_diverging.g.Inline.diff
Original file line number Diff line number Diff line change
@@ -8,8 +8,9 @@
let mut _3: i32; // in scope 0 at $DIR/inline-diverging.rs:13:8: 13:9
let mut _4: i32; // in scope 0 at $DIR/inline-diverging.rs:14:9: 14:10
let mut _5: !; // in scope 0 at $DIR/inline-diverging.rs:15:12: 17:6
let _6: !; // in scope 0 at $DIR/inline-diverging.rs:16:9: 16:16
+ let mut _7: !; // in scope 0 at $DIR/inline-diverging.rs:16:9: 16:16
let _6: (); // in scope 0 at $DIR/inline-diverging.rs:16:9: 16:16
let mut _7: !; // in scope 0 at $DIR/inline-diverging.rs:16:9: 16:16
+ let mut _8: !; // in scope 0 at $DIR/inline-diverging.rs:16:9: 16:16
+ scope 1 (inlined panic) { // at $DIR/inline-diverging.rs:16:9: 16:16
+ }

@@ -33,8 +34,9 @@

bb2: {
StorageLive(_6); // scope 0 at $DIR/inline-diverging.rs:16:9: 16:16
StorageLive(_7); // scope 0 at $DIR/inline-diverging.rs:16:9: 16:16
- panic(); // scope 0 at $DIR/inline-diverging.rs:16:9: 16:16
+ StorageLive(_7); // scope 0 at $DIR/inline-diverging.rs:16:9: 16:16
+ StorageLive(_8); // scope 0 at $DIR/inline-diverging.rs:16:9: 16:16
+ begin_panic::<&str>(const "explicit panic"); // scope 1 at $DIR/inline-diverging.rs:16:9: 16:16
// mir::Constant
- // + span: $DIR/inline-diverging.rs:16:9: 16:14
Original file line number Diff line number Diff line change
@@ -7,6 +7,8 @@ fn main() -> () {
let _3: (); // in scope 0 at $DIR/issue-38669.rs:7:9: 9:10
let mut _4: bool; // in scope 0 at $DIR/issue-38669.rs:7:12: 7:24
let mut _5: !; // in scope 0 at $DIR/issue-38669.rs:7:25: 9:10
let _6: (); // in scope 0 at $DIR/issue-38669.rs:8:13: 8:18
let mut _7: !; // in scope 0 at $DIR/issue-38669.rs:8:13: 8:18
scope 1 {
debug should_break => _1; // in scope 1 at $DIR/issue-38669.rs:5:9: 5:25
}
@@ -30,7 +32,9 @@ fn main() -> () {
}

bb3: {
StorageLive(_6); // scope 1 at $DIR/issue-38669.rs:8:13: 8:18
_0 = const (); // scope 1 at $DIR/issue-38669.rs:8:13: 8:18
StorageDead(_6); // scope 1 at $DIR/issue-38669.rs:8:18: 8:19
StorageDead(_4); // scope 1 at $DIR/issue-38669.rs:9:9: 9:10
StorageDead(_3); // scope 1 at $DIR/issue-38669.rs:9:9: 9:10
StorageDead(_1); // scope 0 at $DIR/issue-38669.rs:12:1: 12:2
13 changes: 8 additions & 5 deletions src/test/mir-opt/issue_72181_1.main.mir_map.0.mir
Original file line number Diff line number Diff line change
@@ -9,8 +9,9 @@ fn main() -> () {
let mut _1: !; // in scope 0 at $DIR/issue-72181-1.rs:15:11: 21:2
let _2: Void as UserTypeProjection { base: UserType(0), projs: [] }; // in scope 0 at $DIR/issue-72181-1.rs:16:9: 16:10
let mut _3: (); // in scope 0 at $DIR/issue-72181-1.rs:17:41: 17:43
let _4: !; // in scope 0 at $DIR/issue-72181-1.rs:20:5: 20:9
let mut _5: Void; // in scope 0 at $DIR/issue-72181-1.rs:20:7: 20:8
let _4: (); // in scope 0 at $DIR/issue-72181-1.rs:20:5: 20:9
let mut _5: !; // in scope 0 at $DIR/issue-72181-1.rs:20:5: 20:9
let mut _6: Void; // in scope 0 at $DIR/issue-72181-1.rs:20:7: 20:8
scope 1 {
debug v => _2; // in scope 1 at $DIR/issue-72181-1.rs:16:9: 16:10
}
@@ -32,15 +33,17 @@ fn main() -> () {
FakeRead(ForLet(None), _2); // scope 0 at $DIR/issue-72181-1.rs:16:9: 16:10
AscribeUserType(_2, o, UserTypeProjection { base: UserType(1), projs: [] }); // scope 0 at $DIR/issue-72181-1.rs:16:12: 16:16
StorageLive(_4); // scope 1 at $DIR/issue-72181-1.rs:20:5: 20:9
StorageLive(_5); // scope 1 at $DIR/issue-72181-1.rs:20:7: 20:8
_5 = move _2; // scope 1 at $DIR/issue-72181-1.rs:20:7: 20:8
f(move _5) -> bb4; // scope 1 at $DIR/issue-72181-1.rs:20:5: 20:9
StorageLive(_5); // scope 1 at $DIR/issue-72181-1.rs:20:5: 20:9
StorageLive(_6); // scope 1 at $DIR/issue-72181-1.rs:20:7: 20:8
_6 = move _2; // scope 1 at $DIR/issue-72181-1.rs:20:7: 20:8
f(move _6) -> bb4; // scope 1 at $DIR/issue-72181-1.rs:20:5: 20:9
// mir::Constant
// + span: $DIR/issue-72181-1.rs:20:5: 20:6
// + literal: Const { ty: fn(Void) -> ! {f}, val: Value(Scalar(<ZST>)) }
}

bb2: {
StorageDead(_6); // scope 1 at $DIR/issue-72181-1.rs:20:8: 20:9
StorageDead(_5); // scope 1 at $DIR/issue-72181-1.rs:20:8: 20:9
StorageDead(_4); // scope 1 at $DIR/issue-72181-1.rs:20:9: 20:10
StorageDead(_2); // scope 0 at $DIR/issue-72181-1.rs:21:1: 21:2
38 changes: 20 additions & 18 deletions src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff
Original file line number Diff line number Diff line change
@@ -19,21 +19,22 @@
let mut _17: i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let mut _18: i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let mut _19: !; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let _21: !; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let mut _22: core::panicking::AssertKind; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let mut _23: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let _24: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let mut _25: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let _26: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let mut _27: std::option::Option<std::fmt::Arguments>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let _21: (); // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let mut _22: !; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let mut _23: core::panicking::AssertKind; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let mut _24: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let _25: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let mut _26: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let _27: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let mut _28: std::option::Option<std::fmt::Arguments>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
scope 1 {
debug split => _1; // in scope 1 at $DIR/issue-73223.rs:2:9: 2:14
let _6: std::option::Option<i32>; // in scope 1 at $DIR/issue-73223.rs:7:9: 7:14
scope 3 {
debug _prev => _6; // in scope 3 at $DIR/issue-73223.rs:7:9: 7:14
let _13: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let _14: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let mut _28: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let mut _29: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
scope 4 {
debug left_val => _13; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
debug right_val => _14; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
@@ -81,14 +82,14 @@
StorageLive(_10); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_10 = &_1; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageLive(_11); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_28 = const main::promoted[0]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_29 = const main::promoted[0]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
// ty::Const
// + ty: &i32
// + val: Unevaluated(main, [], Some(promoted[0]))
// mir::Constant
// + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
// + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
_11 = _28; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_11 = _29; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
(_9.0: &i32) = move _10; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
(_9.1: &i32) = move _11; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageDead(_11); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
@@ -116,24 +117,25 @@
discriminant(_20) = 0; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageLive(_21); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageLive(_22); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_22 = const core::panicking::AssertKind::Eq; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageLive(_23); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_23 = const core::panicking::AssertKind::Eq; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
// ty::Const
// + ty: core::panicking::AssertKind
// + val: Value(Scalar(0x00))
// mir::Constant
// + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
// + literal: Const { ty: core::panicking::AssertKind, val: Value(Scalar(0x00)) }
StorageLive(_23); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageLive(_24); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_24 = _13; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_23 = _24; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageLive(_25); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_25 = _13; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_24 = _25; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageLive(_26); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_26 = _14; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_25 = _26; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageLive(_27); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
discriminant(_27) = 0; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
core::panicking::assert_failed::<i32, i32>(const core::panicking::AssertKind::Eq, move _23, move _25, move _27); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_27 = _14; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_26 = _27; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageLive(_28); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
discriminant(_28) = 0; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
core::panicking::assert_failed::<i32, i32>(const core::panicking::AssertKind::Eq, move _24, move _26, move _28); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
// mir::Constant
// + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
// + literal: Const { ty: for<'r, 's, 't0> fn(core::panicking::AssertKind, &'r i32, &'s i32, std::option::Option<std::fmt::Arguments<'t0>>) -> ! {core::panicking::assert_failed::<i32, i32>}, val: Value(Scalar(<ZST>)) }
38 changes: 20 additions & 18 deletions src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff
Original file line number Diff line number Diff line change
@@ -19,21 +19,22 @@
let mut _17: i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let mut _18: i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let mut _19: !; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let _21: !; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let mut _22: core::panicking::AssertKind; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let mut _23: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let _24: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let mut _25: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let _26: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let mut _27: std::option::Option<std::fmt::Arguments>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let _21: (); // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let mut _22: !; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let mut _23: core::panicking::AssertKind; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let mut _24: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let _25: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let mut _26: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let _27: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let mut _28: std::option::Option<std::fmt::Arguments>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
scope 1 {
debug split => _1; // in scope 1 at $DIR/issue-73223.rs:2:9: 2:14
let _6: std::option::Option<i32>; // in scope 1 at $DIR/issue-73223.rs:7:9: 7:14
scope 3 {
debug _prev => _6; // in scope 3 at $DIR/issue-73223.rs:7:9: 7:14
let _13: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let _14: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let mut _28: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let mut _29: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
scope 4 {
debug left_val => _13; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
debug right_val => _14; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
@@ -81,14 +82,14 @@
StorageLive(_10); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_10 = &_1; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageLive(_11); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_28 = const main::promoted[0]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_29 = const main::promoted[0]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
// ty::Const
// + ty: &i32
// + val: Unevaluated(main, [], Some(promoted[0]))
// mir::Constant
// + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
// + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
_11 = _28; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_11 = _29; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
(_9.0: &i32) = move _10; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
(_9.1: &i32) = move _11; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageDead(_11); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
@@ -116,24 +117,25 @@
discriminant(_20) = 0; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageLive(_21); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageLive(_22); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_22 = const core::panicking::AssertKind::Eq; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageLive(_23); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_23 = const core::panicking::AssertKind::Eq; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
// ty::Const
// + ty: core::panicking::AssertKind
// + val: Value(Scalar(0x00))
// mir::Constant
// + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
// + literal: Const { ty: core::panicking::AssertKind, val: Value(Scalar(0x00)) }
StorageLive(_23); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageLive(_24); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_24 = _13; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_23 = _24; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageLive(_25); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_25 = _13; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_24 = _25; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageLive(_26); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_26 = _14; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_25 = _26; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageLive(_27); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
discriminant(_27) = 0; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
core::panicking::assert_failed::<i32, i32>(const core::panicking::AssertKind::Eq, move _23, move _25, move _27); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_27 = _14; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_26 = _27; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageLive(_28); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
discriminant(_28) = 0; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
core::panicking::assert_failed::<i32, i32>(const core::panicking::AssertKind::Eq, move _24, move _26, move _28); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
// mir::Constant
// + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
// + literal: Const { ty: for<'r, 's, 't0> fn(core::panicking::AssertKind, &'r i32, &'s i32, std::option::Option<std::fmt::Arguments<'t0>>) -> ! {core::panicking::assert_failed::<i32, i32>}, val: Value(Scalar(<ZST>)) }
Original file line number Diff line number Diff line change
@@ -5,11 +5,15 @@ fn main() -> () {
let _1: (); // in scope 0 at $DIR/loop_test.rs:10:5: 12:6
let mut _2: bool; // in scope 0 at $DIR/loop_test.rs:10:8: 10:12
let mut _3: !; // in scope 0 at $DIR/loop_test.rs:10:13: 12:6
let mut _4: !; // in scope 0 at $DIR/loop_test.rs:13:5: 16:6
let mut _5: (); // in scope 0 at $DIR/loop_test.rs:6:1: 17:2
let _6: i32; // in scope 0 at $DIR/loop_test.rs:14:13: 14:14
let _4: (); // in scope 0 at $DIR/loop_test.rs:11:9: 11:15
let mut _5: !; // in scope 0 at $DIR/loop_test.rs:11:9: 11:15
let mut _6: !; // in scope 0 at $DIR/loop_test.rs:13:5: 16:6
let mut _7: (); // in scope 0 at $DIR/loop_test.rs:6:1: 17:2
let _8: i32; // in scope 0 at $DIR/loop_test.rs:14:13: 14:14
let _9: (); // in scope 0 at $DIR/loop_test.rs:15:9: 15:17
let mut _10: !; // in scope 0 at $DIR/loop_test.rs:15:9: 15:17
scope 1 {
debug x => _6; // in scope 1 at $DIR/loop_test.rs:14:13: 14:14
debug x => _8; // in scope 1 at $DIR/loop_test.rs:14:13: 14:14
}

bb0: {
@@ -20,7 +24,9 @@ fn main() -> () {
}

bb1: {
StorageLive(_4); // scope 0 at $DIR/loop_test.rs:11:9: 11:15
_0 = const (); // scope 0 at $DIR/loop_test.rs:11:9: 11:15
StorageDead(_4); // scope 0 at $DIR/loop_test.rs:11:15: 11:16
StorageDead(_2); // scope 0 at $DIR/loop_test.rs:12:5: 12:6
StorageDead(_1); // scope 0 at $DIR/loop_test.rs:12:5: 12:6
return; // scope 0 at $DIR/loop_test.rs:17:2: 17:2
@@ -30,7 +36,7 @@ fn main() -> () {
_1 = const (); // scope 0 at $DIR/loop_test.rs:12:6: 12:6
StorageDead(_2); // scope 0 at $DIR/loop_test.rs:12:5: 12:6
StorageDead(_1); // scope 0 at $DIR/loop_test.rs:12:5: 12:6
StorageLive(_4); // scope 0 at $DIR/loop_test.rs:13:5: 16:6
StorageLive(_6); // scope 0 at $DIR/loop_test.rs:13:5: 16:6
goto -> bb3; // scope 0 at $DIR/loop_test.rs:13:5: 16:6
}

@@ -39,10 +45,12 @@ fn main() -> () {
}

bb4: {
StorageLive(_6); // scope 0 at $DIR/loop_test.rs:14:13: 14:14
_6 = const 1_i32; // scope 0 at $DIR/loop_test.rs:14:17: 14:18
FakeRead(ForLet(None), _6); // scope 0 at $DIR/loop_test.rs:14:13: 14:14
StorageDead(_6); // scope 0 at $DIR/loop_test.rs:16:5: 16:6
StorageLive(_8); // scope 0 at $DIR/loop_test.rs:14:13: 14:14
_8 = const 1_i32; // scope 0 at $DIR/loop_test.rs:14:17: 14:18
FakeRead(ForLet(None), _8); // scope 0 at $DIR/loop_test.rs:14:13: 14:14
StorageLive(_9); // scope 1 at $DIR/loop_test.rs:15:9: 15:17
StorageDead(_9); // scope 1 at $DIR/loop_test.rs:15:17: 15:18
StorageDead(_8); // scope 0 at $DIR/loop_test.rs:16:5: 16:6
goto -> bb3; // scope 0 at $DIR/loop_test.rs:1:1: 1:1
}

Original file line number Diff line number Diff line change
@@ -23,13 +23,14 @@ fn array_casts() -> () {
let mut _24: usize; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let mut _25: usize; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let mut _26: !; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let _28: !; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let mut _29: core::panicking::AssertKind; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let mut _30: &usize; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let _31: &usize; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let mut _32: &usize; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let _33: &usize; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let mut _34: std::option::Option<std::fmt::Arguments>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let _28: (); // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let mut _29: !; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let mut _30: core::panicking::AssertKind; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let mut _31: &usize; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let _32: &usize; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let mut _33: &usize; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let _34: &usize; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let mut _35: std::option::Option<std::fmt::Arguments>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
scope 1 {
debug x => _1; // in scope 1 at $DIR/retag.rs:58:9: 58:14
let _2: *mut usize; // in scope 1 at $DIR/retag.rs:59:9: 59:10
@@ -45,7 +46,7 @@ fn array_casts() -> () {
debug p => _9; // in scope 5 at $DIR/retag.rs:63:9: 63:10
let _20: &usize; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let _21: &usize; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let mut _35: &usize; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let mut _36: &usize; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
scope 6 {
}
scope 7 {
@@ -121,15 +122,15 @@ fn array_casts() -> () {
_14 = &_15; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
Retag(_14); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageLive(_18); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_35 = const array_casts::promoted[0]; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_36 = const array_casts::promoted[0]; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
// ty::Const
// + ty: &usize
// + val: Unevaluated(array_casts, [], Some(promoted[0]))
// mir::Constant
// + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
// + literal: Const { ty: &usize, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:15 ~ retag[317d]::array_casts), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
Retag(_35); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_18 = &(*_35); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
Retag(_36); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_18 = &(*_36); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
Retag(_18); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_13 = (move _14, move _18); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageDead(_18); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
@@ -159,22 +160,23 @@ fn array_casts() -> () {
_27 = core::panicking::AssertKind::Eq; // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageLive(_28); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageLive(_29); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_29 = move _27; // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageLive(_30); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_30 = move _27; // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageLive(_31); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_31 = &(*_20); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
Retag(_31); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_30 = &(*_31); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
Retag(_30); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageLive(_32); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageLive(_33); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_33 = &(*_21); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
Retag(_33); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_32 = &(*_33); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_32 = &(*_20); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
Retag(_32); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_31 = &(*_32); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
Retag(_31); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageLive(_33); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageLive(_34); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_34 = Option::<Arguments>::None; // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
core::panicking::assert_failed::<usize, usize>(move _29, move _30, move _32, move _34); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_34 = &(*_21); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
Retag(_34); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_33 = &(*_34); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
Retag(_33); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageLive(_35); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_35 = Option::<Arguments>::None; // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
core::panicking::assert_failed::<usize, usize>(move _30, move _31, move _33, move _35); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
// mir::Constant
// + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
// + literal: Const { ty: for<'r, 's, 't0> fn(core::panicking::AssertKind, &'r usize, &'s usize, std::option::Option<std::fmt::Arguments<'t0>>) -> ! {core::panicking::assert_failed::<usize, usize>}, val: Value(Scalar(<ZST>)) }
4 changes: 4 additions & 0 deletions src/test/mir-opt/simplify_cfg.main.SimplifyCfg-early-opt.diff
Original file line number Diff line number Diff line change
@@ -6,6 +6,8 @@
let mut _1: (); // in scope 0 at $DIR/simplify_cfg.rs:5:1: 11:2
let mut _2: bool; // in scope 0 at $DIR/simplify_cfg.rs:7:12: 7:17
let mut _3: !; // in scope 0 at $DIR/simplify_cfg.rs:7:18: 9:10
let _4: (); // in scope 0 at $DIR/simplify_cfg.rs:8:13: 8:18
let mut _5: !; // in scope 0 at $DIR/simplify_cfg.rs:8:13: 8:18

bb0: {
- goto -> bb1; // scope 0 at $DIR/simplify_cfg.rs:6:5: 10:6
@@ -28,7 +30,9 @@

- bb3: {
+ bb2: {
StorageLive(_4); // scope 0 at $DIR/simplify_cfg.rs:8:13: 8:18
_0 = const (); // scope 0 at $DIR/simplify_cfg.rs:8:13: 8:18
StorageDead(_4); // scope 0 at $DIR/simplify_cfg.rs:8:18: 8:19
StorageDead(_2); // scope 0 at $DIR/simplify_cfg.rs:9:9: 9:10
return; // scope 0 at $DIR/simplify_cfg.rs:11:2: 11:2
}
45 changes: 27 additions & 18 deletions src/test/mir-opt/simplify_cfg.main.SimplifyCfg-initial.diff
Original file line number Diff line number Diff line change
@@ -6,19 +6,21 @@
let mut _1: (); // in scope 0 at $DIR/simplify_cfg.rs:5:1: 11:2
let mut _2: bool; // in scope 0 at $DIR/simplify_cfg.rs:7:12: 7:17
let mut _3: !; // in scope 0 at $DIR/simplify_cfg.rs:7:18: 9:10
let _4: (); // in scope 0 at $DIR/simplify_cfg.rs:8:13: 8:18
let mut _5: !; // in scope 0 at $DIR/simplify_cfg.rs:8:13: 8:18

bb0: {
- goto -> bb1; // scope 0 at $DIR/simplify_cfg.rs:6:5: 10:6
+ falseUnwind -> [real: bb1, cleanup: bb5]; // scope 0 at $DIR/simplify_cfg.rs:6:5: 10:6
}

bb1: {
- falseUnwind -> [real: bb2, cleanup: bb10]; // scope 0 at $DIR/simplify_cfg.rs:6:5: 10:6
- falseUnwind -> [real: bb2, cleanup: bb11]; // scope 0 at $DIR/simplify_cfg.rs:6:5: 10:6
- }
-
- bb2: {
StorageLive(_2); // scope 0 at $DIR/simplify_cfg.rs:7:12: 7:17
- _2 = bar() -> [return: bb3, unwind: bb10]; // scope 0 at $DIR/simplify_cfg.rs:7:12: 7:17
- _2 = bar() -> [return: bb3, unwind: bb11]; // scope 0 at $DIR/simplify_cfg.rs:7:12: 7:17
+ _2 = bar() -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/simplify_cfg.rs:7:12: 7:17
// mir::Constant
// + span: $DIR/simplify_cfg.rs:7:12: 7:15
@@ -33,38 +35,45 @@

- bb4: {
+ bb3: {
StorageLive(_4); // scope 0 at $DIR/simplify_cfg.rs:8:13: 8:18
_0 = const (); // scope 0 at $DIR/simplify_cfg.rs:8:13: 8:18
- goto -> bb9; // scope 0 at $DIR/simplify_cfg.rs:8:13: 8:18
+ StorageDead(_2); // scope 0 at $DIR/simplify_cfg.rs:9:9: 9:10
+ return; // scope 0 at $DIR/simplify_cfg.rs:11:2: 11:2
}

- goto -> bb10; // scope 0 at $DIR/simplify_cfg.rs:8:13: 8:18
- }
-
- bb5: {
+ bb4: {
_1 = const (); // scope 0 at $DIR/simplify_cfg.rs:9:10: 9:10
- goto -> bb8; // scope 0 at $DIR/simplify_cfg.rs:7:9: 9:10
- _1 = const (); // scope 0 at $DIR/simplify_cfg.rs:9:10: 9:10
- goto -> bb9; // scope 0 at $DIR/simplify_cfg.rs:7:9: 9:10
- }
-
- bb6: {
- unreachable; // scope 0 at $DIR/simplify_cfg.rs:7:18: 9:10
- unreachable; // scope 0 at $DIR/simplify_cfg.rs:8:13: 8:18
- }
-
- bb7: {
- goto -> bb8; // scope 0 at $DIR/simplify_cfg.rs:7:9: 9:10
StorageDead(_4); // scope 0 at $DIR/simplify_cfg.rs:8:18: 8:19
- unreachable; // scope 0 at $DIR/simplify_cfg.rs:7:18: 9:10
- }
-
- bb8: {
- goto -> bb9; // scope 0 at $DIR/simplify_cfg.rs:7:9: 9:10
- }
-
- bb9: {
StorageDead(_2); // scope 0 at $DIR/simplify_cfg.rs:9:9: 9:10
- goto -> bb1; // scope 0 at $DIR/simplify_cfg.rs:6:5: 10:6
+ goto -> bb0; // scope 0 at $DIR/simplify_cfg.rs:6:5: 10:6
+ return; // scope 0 at $DIR/simplify_cfg.rs:11:2: 11:2
}

- bb9: {
- StorageDead(_2); // scope 0 at $DIR/simplify_cfg.rs:9:9: 9:10
- bb10: {
- StorageDead(_4); // scope 0 at $DIR/simplify_cfg.rs:8:18: 8:19
+ bb4: {
+ _1 = const (); // scope 0 at $DIR/simplify_cfg.rs:9:10: 9:10
StorageDead(_2); // scope 0 at $DIR/simplify_cfg.rs:9:9: 9:10
- return; // scope 0 at $DIR/simplify_cfg.rs:11:2: 11:2
- }
-
- bb10 (cleanup): {
+ goto -> bb0; // scope 0 at $DIR/simplify_cfg.rs:6:5: 10:6
}

- bb11 (cleanup): {
+ bb5 (cleanup): {
resume; // scope 0 at $DIR/simplify_cfg.rs:5:1: 11:2
}
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@
fn process_never(_1: *const !) -> () {
debug input => _1; // in scope 0 at $DIR/uninhabited-enum.rs:7:22: 7:27
let mut _0: (); // return place in scope 0 at $DIR/uninhabited-enum.rs:7:39: 7:39
let _2: &!; // in scope 0 at $DIR/uninhabited-enum.rs:8:8: 8:14
let _2: &(); // in scope 0 at $DIR/uninhabited-enum.rs:8:8: 8:14
scope 1 {
debug _input => _2; // in scope 1 at $DIR/uninhabited-enum.rs:8:8: 8:14
}
@@ -12,8 +12,6 @@ fn process_never(_1: *const !) -> () {

bb0: {
StorageLive(_2); // scope 0 at $DIR/uninhabited-enum.rs:8:8: 8:14
_2 = &(*_1); // scope 2 at $DIR/uninhabited-enum.rs:8:26: 8:33
StorageDead(_2); // scope 0 at $DIR/uninhabited-enum.rs:9:1: 9:2
unreachable; // scope 0 at $DIR/uninhabited-enum.rs:7:39: 9:2
unreachable; // scope 2 at $DIR/uninhabited-enum.rs:8:27: 8:33
}
}
Original file line number Diff line number Diff line change
@@ -8,7 +8,9 @@
let mut _3: std::option::Option<u32>; // in scope 0 at $DIR/while_let_loops.rs:7:28: 7:32
let mut _4: isize; // in scope 0 at $DIR/while_let_loops.rs:7:15: 7:25
let mut _5: !; // in scope 0 at $DIR/while_let_loops.rs:7:33: 10:6
let mut _6: !; // in scope 0 at $DIR/while_let_loops.rs:7:5: 10:6
let _6: (); // in scope 0 at $DIR/while_let_loops.rs:9:9: 9:14
let mut _7: !; // in scope 0 at $DIR/while_let_loops.rs:9:9: 9:14
let mut _8: !; // in scope 0 at $DIR/while_let_loops.rs:7:5: 10:6
scope 1 {
debug _x => _1; // in scope 1 at $DIR/while_let_loops.rs:6:9: 6:15
}
@@ -35,8 +37,10 @@

bb3: {
_1 = const 1_i32; // scope 1 at $DIR/while_let_loops.rs:8:9: 8:15
StorageLive(_6); // scope 1 at $DIR/while_let_loops.rs:9:9: 9:14
nop; // scope 1 at $DIR/while_let_loops.rs:9:9: 9:14
goto -> bb4; // scope 1 at $DIR/while_let_loops.rs:9:9: 9:14
StorageDead(_6); // scope 1 at $DIR/while_let_loops.rs:9:14: 9:15
goto -> bb4; // scope 1 at $DIR/while_let_loops.rs:1:1: 1:1
}

bb4: {
Original file line number Diff line number Diff line change
@@ -8,7 +8,9 @@
let mut _3: std::option::Option<u32>; // in scope 0 at $DIR/while_let_loops.rs:7:28: 7:32
let mut _4: isize; // in scope 0 at $DIR/while_let_loops.rs:7:15: 7:25
let mut _5: !; // in scope 0 at $DIR/while_let_loops.rs:7:33: 10:6
let mut _6: !; // in scope 0 at $DIR/while_let_loops.rs:7:5: 10:6
let _6: (); // in scope 0 at $DIR/while_let_loops.rs:9:9: 9:14
let mut _7: !; // in scope 0 at $DIR/while_let_loops.rs:9:9: 9:14
let mut _8: !; // in scope 0 at $DIR/while_let_loops.rs:7:5: 10:6
scope 1 {
debug _x => _1; // in scope 1 at $DIR/while_let_loops.rs:6:9: 6:15
}
@@ -35,8 +37,10 @@

bb3: {
_1 = const 1_i32; // scope 1 at $DIR/while_let_loops.rs:8:9: 8:15
StorageLive(_6); // scope 1 at $DIR/while_let_loops.rs:9:9: 9:14
nop; // scope 1 at $DIR/while_let_loops.rs:9:9: 9:14
goto -> bb4; // scope 1 at $DIR/while_let_loops.rs:9:9: 9:14
StorageDead(_6); // scope 1 at $DIR/while_let_loops.rs:9:14: 9:15
goto -> bb4; // scope 1 at $DIR/while_let_loops.rs:1:1: 1:1
}

bb4: {
4 changes: 2 additions & 2 deletions src/test/ui/asm/type-check-2.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// only-x86_64
// only-x86_6

#![feature(asm, repr_simd, never_type)]
#![feature(asm, repr_simd, never_type, never_type_fallback)]

#[repr(simd)]
struct SimdNonCopy(f32, f32, f32, f32);
2 changes: 1 addition & 1 deletion src/test/ui/diverging-tuple-parts-39485.stderr
Original file line number Diff line number Diff line change
@@ -24,7 +24,7 @@ LL | (return 1, return 2)
| ^^^^^^^^^^^^^^^^^^^^ expected `isize`, found tuple
|
= note: expected type `isize`
found tuple `(!, !)`
found tuple `(_, _)`

error: aborting due to 2 previous errors

2 changes: 1 addition & 1 deletion src/test/ui/index-bot.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
fn main() {
(return)[0]; //~ ERROR cannot index into a value of type `!`
(return)[0]; //~ ERROR cannot index into a value of type `()`
}
4 changes: 2 additions & 2 deletions src/test/ui/index-bot.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error[E0608]: cannot index into a value of type `!`
error[E0608]: cannot index into a value of type `()`
--> $DIR/index-bot.rs:2:5
|
LL | (return)[0];
| ^^^^^^^^^^^
| ^^^^^^^^^^^ help: to access tuple elements, use: `(return).0`

error: aborting due to previous error

2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-13847.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
fn main() {
return.is_failure //~ ERROR no field `is_failure` on type `!`
return.is_failure //~ ERROR no field `is_failure` on type `()`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Haven't looked much at the implementation here, but this change alone signals something is probably not correct with this PR; the type of return should be !, not ()

}
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-13847.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error[E0609]: no field `is_failure` on type `!`
error[E0609]: no field `is_failure` on type `()`
--> $DIR/issue-13847.rs:2:12
|
LL | return.is_failure
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-15207.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
fn main() {
loop {
break.push(1) //~ ERROR no method named `push` found for type `!`
break.push(1) //~ ERROR no method named `push` found for unit type `()`
;
}
}
4 changes: 2 additions & 2 deletions src/test/ui/issues/issue-15207.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error[E0599]: no method named `push` found for type `!` in the current scope
error[E0599]: no method named `push` found for unit type `()` in the current scope
--> $DIR/issue-15207.rs:3:15
|
LL | break.push(1)
| ^^^^ method not found in `!`
| ^^^^ method not found in `()`

error: aborting due to previous error

2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-15965.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
fn main() {
return
{ return () }
//~^ ERROR type annotations needed [E0282]
//~^ ERROR expected function, found `_`
()
;
}
11 changes: 5 additions & 6 deletions src/test/ui/issues/issue-15965.stderr
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
error[E0282]: type annotations needed
error[E0618]: expected function, found `_`
--> $DIR/issue-15965.rs:3:9
|
LL | / { return () }
LL | { return () }
| _________-^^^^^^^^^^^^
LL | |
LL | | ()
| |______^ cannot infer type
|
= note: type must be known at this point
| |______- call expression requires function

error: aborting due to previous error

For more information about this error, try `rustc --explain E0282`.
For more information about this error, try `rustc --explain E0618`.
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-17373.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
fn main() {
*return //~ ERROR type `!` cannot be dereferenced
*return //~ ERROR type `()` cannot be dereferenced
;
}
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-17373.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error[E0614]: type `!` cannot be dereferenced
error[E0614]: type `()` cannot be dereferenced
--> $DIR/issue-17373.rs:2:5
|
LL | *return
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-18532.rs
Original file line number Diff line number Diff line change
@@ -3,5 +3,5 @@
// into it.

fn main() {
(return)((),()); //~ ERROR expected function, found `!`
(return)((),()); //~ ERROR expected function, found `_`
}
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-18532.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error[E0618]: expected function, found `!`
error[E0618]: expected function, found `_`
--> $DIR/issue-18532.rs:6:5
|
LL | (return)((),());
2 changes: 1 addition & 1 deletion src/test/ui/loops/loop-break-value.stderr
Original file line number Diff line number Diff line change
@@ -170,7 +170,7 @@ LL | break (break, break);
| ^^^^^^^^^^^^^^ expected `()`, found tuple
|
= note: expected unit type `()`
found tuple `(!, !)`
found tuple `(_, _)`

error[E0308]: mismatched types
--> $DIR/loop-break-value.rs:85:15
27 changes: 27 additions & 0 deletions src/test/ui/never_type/early-fallback.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#![feature(never_type)]
#![feature(never_type_fallback)]
#![allow(dead_code)]

fn foo() {
{ if true { return } else { return } }.test();
//~^ ERROR no method named `test` found for type `!`
}

fn bar() {
{ if true { Default::default() } else { return } }.test();
//~^ ERROR type annotations needed
}

fn baz() {
let a = return;
{ if true { return } else { a } }.test();
//~^ ERROR type annotations needed
}

fn qux() {
let a: ! = return;
{ if true { return } else { a } }.test();
//~^ ERROR no method named `test` found for type `!`
}

fn main() {}
34 changes: 34 additions & 0 deletions src/test/ui/never_type/early-fallback.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
error[E0599]: no method named `test` found for type `!` in the current scope
--> $DIR/early-fallback.rs:6:44
|
LL | { if true { return } else { return } }.test();
| ^^^^ method not found in `!`

error[E0282]: type annotations needed
--> $DIR/early-fallback.rs:11:5
|
LL | { if true { Default::default() } else { return } }.test();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type
|
= note: type must be known at this point

error[E0282]: type annotations needed
--> $DIR/early-fallback.rs:17:5
|
LL | let a = return;
| - consider giving `a` a type
LL | { if true { return } else { a } }.test();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type
|
= note: type must be known at this point

error[E0599]: no method named `test` found for type `!` in the current scope
--> $DIR/early-fallback.rs:23:39
|
LL | { if true { return } else { a } }.test();
| ^^^^ method not found in `!`

error: aborting due to 4 previous errors

Some errors have detailed explanations: E0282, E0599.
For more information about an error, try `rustc --explain E0282`.
2 changes: 1 addition & 1 deletion src/test/ui/never_type/issue-10176.rs
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ fn f() -> isize {
(return 1, return 2)
//~^ ERROR mismatched types
//~| expected type `isize`
//~| found tuple `(!, !)`
//~| found tuple `(_, _)`
//~| expected `isize`, found tuple
}

2 changes: 1 addition & 1 deletion src/test/ui/never_type/issue-10176.stderr
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@ LL | (return 1, return 2)
| ^^^^^^^^^^^^^^^^^^^^ expected `isize`, found tuple
|
= note: expected type `isize`
found tuple `(!, !)`
found tuple `(_, _)`

error: aborting due to previous error

19 changes: 19 additions & 0 deletions src/test/ui/never_type/tuple.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#[allow(dead_code)]

fn foo() {
let mut a = (return, );
a.0 = 1;
a.0 = 1.1; //~ ERROR mismatched types
}

fn bar() {
let mut a = (return, );
a.0.test(); //~ ERROR type annotations needed for `(_,)`
}

fn baz() {
let mut a = (return, );
a + 1; //~ ERROR cannot add `{integer}` to `(_,)`
}

fn main() {}
28 changes: 28 additions & 0 deletions src/test/ui/never_type/tuple.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
error[E0308]: mismatched types
--> $DIR/tuple.rs:6:11
|
LL | a.0 = 1.1;
| ^^^ expected integer, found floating-point number

error[E0282]: type annotations needed for `(_,)`
--> $DIR/tuple.rs:11:5
|
LL | let mut a = (return, );
| ----- consider giving `a` the explicit type `(_,)`, with the type parameters specified
LL | a.0.test();
| ^^^ cannot infer type
|
= note: type must be known at this point

error[E0369]: cannot add `{integer}` to `(_,)`
--> $DIR/tuple.rs:16:7
|
LL | a + 1;
| - ^ - {integer}
| |
| (_,)

error: aborting due to 3 previous errors

Some errors have detailed explanations: E0282, E0308, E0369.
For more information about an error, try `rustc --explain E0282`.