Skip to content

Commit 1931a64

Browse files
committed
"structural" ruleset: use the "classic" ruleset's diagnostic and fallback for inherited ref mutability mismatches
I think the diagnostic could use some work, but it's more helpful than the alternative. The previous error was misleading, since it ignored the inherited reference altogether.
1 parent a49badf commit 1931a64

File tree

4 files changed

+151
-382
lines changed

4 files changed

+151
-382
lines changed

compiler/rustc_hir_typeck/src/pat.rs

+31-27
Original file line numberDiff line numberDiff line change
@@ -2288,22 +2288,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
22882288
// NB: This assumes that `&` patterns can match against mutable references
22892289
// (RFC 3627, Rule 5). If we implement a pattern typing ruleset with Rule 4E
22902290
// but not Rule 5, we'll need to check that here.
2291-
let err_msg = "mismatched types";
2292-
let err = if let Some(span) = pat_prefix_span {
2293-
let mut err = self.dcx().struct_span_err(span, err_msg);
2294-
err.code(E0308);
2295-
err.note("cannot match inherited `&` with `&mut` pattern");
2296-
err.span_suggestion_verbose(
2297-
span,
2298-
"replace this `&mut` pattern with `&`",
2299-
"&",
2300-
Applicability::MachineApplicable,
2301-
);
2302-
err
2303-
} else {
2304-
self.dcx().struct_span_err(pat.span, err_msg)
2305-
};
2306-
err.emit();
2291+
self.error_inherited_ref_mutability_mismatch(pat, pat_prefix_span);
23072292
}
23082293

23092294
pat_info.binding_mode = ByRef::No;
@@ -2322,21 +2307,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
23222307
} else {
23232308
// The expected type isn't a reference, so match against the inherited ref.
23242309
if pat_mutbl > inh_mut {
2325-
// We can't match an inherited shared reference with `&mut`. This will
2326-
// be a type error later, since we're matching a reference pattern
2327-
// against a non-reference type.
2310+
// We can't match an inherited shared reference with `&mut`.
23282311
// NB: This assumes that `&` patterns can match against mutable
23292312
// references (RFC 3627, Rule 5). If we implement a pattern typing
23302313
// ruleset with Rule 4 but not Rule 5, we'll need to check that here.
2331-
} else {
2332-
pat_info.binding_mode = ByRef::No;
2333-
self.typeck_results
2334-
.borrow_mut()
2335-
.skipped_ref_pats_mut()
2336-
.insert(pat.hir_id);
2337-
self.check_pat(inner, expected, pat_info);
2338-
return expected;
2314+
self.error_inherited_ref_mutability_mismatch(pat, pat_prefix_span);
23392315
}
2316+
2317+
pat_info.binding_mode = ByRef::No;
2318+
self.typeck_results.borrow_mut().skipped_ref_pats_mut().insert(pat.hir_id);
2319+
self.check_pat(inner, expected, pat_info);
2320+
return expected;
23402321
}
23412322
}
23422323
InheritedRefMatchRule::EatBoth => {
@@ -2410,6 +2391,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
24102391
Ty::new_ref(self.tcx, region, ty, mutbl)
24112392
}
24122393

2394+
fn error_inherited_ref_mutability_mismatch(
2395+
&self,
2396+
pat: &'tcx Pat<'tcx>,
2397+
pat_prefix_span: Option<Span>,
2398+
) -> ErrorGuaranteed {
2399+
let err_msg = "mismatched types";
2400+
let err = if let Some(span) = pat_prefix_span {
2401+
let mut err = self.dcx().struct_span_err(span, err_msg);
2402+
err.code(E0308);
2403+
err.note("cannot match inherited `&` with `&mut` pattern");
2404+
err.span_suggestion_verbose(
2405+
span,
2406+
"replace this `&mut` pattern with `&`",
2407+
"&",
2408+
Applicability::MachineApplicable,
2409+
);
2410+
err
2411+
} else {
2412+
self.dcx().struct_span_err(pat.span, err_msg)
2413+
};
2414+
err.emit()
2415+
}
2416+
24132417
fn try_resolve_slice_ty_to_array_ty(
24142418
&self,
24152419
before: &'tcx [Pat<'tcx>],

tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ LL | if let Some(&Some(x)) = &Some(Some(0)) {
8383
| ~
8484

8585
error[E0308]: mismatched types
86-
--> $DIR/pattern-errors.rs:125:10
86+
--> $DIR/pattern-errors.rs:123:10
8787
|
8888
LL | let [&mut x] = &[&mut 0];
8989
| ^^^^^
@@ -95,7 +95,7 @@ LL | let [&x] = &[&mut 0];
9595
| ~
9696

9797
error[E0308]: mismatched types
98-
--> $DIR/pattern-errors.rs:130:10
98+
--> $DIR/pattern-errors.rs:128:10
9999
|
100100
LL | let [&mut &x] = &[&mut 0];
101101
| ^^^^^
@@ -107,7 +107,7 @@ LL | let [&&x] = &[&mut 0];
107107
| ~
108108

109109
error[E0308]: mismatched types
110-
--> $DIR/pattern-errors.rs:135:10
110+
--> $DIR/pattern-errors.rs:133:10
111111
|
112112
LL | let [&mut &ref x] = &[&mut 0];
113113
| ^^^^^
@@ -119,7 +119,7 @@ LL | let [&&ref x] = &[&mut 0];
119119
| ~
120120

121121
error[E0308]: mismatched types
122-
--> $DIR/pattern-errors.rs:140:10
122+
--> $DIR/pattern-errors.rs:138:10
123123
|
124124
LL | let [&mut &(mut x)] = &[&mut 0];
125125
| ^^^^^

tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs

+14-16
Original file line numberDiff line numberDiff line change
@@ -45,37 +45,36 @@ pub fn main() {
4545
}
4646
}
4747

48-
// TODO: these should be mutability mismatches on `structural`
4948
fn structural_errors_0() {
5049
let &[&mut x] = &&mut [0];
5150
//[structural]~^ ERROR: mismatched types
51+
//[structural]~| cannot match inherited `&` with `&mut` pattern
5252
let _: u32 = x;
53-
//[structural]~^ ERROR: mismatched types
5453

5554
let &[&mut x] = &mut &mut [0];
5655
//[structural]~^ ERROR: mismatched types
56+
//[structural]~| cannot match inherited `&` with `&mut` pattern
5757
let _: u32 = x;
58-
//[structural]~^ ERROR: mismatched types
5958

6059
let &[&mut ref x] = &&mut [0];
6160
//[structural]~^ ERROR: mismatched types
61+
//[structural]~| cannot match inherited `&` with `&mut` pattern
6262
let _: &u32 = x;
6363

6464
let &[&mut ref x] = &mut &mut [0];
6565
//[structural]~^ ERROR: mismatched types
66+
//[structural]~| cannot match inherited `&` with `&mut` pattern
6667
let _: &u32 = x;
6768

6869
let &[&mut mut x] = &&mut [0];
6970
//[structural]~^ ERROR: mismatched types
70-
//[structural]~| ERROR: binding cannot be both mutable and by-reference
71+
//[structural]~| cannot match inherited `&` with `&mut` pattern
7172
let _: u32 = x;
72-
//[structural]~^ ERROR: mismatched types
7373

7474
let &[&mut mut x] = &mut &mut [0];
7575
//[structural]~^ ERROR: mismatched types
76-
//[structural]~| ERROR: binding cannot be both mutable and by-reference
76+
//[structural]~| cannot match inherited `&` with `&mut` pattern
7777
let _: u32 = x;
78-
//[structural]~^ ERROR: mismatched types
7978
}
8079

8180
fn structural_errors_1() {
@@ -88,37 +87,36 @@ fn structural_errors_1() {
8887
let _: &u32 = x;
8988
}
9089

91-
// TODO: these should be mutability mismatches on `structural`
9290
fn structural_errors_2() {
9391
let [&&mut x] = &[&mut 0];
9492
//[structural]~^ ERROR: mismatched types
93+
//[structural]~| cannot match inherited `&` with `&mut` pattern
9594
let _: u32 = x;
96-
//[structural]~^ ERROR: mismatched types
9795

9896
let [&&mut x] = &mut [&mut 0];
9997
//[structural]~^ ERROR: mismatched types
98+
//[structural]~| cannot match inherited `&` with `&mut` pattern
10099
let _: u32 = x;
101-
//[structural]~^ ERROR: mismatched types
102100

103101
let [&&mut ref x] = &[&mut 0];
104102
//[structural]~^ ERROR: mismatched types
103+
//[structural]~| cannot match inherited `&` with `&mut` pattern
105104
let _: &u32 = x;
106105

107106
let [&&mut ref x] = &mut [&mut 0];
108107
//[structural]~^ ERROR: mismatched types
108+
//[structural]~| cannot match inherited `&` with `&mut` pattern
109109
let _: &u32 = x;
110110

111111
let [&&mut mut x] = &[&mut 0];
112-
//[structural]~^ ERROR: binding cannot be both mutable and by-reference
113-
//[structural]~| ERROR: mismatched types
114-
let _: u32 = x;
115112
//[structural]~^ ERROR: mismatched types
113+
//[structural]~| cannot match inherited `&` with `&mut` pattern
114+
let _: u32 = x;
116115

117116
let [&&mut mut x] = &mut [&mut 0];
118-
//[structural]~^ ERROR: binding cannot be both mutable and by-reference
119-
//[structural]~| ERROR: mismatched types
120-
let _: u32 = x;
121117
//[structural]~^ ERROR: mismatched types
118+
//[structural]~| cannot match inherited `&` with `&mut` pattern
119+
let _: u32 = x;
122120
}
123121

124122
fn classic_errors_0() {

0 commit comments

Comments
 (0)