Skip to content

Commit e1643a8

Browse files
committed
Auto merge of #54757 - nikomatsakis:nll-issue-54573-user-annot, r=pnkfelix
user annotations in patterns Fixes #54573 r? @pnkfelix
2 parents 607243b + ccba716 commit e1643a8

18 files changed

+387
-77
lines changed

src/librustc/mir/visit.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ macro_rules! make_mir_visitor {
214214
self.super_ty(ty);
215215
}
216216

217-
fn visit_canonical_ty(&mut self, ty: & $($mutability)* CanonicalTy<'tcx>) {
217+
fn visit_user_ty(&mut self, ty: & $($mutability)* CanonicalTy<'tcx>) {
218218
self.super_canonical_ty(ty);
219219
}
220220

@@ -640,7 +640,7 @@ macro_rules! make_mir_visitor {
640640
c_ty: & $($mutability)* CanonicalTy<'tcx>,
641641
location: Location) {
642642
self.visit_place(place, PlaceContext::Validate, location);
643-
self.visit_canonical_ty(c_ty);
643+
self.visit_user_ty(c_ty);
644644
}
645645

646646
fn super_place(&mut self,
@@ -736,7 +736,7 @@ macro_rules! make_mir_visitor {
736736
source_info: *source_info,
737737
});
738738
if let Some(user_ty) = user_ty {
739-
self.visit_canonical_ty(user_ty);
739+
self.visit_user_ty(user_ty);
740740
}
741741
self.visit_source_info(source_info);
742742
self.visit_source_scope(visibility_scope);

src/librustc_mir/borrow_check/nll/renumber.rs

+9-14
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
use rustc::ty::subst::Substs;
1212
use rustc::ty::{self, CanonicalTy, ClosureSubsts, GeneratorSubsts, Ty, TypeFoldable};
13-
use rustc::mir::{BasicBlock, Location, Mir, Place, Statement, StatementKind};
13+
use rustc::mir::{BasicBlock, Location, Mir, Statement, StatementKind};
1414
use rustc::mir::visit::{MutVisitor, TyContext};
1515
use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
1616

@@ -65,6 +65,14 @@ impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> {
6565
debug!("visit_ty: ty={:?}", ty);
6666
}
6767

68+
fn visit_user_ty(&mut self, _ty: &mut CanonicalTy<'tcx>) {
69+
// `user_ty` annotations represent the types that the user
70+
// wrote in the progarm. We don't want to erase the regions
71+
// from these types: rather, we want to add them as
72+
// constraints at type-check time.
73+
debug!("visit_user_ty: skipping renumber");
74+
}
75+
6876
fn visit_substs(&mut self, substs: &mut &'tcx Substs<'tcx>, location: Location) {
6977
debug!("visit_substs(substs={:?}, location={:?})", substs, location);
7078

@@ -112,19 +120,6 @@ impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> {
112120
debug!("visit_closure_substs: substs={:?}", substs);
113121
}
114122

115-
fn visit_ascribe_user_ty(
116-
&mut self,
117-
_place: &mut Place<'tcx>,
118-
_variance: &mut ty::Variance,
119-
_c_ty: &mut CanonicalTy<'tcx>,
120-
_location: Location,
121-
) {
122-
// User-assert-ty statements represent types that the user added explicitly.
123-
// We don't want to erase the regions from these types: rather, we want to
124-
// add them as constraints at type-check time.
125-
debug!("visit_user_assert_ty: skipping renumber");
126-
}
127-
128123
fn visit_statement(
129124
&mut self,
130125
block: BasicBlock,

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/cx/expr.rs

+8-38
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use rustc_data_structures::indexed_vec::Idx;
1313
use hair::cx::Cx;
1414
use hair::cx::block;
1515
use hair::cx::to_ref::ToRef;
16+
use hair::util::UserAnnotatedTyHelpers;
1617
use rustc::hir::def::{Def, CtorKind};
1718
use rustc::mir::interpret::GlobalId;
1819
use rustc::ty::{self, AdtKind, Ty};
@@ -475,7 +476,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
475476
adt_def: adt,
476477
variant_index: 0,
477478
substs,
478-
user_ty: user_annotated_ty_for_adt(cx, expr.hir_id, adt),
479+
user_ty: cx.user_substs_applied_to_adt(expr.hir_id, adt),
479480
fields: field_refs(cx, fields),
480481
base: base.as_ref().map(|base| {
481482
FruInfo {
@@ -501,7 +502,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
501502
adt_def: adt,
502503
variant_index: index,
503504
substs,
504-
user_ty: user_annotated_ty_for_adt(cx, expr.hir_id, adt),
505+
user_ty: cx.user_substs_applied_to_adt(expr.hir_id, adt),
505506
fields: field_refs(cx, fields),
506507
base: None,
507508
}
@@ -787,48 +788,17 @@ fn user_annotated_ty_for_def(
787788
// user.
788789
Def::StructCtor(_def_id, CtorKind::Const) |
789790
Def::VariantCtor(_def_id, CtorKind::Const) =>
790-
match &cx.tables().node_id_to_type(hir_id).sty {
791-
ty::Adt(adt_def, _) => user_annotated_ty_for_adt(cx, hir_id, adt_def),
792-
sty => bug!("unexpected sty: {:?}", sty),
793-
},
791+
cx.user_substs_applied_to_ty_of_hir_id(hir_id),
794792

795793
// `Self` is used in expression as a tuple struct constructor or an unit struct constructor
796-
Def::SelfCtor(_) => {
797-
let sty = &cx.tables().node_id_to_type(hir_id).sty;
798-
match sty {
799-
ty::FnDef(ref def_id, _) => {
800-
Some(cx.tables().user_substs(hir_id)?.unchecked_map(|user_substs| {
801-
// Here, we just pair a `DefId` with the
802-
// `user_substs`, so no new types etc are introduced.
803-
cx.tcx().mk_fn_def(*def_id, user_substs)
804-
}))
805-
}
806-
ty::Adt(ref adt_def, _) => {
807-
user_annotated_ty_for_adt(cx, hir_id, adt_def)
808-
}
809-
_ => {
810-
bug!("unexpected sty: {:?}", sty)
811-
}
812-
}
813-
}
794+
Def::SelfCtor(_) =>
795+
cx.user_substs_applied_to_ty_of_hir_id(hir_id),
796+
814797
_ =>
815798
bug!("user_annotated_ty_for_def: unexpected def {:?} at {:?}", def, hir_id)
816799
}
817800
}
818801

819-
fn user_annotated_ty_for_adt(
820-
cx: &mut Cx<'a, 'gcx, 'tcx>,
821-
hir_id: hir::HirId,
822-
adt_def: &'tcx AdtDef,
823-
) -> Option<CanonicalTy<'tcx>> {
824-
let user_substs = cx.tables().user_substs(hir_id)?;
825-
Some(user_substs.unchecked_map(|user_substs| {
826-
// Here, we just pair an `AdtDef` with the
827-
// `user_substs`, so no new types etc are introduced.
828-
cx.tcx().mk_adt(adt_def, user_substs)
829-
}))
830-
}
831-
832802
fn method_callee<'a, 'gcx, 'tcx>(
833803
cx: &mut Cx<'a, 'gcx, 'tcx>,
834804
expr: &hir::Expr,
@@ -943,7 +913,7 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
943913
adt_def,
944914
variant_index: adt_def.variant_index_with_id(def_id),
945915
substs,
946-
user_ty: user_annotated_ty_for_adt(cx, expr.hir_id, adt_def),
916+
user_ty: cx.user_substs_applied_to_adt(expr.hir_id, adt_def),
947917
fields: vec![],
948918
base: None,
949919
}

src/librustc_mir/hair/cx/mod.rs

+11
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
//!
1616
1717
use hair::*;
18+
use hair::util::UserAnnotatedTyHelpers;
1819

1920
use rustc_data_structures::indexed_vec::Idx;
2021
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
@@ -272,6 +273,16 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
272273
}
273274
}
274275

