]> git.lizzy.rs Git - rust.git/commitdiff
Remove the "lift constant to reference" logic
authorOliver Scherer <github35764891676564198441@oli-obk.de>
Wed, 23 Sep 2020 14:28:45 +0000 (16:28 +0200)
committerOliver Scherer <github35764891676564198441@oli-obk.de>
Wed, 23 Sep 2020 14:28:45 +0000 (16:28 +0200)
compiler/rustc_mir_build/src/build/matches/test.rs
compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs

index 796815cf2168c9f98d5398f7768f7a288c604445..d81c3b68f4853d27f3c1ce63d821a9b3f64013d4 100644 (file)
@@ -409,40 +409,7 @@ fn non_scalar_compare(
 
         let deref_ty = match *ty.kind() {
             ty::Ref(_, deref_ty, _) => deref_ty,
-            _ => {
-                trace!("non_scalar_compare called on non-reference type: {}", ty);
-                // Backcompat hack: due to non-structural matches not being a hard error, we can
-                // reach this for types that have manual `Eq` or `PartialEq` impls.
-                assert!(!ty.is_structural_eq_shallow(self.hir.tcx()));
-                let ref_ty = self.hir.tcx().mk_imm_ref(self.hir.tcx().lifetimes.re_erased, ty);
-                // let y = &place;
-                let y = self.temp(ref_ty, source_info.span);
-                self.cfg.push_assign(
-                    block,
-                    source_info,
-                    y,
-                    Rvalue::Ref(self.hir.tcx().lifetimes.re_erased, BorrowKind::Shared, place),
-                );
-                val = Operand::Move(y);
-                // let temp = expect;
-                let temp = self.temp(ty, source_info.span);
-                self.cfg.push_assign(
-                    block,
-                    source_info,
-                    temp,
-                    Rvalue::Use(expect),
-                );
-                // reftemp = &temp;
-                let reftemp = self.temp(ref_ty, source_info.span);
-                self.cfg.push_assign(
-                    block,
-                    source_info,
-                    reftemp,
-                    Rvalue::Ref(self.hir.tcx().lifetimes.re_erased, BorrowKind::Shared, temp),
-                );
-                expect = Operand::Move(reftemp);
-                ty
-            },
+            _ => bug!("non_scalar_compare called on non-reference type: {}", ty),
         };
 
         let eq_def_id = self.hir.tcx().require_lang_item(LangItem::PartialEq, None);
index ad0bcfeb367f946eed48dfd8d9b495cf6b957aa6..4a50bbca066749dd3761e944673e648a7ea625bb 100644 (file)
@@ -58,6 +58,9 @@ struct ConstToPat<'a, 'tcx> {
     include_lint_checks: bool,
 }
 
+#[derive(Debug)]
+struct FallbackToConstRef;
+
 impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
     fn new(
         pat_ctxt: &PatCtxt<'_, 'tcx>,
@@ -103,7 +106,7 @@ fn to_pat(
         // once indirect_structural_match is a full fledged error, this
         // level of indirection can be eliminated
 
-        let inlined_const_as_pat = self.recur(cv, mir_structural_match_violation);
+        let inlined_const_as_pat = self.recur(cv, mir_structural_match_violation).unwrap();
 
         if self.include_lint_checks && !self.saw_const_match_error.get() {
             // If we were able to successfully convert the const to some pat,
@@ -216,18 +219,22 @@ fn type_has_partial_eq_impl(&self, ty: Ty<'tcx>) -> bool {
     }
 
     // Recursive helper for `to_pat`; invoke that (instead of calling this directly).
-    fn recur(&self, cv: &'tcx ty::Const<'tcx>, mir_structural_match_violation: bool) -> Pat<'tcx> {
+    fn recur(
+        &self,
+        cv: &'tcx ty::Const<'tcx>,
+        mir_structural_match_violation: bool,
+    ) -> Result<Pat<'tcx>, FallbackToConstRef> {
         let id = self.id;
         let span = self.span;
         let tcx = self.tcx();
         let param_env = self.param_env;
 
-        let field_pats = |vals: &[&'tcx ty::Const<'tcx>]| {
+        let field_pats = |vals: &[&'tcx ty::Const<'tcx>]| -> Result<_, _> {
             vals.iter()
                 .enumerate()
                 .map(|(idx, val)| {
                     let field = Field::new(idx);
-                    FieldPat { field, pattern: self.recur(val, false) }
+                    Ok(FieldPat { field, pattern: self.recur(val, false)? })
                 })
                 .collect()
         };
@@ -287,7 +294,10 @@ fn recur(&self, cv: &'tcx ty::Const<'tcx>, mir_structural_match_violation: bool)
                         |lint| lint.build(&msg).emit(),
                     );
                 }
-                PatKind::Constant { value: cv }
+                // Since we are behind a reference, we can just bubble the error up so we get a
+                // constant at reference type, making it easy to let the fallback call
+                // `PartialEq::eq` on it.
+                return Err(FallbackToConstRef);
             }
             ty::Adt(adt_def, _) if !self.type_marked_structural(cv.ty) => {
                 debug!("adt_def {:?} has !type_marked_structural for cv.ty: {:?}", adt_def, cv.ty);
@@ -309,12 +319,12 @@ fn recur(&self, cv: &'tcx ty::Const<'tcx>, mir_structural_match_violation: bool)
                     variant_index: destructured
                         .variant
                         .expect("destructed const of adt without variant id"),
-                    subpatterns: field_pats(destructured.fields),
+                    subpatterns: field_pats(destructured.fields)?,
                 }
             }
             ty::Tuple(_) | ty::Adt(_, _) => {
                 let destructured = tcx.destructure_const(param_env.and(cv));
-                PatKind::Leaf { subpatterns: field_pats(destructured.fields) }
+                PatKind::Leaf { subpatterns: field_pats(destructured.fields)? }
             }
             ty::Array(..) => PatKind::Array {
                 prefix: tcx
@@ -322,7 +332,7 @@ fn recur(&self, cv: &'tcx ty::Const<'tcx>, mir_structural_match_violation: bool)
                     .fields
                     .iter()
                     .map(|val| self.recur(val, false))
-                    .collect(),
+                    .collect::<Result<_, _>>()?,
                 slice: None,
                 suffix: Vec::new(),
             },
@@ -355,7 +365,7 @@ fn recur(&self, cv: &'tcx ty::Const<'tcx>, mir_structural_match_violation: bool)
                                     .fields
                                     .iter()
                                     .map(|val| self.recur(val, false))
-                                    .collect(),
+                                    .collect::<Result<_, _>>()?,
                                 slice: None,
                                 suffix: vec![],
                             }),
