Skip to content

Commit 40ab41f

Browse files
committed
add pattern type ascriptions for tuple/brace structs/enums
1 parent a609384 commit 40ab41f

11 files changed

+246
-8
lines changed

src/librustc_mir/build/matches/mod.rs

+8
Original file line numberDiff line numberDiff line change
@@ -1307,6 +1307,14 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
13071307
) {
13081308
for ascription in ascriptions {
13091309
let source_info = self.source_info(ascription.span);
1310+
1311+
debug!(
1312+
"adding user ascription at span {:?} of place {:?} and {:?}",
1313+
source_info.span,
1314+
ascription.source,
1315+
ascription.user_ty,
1316+
);
1317+
13101318
self.cfg.push(
13111319
block,
13121320
Statement {

src/librustc_mir/hair/pattern/mod.rs

+39-8
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ pub(crate) use self::check_match::check_match;
1818

1919
use const_eval::{const_field, const_variant_index};
2020

21+
use hair::util::UserAnnotatedTyHelpers;
22+
2123
use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability};
2224
use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, sign_extend};
2325
use rustc::ty::{self, CanonicalTy, TyCtxt, AdtDef, Ty, Region};
@@ -529,8 +531,9 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
529531
field: Field::new(i),
530532
pattern: self.lower_pattern(field),
531533
})
532-
.collect();
533-
self.lower_variant_or_leaf(def, pat.span, ty, subpatterns)
534+
.collect();
535+
536+
self.lower_variant_or_leaf(def, pat.hir_id, pat.span, ty, subpatterns)
534537
}
535538

536539
PatKind::Struct(ref qpath, ref fields, _) => {
@@ -546,7 +549,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
546549
})
547550
.collect();
548551

549-
self.lower_variant_or_leaf(def, pat.span, ty, subpatterns)
552+
self.lower_variant_or_leaf(def, pat.hir_id, pat.span, ty, subpatterns)
550553
}
551554
};
552555

@@ -637,12 +640,12 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
637640
fn lower_variant_or_leaf(
638641
&mut self,
639642
def: Def,
643+
hir_id: hir::HirId,
640644
span: Span,
641645
ty: Ty<'tcx>,
642-
subpatterns: Vec<FieldPattern<'tcx>>)
643-
-> PatternKind<'tcx>
644-
{
645-
match def {
646+
subpatterns: Vec<FieldPattern<'tcx>>,
647+
) -> PatternKind<'tcx> {
648+
let mut kind = match def {
646649
Def::Variant(variant_id) | Def::VariantCtor(variant_id, ..) => {
647650
let enum_id = self.tcx.parent_def_id(variant_id).unwrap();
648651
let adt_def = self.tcx.adt_def(enum_id);
@@ -675,7 +678,24 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
675678
self.errors.push(PatternError::NonConstPath(span));
676679
PatternKind::Wild
677680
}
681+
};
682+
683+
if let Some(user_ty) = self.user_substs_applied_to_ty_of_hir_id(hir_id) {
684+
let subpattern = Pattern {
685+
span,
686+
ty,
687+
kind: Box::new(kind),
688+
};
689+
690+
debug!("pattern user_ty = {:?} for pattern at {:?}", user_ty, span);
691+
692+
kind = PatternKind::AscribeUserType {
693+
subpattern,
694+
user_ty,
695+
};
678696
}
697+
698+
kind
679699
}
680700

681701
/// Takes a HIR Path. If the path is a constant, evaluates it and feeds
@@ -729,7 +749,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
729749
},
730750
}
731751
}
732-
_ => self.lower_variant_or_leaf(def, span, ty, vec![]),
752+
_ => self.lower_variant_or_leaf(def, id, span, ty, vec![]),
733753
};
734754

735755
Pattern {
@@ -894,6 +914,17 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
894914
}
895915
}
896916

917+
impl UserAnnotatedTyHelpers<'tcx, 'tcx> for PatternContext<'_, 'tcx> {
918+
fn tcx(&self) -> TyCtxt<'_, 'tcx, 'tcx> {
919+
self.tcx
920+
}
921+
922+
fn tables(&self) -> &ty::TypeckTables<'tcx> {
923+
self.tables
924+
}
925+
}
926+
927+
897928
pub trait PatternFoldable<'tcx> : Sized {
898929
fn fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
899930
self.super_fold_with(folder)

src/librustc_typeck/check/mod.rs

