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 d056f2c90f988..6fb0529b6690d 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 236fec94bdba7..3b305724f7540 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 d0cbb58fb10eb..f0dc39ed8f43c 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 6e36dc06a201e..6e5690823e9d0 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 97ffd664463bb..4c99529ab374a 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 8355b2d195e14..6a359cb6c26d3 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 3c26b20c35e2d..74682b59d069a 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 261eb3b27eafd..f0e4d33cea910 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 261eb3b27eafd..f0e4d33cea910 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 99c7ac8d5b708..db85fe8609313 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 c6ef403c3c130..916b0aee12efd 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 52e705fdbeba8..4f044a0d350f4 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 fef3ae2e461d8..35fca87efe786 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 c17fe3bb75757..40b997edfa50b 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 de8a29ea25fcd..1c30d502e8a22 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 de8a29ea25fcd..1c30d502e8a22 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 c70a8802814f7..df48a19cc6d04 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 ad3e5ab3dc9d8..90a6f2ede7022 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 e69c4019f61e5..4945af668115f 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 b5d78297505d3..2f368875abb7a 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 06a0304ae4975..002698abf4d81 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 52b8dc049702a..7e682f8a717f5 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 356e55ac912ec..10b1647cc6ab5 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 25ce7cb5cc069..7a2164cda561c 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 dc3be48a7ead7..cafb589f8fb61 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 5c429d1113df4..5e852f7e3660a 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 31fd87961dc9f..a668f6b784552 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 4c224eb2d2430..7f5f2cd0ca11c 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 adb099f9b1769..3d244ccce85aa 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 6277aa05eb365..b9d34e005f887 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 cd5361ffad398..6aab366ab5a0c 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 0000000000000..c4f349277389e --- /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 0000000000000..ea18b7c70150c --- /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 f39431f2494b1..23805cdfd7a74 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 683c1df783e63..b95548a8b35a3 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 5ad2519a93c5f..a2132f81f138e 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 4de8216884a68..9be70094d5326 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 df48a19cc6d04..a56ccc7078835 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 4945af668115f..a6930eaf08cc6 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 2f368875abb7a..225bf7724af3a 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 002698abf4d81..c8e72d1315257 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 7e682f8a717f5..c262802ca8a15 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 10b1647cc6ab5..199cf71b75437 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 7a2164cda561c..f9624238b4568 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 eef4900d432d0..0bfe02c0689e5 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 90377c19dee02..517097b159941 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 cafb589f8fb61..149226e8ec2a3 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 5e852f7e3660a..04d18911ce1b8 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 a668f6b784552..914a424f2c0d8 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 7f5f2cd0ca11c..fd17829479969 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 0000000000000..53df2321a8416 --- /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 0000000000000..2c0286c011a5d --- /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`.