about summary refs log tree commit diff
path: root/compiler/rustc_middle
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2024-12-14 23:56:28 +0100
committerGitHub <noreply@github.com>2024-12-14 23:56:28 +0100
commitdb77788dc5d72da6dc2077e59d9ff321cbda1cec (patch)
treec66a72aeeff0f31ff9a70e4a3b0b9c49fb0c9569 /compiler/rustc_middle
parent0aeaa5eb22180fdf12a8489e63c4daa18da6f236 (diff)
parent831f4549cd1b23915729cbd2f1dd841621c4e8b8 (diff)
downloadrust-db77788dc5d72da6dc2077e59d9ff321cbda1cec.tar.gz
rust-db77788dc5d72da6dc2077e59d9ff321cbda1cec.zip
Rollup merge of #132939 - uellenberg:suggest-deref, r=oli-obk
Suggest using deref in patterns

Fixes #132784

This changes the following code:
```rs
use std::sync::Arc;
fn main() {
    let mut x = Arc::new(Some(1));
    match x {
        Some(_) => {}
        None => {}
    }
}
```

to output
```rs
error[E0308]: mismatched types
  --> src/main.rs:5:9
   |
LL |     match x {
   |           - this expression has type `Arc<Option<{integer}>>`
...
LL |         Some(_) => {}
   |         ^^^^^^^ expected `Arc<Option<{integer}>>`, found `Option<_>`
   |
   = note: expected struct `Arc<Option<{integer}>>`
                found enum `Option<_>`
help: consider dereferencing to access the inner value using the Deref trait
   |
LL |     match *x {
   |           ~~
```

instead of
```rs
error[E0308]: mismatched types
 --> src/main.rs:5:9
  |
4 |     match x {
  |           - this expression has type `Arc<Option<{integer}>>`
5 |         Some(_) => {}
  |         ^^^^^^^ expected `Arc<Option<{integer}>>`, found `Option<_>`
  |
  = note: expected struct `Arc<Option<{integer}>>`
               found enum `Option<_>`
```

This makes it more obvious that a Deref is available, and gives a suggestion on how to use it in order to fix the issue at hand.
Diffstat (limited to 'compiler/rustc_middle')
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs23
1 files changed, 21 insertions, 2 deletions
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index 0a77c3bc42f..8c434265d27 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -316,8 +316,8 @@ pub enum ObligationCauseCode<'tcx> {
         span: Option<Span>,
         /// The root expected type induced by a scrutinee or type expression.
         root_ty: Ty<'tcx>,
-        /// Whether the `Span` came from an expression or a type expression.
-        origin_expr: bool,
+        /// Information about the `Span`, if it came from an expression, otherwise `None`.
+        origin_expr: Option<PatternOriginExpr>,
     },
 
     /// Computing common supertype in an if expression
@@ -530,6 +530,25 @@ pub struct MatchExpressionArmCause<'tcx> {
     pub tail_defines_return_position_impl_trait: Option<LocalDefId>,
 }
 
+/// Information about the origin expression of a pattern, relevant to diagnostics.
+/// Fields here refer to the scrutinee of a pattern.
+/// If the scrutinee isn't given in the diagnostic, then this won't exist.
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+#[derive(TypeFoldable, TypeVisitable, HashStable, TyEncodable, TyDecodable)]
+pub struct PatternOriginExpr {
+    /// A span representing the scrutinee expression, with all leading references
+    /// peeled from the expression.
+    /// Only references in the expression are peeled - if the expression refers to a variable
+    /// whose type is a reference, then that reference is kept because it wasn't created
+    /// in the expression.
+    pub peeled_span: Span,
+    /// The number of references that were peeled to produce `peeled_span`.
+    pub peeled_count: usize,
+    /// Does the peeled expression need to be wrapped in parentheses for
+    /// a prefix suggestion (i.e., dereference) to be valid.
+    pub peeled_prefix_suggestion_parentheses: bool,
+}
+
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
 #[derive(TypeFoldable, TypeVisitable, HashStable, TyEncodable, TyDecodable)]
 pub struct IfExpressionCause<'tcx> {