Skip to content

Commit bfb1d95

Browse files
committed
normalize and prove predicates
Also include a test that was not working previously.
1 parent 121f3c8 commit bfb1d95

File tree

3 files changed

+76
-1
lines changed

3 files changed

+76
-1
lines changed

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

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ use rustc::traits::query::type_op::custom::CustomTypeOp;
4242
use rustc::traits::query::{Fallible, NoSolution};
4343
use rustc::traits::{ObligationCause, PredicateObligations};
4444
use rustc::ty::fold::TypeFoldable;
45-
use rustc::ty::subst::{Subst, Substs, UnpackedKind, UserSubsts, UserSelfTy};
45+
use rustc::ty::subst::{Subst, Substs, UnpackedKind, UserSelfTy, UserSubsts};
4646
use rustc::ty::{self, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind};
4747
use std::rc::Rc;
4848
use std::{fmt, iter};
@@ -1034,13 +1034,62 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
10341034
self.eq_types(self_ty, impl_self_ty, locations, category)?;
10351035
}
10361036

1037+
// Prove the predicates coming along with `def_id`.
1038+
//
1039+
// Also, normalize the `instantiated_predicates`
1040+
// because otherwise we wind up with duplicate "type
1041+
// outlives" error messages.
1042+
let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, substs);
1043+
let instantiated_predicates = self.fold_to_region_vid(instantiated_predicates);
1044+
self.normalize_and_prove_instantiated_predicates(
1045+
instantiated_predicates,
1046+
locations,
1047+
);
1048+
1049+
// In addition to proving the predicates, we have to
1050+
// prove that `ty` is well-formed -- this is because
1051+
// the WF of `ty` is predicated on the substs being
1052+
// well-formed, and we haven't proven *that*. We don't
1053+
// want to prove the WF of types from `substs` directly because they
1054+
// haven't been normalized.
1055+
//
1056+
// FIXME(nmatsakis): Well, perhaps we should normalize
1057+
// them? This would only be relevant if some input
1058+
// type were ill-formed but did not appear in `ty`,
1059+
// which...could happen with normalization...
10371060
self.prove_predicate(ty::Predicate::WellFormed(ty), locations, category);
10381061
}
10391062
}
10401063

10411064
Ok(())
10421065
}
10431066

1067+
/// Replace all free regions in `value` with their NLL `RegionVid`
1068+
/// equivalents; if not in NLL, does nothing. This is never
1069+
/// particularly necessary -- we'll do it lazilly as we process
1070+
/// the value anyway -- but in some specific cases it is useful to
1071+
/// normalize so we can suppress duplicate error messages.
1072+
fn fold_to_region_vid<T>(
1073+
&self,
1074+
value: T
1075+
) -> T
1076+
where T: TypeFoldable<'tcx>
1077+
{
1078+
if let Some(borrowck_context) = &self.borrowck_context {
1079+
self.tcx().fold_regions(&value, &mut false, |r, _debruijn| {
1080+
if r.has_free_regions() {
1081+
self.tcx().mk_region(ty::RegionKind::ReVar(
1082+
borrowck_context.universal_regions.to_region_vid(r),
1083+
))
1084+
} else {
1085+
r
1086+
}
1087+
})
1088+
} else {
1089+
value
1090+
}
1091+
}
1092+
10441093
fn eq_opaque_type_and_type(
10451094
&mut self,
10461095
revealed_ty: Ty<'tcx>,
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#![feature(nll)]
2+
3+
trait Foo<'a> {
4+
const C: &'a u32;
5+
}
6+
7+
impl<'a, T> Foo<'a> for T {
8+
const C: &'a u32 = &22;
9+
}
10+
11+
fn foo<'a, T: Foo<'a>>() -> &'static u32 {
12+
T::C //~ ERROR
13+
}
14+
15+
fn main() {
16+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error: unsatisfied lifetime constraints
2+
--> $DIR/constant-in-expr-trait-item-3.rs:12:5
3+
|
4+
LL | fn foo<'a, T: Foo<'a>>() -> &'static u32 {
5+
| -- lifetime `'a` defined here
6+
LL | T::C //~ ERROR
7+
| ^^^^ returning this value requires that `'a` must outlive `'static`
8+
9+
error: aborting due to previous error
10+

0 commit comments

Comments
 (0)