276+
impl UserAnnotatedTyHelpers<'gcx, 'tcx> for Cx<'_, 'gcx, 'tcx> {
277+
fn tcx(&self) -> TyCtxt<'_, 'gcx, 'tcx> {
278+
self.tcx()
279+
}
280+
281+
fn tables(&self) -> &ty::TypeckTables<'tcx> {
282+
self.tables()
283+
}
284+
}
285+
275286
fn lint_level_for_hir_id(tcx: TyCtxt, mut id: ast::NodeId) -> ast::NodeId {
276287
// Right now we insert a `with_ignore` node in the dep graph here to
277288
// ignore the fact that `lint_levels` below depends on the entire crate.

src/librustc_mir/hair/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ pub mod cx;
2929
pub mod pattern;
3030
pub use self::pattern::{BindingMode, Pattern, PatternKind, FieldPattern};
3131

32+
mod util;
33+
3234
#[derive(Copy, Clone, Debug)]
3335
pub enum LintLevel {
3436
Inherited,

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_mir/hair/util.rs

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use rustc::hir;
12+
use rustc::ty::{self, AdtDef, CanonicalTy, TyCtxt};
13+
14+
crate trait UserAnnotatedTyHelpers<'gcx: 'tcx, 'tcx> {
15+
fn tcx(&self) -> TyCtxt<'_, 'gcx, 'tcx>;
16+
17+
fn tables(&self) -> &ty::TypeckTables<'tcx>;
18+
19+
fn user_substs_applied_to_adt(
20+
&self,
21+
hir_id: hir::HirId,
22+
adt_def: &'tcx AdtDef,
23+
) -> Option<CanonicalTy<'tcx>> {
24+
let user_substs = self.tables().user_substs(hir_id)?;
25+
Some(user_substs.unchecked_map(|user_substs| {
26+
// Here, we just pair an `AdtDef` with the
27+
// `user_substs`, so no new types etc are introduced.
28+
self.tcx().mk_adt(adt_def, user_substs)
29+
}))
30+
}
31+
32+
/// Looks up the type associated with this hir-id and applies the
33+
/// user-given substitutions; the hir-id must map to a suitable
34+
/// type.
35+
fn user_substs_applied_to_ty_of_hir_id(&self, hir_id: hir::HirId) -> Option<CanonicalTy<'tcx>> {
36+
let user_substs = self.tables().user_substs(hir_id)?;
37+
match &self.tables().node_id_to_type(hir_id).sty {
38+
ty::Adt(adt_def, _) => Some(user_substs.unchecked_map(|user_substs| {
39+
// Ok to call `unchecked_map` because we just pair an
40+
// `AdtDef` with the `user_substs`, so no new types
41+
// etc are introduced.
42+
self.tcx().mk_adt(adt_def, user_substs)
43+
})),
44+
ty::FnDef(def_id, _) => Some(user_substs.unchecked_map(|user_substs| {
45+
// Here, we just pair a `DefId` with the
46+
// `user_substs`, so no new types etc are introduced.
47+
self.tcx().mk_fn_def(*def_id, user_substs)
48+
})),
49+
sty => bug!(
50+
"sty: {:?} should not have user-substs {:?} recorded ",
51+
sty,
52+
user_substs
53+
),
54+
}
55+
}
56+
}

0 commit comments

Comments
 (0)