Support let &mut x = &&mut 0;

This commit is contained in:
Jules Bertholet 2024-04-05 22:07:57 -04:00
parent 4cd87c463c
commit b6c409723b
No known key found for this signature in database
GPG Key ID: 32034DAFC38C1BFC
4 changed files with 60 additions and 10 deletions

View File

@ -299,18 +299,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if mutbls_match { if mutbls_match {
(expected, INITIAL_BM, true) (expected, INITIAL_BM, true)
} else { } else {
let mut new_bm = def_bm; let (new_ty, new_bm) = if mutbl == Mutability::Mut {
if new_bm.0 == ByRef::Yes(Mutability::Mut) && mutbl == Mutability::Not { self.peel_off_references(pat, expected, def_bm, Mutability::Not)
new_bm.0 = ByRef::Yes(Mutability::Not); } else {
} let new_byref = if def_bm.0 == ByRef::Yes(Mutability::Mut) {
(expected, new_bm, false) ByRef::Yes(Mutability::Not)
} else {
def_bm.0
};
(expected, BindingAnnotation(new_byref, def_bm.1))
};
(new_ty, new_bm, false)
} }
} else { } else {
(expected, INITIAL_BM, mutbls_match) (expected, INITIAL_BM, mutbls_match)
} }
} }
AdjustMode::Peel => { AdjustMode::Peel => {
let peeled = self.peel_off_references(pat, expected, def_bm); let peeled = self.peel_off_references(pat, expected, def_bm, Mutability::Mut);
(peeled.0, peeled.1, false) (peeled.0, peeled.1, false)
} }
} }
@ -392,6 +398,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pat: &'tcx Pat<'tcx>, pat: &'tcx Pat<'tcx>,
expected: Ty<'tcx>, expected: Ty<'tcx>,
mut def_bm: BindingAnnotation, mut def_bm: BindingAnnotation,
max_mutability: Mutability,
) -> (Ty<'tcx>, BindingAnnotation) { ) -> (Ty<'tcx>, BindingAnnotation) {
let mut expected = self.try_structurally_resolve_type(pat.span, expected); let mut expected = self.try_structurally_resolve_type(pat.span, expected);
// Peel off as many `&` or `&mut` from the scrutinee type as possible. For example, // Peel off as many `&` or `&mut` from the scrutinee type as possible. For example,
@ -403,7 +410,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// //
// See the examples in `ui/match-defbm*.rs`. // See the examples in `ui/match-defbm*.rs`.
let mut pat_adjustments = vec![]; let mut pat_adjustments = vec![];
while let ty::Ref(_, inner_ty, inner_mutability) = *expected.kind() { while let ty::Ref(_, inner_ty, inner_mutability) = *expected.kind()
&& inner_mutability <= max_mutability
{
debug!("inspecting {:?}", expected); debug!("inspecting {:?}", expected);
debug!("current discriminant is Ref, inserting implicit deref"); debug!("current discriminant is Ref, inserting implicit deref");

View File

@ -38,4 +38,13 @@ pub fn main() {
if let Some(Some(&mut x)) = &Some(Some(&mut 0)) { if let Some(Some(&mut x)) = &Some(Some(&mut 0)) {
let _: &u32 = x; let _: &u32 = x;
} }
let &mut x = &&mut 0;
let _: &u32 = x;
let &mut x = &&&&&&&&&&&&&&&&&&&&&&&&&&&&mut 0;
let _: &u32 = x;
let &mut &mut &mut &mut x = &mut &&&&mut &&&mut &mut 0;
let _: &u32 = x;
} }

View File

@ -17,4 +17,12 @@ pub fn main() {
if let Some(&Some(&x)) = Some(&Some(&mut 0)) { if let Some(&Some(&x)) = Some(&Some(&mut 0)) {
//~^ ERROR: mismatched types //~^ ERROR: mismatched types
} }
let &mut x = &&0;
//~^ ERROR: mismatched types
let _: &u32 = x;
let &mut x = &&&&&&&&&&&&&&&&&&&&&&&&&&&&0;
//~^ ERROR: mismatched types
let _: &u32 = x;
} }

View File

@ -4,9 +4,9 @@ error[E0308]: mismatched types
LL | if let Some(&mut Some(&_)) = &Some(&Some(0)) { LL | if let Some(&mut Some(&_)) = &Some(&Some(0)) {
| ^^^^^^^^^^^^^ --------------- this expression has type `&Option<&Option<{integer}>>` | ^^^^^^^^^^^^^ --------------- this expression has type `&Option<&Option<{integer}>>`
| | | |
| types differ in mutability | expected `Option<{integer}>`, found `&mut _`
| |
= note: expected reference `&Option<{integer}>` = note: expected enum `Option<{integer}>`
found mutable reference `&mut _` found mutable reference `&mut _`
error[E0308]: mismatched types error[E0308]: mismatched types
@ -46,6 +46,30 @@ help: consider removing `&` from the pattern
LL | if let Some(&Some(x)) = Some(&Some(&mut 0)) { LL | if let Some(&Some(x)) = Some(&Some(&mut 0)) {
| ~ | ~
error: aborting due to 4 previous errors error[E0308]: mismatched types
--> $DIR/ref_pat_eat_one_layer_2024_fail.rs:21:9
|
LL | let &mut x = &&0;
| ^^^^^^ --- this expression has type `&&{integer}`
| |
| expected integer, found `&mut _`
| help: to declare a mutable variable use: `mut x`
|
= note: expected type `{integer}`
found mutable reference `&mut _`
error[E0308]: mismatched types
--> $DIR/ref_pat_eat_one_layer_2024_fail.rs:25:9
|
LL | let &mut x = &&&&&&&&&&&&&&&&&&&&&&&&&&&&0;
| ^^^^^^ ----------------------------- this expression has type `&&&&&&&&&&&&&&&&&&&&&&&&&&&&{integer}`
| |
| expected integer, found `&mut _`
| help: to declare a mutable variable use: `mut x`
|
= note: expected type `{integer}`
found mutable reference `&mut _`
error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0308`. For more information about this error, try `rustc --explain E0308`.