]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc/middle/check_match.rs
Auto merge of #31461 - jseyfried:remove_import_resolutions, r=nrc
[rust.git] / src / librustc / middle / check_match.rs
index a33142433463adb5b0760b50b4a49abc57b10a3e..fa09c9d2bb6bade3d241b48a14bd8ca306c19b3e 100644 (file)
@@ -246,7 +246,7 @@ fn check_for_bindings_named_the_same_as_variants(cx: &MatchCheckCtxt, pat: &Pat)
                 let pat_ty = cx.tcx.pat_ty(p);
                 if let ty::TyEnum(edef, _) = pat_ty.sty {
                     let def = cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def());
-                    if let Some(DefLocal(..)) = def {
+                    if let Some(Def::Local(..)) = def {
                         if edef.variants.iter().any(|variant|
                             variant.name == ident.node.unhygienic_name
                                 && variant.kind() == VariantKind::Unit
@@ -368,31 +368,46 @@ fn raw_pat<'a>(p: &'a Pat) -> &'a Pat {
 fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, matrix: &Matrix, source: hir::MatchSource) {
     match is_useful(cx, matrix, &[DUMMY_WILD_PAT], ConstructWitness) {
         UsefulWithWitness(pats) => {
-            let witness = match &pats[..] {
-                [ref witness] => &**witness,
-                [] => DUMMY_WILD_PAT,
-                _ => unreachable!()
+            let witnesses = if pats.is_empty() {
+                vec![DUMMY_WILD_PAT]
+            } else {
+                pats.iter().map(|w| &**w ).collect()
             };
             match source {
                 hir::MatchSource::ForLoopDesugar => {
-                    // `witness` has the form `Some(<head>)`, peel off the `Some`
-                    let witness = match witness.node {
+                    // `witnesses[0]` has the form `Some(<head>)`, peel off the `Some`
+                    let witness = match witnesses[0].node {
                         hir::PatEnum(_, Some(ref pats)) => match &pats[..] {
                             [ref pat] => &**pat,
                             _ => unreachable!(),
                         },
                         _ => unreachable!(),
                     };
-
                     span_err!(cx.tcx.sess, sp, E0297,
                         "refutable pattern in `for` loop binding: \
                                 `{}` not covered",
                                 pat_to_string(witness));
                 },
                 _ => {
+                    let pattern_strings: Vec<_> = witnesses.iter().map(|w| {
+                        pat_to_string(w)
+                    }).collect();
+                    const LIMIT: usize = 3;
+                    let joined_patterns = match pattern_strings.len() {
+                        0 => unreachable!(),
+                        1 => format!("`{}`", pattern_strings[0]),
+                        2...LIMIT => {
+                            let (tail, head) = pattern_strings.split_last().unwrap();
+                            format!("`{}`", head.join("`, `") + "` and `" + tail)
+                        },
+                        _ => {
+                            let (head, tail) = pattern_strings.split_at(LIMIT);
+                            format!("`{}` and {} more", head.join("`, `"), tail.len())
+                        }
+                    };
                     span_err!(cx.tcx.sess, sp, E0004,
-                        "non-exhaustive patterns: `{}` not covered",
-                        pat_to_string(witness)
+                        "non-exhaustive patterns: {} not covered",
+                        joined_patterns
                     );
                 },
             }
@@ -454,8 +469,9 @@ fn fold_pat(&mut self, pat: P<Pat>) -> P<Pat> {
             hir::PatIdent(..) | hir::PatEnum(..) | hir::PatQPath(..) => {
                 let def = self.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def());
                 match def {
-                    Some(DefAssociatedConst(did)) |
-                    Some(DefConst(did)) => match lookup_const_by_id(self.tcx, did, Some(pat.id)) {
+                    Some(Def::AssociatedConst(did)) |
+                    Some(Def::Const(did)) => match lookup_const_by_id(self.tcx, did,
+                                                                    Some(pat.id), None) {
                         Some(const_expr) => {
                             const_expr_to_pat(self.tcx, const_expr, pat.span).map(|new_pat| {
 
@@ -593,14 +609,15 @@ fn variant_of_ctor(&self,
     }
 }
 
-fn missing_constructor(cx: &MatchCheckCtxt, &Matrix(ref rows): &Matrix,
-                       left_ty: Ty, max_slice_length: usize) -> Option<Constructor> {
+fn missing_constructors(cx: &MatchCheckCtxt, &Matrix(ref rows): &Matrix,
+                       left_ty: Ty, max_slice_length: usize) -> Vec<Constructor> {
     let used_constructors: Vec<Constructor> = rows.iter()
         .flat_map(|row| pat_constructors(cx, row[0], left_ty, max_slice_length))
         .collect();
     all_constructors(cx, left_ty, max_slice_length)
         .into_iter()
-        .find(|c| !used_constructors.contains(c))
+        .filter(|c| !used_constructors.contains(c))
+        .collect()
 }
 
 /// This determines the set of all possible constructors of a pattern matching
@@ -679,46 +696,44 @@ fn is_useful(cx: &MatchCheckCtxt,
 
     let constructors = pat_constructors(cx, v[0], left_ty, max_slice_length);
     if constructors.is_empty() {
-        match missing_constructor(cx, matrix, left_ty, max_slice_length) {
-            None => {
-                all_constructors(cx, left_ty, max_slice_length).into_iter().map(|c| {
-                    match is_useful_specialized(cx, matrix, v, c.clone(), left_ty, witness) {
-                        UsefulWithWitness(pats) => UsefulWithWitness({
-                            let arity = constructor_arity(cx, &c, left_ty);
-                            let mut result = {
-                                let pat_slice = &pats[..];
-                                let subpats: Vec<_> = (0..arity).map(|i| {
-                                    pat_slice.get(i).map_or(DUMMY_WILD_PAT, |p| &**p)
-                                }).collect();
-                                vec![construct_witness(cx, &c, subpats, left_ty)]
-                            };
-                            result.extend(pats.into_iter().skip(arity));
-                            result
-                        }),
-                        result => result
-                    }
-                }).find(|result| result != &NotUseful).unwrap_or(NotUseful)
-            },
-
-            Some(constructor) => {
-                let matrix = rows.iter().filter_map(|r| {
-                    if pat_is_binding_or_wild(&cx.tcx.def_map.borrow(), raw_pat(r[0])) {
-                        Some(r[1..].to_vec())
-                    } else {
-                        None
-                    }
-                }).collect();
-                match is_useful(cx, &matrix, &v[1..], witness) {
-                    UsefulWithWitness(pats) => {
-                        let arity = constructor_arity(cx, &constructor, left_ty);
-                        let wild_pats = vec![DUMMY_WILD_PAT; arity];
-                        let enum_pat = construct_witness(cx, &constructor, wild_pats, left_ty);
-                        let mut new_pats = vec![enum_pat];
-                        new_pats.extend(pats);
-                        UsefulWithWitness(new_pats)
-                    },
+        let constructors = missing_constructors(cx, matrix, left_ty, max_slice_length);
+        if constructors.is_empty() {
+            all_constructors(cx, left_ty, max_slice_length).into_iter().map(|c| {
+                match is_useful_specialized(cx, matrix, v, c.clone(), left_ty, witness) {
+                    UsefulWithWitness(pats) => UsefulWithWitness({
+                        let arity = constructor_arity(cx, &c, left_ty);
+                        let mut result = {
+                            let pat_slice = &pats[..];
+                            let subpats: Vec<_> = (0..arity).map(|i| {
+                                pat_slice.get(i).map_or(DUMMY_WILD_PAT, |p| &**p)
+                            }).collect();
+                            vec![construct_witness(cx, &c, subpats, left_ty)]
+                        };
+                        result.extend(pats.into_iter().skip(arity));
+                        result
+                    }),
                     result => result
                 }
+            }).find(|result| result != &NotUseful).unwrap_or(NotUseful)
+        } else {
+            let matrix = rows.iter().filter_map(|r| {
+                if pat_is_binding_or_wild(&cx.tcx.def_map.borrow(), raw_pat(r[0])) {
+                    Some(r[1..].to_vec())
+                } else {
+                    None
+                }
+            }).collect();
+            match is_useful(cx, &matrix, &v[1..], witness) {
+                UsefulWithWitness(pats) => {
+                    let mut new_pats: Vec<_> = constructors.into_iter().map(|constructor| {
+                        let arity = constructor_arity(cx, &constructor, left_ty);
+                        let wild_pats = vec![DUMMY_WILD_PAT; arity];
+                        construct_witness(cx, &constructor, wild_pats, left_ty)
+                    }).collect();
+                    new_pats.extend(pats);
+                    UsefulWithWitness(new_pats)
+                },
+                result => result
             }
         }
     } else {
@@ -756,19 +771,19 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: &Pat,
     match pat.node {
         hir::PatIdent(..) =>
             match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
-                Some(DefConst(..)) | Some(DefAssociatedConst(..)) =>
+                Some(Def::Const(..)) | Some(Def::AssociatedConst(..)) =>
                     cx.tcx.sess.span_bug(pat.span, "const pattern should've \
                                                     been rewritten"),
-                Some(DefStruct(_)) => vec!(Single),
-                Some(DefVariant(_, id, _)) => vec!(Variant(id)),
+                Some(Def::Struct(..)) => vec!(Single),
+                Some(Def::Variant(_, id)) => vec!(Variant(id)),
                 _ => vec!()
             },
         hir::PatEnum(..) =>
             match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
-                Some(DefConst(..)) | Some(DefAssociatedConst(..)) =>
+                Some(Def::Const(..)) | Some(Def::AssociatedConst(..)) =>
                     cx.tcx.sess.span_bug(pat.span, "const pattern should've \
                                                     been rewritten"),
-                Some(DefVariant(_, id, _)) => vec!(Variant(id)),
+                Some(Def::Variant(_, id)) => vec!(Variant(id)),
                 _ => vec!(Single)
             },
         hir::PatQPath(..) =>
@@ -776,10 +791,10 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: &Pat,
                                             been rewritten"),
         hir::PatStruct(..) =>
             match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
-                Some(DefConst(..)) | Some(DefAssociatedConst(..)) =>
+                Some(Def::Const(..)) | Some(Def::AssociatedConst(..)) =>
                     cx.tcx.sess.span_bug(pat.span, "const pattern should've \
                                                     been rewritten"),
-                Some(DefVariant(_, id, _)) => vec!(Variant(id)),
+                Some(Def::Variant(_, id)) => vec!(Variant(id)),
                 _ => vec!(Single)
             },
         hir::PatLit(ref expr) =>
@@ -868,10 +883,10 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
         hir::PatIdent(_, _, _) => {
             let opt_def = cx.tcx.def_map.borrow().get(&pat_id).map(|d| d.full_def());
             match opt_def {
-                Some(DefConst(..)) | Some(DefAssociatedConst(..)) =>
+                Some(Def::Const(..)) | Some(Def::AssociatedConst(..)) =>
                     cx.tcx.sess.span_bug(pat_span, "const pattern should've \
                                                     been rewritten"),
-                Some(DefVariant(_, id, _)) => if *constructor == Variant(id) {
+                Some(Def::Variant(_, id)) => if *constructor == Variant(id) {
                     Some(vec!())
                 } else {
                     None
@@ -883,11 +898,11 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
         hir::PatEnum(_, ref args) => {
             let def = cx.tcx.def_map.borrow().get(&pat_id).unwrap().full_def();
             match def {
-                DefConst(..) | DefAssociatedConst(..) =>
+                Def::Const(..) | Def::AssociatedConst(..) =>
                     cx.tcx.sess.span_bug(pat_span, "const pattern should've \
                                                     been rewritten"),
-                DefVariant(_, id, _) if *constructor != Variant(id) => None,
-                DefVariant(..) | DefStruct(..) => {
+                Def::Variant(_, id) if *constructor != Variant(id) => None,
+                Def::Variant(..) | Def::Struct(..) => {
                     Some(match args {
                         &Some(ref args) => args.iter().map(|p| &**p).collect(),
                         &None => vec![DUMMY_WILD_PAT; arity],
@@ -1094,8 +1109,7 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
                         //FIXME: (@jroesch) this code should be floated up as well
                         let infcx = infer::new_infer_ctxt(cx.tcx,
                                                           &cx.tcx.tables,
-                                                          Some(cx.param_env.clone()),
-                                                          false);
+                                                          Some(cx.param_env.clone()));
                         if infcx.type_moves_by_default(pat_ty, pat.span) {
                             check_move(p, sub.as_ref().map(|p| &**p));
                         }
@@ -1127,8 +1141,7 @@ fn check_for_mutation_in_guard<'a, 'tcx>(cx: &'a MatchCheckCtxt<'a, 'tcx>,
 
     let infcx = infer::new_infer_ctxt(cx.tcx,
                                       &cx.tcx.tables,
-                                      Some(checker.cx.param_env.clone()),
-                                      false);
+                                      Some(checker.cx.param_env.clone()));
 
     let mut visitor = ExprUseVisitor::new(&mut checker, &infcx);
     visitor.walk_expr(guard);