@@ -379,8 +389,13 @@ fn recur(&self, cv: &'tcx ty::Const<'tcx>, mir_structural_match_violation: bool)
                 // deref pattern.
                 _ => {
                     let old = self.behind_reference.replace(true);
-                    let val = PatKind::Deref {
-                        subpattern: self.recur(tcx.deref_const(self.param_env.and(cv)), false),
+                    // In case there are structural-match violations somewhere in this subpattern,
+                    // we fall back to a const pattern. If we do not do this, we may end up with
+                    // a !structural-match constant that is not of reference type, which makes it
+                    // very hard to invoke `PartialEq::eq` on it as a fallback.
+                    let val = match self.recur(tcx.deref_const(self.param_env.and(cv)), false) {
+                        Ok(subpattern) => PatKind::Deref { subpattern },
+                        Err(FallbackToConstRef) => PatKind::Constant { value: cv },
                     };
                     self.behind_reference.set(old);
                     val
@@ -439,6 +454,6 @@ fn recur(&self, cv: &'tcx ty::Const<'tcx>, mir_structural_match_violation: bool)
             );
         }
 
-        Pat { span, ty: cv.ty, kind: Box::new(kind) }
+        Ok(Pat { span, ty: cv.ty, kind: Box::new(kind) })
     }
 }