Skip to content

Commit 65fe251

Browse files
committed
Handle lifetime annotations in unreachable code
We equate the type in the annotation with the inferred type first so that we have a fully inferred type to perform the well-formedness check on.
1 parent ed871cb commit 65fe251

34 files changed

+514
-166
lines changed

src/librustc/ich/impls_ty.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1242,7 +1242,7 @@ impl_stable_hash_for!(
12421242

12431243
impl_stable_hash_for!(
12441244
struct ty::CanonicalUserTypeAnnotation<'tcx> {
1245-
user_ty, span
1245+
user_ty, span, inferred_ty
12461246
}
12471247
);
12481248

src/librustc/mir/tcx.rs

+6-7
Original file line numberDiff line numberDiff line change
@@ -75,21 +75,20 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> {
7575
elem: &PlaceElem<'tcx>)
7676
-> PlaceTy<'tcx>
7777
{
78-
self.projection_ty_core(tcx, elem, |_, _, ty| -> Result<Ty<'tcx>, ()> { Ok(ty) })
79-
.unwrap()
78+
self.projection_ty_core(tcx, elem, |_, _, ty| ty)
8079
}
8180

8281
/// `place_ty.projection_ty_core(tcx, elem, |...| { ... })`
8382
/// projects `place_ty` onto `elem`, returning the appropriate
8483
/// `Ty` or downcast variant corresponding to that projection.
8584
/// The `handle_field` callback must map a `Field` to its `Ty`,
8685
/// (which should be trivial when `T` = `Ty`).
87-
pub fn projection_ty_core<V, T, E>(
86+
pub fn projection_ty_core<V, T>(
8887
self,
8988
tcx: TyCtxt<'a, 'gcx, 'tcx>,
9089
elem: &ProjectionElem<'tcx, V, T>,
91-
mut handle_field: impl FnMut(&Self, &Field, &T) -> Result<Ty<'tcx>, E>)
92-
-> Result<PlaceTy<'tcx>, E>
90+
mut handle_field: impl FnMut(&Self, &Field, &T) -> Ty<'tcx>)
91+
-> PlaceTy<'tcx>
9392
where
9493
V: ::std::fmt::Debug, T: ::std::fmt::Debug
9594
{
@@ -140,10 +139,10 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> {
140139
}
141140
},
142141
ProjectionElem::Field(ref f, ref fty) =>
143-
PlaceTy::Ty { ty: handle_field(&self, f, fty)? },
142+
PlaceTy::Ty { ty: handle_field(&self, f, fty) },
144143
};
145144
debug!("projection_ty self: {:?} elem: {:?} yields: {:?}", self, elem, answer);
146-
Ok(answer)
145+
answer
147146
}
148147
}
149148

src/librustc/mir/visit.rs

+4
Original file line numberDiff line numberDiff line change
@@ -887,6 +887,7 @@ macro_rules! make_mir_visitor {
887887
ty: & $($mutability)* CanonicalUserTypeAnnotation<'tcx>,
888888
) {
889889
self.visit_span(& $($mutability)* ty.span);
890+
self.visit_ty(& $($mutability)* ty.inferred_ty, TyContext::UserTy(ty.span));
890891
}
891892

892893
fn super_ty(&mut self, _ty: & $($mutability)* Ty<'tcx>) {
@@ -967,6 +968,9 @@ pub enum TyContext {
967968
source_info: SourceInfo,
968969
},
969970

971+
/// The inferred type of a user type annotation.
972+
UserTy(Span),
973+
970974
/// The return type of the function.
971975
ReturnTy(SourceInfo),
972976

src/librustc/traits/query/type_op/ascribe_user_type.rs

+5-10
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,23 @@
11
use infer::canonical::{Canonical, Canonicalized, CanonicalizedQueryResponse, QueryResponse};
22
use traits::query::Fallible;
33
use hir::def_id::DefId;
4-
use mir::ProjectionKind;
5-
use ty::{self, ParamEnvAnd, Ty, TyCtxt};
4+
use ty::{ParamEnvAnd, Ty, TyCtxt};
65
use ty::subst::UserSubsts;
76

87
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
98
pub struct AscribeUserType<'tcx> {
109
pub mir_ty: Ty<'tcx>,
11-
pub variance: ty::Variance,
1210
pub def_id: DefId,
1311
pub user_substs: UserSubsts<'tcx>,
14-
pub projs: &'tcx ty::List<ProjectionKind<'tcx>>,
1512
}
1613

1714
impl<'tcx> AscribeUserType<'tcx> {
1815
pub fn new(
1916
mir_ty: Ty<'tcx>,
20-
variance: ty::Variance,
2117
def_id: DefId,
2218
user_substs: UserSubsts<'tcx>,
23-
projs: &'tcx ty::List<ProjectionKind<'tcx>>,
2419
) -> Self {
25-
Self { mir_ty, variance, def_id, user_substs, projs }
20+
Self { mir_ty, def_id, user_substs }
2621
}
2722
}
2823

@@ -52,19 +47,19 @@ impl<'gcx: 'tcx, 'tcx> super::QueryTypeOp<'gcx, 'tcx> for AscribeUserType<'tcx>
5247

5348
BraceStructTypeFoldableImpl! {
5449
impl<'tcx> TypeFoldable<'tcx> for AscribeUserType<'tcx> {
55-
mir_ty, variance, def_id, user_substs, projs
50+
mir_ty, def_id, user_substs
5651
}
5752
}
5853