+7
Original file line numberDiff line numberDiff line change
@@ -2164,6 +2164,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
21642164
/// occurred**, so that annotations like `Vec<_>` are preserved
21652165
/// properly.
21662166
pub fn write_user_substs_from_substs(&self, hir_id: hir::HirId, substs: &'tcx Substs<'tcx>) {
2167+
debug!(
2168+
"write_user_substs_from_substs({:?}, {:?}) in fcx {}",
2169+
hir_id,
2170+
substs,
2171+
self.tag(),
2172+
);
2173+
21672174
if !substs.is_noop() {
21682175
let user_substs = self.infcx.canonicalize_response(&substs);
21692176
debug!("instantiate_value_path: user_substs = {:?}", user_substs);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#![feature(nll)]
2+
3+
enum Foo<'a> {
4+
Bar { field: &'a u32 }
5+
}
6+
7+
fn in_let() {
8+
let y = 22;
9+
let foo = Foo::Bar { field: &y };
10+
//~^ ERROR `y` does not live long enough
11+
let Foo::Bar::<'static> { field: _z } = foo;
12+
}
13+
14+
fn in_match() {
15+
let y = 22;
16+
let foo = Foo::Bar { field: &y };
17+
//~^ ERROR `y` does not live long enough
18+
match foo {
19+
Foo::Bar::<'static> { field: _z } => {
20+
}
21+
}
22+
}
23+
24+
fn main() { }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
error[E0597]: `y` does not live long enough
2+
--> $DIR/pattern_substs_on_brace_enum_variant.rs:9:33
3+
|
4+
LL | let foo = Foo::Bar { field: &y };
5+
| ^^ borrowed value does not live long enough
6+
...
7+
LL | }
8+
| - `y` dropped here while still borrowed
9+
|
10+
= note: borrowed value must be valid for the static lifetime...
11+
12+
error[E0597]: `y` does not live long enough
13+
--> $DIR/pattern_substs_on_brace_enum_variant.rs:16:33
14+
|
15+
LL | let foo = Foo::Bar { field: &y };
16+
| ^^ borrowed value does not live long enough
17+
...
18+
LL | }
19+
| - `y` dropped here while still borrowed
20+
|
21+
= note: borrowed value must be valid for the static lifetime...
22+
23+
error: aborting due to 2 previous errors
24+
25+
For more information about this error, try `rustc --explain E0597`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#![feature(nll)]
2+
3+
struct Foo<'a> { field: &'a u32 }
4+
5+
fn in_let() {
6+
let y = 22;
7+
let foo = Foo { field: &y };
8+
//~^ ERROR `y` does not live long enough
9+
let Foo::<'static> { field: _z } = foo;
10+
}
11+
12+
fn in_main() {
13+
let y = 22;
14+
let foo = Foo { field: &y };
15+
//~^ ERROR `y` does not live long enough
16+
match foo {
17+
Foo::<'static> { field: _z } => {
18+
}
19+
}
20+
}
21+
22+
fn main() { }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
error[E0597]: `y` does not live long enough
2+
--> $DIR/pattern_substs_on_brace_struct.rs:7:28
3+
|
4+
LL | let foo = Foo { field: &y };
5+
| ^^ borrowed value does not live long enough
6+
...
7+
LL | }
8+
| - `y` dropped here while still borrowed
9+
|
10+
= note: borrowed value must be valid for the static lifetime...
11+
12+
error[E0597]: `y` does not live long enough
13+
--> $DIR/pattern_substs_on_brace_struct.rs:14:28
14+
|
15+
LL | let foo = Foo { field: &y };
16+
| ^^ borrowed value does not live long enough
17+
...
18+
LL | }
19+
| - `y` dropped here while still borrowed
20+
|
21+
= note: borrowed value must be valid for the static lifetime...
22+
23+
error: aborting due to 2 previous errors
24+
25+
For more information about this error, try `rustc --explain E0597`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#![feature(nll)]
2+
3+
enum Foo<'a> {
4+
Bar(&'a u32)
5+
}
6+
7+
fn in_let() {
8+
let y = 22;
9+
let foo = Foo::Bar(&y);
10+
//~^ ERROR `y` does not live long enough
11+
let Foo::Bar::<'static>(_z) = foo;
12+
}
13+
14+
fn in_match() {
15+
let y = 22;
16+
let foo = Foo::Bar(&y);
17+
//~^ ERROR `y` does not live long enough
18+
match foo {
19+
Foo::Bar::<'static>(_z) => {
20+
}
21+
}
22+
}
23+
24+
fn main() { }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
error[E0597]: `y` does not live long enough
2+
--> $DIR/pattern_substs_on_tuple_enum_variant.rs:9:24
3+
|
4+
LL | let foo = Foo::Bar(&y);
5+
| ^^ borrowed value does not live long enough
6+
...
7+
LL | }
8+
| - `y` dropped here while still borrowed
9+
|
10+
= note: borrowed value must be valid for the static lifetime...
11+
12+
error[E0597]: `y` does not live long enough
13+
--> $DIR/pattern_substs_on_tuple_enum_variant.rs:16:24
14+
|
15+
LL | let foo = Foo::Bar(&y);
16+
| ^^ borrowed value does not live long enough
17+
...
18+
LL | }
19+
| - `y` dropped here while still borrowed
20+
|
21+
= note: borrowed value must be valid for the static lifetime...
22+
23+
error: aborting due to 2 previous errors
24+
25+
For more information about this error, try `rustc --explain E0597`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#![feature(nll)]
2+
3+
struct Foo<'a>(&'a u32);
4+
5+
fn in_let() {
6+
let y = 22;
7+
let foo = Foo(&y);
8+
//~^ ERROR `y` does not live long enough
9+
let Foo::<'static>(_z) = foo;
10+
}
11+
12+
fn in_match() {
13+
let y = 22;
14+
let foo = Foo(&y);
15+
//~^ ERROR `y` does not live long enough
16+
match foo {
17+
Foo::<'static>(_z) => {
18+
}
19+
}
20+
}
21+
22+
fn main() { }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
error[E0597]: `y` does not live long enough
2+
--> $DIR/pattern_substs_on_tuple_struct.rs:7:19
3+
|
4+
LL | let foo = Foo(&y);
5+
| ^^ borrowed value does not live long enough
6+
...
7+
LL | }
8+
| - `y` dropped here while still borrowed
9+
|
10+
= note: borrowed value must be valid for the static lifetime...
11+
12+
error[E0597]: `y` does not live long enough
13+
--> $DIR/pattern_substs_on_tuple_struct.rs:14:19
14+
|
15+
LL | let foo = Foo(&y);
16+
| ^^ borrowed value does not live long enough
17+
...
18+
LL | }
19+
| - `y` dropped here while still borrowed
20+
|
21+
= note: borrowed value must be valid for the static lifetime...
22+
23+
error: aborting due to 2 previous errors
24+
25+
For more information about this error, try `rustc --explain E0597`.

0 commit comments

Comments
 (0)