diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs index 44baa213b2847..29e63f37e4932 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs @@ -11,7 +11,9 @@ use rustc_hir::{MatchSource, Node}; use rustc_middle::traits::{MatchExpressionArmCause, ObligationCause, ObligationCauseCode}; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::print::with_no_trimmed_paths; -use rustc_middle::ty::{self as ty, GenericArgKind, IsSuggestable, Ty, TypeVisitableExt}; +use rustc_middle::ty::{ + self as ty, GenericArgKind, IsSuggestable, Ty, TypeFlags, TypeVisitableExt, +}; use rustc_span::{Span, sym}; use tracing::debug; @@ -89,6 +91,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { exp_found: &ty::error::ExpectedFound>, diag: &mut Diag<'_>, ) { + // when found is unresolved var, we can't suggest anything + if exp_found.found.has_type_flags(TypeFlags::HAS_INFER_TY_VAR) { + return; + } + // Heavily inspired by `FnCtxt::suggest_compatible_variants`, with // some modifications due to that being in typeck and this being in infer. if let ObligationCauseCode::Pattern { .. } = cause.code() diff --git a/compiler/rustc_type_ir/src/flags.rs b/compiler/rustc_type_ir/src/flags.rs index 23b7f55fbbe53..df4d050fee7d3 100644 --- a/compiler/rustc_type_ir/src/flags.rs +++ b/compiler/rustc_type_ir/src/flags.rs @@ -133,6 +133,9 @@ bitflags::bitflags! { /// Does this type have any coroutines in it? const HAS_TY_CORO = 1 << 24; + + /// Does this type have any Infer(TyVar(_)) in it? + const HAS_INFER_TY_VAR = 1 << 25; } } @@ -267,9 +270,10 @@ impl FlagComputation { ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => { self.add_flags(TypeFlags::HAS_TY_FRESH) } - - ty::TyVar(_) | ty::IntVar(_) | ty::FloatVar(_) => { - self.add_flags(TypeFlags::HAS_TY_INFER) + ty::IntVar(_) | ty::FloatVar(_) => self.add_flags(TypeFlags::HAS_TY_INFER), + ty::TyVar(_) => { + self.add_flags(TypeFlags::HAS_INFER_TY_VAR); + self.add_flags(TypeFlags::HAS_TY_INFER); } }, diff --git a/tests/ui/issues/issue-3680.stderr b/tests/ui/issues/issue-3680.stderr index 2a757b44dc834..85beac9e2943a 100644 --- a/tests/ui/issues/issue-3680.stderr +++ b/tests/ui/issues/issue-3680.stderr @@ -8,10 +8,6 @@ LL | Err(_) => () | = note: expected enum `Option<_>` found enum `Result<_, _>` -help: try wrapping the pattern in `Some` - | -LL | Some(Err(_)) => () - | +++++ + error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-5358-1.stderr b/tests/ui/issues/issue-5358-1.stderr index e68db865dc414..1cafff19f077a 100644 --- a/tests/ui/issues/issue-5358-1.stderr +++ b/tests/ui/issues/issue-5358-1.stderr @@ -8,10 +8,6 @@ LL | Either::Right(_) => {} | = note: expected struct `S` found enum `Either<_, _>` -help: try wrapping the pattern in `S` - | -LL | S(Either::Right(_)) => {} - | ++ + help: you might have meant to use field `0` whose type is `Either` | LL | match S(Either::Left(5)).0 { diff --git a/tests/ui/match/issue-12552.stderr b/tests/ui/match/issue-12552.stderr index 195192fbd8240..58a8340f751de 100644 --- a/tests/ui/match/issue-12552.stderr +++ b/tests/ui/match/issue-12552.stderr @@ -8,10 +8,6 @@ LL | Some(k) => match k { | = note: expected enum `Result<_, {integer}>` found enum `Option<_>` -help: try wrapping the pattern in `Ok` - | -LL | Ok(Some(k)) => match k { - | +++ + error[E0308]: mismatched types --> $DIR/issue-12552.rs:9:5 @@ -24,10 +20,6 @@ LL | None => () | = note: expected enum `Result<_, {integer}>` found enum `Option<_>` -help: try wrapping the pattern in `Ok` - | -LL | Ok(None) => () - | +++ + error: aborting due to 2 previous errors diff --git a/tests/ui/type/type-mismatch-suggest-wrap-issue-145634.rs b/tests/ui/type/type-mismatch-suggest-wrap-issue-145634.rs new file mode 100644 index 0000000000000..9ad9f2a9a7d6d --- /dev/null +++ b/tests/ui/type/type-mismatch-suggest-wrap-issue-145634.rs @@ -0,0 +1,9 @@ +// We should not suggest wrapping rhs with `Some` +// when the found type is an unresolved type variable +// +// See https://github.com/rust-lang/rust/issues/145634 + +fn main() { + let foo = Some(&(1, 2)); + assert!(matches!(foo, &Some((1, 2)))); //~ ERROR mismatched types [E0308] +} diff --git a/tests/ui/type/type-mismatch-suggest-wrap-issue-145634.stderr b/tests/ui/type/type-mismatch-suggest-wrap-issue-145634.stderr new file mode 100644 index 0000000000000..9dfa1ef513c5e --- /dev/null +++ b/tests/ui/type/type-mismatch-suggest-wrap-issue-145634.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/type-mismatch-suggest-wrap-issue-145634.rs:8:27 + | +LL | assert!(matches!(foo, &Some((1, 2)))); + | --- ^^^^^^^^^^^^^ expected `Option<&({integer}, {integer})>`, found `&_` + | | + | this expression has type `Option<&({integer}, {integer})>` + | + = note: expected enum `Option<&({integer}, {integer})>` + found reference `&_` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`.