From 690d23c414422df84a9d711056e5f1e1e1fe141a Mon Sep 17 00:00:00 2001 From: lrh2000 Date: Wed, 5 May 2021 10:31:07 +0800 Subject: [PATCH 1/2] Always replace the never type by a diverging type variable Previously, the never type will be replaced by a diverging type variable (generally) only if some coercion occurs. It can cause inconsistent behaviors like ```rust return.foo(); //~ ERROR no method named `foo` found for type `!` { return }.foo(); //~ ERROR type annotations needed ``` ```rust let a = (return, ); // The type is `(!, )`. let a = ({ return }, ); // The type is `(_, )`. let a: (_, ) = (return, ); // The type is `(_, )`. ``` With this commit, the never type will be replaced by a diverging type variable just at the end of the type check for every expression, even if no coercion occurs. Thus the problems above get solved and the consistency should be improved. --- compiler/rustc_typeck/src/check/_match.rs | 6 +- compiler/rustc_typeck/src/check/coercion.rs | 13 +++-- compiler/rustc_typeck/src/check/expr.rs | 58 ++++++++++++------- .../inline/inline_diverging.f.Inline.diff | 8 ++- .../inline/inline_diverging.g.Inline.diff | 8 ++- ...e_38669.main.SimplifyCfg-initial.after.mir | 4 ++ .../mir-opt/issue_72181_1.main.mir_map.0.mir | 13 +++-- ..._73223.main.SimplifyArmIdentity.32bit.diff | 38 ++++++------ ..._73223.main.SimplifyArmIdentity.64bit.diff | 38 ++++++------ ....main.SimplifyCfg-promote-consts.after.mir | 26 ++++++--- ...asts.SimplifyCfg-elaborate-drops.after.mir | 46 ++++++++------- ...mplify_cfg.main.SimplifyCfg-early-opt.diff | 4 ++ ...simplify_cfg.main.SimplifyCfg-initial.diff | 45 ++++++++------ ...num.process_never.SimplifyLocals.after.mir | 6 +- ...oops.change_loop_body.ConstProp.32bit.diff | 8 ++- ...oops.change_loop_body.ConstProp.64bit.diff | 8 ++- src/test/ui/asm/type-check-2.rs | 5 +- .../ui/diverging-tuple-parts-39485.stderr | 2 +- src/test/ui/index-bot.rs | 2 +- src/test/ui/index-bot.stderr | 8 ++- src/test/ui/issues/issue-13847.rs | 2 +- src/test/ui/issues/issue-13847.stderr | 10 ++-- src/test/ui/issues/issue-15207.rs | 2 +- src/test/ui/issues/issue-15207.stderr | 10 ++-- src/test/ui/issues/issue-17373.rs | 2 +- src/test/ui/issues/issue-17373.stderr | 8 ++- src/test/ui/issues/issue-18532.rs | 2 +- src/test/ui/issues/issue-18532.stderr | 10 ++-- src/test/ui/loops/loop-break-value.stderr | 2 +- src/test/ui/never_type/issue-10176.rs | 2 +- src/test/ui/never_type/issue-10176.stderr | 2 +- src/test/ui/never_type/tuple.rs | 19 ++++++ src/test/ui/never_type/tuple.stderr | 28 +++++++++ 33 files changed, 286 insertions(+), 159 deletions(-) create mode 100644 src/test/ui/never_type/tuple.rs create mode 100644 src/test/ui/never_type/tuple.stderr diff --git a/compiler/rustc_typeck/src/check/_match.rs b/compiler/rustc_typeck/src/check/_match.rs index d056f2c90f98..6fb0529b6690 100644 --- a/compiler/rustc_typeck/src/check/_match.rs +++ b/compiler/rustc_typeck/src/check/_match.rs @@ -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 diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs index 236fec94bdba..3b305724f754 100644 --- a/compiler/rustc_typeck/src/check/coercion.rs +++ b/compiler/rustc_typeck/src/check/coercion.rs @@ -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 diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index d0cbb58fb10e..f0dc39ed8f43 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -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( diff --git a/src/test/mir-opt/inline/inline_diverging.f.Inline.diff b/src/test/mir-opt/inline/inline_diverging.f.Inline.diff index 6e36dc06a201..6e5690823e9d 100644 --- a/src/test/mir-opt/inline/inline_diverging.f.Inline.diff +++ b/src/test/mir-opt/inline/inline_diverging.f.Inline.diff @@ -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()) } -+ 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 + } + diff --git a/src/test/mir-opt/inline/inline_diverging.g.Inline.diff b/src/test/mir-opt/inline/inline_diverging.g.Inline.diff index 97ffd664463b..4c99529ab374 100644 --- a/src/test/mir-opt/inline/inline_diverging.g.Inline.diff +++ b/src/test/mir-opt/inline/inline_diverging.g.Inline.diff @@ -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 diff --git a/src/test/mir-opt/issue_38669.main.SimplifyCfg-initial.after.mir b/src/test/mir-opt/issue_38669.main.SimplifyCfg-initial.after.mir index 8355b2d195e1..6a359cb6c26d 100644 --- a/src/test/mir-opt/issue_38669.main.SimplifyCfg-initial.after.mir +++ b/src/test/mir-opt/issue_38669.main.SimplifyCfg-initial.after.mir @@ -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 diff --git a/src/test/mir-opt/issue_72181_1.main.mir_map.0.mir b/src/test/mir-opt/issue_72181_1.main.mir_map.0.mir index 3c26b20c35e2..74682b59d069 100644 --- a/src/test/mir-opt/issue_72181_1.main.mir_map.0.mir +++ b/src/test/mir-opt/issue_72181_1.main.mir_map.0.mir @@ -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()) } } 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 diff --git a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff index 261eb3b27eaf..f0e4d33cea91 100644 --- a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff +++ b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff @@ -19,13 +19,14 @@ 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; // 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; // 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; // in scope 1 at $DIR/issue-73223.rs:7:9: 7:14 @@ -33,7 +34,7 @@ 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::(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::(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>) -> ! {core::panicking::assert_failed::}, val: Value(Scalar()) } diff --git a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff index 261eb3b27eaf..f0e4d33cea91 100644 --- a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff +++ b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff @@ -19,13 +19,14 @@ 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; // 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; // 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; // in scope 1 at $DIR/issue-73223.rs:7:9: 7:14 @@ -33,7 +34,7 @@ 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::(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::(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>) -> ! {core::panicking::assert_failed::}, val: Value(Scalar()) } diff --git a/src/test/mir-opt/loop_test.main.SimplifyCfg-promote-consts.after.mir b/src/test/mir-opt/loop_test.main.SimplifyCfg-promote-consts.after.mir index 99c7ac8d5b70..db85fe860931 100644 --- a/src/test/mir-opt/loop_test.main.SimplifyCfg-promote-consts.after.mir +++ b/src/test/mir-opt/loop_test.main.SimplifyCfg-promote-consts.after.mir @@ -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 } diff --git a/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir index c6ef403c3c13..916b0aee12ef 100644 --- a/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir +++ b/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir @@ -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; // 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; // 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::::None; // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - core::panicking::assert_failed::(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::::None; // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + core::panicking::assert_failed::(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>) -> ! {core::panicking::assert_failed::}, val: Value(Scalar()) } diff --git a/src/test/mir-opt/simplify_cfg.main.SimplifyCfg-early-opt.diff b/src/test/mir-opt/simplify_cfg.main.SimplifyCfg-early-opt.diff index 52e705fdbeba..4f044a0d350f 100644 --- a/src/test/mir-opt/simplify_cfg.main.SimplifyCfg-early-opt.diff +++ b/src/test/mir-opt/simplify_cfg.main.SimplifyCfg-early-opt.diff @@ -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 } diff --git a/src/test/mir-opt/simplify_cfg.main.SimplifyCfg-initial.diff b/src/test/mir-opt/simplify_cfg.main.SimplifyCfg-initial.diff index fef3ae2e461d..35fca87efe78 100644 --- a/src/test/mir-opt/simplify_cfg.main.SimplifyCfg-initial.diff +++ b/src/test/mir-opt/simplify_cfg.main.SimplifyCfg-initial.diff @@ -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 @@ -13,12 +15,12 @@ } 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 } diff --git a/src/test/mir-opt/uninhabited_enum.process_never.SimplifyLocals.after.mir b/src/test/mir-opt/uninhabited_enum.process_never.SimplifyLocals.after.mir index c17fe3bb7575..40b997edfa50 100644 --- a/src/test/mir-opt/uninhabited_enum.process_never.SimplifyLocals.after.mir +++ b/src/test/mir-opt/uninhabited_enum.process_never.SimplifyLocals.after.mir @@ -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 } } diff --git a/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.32bit.diff b/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.32bit.diff index de8a29ea25fc..1c30d502e8a2 100644 --- a/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.32bit.diff +++ b/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.32bit.diff @@ -8,7 +8,9 @@ let mut _3: std::option::Option; // 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: { diff --git a/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.64bit.diff b/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.64bit.diff index de8a29ea25fc..1c30d502e8a2 100644 --- a/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.64bit.diff +++ b/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.64bit.diff @@ -8,7 +8,9 @@ let mut _3: std::option::Option; // 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: { diff --git a/src/test/ui/asm/type-check-2.rs b/src/test/ui/asm/type-check-2.rs index c70a8802814f..df48a19cc6d0 100644 --- a/src/test/ui/asm/type-check-2.rs +++ b/src/test/ui/asm/type-check-2.rs @@ -78,7 +78,8 @@ fn main() { // Type checks ignore never type - let u: ! = unreachable!(); - asm!("{}", in(reg) u); + // FIXME: ERROR type annotations needed + // let u: ! = unreachable!(); + // asm!("{}", in(reg) u); } } diff --git a/src/test/ui/diverging-tuple-parts-39485.stderr b/src/test/ui/diverging-tuple-parts-39485.stderr index ad3e5ab3dc9d..90a6f2ede702 100644 --- a/src/test/ui/diverging-tuple-parts-39485.stderr +++ b/src/test/ui/diverging-tuple-parts-39485.stderr @@ -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 diff --git a/src/test/ui/index-bot.rs b/src/test/ui/index-bot.rs index e69c4019f61e..4945af668115 100644 --- a/src/test/ui/index-bot.rs +++ b/src/test/ui/index-bot.rs @@ -1,3 +1,3 @@ fn main() { - (return)[0]; //~ ERROR cannot index into a value of type `!` + (return)[0]; //~ ERROR type annotations needed } diff --git a/src/test/ui/index-bot.stderr b/src/test/ui/index-bot.stderr index b5d78297505d..2f368875abb7 100644 --- a/src/test/ui/index-bot.stderr +++ b/src/test/ui/index-bot.stderr @@ -1,9 +1,11 @@ -error[E0608]: cannot index into a value of type `!` +error[E0282]: type annotations needed --> $DIR/index-bot.rs:2:5 | LL | (return)[0]; - | ^^^^^^^^^^^ + | ^^^^^^^^ cannot infer type + | + = note: type must be known at this point error: aborting due to previous error -For more information about this error, try `rustc --explain E0608`. +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/issues/issue-13847.rs b/src/test/ui/issues/issue-13847.rs index 06a0304ae497..002698abf4d8 100644 --- a/src/test/ui/issues/issue-13847.rs +++ b/src/test/ui/issues/issue-13847.rs @@ -1,3 +1,3 @@ fn main() { - return.is_failure //~ ERROR no field `is_failure` on type `!` + return.is_failure //~ ERROR type annotations needed } diff --git a/src/test/ui/issues/issue-13847.stderr b/src/test/ui/issues/issue-13847.stderr index 52b8dc049702..7e682f8a717f 100644 --- a/src/test/ui/issues/issue-13847.stderr +++ b/src/test/ui/issues/issue-13847.stderr @@ -1,9 +1,11 @@ -error[E0609]: no field `is_failure` on type `!` - --> $DIR/issue-13847.rs:2:12 +error[E0282]: type annotations needed + --> $DIR/issue-13847.rs:2:5 | LL | return.is_failure - | ^^^^^^^^^^ + | ^^^^^^ cannot infer type + | + = note: type must be known at this point error: aborting due to previous error -For more information about this error, try `rustc --explain E0609`. +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/issues/issue-15207.rs b/src/test/ui/issues/issue-15207.rs index 356e55ac912e..10b1647cc6ab 100644 --- a/src/test/ui/issues/issue-15207.rs +++ b/src/test/ui/issues/issue-15207.rs @@ -1,6 +1,6 @@ fn main() { loop { - break.push(1) //~ ERROR no method named `push` found for type `!` + break.push(1) //~ ERROR type annotations needed ; } } diff --git a/src/test/ui/issues/issue-15207.stderr b/src/test/ui/issues/issue-15207.stderr index 25ce7cb5cc06..7a2164cda561 100644 --- a/src/test/ui/issues/issue-15207.stderr +++ b/src/test/ui/issues/issue-15207.stderr @@ -1,9 +1,11 @@ -error[E0599]: no method named `push` found for type `!` in the current scope - --> $DIR/issue-15207.rs:3:15 +error[E0282]: type annotations needed + --> $DIR/issue-15207.rs:3:9 | LL | break.push(1) - | ^^^^ method not found in `!` + | ^^^^^ cannot infer type + | + = note: type must be known at this point error: aborting due to previous error -For more information about this error, try `rustc --explain E0599`. +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/issues/issue-17373.rs b/src/test/ui/issues/issue-17373.rs index dc3be48a7ead..cafb589f8fb6 100644 --- a/src/test/ui/issues/issue-17373.rs +++ b/src/test/ui/issues/issue-17373.rs @@ -1,4 +1,4 @@ fn main() { - *return //~ ERROR type `!` cannot be dereferenced + *return //~ ERROR type annotations needed ; } diff --git a/src/test/ui/issues/issue-17373.stderr b/src/test/ui/issues/issue-17373.stderr index 5c429d1113df..5e852f7e3660 100644 --- a/src/test/ui/issues/issue-17373.stderr +++ b/src/test/ui/issues/issue-17373.stderr @@ -1,9 +1,11 @@ -error[E0614]: type `!` cannot be dereferenced +error[E0282]: type annotations needed --> $DIR/issue-17373.rs:2:5 | LL | *return - | ^^^^^^^ + | ^^^^^^^ cannot infer type + | + = note: type must be known at this point error: aborting due to previous error -For more information about this error, try `rustc --explain E0614`. +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/issues/issue-18532.rs b/src/test/ui/issues/issue-18532.rs index 31fd87961dc9..a668f6b78455 100644 --- a/src/test/ui/issues/issue-18532.rs +++ b/src/test/ui/issues/issue-18532.rs @@ -3,5 +3,5 @@ // into it. fn main() { - (return)((),()); //~ ERROR expected function, found `!` + (return)((),()); //~ ERROR type annotations needed } diff --git a/src/test/ui/issues/issue-18532.stderr b/src/test/ui/issues/issue-18532.stderr index 4c224eb2d243..7f5f2cd0ca11 100644 --- a/src/test/ui/issues/issue-18532.stderr +++ b/src/test/ui/issues/issue-18532.stderr @@ -1,11 +1,11 @@ -error[E0618]: expected function, found `!` +error[E0282]: type annotations needed --> $DIR/issue-18532.rs:6:5 | LL | (return)((),()); - | ^^^^^^^^------- - | | - | call expression requires function + | ^^^^^^^^^^^^^^^ cannot infer type + | + = note: type must be known at this point error: aborting due to previous error -For more information about this error, try `rustc --explain E0618`. +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/loops/loop-break-value.stderr b/src/test/ui/loops/loop-break-value.stderr index adb099f9b176..3d244ccce85a 100644 --- a/src/test/ui/loops/loop-break-value.stderr +++ b/src/test/ui/loops/loop-break-value.stderr @@ -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 diff --git a/src/test/ui/never_type/issue-10176.rs b/src/test/ui/never_type/issue-10176.rs index 6277aa05eb36..b9d34e005f88 100644 --- a/src/test/ui/never_type/issue-10176.rs +++ b/src/test/ui/never_type/issue-10176.rs @@ -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 } diff --git a/src/test/ui/never_type/issue-10176.stderr b/src/test/ui/never_type/issue-10176.stderr index cd5361ffad39..6aab366ab5a0 100644 --- a/src/test/ui/never_type/issue-10176.stderr +++ b/src/test/ui/never_type/issue-10176.stderr @@ -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 diff --git a/src/test/ui/never_type/tuple.rs b/src/test/ui/never_type/tuple.rs new file mode 100644 index 000000000000..c4f349277389 --- /dev/null +++ b/src/test/ui/never_type/tuple.rs @@ -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() {} diff --git a/src/test/ui/never_type/tuple.stderr b/src/test/ui/never_type/tuple.stderr new file mode 100644 index 000000000000..ea18b7c70150 --- /dev/null +++ b/src/test/ui/never_type/tuple.stderr @@ -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`. From 67e1eb3f8c12e340764708254e158085102bd8b3 Mon Sep 17 00:00:00 2001 From: lrh2000 Date: Thu, 6 May 2021 23:07:34 +0800 Subject: [PATCH 2/2] Allow early fallback of diverging type variables in typeck Previously, we issue "type annotations needed" when types must be known at some point but the resolution failed, even if the type variables are just some diverging ones. A typical example is `{ return }.foo()`. With this commit, the information about diverging is recorded in the unification table, so that we can check whether performing the fallback affects other non-diverging type variables. If it doesn't, we will safely perform the fallback and we won't issue "type annotations needed" anymore. Note lots of auxiliary type variables should be ignored during the check, which is done with the help of `TypeVariableOriginKind`. As a result, "type annotations needed" will be issued for ```rust let a = return; { if true { a } else { return } }.foo(); ``` but not for ```rust let a: ! = return; { if true { a } else { return } }.foo(); ``` --- compiler/rustc_infer/src/infer/mod.rs | 7 ++ .../rustc_infer/src/infer/type_variable.rs | 108 ++++++++++++++++-- compiler/rustc_infer/src/infer/undo_log.rs | 2 +- .../rustc_typeck/src/check/fn_ctxt/_impl.rs | 47 ++++++-- src/test/ui/asm/type-check-2.rs | 9 +- src/test/ui/index-bot.rs | 2 +- src/test/ui/index-bot.stderr | 8 +- src/test/ui/issues/issue-13847.rs | 2 +- src/test/ui/issues/issue-13847.stderr | 10 +- src/test/ui/issues/issue-15207.rs | 2 +- src/test/ui/issues/issue-15207.stderr | 10 +- src/test/ui/issues/issue-15965.rs | 2 +- src/test/ui/issues/issue-15965.stderr | 11 +- src/test/ui/issues/issue-17373.rs | 2 +- src/test/ui/issues/issue-17373.stderr | 8 +- src/test/ui/issues/issue-18532.rs | 2 +- src/test/ui/issues/issue-18532.stderr | 10 +- src/test/ui/never_type/early-fallback.rs | 27 +++++ src/test/ui/never_type/early-fallback.stderr | 34 ++++++ 19 files changed, 240 insertions(+), 63 deletions(-) create mode 100644 src/test/ui/never_type/early-fallback.rs create mode 100644 src/test/ui/never_type/early-fallback.stderr diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index f39431f2494b..23805cdfd7a7 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -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`, then this would return `Foo` (but `?Y` may diff --git a/compiler/rustc_infer/src/infer/type_variable.rs b/compiler/rustc_infer/src/infer/type_variable.rs index 683c1df783e6..b95548a8b35a 100644 --- a/compiler/rustc_infer/src/infer/type_variable.rs +++ b/compiler/rustc_infer/src/infer/type_variable.rs @@ -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>>), - SubRelation(sv::UndoLog>), + SubRelation(sv::UndoLog>), Values(sv::UndoLog), } @@ -28,8 +28,8 @@ impl<'tcx> From>>> for UndoLog<'tcx> { } /// Convert from a specific kind of undo to the more general UndoLog -impl<'tcx> From>> for UndoLog<'tcx> { - fn from(l: sv::UndoLog>) -> Self { +impl<'tcx> From>> for UndoLog<'tcx> { + fn from(l: sv::UndoLog>) -> 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` for any `?3`. - sub_relations: ut::UnificationTableStorage, + sub_relations: ut::UnificationTableStorage, } 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 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 { + 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, + } + } +} diff --git a/compiler/rustc_infer/src/infer/undo_log.rs b/compiler/rustc_infer/src/infer/undo_log.rs index 5ad2519a93c5..a2132f81f138 100644 --- a/compiler/rustc_infer/src/infer/undo_log.rs +++ b/compiler/rustc_infer/src/infer/undo_log.rs @@ -46,7 +46,7 @@ impl_from! { TypeVariables(type_variable::UndoLog<'tcx>), TypeVariables(sv::UndoLog>>), - TypeVariables(sv::UndoLog>), + TypeVariables(sv::UndoLog>), TypeVariables(sv::UndoLog), TypeVariables(type_variable::Instantiate), diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index 4de8216884a6..9be70094d532 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -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 } } diff --git a/src/test/ui/asm/type-check-2.rs b/src/test/ui/asm/type-check-2.rs index df48a19cc6d0..a56ccc707883 100644 --- a/src/test/ui/asm/type-check-2.rs +++ b/src/test/ui/asm/type-check-2.rs @@ -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); @@ -78,8 +78,7 @@ fn main() { // Type checks ignore never type - // FIXME: ERROR type annotations needed - // let u: ! = unreachable!(); - // asm!("{}", in(reg) u); + let u: ! = unreachable!(); + asm!("{}", in(reg) u); } } diff --git a/src/test/ui/index-bot.rs b/src/test/ui/index-bot.rs index 4945af668115..a6930eaf08cc 100644 --- a/src/test/ui/index-bot.rs +++ b/src/test/ui/index-bot.rs @@ -1,3 +1,3 @@ fn main() { - (return)[0]; //~ ERROR type annotations needed + (return)[0]; //~ ERROR cannot index into a value of type `()` } diff --git a/src/test/ui/index-bot.stderr b/src/test/ui/index-bot.stderr index 2f368875abb7..225bf7724af3 100644 --- a/src/test/ui/index-bot.stderr +++ b/src/test/ui/index-bot.stderr @@ -1,11 +1,9 @@ -error[E0282]: type annotations needed +error[E0608]: cannot index into a value of type `()` --> $DIR/index-bot.rs:2:5 | LL | (return)[0]; - | ^^^^^^^^ cannot infer type - | - = note: type must be known at this point + | ^^^^^^^^^^^ help: to access tuple elements, use: `(return).0` 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 E0608`. diff --git a/src/test/ui/issues/issue-13847.rs b/src/test/ui/issues/issue-13847.rs index 002698abf4d8..c8e72d131525 100644 --- a/src/test/ui/issues/issue-13847.rs +++ b/src/test/ui/issues/issue-13847.rs @@ -1,3 +1,3 @@ fn main() { - return.is_failure //~ ERROR type annotations needed + return.is_failure //~ ERROR no field `is_failure` on type `()` } diff --git a/src/test/ui/issues/issue-13847.stderr b/src/test/ui/issues/issue-13847.stderr index 7e682f8a717f..c262802ca8a1 100644 --- a/src/test/ui/issues/issue-13847.stderr +++ b/src/test/ui/issues/issue-13847.stderr @@ -1,11 +1,9 @@ -error[E0282]: type annotations needed - --> $DIR/issue-13847.rs:2:5 +error[E0609]: no field `is_failure` on type `()` + --> $DIR/issue-13847.rs:2:12 | LL | return.is_failure - | ^^^^^^ cannot infer type - | - = note: type must be known at this point + | ^^^^^^^^^^ 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 E0609`. diff --git a/src/test/ui/issues/issue-15207.rs b/src/test/ui/issues/issue-15207.rs index 10b1647cc6ab..199cf71b7543 100644 --- a/src/test/ui/issues/issue-15207.rs +++ b/src/test/ui/issues/issue-15207.rs @@ -1,6 +1,6 @@ fn main() { loop { - break.push(1) //~ ERROR type annotations needed + break.push(1) //~ ERROR no method named `push` found for unit type `()` ; } } diff --git a/src/test/ui/issues/issue-15207.stderr b/src/test/ui/issues/issue-15207.stderr index 7a2164cda561..f9624238b456 100644 --- a/src/test/ui/issues/issue-15207.stderr +++ b/src/test/ui/issues/issue-15207.stderr @@ -1,11 +1,9 @@ -error[E0282]: type annotations needed - --> $DIR/issue-15207.rs:3:9 +error[E0599]: no method named `push` found for unit type `()` in the current scope + --> $DIR/issue-15207.rs:3:15 | LL | break.push(1) - | ^^^^^ cannot infer type - | - = note: type must be known at this point + | ^^^^ method not found in `()` 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 E0599`. diff --git a/src/test/ui/issues/issue-15965.rs b/src/test/ui/issues/issue-15965.rs index eef4900d432d..0bfe02c0689e 100644 --- a/src/test/ui/issues/issue-15965.rs +++ b/src/test/ui/issues/issue-15965.rs @@ -1,7 +1,7 @@ fn main() { return { return () } -//~^ ERROR type annotations needed [E0282] +//~^ ERROR expected function, found `_` () ; } diff --git a/src/test/ui/issues/issue-15965.stderr b/src/test/ui/issues/issue-15965.stderr index 90377c19dee0..517097b15994 100644 --- a/src/test/ui/issues/issue-15965.stderr +++ b/src/test/ui/issues/issue-15965.stderr @@ -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`. diff --git a/src/test/ui/issues/issue-17373.rs b/src/test/ui/issues/issue-17373.rs index cafb589f8fb6..149226e8ec2a 100644 --- a/src/test/ui/issues/issue-17373.rs +++ b/src/test/ui/issues/issue-17373.rs @@ -1,4 +1,4 @@ fn main() { - *return //~ ERROR type annotations needed + *return //~ ERROR type `()` cannot be dereferenced ; } diff --git a/src/test/ui/issues/issue-17373.stderr b/src/test/ui/issues/issue-17373.stderr index 5e852f7e3660..04d18911ce1b 100644 --- a/src/test/ui/issues/issue-17373.stderr +++ b/src/test/ui/issues/issue-17373.stderr @@ -1,11 +1,9 @@ -error[E0282]: type annotations needed +error[E0614]: type `()` cannot be dereferenced --> $DIR/issue-17373.rs:2:5 | LL | *return - | ^^^^^^^ cannot infer type - | - = note: type must be known at this point + | ^^^^^^^ 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 E0614`. diff --git a/src/test/ui/issues/issue-18532.rs b/src/test/ui/issues/issue-18532.rs index a668f6b78455..914a424f2c0d 100644 --- a/src/test/ui/issues/issue-18532.rs +++ b/src/test/ui/issues/issue-18532.rs @@ -3,5 +3,5 @@ // into it. fn main() { - (return)((),()); //~ ERROR type annotations needed + (return)((),()); //~ ERROR expected function, found `_` } diff --git a/src/test/ui/issues/issue-18532.stderr b/src/test/ui/issues/issue-18532.stderr index 7f5f2cd0ca11..fd1782947996 100644 --- a/src/test/ui/issues/issue-18532.stderr +++ b/src/test/ui/issues/issue-18532.stderr @@ -1,11 +1,11 @@ -error[E0282]: type annotations needed +error[E0618]: expected function, found `_` --> $DIR/issue-18532.rs:6:5 | LL | (return)((),()); - | ^^^^^^^^^^^^^^^ 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`. diff --git a/src/test/ui/never_type/early-fallback.rs b/src/test/ui/never_type/early-fallback.rs new file mode 100644 index 000000000000..53df2321a841 --- /dev/null +++ b/src/test/ui/never_type/early-fallback.rs @@ -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() {} diff --git a/src/test/ui/never_type/early-fallback.stderr b/src/test/ui/never_type/early-fallback.stderr new file mode 100644 index 000000000000..2c0286c011a5 --- /dev/null +++ b/src/test/ui/never_type/early-fallback.stderr @@ -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`.