5954
BraceStructLiftImpl! {
6055
impl<'a, 'tcx> Lift<'tcx> for AscribeUserType<'a> {
6156
type Lifted = AscribeUserType<'tcx>;
62-
mir_ty, variance, def_id, user_substs, projs
57+
mir_ty, def_id, user_substs
6358
}
6459
}
6560

6661
impl_stable_hash_for! {
6762
struct AscribeUserType<'tcx> {
68-
mir_ty, variance, def_id, user_substs, projs
63+
mir_ty, def_id, user_substs
6964
}
7065
}

src/librustc/ty/context.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -813,18 +813,19 @@ pub type CanonicalUserTypeAnnotations<'tcx> =
813813
pub struct CanonicalUserTypeAnnotation<'tcx> {
814814
pub user_ty: CanonicalUserType<'tcx>,
815815
pub span: Span,
816+
pub inferred_ty: Ty<'tcx>,
816817
}
817818

818819
BraceStructTypeFoldableImpl! {
819820
impl<'tcx> TypeFoldable<'tcx> for CanonicalUserTypeAnnotation<'tcx> {
820-
user_ty, span
821+
user_ty, span, inferred_ty
821822
}
822823
}
823824

824825
BraceStructLiftImpl! {
825826
impl<'a, 'tcx> Lift<'tcx> for CanonicalUserTypeAnnotation<'a> {
826827
type Lifted = CanonicalUserTypeAnnotation<'tcx>;
827-
user_ty, span
828+
user_ty, span, inferred_ty
828829
}
829830
}
830831

