From ac06d9cca369b164ab522eba81d6b048309f058a Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 23 Sep 2022 13:24:35 -0700 Subject: [PATCH] diagnostics: avoid syntactically invalid suggestion in if conditionals Fixes #101065 --- compiler/rustc_typeck/src/check/demand.rs | 10 +++++++++ src/test/ui/suggestions/issue-101065.fixed | 14 +++++++++++++ src/test/ui/suggestions/issue-101065.rs | 14 +++++++++++++ src/test/ui/suggestions/issue-101065.stderr | 23 +++++++++++++++++++++ 4 files changed, 61 insertions(+) create mode 100644 src/test/ui/suggestions/issue-101065.fixed create mode 100644 src/test/ui/suggestions/issue-101065.rs create mode 100644 src/test/ui/suggestions/issue-101065.stderr diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index e1d55ff82cbad..2c07c333a6f98 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -417,6 +417,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { hir::def::CtorKind::Const => unreachable!(), }; + // Suggest constructor as deep into the block tree as possible. + // This fixes https://github.com/rust-lang/rust/issues/101065, + // and also just helps make the most minimal suggestions. + let mut expr = expr; + while let hir::ExprKind::Block(block, _) = &expr.kind + && let Some(expr_) = &block.expr + { + expr = expr_ + } + vec![ (expr.span.shrink_to_lo(), format!("{prefix}{variant}{open}")), (expr.span.shrink_to_hi(), close.to_owned()), diff --git a/src/test/ui/suggestions/issue-101065.fixed b/src/test/ui/suggestions/issue-101065.fixed new file mode 100644 index 0000000000000..88c716cc86ce8 --- /dev/null +++ b/src/test/ui/suggestions/issue-101065.fixed @@ -0,0 +1,14 @@ +// check-fail +// run-rustfix + +enum FakeResult { + Ok(T) +} + +fn main() { + let _x = if true { + FakeResult::Ok(FakeResult::Ok(())) + } else { + FakeResult::Ok(FakeResult::Ok(())) //~ERROR E0308 + }; +} diff --git a/src/test/ui/suggestions/issue-101065.rs b/src/test/ui/suggestions/issue-101065.rs new file mode 100644 index 0000000000000..2715f1027082f --- /dev/null +++ b/src/test/ui/suggestions/issue-101065.rs @@ -0,0 +1,14 @@ +// check-fail +// run-rustfix + +enum FakeResult { + Ok(T) +} + +fn main() { + let _x = if true { + FakeResult::Ok(FakeResult::Ok(())) + } else { + FakeResult::Ok(()) //~ERROR E0308 + }; +} diff --git a/src/test/ui/suggestions/issue-101065.stderr b/src/test/ui/suggestions/issue-101065.stderr new file mode 100644 index 0000000000000..6f7ecd24ca428 --- /dev/null +++ b/src/test/ui/suggestions/issue-101065.stderr @@ -0,0 +1,23 @@ +error[E0308]: `if` and `else` have incompatible types + --> $DIR/issue-101065.rs:12:9 + | +LL | let _x = if true { + | ______________- +LL | | FakeResult::Ok(FakeResult::Ok(())) + | | ---------------------------------- expected because of this +LL | | } else { +LL | | FakeResult::Ok(()) + | | ^^^^^^^^^^^^^^^^^^ expected enum `FakeResult`, found `()` +LL | | }; + | |_____- `if` and `else` have incompatible types + | + = note: expected enum `FakeResult>` + found enum `FakeResult<()>` +help: try wrapping the expression in `FakeResult::Ok` + | +LL | FakeResult::Ok(FakeResult::Ok(())) + | +++++++++++++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`.