about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-06-15 03:47:55 +0000
committerbors <bors@rust-lang.org>2019-06-15 03:47:55 +0000
commit9f8cd9da7b6380b5658163141c767a321f5f0f62 (patch)
tree45a2ed6d8654f6b100a0a08d821b1932d3c40a70
parent9606f6fa64926a84d82e3c62dbdc57f5c10f756d (diff)
parent065151f8b2c31d9e4ddd34aaf8d3263a997f5cfe (diff)
downloadrust-9f8cd9da7b6380b5658163141c767a321f5f0f62.tar.gz
rust-9f8cd9da7b6380b5658163141c767a321f5f0f62.zip
Auto merge of #61825 - Centril:tauv-infer-fix, r=petrochenkov
type_alias_enum_variants: fix #61801; allow a path pattern to infer

Fix #61801.

Given a type-relative path pattern referring to an enum variant through a type alias, allow inferring the generic argument applied in the expectation set by the scrutinee of a `match` expression.

Similar issues may exist for `let` statements but I don't know how to test for that since `PhantomData<T>` is necessary...)

The gist of the problem here was that `resolve_ty_and_res_ufcs` was called twice which is apparently no good... It is possible that this PR is papering over some deeper problem, but that is beyond my knowledge of the compiler.

r? @petrochenkov
cc @eddyb @alexreg
cc https://github.com/rust-lang/rust/pull/61682
cc https://github.com/rust-lang/rust/issues/49683
-rw-r--r--src/librustc_typeck/check/_match.rs13
-rw-r--r--src/test/ui/type-alias-enum-variants/issue-61801-path-pattern-can-infer.rs30
2 files changed, 38 insertions, 5 deletions
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index 9ffbbd384c6..f74dbe30d3c 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -50,6 +50,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         debug!("check_pat_walk(pat={:?},expected={:?},def_bm={:?})", pat, expected, def_bm);
 
+        let mut path_resolution = None;
         let is_non_ref_pat = match pat.node {
             PatKind::Struct(..) |
             PatKind::TupleStruct(..) |
@@ -65,8 +66,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 }
             }
             PatKind::Path(ref qpath) => {
-                let (def, _, _) = self.resolve_ty_and_res_ufcs(qpath, pat.hir_id, pat.span);
-                match def {
+                let resolution = self.resolve_ty_and_res_ufcs(qpath, pat.hir_id, pat.span);
+                path_resolution = Some(resolution);
+                match resolution.0 {
                     Res::Def(DefKind::Const, _) | Res::Def(DefKind::AssocConst, _) => false,
                     _ => true,
                 }
@@ -294,7 +296,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 )
             }
             PatKind::Path(ref qpath) => {
-                self.check_pat_path(pat, qpath, expected)
+                self.check_pat_path(pat, path_resolution.unwrap(), qpath, expected)
             }
             PatKind::Struct(ref qpath, ref fields, etc) => {
                 self.check_pat_struct(pat, qpath, fields, etc, expected, def_bm, discrim_span)
@@ -1054,13 +1056,14 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
     fn check_pat_path(
         &self,
         pat: &hir::Pat,
+        path_resolution: (Res, Option<Ty<'tcx>>, &'b [hir::PathSegment]),
         qpath: &hir::QPath,
         expected: Ty<'tcx>,
     ) -> Ty<'tcx> {
         let tcx = self.tcx;
 
-        // Resolve the path and check the definition for errors.
-        let (res, opt_ty, segments) = self.resolve_ty_and_res_ufcs(qpath, pat.hir_id, pat.span);
+        // We have already resolved the path.
+        let (res, opt_ty, segments) = path_resolution;
         match res {
             Res::Err => {
                 self.set_tainted_by_errors();
diff --git a/src/test/ui/type-alias-enum-variants/issue-61801-path-pattern-can-infer.rs b/src/test/ui/type-alias-enum-variants/issue-61801-path-pattern-can-infer.rs
new file mode 100644
index 00000000000..21be61acb0c
--- /dev/null
+++ b/src/test/ui/type-alias-enum-variants/issue-61801-path-pattern-can-infer.rs
@@ -0,0 +1,30 @@
+// In this regression test we check that a path pattern referring to a unit variant
+// through a type alias is successful in inferring the generic argument.
+
+// compile-pass
+
+#![feature(type_alias_enum_variants)]
+
+enum Opt<T> {
+    N,
+    S(T),
+}
+
+type OptAlias<T> = Opt<T>;
+
+fn f1(x: OptAlias<u8>) {
+    match x {
+        OptAlias::N // We previously failed to infer `T` to `u8`.
+            => (),
+        _ => (),
+    }
+
+    match x {
+        <
+            OptAlias<_> // And we failed to infer this type also.
+        >::N => (),
+        _ => (),
+    }
+}
+
+fn main() {}