diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2018-10-17 11:10:08 -0400 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2018-10-19 09:34:27 -0400 |
| commit | bfb1d959c3cc64d54d1a1f3d586d90b6ce0d5357 (patch) | |
| tree | 4c0a50fb6181e5a1f0a06e8170e2106cb6bdd3e0 | |
| parent | 121f3c8d19c3549ab0b51a14034ffb8b097faf42 (diff) | |
| download | rust-bfb1d959c3cc64d54d1a1f3d586d90b6ce0d5357.tar.gz rust-bfb1d959c3cc64d54d1a1f3d586d90b6ce0d5357.zip | |
normalize and prove predicates
Also include a test that was not working previously.
3 files changed, 76 insertions, 1 deletions
diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index d64643430c9..6783083c958 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -42,7 +42,7 @@ use rustc::traits::query::type_op::custom::CustomTypeOp; use rustc::traits::query::{Fallible, NoSolution}; use rustc::traits::{ObligationCause, PredicateObligations}; use rustc::ty::fold::TypeFoldable; -use rustc::ty::subst::{Subst, Substs, UnpackedKind, UserSubsts, UserSelfTy}; +use rustc::ty::subst::{Subst, Substs, UnpackedKind, UserSelfTy, UserSubsts}; use rustc::ty::{self, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind}; use std::rc::Rc; use std::{fmt, iter}; @@ -1034,6 +1034,29 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { self.eq_types(self_ty, impl_self_ty, locations, category)?; } + // Prove the predicates coming along with `def_id`. + // + // Also, normalize the `instantiated_predicates` + // because otherwise we wind up with duplicate "type + // outlives" error messages. + let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, substs); + let instantiated_predicates = self.fold_to_region_vid(instantiated_predicates); + self.normalize_and_prove_instantiated_predicates( + instantiated_predicates, + locations, + ); + + // In addition to proving the predicates, we have to + // prove that `ty` is well-formed -- this is because + // the WF of `ty` is predicated on the substs being + // well-formed, and we haven't proven *that*. We don't + // want to prove the WF of types from `substs` directly because they + // haven't been normalized. + // + // FIXME(nmatsakis): Well, perhaps we should normalize + // them? This would only be relevant if some input + // type were ill-formed but did not appear in `ty`, + // which...could happen with normalization... self.prove_predicate(ty::Predicate::WellFormed(ty), locations, category); } } @@ -1041,6 +1064,32 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { Ok(()) } + /// Replace all free regions in `value` with their NLL `RegionVid` + /// equivalents; if not in NLL, does nothing. This is never + /// particularly necessary -- we'll do it lazilly as we process + /// the value anyway -- but in some specific cases it is useful to + /// normalize so we can suppress duplicate error messages. + fn fold_to_region_vid<T>( + &self, + value: T + ) -> T + where T: TypeFoldable<'tcx> + { + if let Some(borrowck_context) = &self.borrowck_context { + self.tcx().fold_regions(&value, &mut false, |r, _debruijn| { + if r.has_free_regions() { + self.tcx().mk_region(ty::RegionKind::ReVar( + borrowck_context.universal_regions.to_region_vid(r), + )) + } else { + r + } + }) + } else { + value + } + } + fn eq_opaque_type_and_type( &mut self, revealed_ty: Ty<'tcx>, diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.rs b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.rs new file mode 100644 index 00000000000..f83ae2438e6 --- /dev/null +++ b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.rs @@ -0,0 +1,16 @@ +#![feature(nll)] + +trait Foo<'a> { + const C: &'a u32; +} + +impl<'a, T> Foo<'a> for T { + const C: &'a u32 = &22; +} + +fn foo<'a, T: Foo<'a>>() -> &'static u32 { + T::C //~ ERROR +} + +fn main() { +} diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr new file mode 100644 index 00000000000..b373cebacb0 --- /dev/null +++ b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr @@ -0,0 +1,10 @@ +error: unsatisfied lifetime constraints + --> $DIR/constant-in-expr-trait-item-3.rs:12:5 + | +LL | fn foo<'a, T: Foo<'a>>() -> &'static u32 { + | -- lifetime `'a` defined here +LL | T::C //~ ERROR + | ^^^^ returning this value requires that `'a` must outlive `'static` + +error: aborting due to previous error + |
