From 2ea113aa27277d21c7a2a8103385a3022eeb239a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 20 Apr 2017 16:46:43 -0700 Subject: [PATCH] Emit diagnostic when using `const` storing `Fn` as pattern ```rust fn f1() { println!("1"); } fn f2() { println!("2"); } struct S(fn()); const CONST: S = S(f1); fn main() { let x = S(f2); match x { CONST => { println!("match"); } _ => {} } } ``` ```rust error: pattern contains `Fn`, use pattern guard instead --> .rs:14:9 | 13 | CONST => { | ^^^^^ pattern contains `Fn` | help: use a pattern guard instead: | x if x == CONST => { ``` Fix ICE. --- src/librustc_const_eval/pattern.rs | 28 +++++++++++++++------ src/test/ui/did_you_mean/issue-40657.rs | 26 +++++++++++++++++++ src/test/ui/did_you_mean/issue-40657.stderr | 11 ++++++++ 3 files changed, 57 insertions(+), 8 deletions(-) create mode 100644 src/test/ui/did_you_mean/issue-40657.rs create mode 100644 src/test/ui/did_you_mean/issue-40657.stderr diff --git a/src/librustc_const_eval/pattern.rs b/src/librustc_const_eval/pattern.rs index f20fa27dc2251..81550c81de44b 100644 --- a/src/librustc_const_eval/pattern.rs +++ b/src/librustc_const_eval/pattern.rs @@ -417,7 +417,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { pattern: self.lower_pattern(field), }) .collect(); - self.lower_variant_or_leaf(def, ty, subpatterns) + self.lower_variant_or_leaf(def, ty, subpatterns, pat.span) } PatKind::Struct(ref qpath, ref fields, _) => { @@ -449,7 +449,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { }) .collect(); - self.lower_variant_or_leaf(def, ty, subpatterns) + self.lower_variant_or_leaf(def, ty, subpatterns, pat.span) } }; @@ -540,7 +540,8 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { &mut self, def: Def, ty: Ty<'tcx>, - subpatterns: Vec>) + subpatterns: Vec>, + span: Span) -> PatternKind<'tcx> { match def { @@ -568,8 +569,19 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) => { PatternKind::Leaf { subpatterns: subpatterns } } - - _ => bug!() + Def::Fn(..) => { + let mut err = self.tcx.sess.struct_span_err(span, "pattern contains `Fn`, \ + use pattern guard instead"); + err.span_label(span, &"pattern contains `Fn`"); + if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(span) { + err.span_suggestion(span, + "use a pattern guard instead:", + format!("x if x == {}", snippet)); + } + err.emit(); + PatternKind::Wild + }, + d => bug!("lower_variant_or_leaf with incorrect Def: {:?}", d) } } @@ -601,7 +613,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { } } } - _ => self.lower_variant_or_leaf(def, ty, vec![]), + _ => self.lower_variant_or_leaf(def, ty, vec![], span), }; Pattern { @@ -686,7 +698,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { pattern: self.lower_const_expr(expr, pat_id, span) } }).collect(); - self.lower_variant_or_leaf(def, ty, subpatterns) + self.lower_variant_or_leaf(def, ty, subpatterns, span) } } } @@ -720,7 +732,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { }) .collect(); - self.lower_variant_or_leaf(def, pat_ty, subpatterns) + self.lower_variant_or_leaf(def, pat_ty, subpatterns, span) } hir::ExprArray(ref exprs) => { diff --git a/src/test/ui/did_you_mean/issue-40657.rs b/src/test/ui/did_you_mean/issue-40657.rs new file mode 100644 index 0000000000000..2dc9a11e4976f --- /dev/null +++ b/src/test/ui/did_you_mean/issue-40657.rs @@ -0,0 +1,26 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn f1() { println!("1"); } +fn f2() { println!("2"); } + +struct S(fn()); +const CONST: S = S(f1); + +fn main() { + let x = S(f2); + + match x { + CONST => { + println!("match"); + } + _ => {} + } +} diff --git a/src/test/ui/did_you_mean/issue-40657.stderr b/src/test/ui/did_you_mean/issue-40657.stderr new file mode 100644 index 0000000000000..61b045d7ab9c7 --- /dev/null +++ b/src/test/ui/did_you_mean/issue-40657.stderr @@ -0,0 +1,11 @@ +error: pattern contains `Fn`, use pattern guard instead + --> $DIR/issue-40657.rs:21:9 + | +21 | CONST => { + | ^^^^^ pattern contains `Fn` + | +help: use a pattern guard instead: + | x if x == CONST => { + +error: aborting due to previous error +