diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 01d2986a53ca7602d56178a347c6c45f804f4d7e..eaff8e7b8ace7d195d54fd472bcff4c59314a4b3 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -410,6 +410,49 @@ pub fn check_match(&self, // is problematic as the HIR is being scraped, but ref bindings may be // implicit after #42640. We need to make sure that pat_adjustments // (once introduced) is populated by the time we get here. + // + // arielb1 [writes here in this comment thread][c] that there + // is certainly *some* potential danger, e.g. for an example + // like: + // + // [c]: https://github.com/rust-lang/rust/pull/43399#discussion_r130223956 + // + // ``` + // let Foo(x) = f()[0]; + // ``` + // + // Then if the pattern matches by reference, we want to match + // `f()[0]` as a lexpr, so we can't allow it to be + // coerced. But if the pattern matches by value, `f()[0]` is + // still syntactically a lexpr, but we *do* want to allow + // coercions. + // + // However, *likely* we are ok with allowing coercions to + // happen if there are no explicit ref mut patterns - all + // implicit ref mut patterns must occur behind a reference, so + // they will have the "correct" variance and lifetime. + // + // This does mean that the following pattern would be legal: + // + // ``` + // struct Foo(Bar); + // struct Bar(u32); + // impl Deref for Foo { + // type Target = Bar; + // fn deref(&self) -> &Bar { &self.0 } + // } + // impl DerefMut for Foo { + // fn deref_mut(&mut self) -> &mut Bar { &mut self.0 } + // } + // fn foo(x: &mut Foo) { + // { + // let Bar(z): &mut Bar = x; + // *z = 42; + // } + // assert_eq!(foo.0.0, 42); + // } + // ``` + let contains_ref_bindings = arms.iter() .filter_map(|a| a.contains_explicit_ref_binding()) .max_by_key(|m| match *m {