Skip to content

Commit

Permalink
Rollup merge of rust-lang#61825 - Centril:tauv-infer-fix, r=petrochenkov
Browse files Browse the repository at this point in the history
type_alias_enum_variants: fix rust-lang#61801; allow a path pattern to infer

Fix rust-lang#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 rust-lang#61682
cc rust-lang#49683
  • Loading branch information
Centril authored Jun 14, 2019
2 parents 57822f9 + 065151f commit 140fa2f
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 5 deletions.
13 changes: 8 additions & 5 deletions src/librustc_typeck/check/_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(..) |
Expand All @@ -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,
}
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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();
Expand Down
Original file line number Diff line number Diff line change
@@ -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() {}

0 comments on commit 140fa2f

Please sign in to comment.