src/librustc_mir/borrow_check/nll/constraint_generation.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use rustc::infer::InferCtxt;
77
use rustc::mir::visit::TyContext;
88
use rustc::mir::visit::Visitor;
99
use rustc::mir::{BasicBlock, BasicBlockData, Location, Mir, Place, Rvalue};
10-
use rustc::mir::{Statement, Terminator};
10+
use rustc::mir::{SourceInfo, Statement, Terminator};
1111
use rustc::mir::UserTypeProjection;
1212
use rustc::ty::fold::TypeFoldable;
1313
use rustc::ty::subst::Substs;
@@ -66,11 +66,12 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx
6666
/// call. Make them live at the location where they appear.
6767
fn visit_ty(&mut self, ty: &ty::Ty<'tcx>, ty_context: TyContext) {
6868
match ty_context {
69-
TyContext::ReturnTy(source_info)
70-
| TyContext::YieldTy(source_info)
71-
| TyContext::LocalDecl { source_info, .. } => {
69+
TyContext::ReturnTy(SourceInfo { span, .. })
70+
| TyContext::YieldTy(SourceInfo { span, .. })
71+
| TyContext::UserTy(span)
72+
| TyContext::LocalDecl { source_info: SourceInfo { span, .. }, .. } => {
7273
span_bug!(
73-
source_info.span,
74+
span,
7475
"should not be visiting outside of the CFG: {:?}",
7576
ty_context
7677
);

src/librustc_mir/borrow_check/nll/renumber.rs

+1-16
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
use rustc::ty::subst::Substs;
2-
use rustc::ty::{
3-
self, ClosureSubsts, GeneratorSubsts, Ty, TypeFoldable,
4-
UserTypeAnnotationIndex, CanonicalUserTypeAnnotation
5-
};
2+
use rustc::ty::{self, ClosureSubsts, GeneratorSubsts, Ty, TypeFoldable};
63
use rustc::mir::{Location, Mir};
74
use rustc::mir::visit::{MutVisitor, TyContext};
85
use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
@@ -58,18 +55,6 @@ impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> {
5855
debug!("visit_ty: ty={:?}", ty);
5956
}
6057

61-
fn visit_user_type_annotation(
62-
&mut self,
63-
_index: UserTypeAnnotationIndex,
64-
_ty: &mut CanonicalUserTypeAnnotation,
65-
) {
66-
// User type annotations represent the types that the user
67-
// wrote in the progarm. We don't want to erase the regions
68-
// from these types: rather, we want to add them as
69-
// constraints at type-check time.
70-
debug!("visit_user_type_annotation: skipping renumber");
71-
}
72-
7358
fn visit_substs(&mut self, substs: &mut &'tcx Substs<'tcx>, location: Location) {
7459
debug!("visit_substs(substs={:?}, location={:?})", substs, location);
7560

src/librustc_mir/borrow_check/nll/type_check/mod.rs

+62-56
Original file line numberDiff line numberDiff line change
@@ -748,7 +748,7 @@ struct TypeChecker<'a, 'gcx: 'tcx, 'tcx: 'a> {
748748
/// annotations. Part of the reason for this setup is that it allows us to enforce basic
749749
/// WF criteria on the types even if the code that referenced them is dead
750750
/// code (see #54943).
751-
instantiated_type_annotations: FxHashMap<UserTypeAnnotationIndex, UserType<'tcx>>,
751+
instantiated_type_annotations: FxHashMap<UserTypeAnnotationIndex, Ty<'tcx>>,
752752
}
753753

754754
struct BorrowCheckContext<'a, 'tcx: 'a> {
@@ -920,17 +920,58 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
920920
self.mir.user_type_annotations
921921
);
922922
for annotation_index in self.mir.user_type_annotations.indices() {
923-
let CanonicalUserTypeAnnotation { span, ref user_ty } =
923+
let CanonicalUserTypeAnnotation { span, ref user_ty, inferred_ty } =
924924
self.mir.user_type_annotations[annotation_index];
925-
let (mut annotation, _) = self.infcx.instantiate_canonical_with_fresh_inference_vars(
925+
let (annotation, _) = self.infcx.instantiate_canonical_with_fresh_inference_vars(
926926
span, user_ty
927927
);
928928
match annotation {
929-
UserType::Ty(ref mut ty) =>
930-
*ty = self.normalize(ty, Locations::All(span)),
931-
_ => {},
929+
UserType::Ty(mut ty) => {
930+
ty = self.normalize(ty, Locations::All(span));
931+
932+
if let Err(terr) = self.eq_types(
933+
ty,
934+
inferred_ty,
935+
Locations::All(span),
936+
ConstraintCategory::BoringNoLocation,
937+
) {
938+
span_mirbug!(
939+
self,
940+
self.mir.user_type_annotations[annotation_index],
941+
"bad user type ({:?} = {:?}): {:?}",
942+
ty,
943+
inferred_ty,
944+
terr
945+
);
946+
}
947+
948+
self.prove_predicate(
949+
ty::Predicate::WellFormed(inferred_ty),
950+
Locations::All(span),
951+
ConstraintCategory::TypeAnnotation,
952+
);
953+
},
954+
UserType::TypeOf(def_id, user_substs) => {
955+
if let Err(terr) = self.fully_perform_op(
956+
Locations::All(span),
957+
ConstraintCategory::BoringNoLocation,
958+
self.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(
959+
inferred_ty, def_id, user_substs,
960+
)),
961+
) {
962+
span_mirbug!(
963+
self,
964+
self.mir.user_type_annotations[annotation_index],
965+
"bad user type AscribeUserType({:?}, {:?} {:?}): {:?}",
966+
inferred_ty,
967+
def_id,
968+
user_substs,
969+
terr
970+
);
971+
}
972+
},
932973
}
933-
self.instantiated_type_annotations.insert(annotation_index, annotation);
974+
self.instantiated_type_annotations.insert(annotation_index, inferred_ty);
934975
}
935976
debug!(
936977
"instantiate_user_type_annotations: instantiated_type_annotations={:?}",
@@ -1067,58 +1108,23 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
10671108
a, v, user_ty, locations,
10681109
);
10691110

1070-
let type_annotation = self.instantiated_type_annotations[&user_ty.base];
1071-
match type_annotation {
1072-
UserType::Ty(ty) => {
1073-
// The `TypeRelating` code assumes that "unresolved inference
1074-
// variables" appear in the "a" side, so flip `Contravariant`
1075-
// ambient variance to get the right relationship.
1076-
let v1 = ty::Contravariant.xform(v);
1077-
let tcx = self.infcx.tcx;
1111+
let annotated_type = self.instantiated_type_annotations[&user_ty.base];
1112+
let mut curr_projected_ty = PlaceTy::from_ty(annotated_type);
10781113

1079-
// We need to follow any provided projetions into the type.
1080-
//
1081-
// if we hit a ty var as we descend, then just skip the
1082-
// attempt to relate the mir local with any type.
1083-
#[derive(Debug)] struct HitTyVar;
1084-
let mut curr_projected_ty: Result<PlaceTy, HitTyVar>;
1085-
1086-
curr_projected_ty = Ok(PlaceTy::from_ty(ty));
1087-
for proj in &user_ty.projs {
1088-
let projected_ty = if let Ok(projected_ty) = curr_projected_ty {
1089-
projected_ty
1090-
} else {
1091-
break;
1092-
};
1093-
curr_projected_ty = projected_ty.projection_ty_core(
1094-
tcx, proj, |this, field, &()| {
1095-
if this.to_ty(tcx).is_ty_var() {
1096-
Err(HitTyVar)
1097-
} else {
1098-
let ty = this.field_ty(tcx, field);
1099-
Ok(self.normalize(ty, locations))
1100-
}
1101-
});
1102-
}
1103-
debug!("user_ty base: {:?} freshened: {:?} projs: {:?} yields: {:?}",
1104-
user_ty.base, ty, user_ty.projs, curr_projected_ty);
1114+
let tcx = self.infcx.tcx;
11051115

1106-
if let Ok(projected_ty) = curr_projected_ty {
1107-
let ty = projected_ty.to_ty(tcx);
1108-
self.relate_types(ty, v1, a, locations, category)?;
1109-
}
1110-
}
1111-
UserType::TypeOf(def_id, user_substs) => {
1112-
let projs = self.infcx.tcx.intern_projs(&user_ty.projs);
1113-
self.fully_perform_op(
1114-
locations,
1115-
category,
1116-
self.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(
1117-
a, v, def_id, user_substs, projs,
1118-
)),
1119-
)?;
1120-
}
1116+
for proj in &user_ty.projs {
1117+
let projected_ty = curr_projected_ty.projection_ty_core(tcx, proj, |this, field, &()| {
1118+
let ty = this.field_ty(tcx, field);
1119+
self.normalize(ty, locations)
1120+
});
1121+
curr_projected_ty = projected_ty;
11211122
}
1123+
debug!("user_ty base: {:?} freshened: {:?} projs: {:?} yields: {:?}",
1124+
user_ty.base, annotated_type, user_ty.projs, curr_projected_ty);
1125+
1126+
let ty = curr_projected_ty.to_ty(tcx);
1127+
self.relate_types(a, v, ty, locations, category)?;
11221128

11231129
Ok(())
11241130
}

src/librustc_mir/build/expr/as_constant.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
3131
value,
3232
} => this.as_constant(value),
3333
ExprKind::Literal { literal, user_ty } => {
34-
let user_ty = user_ty.map(|ty| {
34+
let user_ty = user_ty.map(|user_ty| {
3535
this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
3636
span,
37-
user_ty: ty,
37+
user_ty,
38+
inferred_ty: ty,
3839
})
3940
});
4041
Constant {

src/librustc_mir/build/expr/as_place.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
134134
let place = unpack!(block = this.as_place(block, source));
135135
if let Some(user_ty) = user_ty {
136136
let annotation_index = this.canonical_user_type_annotations.push(
137-
CanonicalUserTypeAnnotation { span: source_info.span, user_ty }
137+
CanonicalUserTypeAnnotation {
138+
span: source_info.span,
139+
user_ty,
140+
inferred_ty: expr.ty,
141+
}
138142
);
139143
this.cfg.push(
140144
block,
@@ -157,7 +161,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
157161
);
158162
if let Some(user_ty) = user_ty {
159163
let annotation_index = this.canonical_user_type_annotations.push(
160-
CanonicalUserTypeAnnotation { span: source_info.span, user_ty }
164+
CanonicalUserTypeAnnotation {
165+
span: source_info.span,
166+
user_ty,
167+
inferred_ty: expr.ty,
168+
}
161169
);
162170
this.cfg.push(
163171
block,

src/librustc_mir/build/expr/as_rvalue.rs

+2
Original file line numberDiff line numberDiff line change
@@ -331,10 +331,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
331331
.collect()
332332
};
333333

334+
let inferred_ty = expr.ty;
334335
let user_ty = user_ty.map(|ty| {
335336
this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
336337
span: source_info.span,
337338
user_ty: ty,
339+
inferred_ty,
338340
})
339341
});
340342
let adt = box AggregateKind::Adt(

0 commit comments

Comments
 (0)