use traits;
use traits::query::{
CanonicalProjectionGoal, CanonicalTyGoal, CanonicalTypeOpAscribeUserTypeGoal,
- CanonicalTypeOpEqGoal, CanonicalTypeOpSubtypeGoal, CanonicalPredicateGoal,
+ CanonicalTypeOpAscribeUserTypeWellFormedGoal, CanonicalTypeOpEqGoal,
+ CanonicalTypeOpSubtypeGoal, CanonicalPredicateGoal,
CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpNormalizeGoal,
};
use ty::{TyCtxt, FnSig, Instance, InstanceDef,
[] EvaluateObligation(CanonicalPredicateGoal<'tcx>),
[] EvaluateGoal(traits::ChalkCanonicalGoal<'tcx>),
[] TypeOpAscribeUserType(CanonicalTypeOpAscribeUserTypeGoal<'tcx>),
+ [] TypeOpAscribeUserTypeWellFormed(CanonicalTypeOpAscribeUserTypeWellFormedGoal<'tcx>),
[] TypeOpEq(CanonicalTypeOpEqGoal<'tcx>),
[] TypeOpSubtype(CanonicalTypeOpSubtypeGoal<'tcx>),
[] TypeOpProvePredicate(CanonicalTypeOpProvePredicateGoal<'tcx>),
pub type CanonicalTypeOpAscribeUserTypeGoal<'tcx> =
Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::ascribe_user_type::AscribeUserType<'tcx>>>;
+pub type CanonicalTypeOpAscribeUserTypeWellFormedGoal<'tcx> =
+ Canonical<'tcx, ty::ParamEnvAnd<'tcx,
+ type_op::ascribe_user_type::AscribeUserTypeWellFormed<'tcx>>>;
+
pub type CanonicalTypeOpEqGoal<'tcx> =
Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::eq::Eq<'tcx>>>;
use traits::query::Fallible;
use hir::def_id::DefId;
use mir::ProjectionKind;
-use ty::{self, ParamEnvAnd, Ty, TyCtxt};
+use ty::{self, ParamEnvAnd, Ty, TyCtxt, UserTypeAnnotation};
use ty::subst::UserSubsts;
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
user_substs: UserSubsts<'tcx>,
projs: &'tcx ty::List<ProjectionKind<'tcx>>,
) -> Self {
- AscribeUserType { mir_ty, variance, def_id, user_substs, projs }
+ Self { mir_ty, variance, def_id, user_substs, projs }
}
}
mir_ty, variance, def_id, user_substs, projs
}
}
+
+#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
+pub struct AscribeUserTypeWellFormed<'tcx> {
+ pub user_type_annotation: UserTypeAnnotation<'tcx>,
+}
+
+impl<'tcx> AscribeUserTypeWellFormed<'tcx> {
+ pub fn new(
+ user_type_annotation: UserTypeAnnotation<'tcx>,
+ ) -> Self {
+ Self { user_type_annotation, }
+ }
+}
+
+impl<'gcx: 'tcx, 'tcx> super::QueryTypeOp<'gcx, 'tcx> for AscribeUserTypeWellFormed<'tcx> {
+ type QueryResponse = ();
+
+ fn try_fast_path(
+ _tcx: TyCtxt<'_, 'gcx, 'tcx>,
+ _key: &ParamEnvAnd<'tcx, Self>,
+ ) -> Option<Self::QueryResponse> {
+ None
+ }
+
+ fn perform_query(
+ tcx: TyCtxt<'_, 'gcx, 'tcx>,
+ canonicalized: Canonicalized<'gcx, ParamEnvAnd<'tcx, Self>>,
+ ) -> Fallible<CanonicalizedQueryResponse<'gcx, ()>> {
+ tcx.type_op_ascribe_user_type_well_formed(canonicalized)
+ }
+
+ fn shrink_to_tcx_lifetime(
+ v: &'a CanonicalizedQueryResponse<'gcx, ()>,
+ ) -> &'a Canonical<'tcx, QueryResponse<'tcx, ()>> {
+ v
+ }
+}
+
+BraceStructTypeFoldableImpl! {
+ impl<'tcx> TypeFoldable<'tcx> for AscribeUserTypeWellFormed<'tcx> {
+ user_type_annotation
+ }
+}
+
+BraceStructLiftImpl! {
+ impl<'a, 'tcx> Lift<'tcx> for AscribeUserTypeWellFormed<'a> {
+ type Lifted = AscribeUserTypeWellFormed<'tcx>;
+ user_type_annotation
+ }
+}
+
+impl_stable_hash_for! {
+ struct AscribeUserTypeWellFormed<'tcx> {
+ user_type_annotation
+ }
+}
use traits;
use traits::query::{
CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal,
- CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpNormalizeGoal,
+ CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpAscribeUserTypeWellFormedGoal,
+ CanonicalTypeOpEqGoal, CanonicalTypeOpNormalizeGoal,
CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpSubtypeGoal,
};
use ty::{self, ParamEnvAnd, Ty, TyCtxt};
}
}
+impl<'tcx> QueryDescription<'tcx> for queries::type_op_ascribe_user_type_well_formed<'tcx> {
+ fn describe(
+ _tcx: TyCtxt<'_, '_, '_>,
+ goal: CanonicalTypeOpAscribeUserTypeWellFormedGoal<'tcx>,
+ ) -> Cow<'static, str> {
+ format!("evaluating `type_op_ascribe_user_type_well_formed` `{:?}`", goal).into()
+ }
+}
+
impl<'tcx> QueryDescription<'tcx> for queries::type_op_eq<'tcx> {
fn describe(_tcx: TyCtxt<'_, '_, '_>, goal: CanonicalTypeOpEqGoal<'tcx>) -> Cow<'static, str> {
format!("evaluating `type_op_eq` `{:?}`", goal).into()
use traits::{self, Vtable};
use traits::query::{
CanonicalPredicateGoal, CanonicalProjectionGoal,
- CanonicalTyGoal, CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpEqGoal,
+ CanonicalTyGoal, CanonicalTypeOpAscribeUserTypeGoal,
+ CanonicalTypeOpAscribeUserTypeWellFormedGoal, CanonicalTypeOpEqGoal,
CanonicalTypeOpSubtypeGoal, CanonicalTypeOpProvePredicateGoal,
CanonicalTypeOpNormalizeGoal, NoSolution,
};
NoSolution,
>,
+ /// Do not call this query directly: part of the `Eq` type-op
+ [] fn type_op_ascribe_user_type_well_formed: TypeOpAscribeUserTypeWellFormed(
+ CanonicalTypeOpAscribeUserTypeWellFormedGoal<'tcx>
+ ) -> Result<
+ Lrc<Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>>,
+ NoSolution,
+ >,
+
/// Do not call this query directly: part of the `Eq` type-op
[] fn type_op_eq: TypeOpEq(
CanonicalTypeOpEqGoal<'tcx>
DepKind::EvaluateObligation |
DepKind::EvaluateGoal |
DepKind::TypeOpAscribeUserType |
+ DepKind::TypeOpAscribeUserTypeWellFormed |
DepKind::TypeOpEq |
DepKind::TypeOpSubtype |
DepKind::TypeOpProvePredicate |
);
}
+ /// Check that user type annotations are well formed.
+ fn check_user_type_annotations_are_well_formed(&mut self) {
+ for index in self.mir.user_type_annotations.indices() {
+ let (span, _) = &self.mir.user_type_annotations[index];
+ let type_annotation = self.instantiated_type_annotations[&index];
+ if let Err(terr) = self.fully_perform_op(
+ Locations::All(*span),
+ ConstraintCategory::Assignment,
+ self.param_env.and(type_op::ascribe_user_type::AscribeUserTypeWellFormed::new(
+ type_annotation,
+ )),
+ ) {
+ span_mirbug!(
+ self,
+ type_annotation,
+ "bad user type annotation: {:?}",
+ terr,
+ );
+ }
+ }
+ }
+
/// Given some operation `op` that manipulates types, proves
/// predicates, or otherwise uses the inference context, executes
/// `op` and then executes all the further obligations that `op`
self.check_terminator(mir, block_data.terminator(), location);
self.check_iscleanup(mir, block_data);
}
+
+ self.check_user_type_annotations_are_well_formed();
}
fn normalize<T>(&mut self, value: T, location: impl NormalizeLocation) -> T
use rustc::hir::def_id::DefId;
use rustc::mir::ProjectionKind;
use rustc::mir::tcx::PlaceTy;
-use rustc::traits::query::type_op::ascribe_user_type::AscribeUserType;
+use rustc::traits::query::type_op::ascribe_user_type::{AscribeUserType, AscribeUserTypeWellFormed};
use rustc::traits::query::type_op::eq::Eq;
use rustc::traits::query::type_op::normalize::Normalize;
use rustc::traits::query::type_op::prove_predicate::ProvePredicate;
use rustc::ty::subst::{Kind, Subst, UserSubsts, UserSelfTy};
use rustc::ty::{
FnSig, Lift, ParamEnv, ParamEnvAnd, PolyFnSig, Predicate, Ty, TyCtxt, TypeFoldable, Variance,
+ UserTypeAnnotation,
};
use rustc_data_structures::sync::Lrc;
use std::fmt;
crate fn provide(p: &mut Providers) {
*p = Providers {
type_op_ascribe_user_type,
+ type_op_ascribe_user_type_well_formed,
type_op_eq,
type_op_prove_predicate,
type_op_subtype,
) = key.into_parts();
debug!(
- "type_op_user_type_relation: mir_ty={:?} variance={:?} def_id={:?} \
+ "type_op_ascribe_user_type: mir_ty={:?} variance={:?} def_id={:?} \
user_substs={:?} projs={:?}",
mir_ty, variance, def_id, user_substs, projs
);
})
}
+fn type_op_ascribe_user_type_well_formed<'tcx>(
+ tcx: TyCtxt<'_, 'tcx, 'tcx>,
+ canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, AscribeUserTypeWellFormed<'tcx>>>,
+) -> Result<Lrc<Canonical<'tcx, QueryResponse<'tcx, ()>>>, NoSolution> {
+ tcx.infer_ctxt()
+ .enter_canonical_trait_query(&canonicalized, |infcx, fulfill_cx, key| {
+ let (
+ param_env, AscribeUserTypeWellFormed { user_type_annotation }
+ ) = key.into_parts();
+
+ debug!(
+ "type_op_ascribe_user_type_well_formed: user_type_annotation={:?}",
+ user_type_annotation,
+ );
+
+ let mut cx = AscribeUserTypeCx { infcx, param_env, fulfill_cx };
+ cx.well_formed(user_type_annotation)?;
+
+ Ok(())
+ })
+}
+
struct AscribeUserTypeCx<'me, 'gcx: 'tcx, 'tcx: 'me> {
infcx: &'me InferCtxt<'me, 'gcx, 'tcx>,
param_env: ParamEnv<'tcx>,
value.subst(self.tcx(), substs)
}
+ fn well_formed(
+ &mut self,
+ type_annotation: UserTypeAnnotation<'tcx>
+ ) -> Result<(), NoSolution> {
+ match type_annotation {
+ UserTypeAnnotation::Ty(ty) => {
+ self.prove_predicate(Predicate::WellFormed(ty));
+ Ok(())
+ },
+ UserTypeAnnotation::TypeOf(did, user_substs) => {
+ let UserSubsts {
+ user_self_ty,
+ substs,
+ } = user_substs;
+
+ let ty = self.tcx().type_of(did);
+ let ty = self.subst(ty, substs);
+ debug!("relate_type_and_user_type: ty of def-id is {:?}", ty);
+ let ty = self.normalize(ty);
+
+ if let Some(UserSelfTy {
+ impl_def_id,
+ self_ty,
+ }) = user_self_ty {
+ let impl_self_ty = self.tcx().type_of(impl_def_id);
+ let impl_self_ty = self.subst(impl_self_ty, &substs);
+ let impl_self_ty = self.normalize(impl_self_ty);
+
+ self.relate(self_ty, Variance::Invariant, impl_self_ty)?;
+
+ self.prove_predicate(Predicate::WellFormed(impl_self_ty));
+ }
+
+ // 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(Predicate::WellFormed(ty));
+ Ok(())
+ },
+ }
+ }
+
fn relate_mir_and_user_ty(
&mut self,
mir_ty: Ty<'tcx>,
projs: &[ProjectionKind<'tcx>],
) -> Result<(), NoSolution> {
let UserSubsts {
- user_self_ty,
+ user_self_ty: _,
substs,
} = user_substs;
let tcx = self.tcx();
self.relate(mir_ty, variance, ty)?;
}
- if let Some(UserSelfTy {
- impl_def_id,
- self_ty,
- }) = user_self_ty {
- let impl_self_ty = self.tcx().type_of(impl_def_id);
- let impl_self_ty = self.subst(impl_self_ty, &substs);
- let impl_self_ty = self.normalize(impl_self_ty);
-
- self.relate(self_ty, Variance::Invariant, impl_self_ty)?;
-
- self.prove_predicate(Predicate::WellFormed(impl_self_ty));
- }
-
// Prove the predicates coming along with `def_id`.
//
// Also, normalize the `instantiated_predicates`
self.prove_predicate(instantiated_predicate);
}
- // 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(Predicate::WellFormed(ty));
-
Ok(())
}
}
LL | }
| - temporary value is freed at the end of this statement
-error: aborting due to previous error
+error[E0597]: `y` does not live long enough
+ --> $DIR/regions-free-region-ordering-caller1.rs:9:27
+ |
+LL | fn call1<'a>(x: &'a usize) {
+ | -- lifetime `'a` defined here
+...
+LL | let z: &'a & usize = &(&y);
+ | ----------- ^^^^ borrowed value does not live long enough
+ | |
+ | assignment requires that `y` is borrowed for `'a`
+...
+LL | }
+ | - `y` dropped here while still borrowed
+
+error: aborting due to 2 previous errors
-For more information about this error, try `rustc --explain E0716`.
+Some errors occurred: E0597, E0716.
+For more information about an error, try `rustc --explain E0597`.
// outlive 'a. In this case, that means TheType<'b>::TheAssocType,
// which is &'b (), must outlive 'a.
- // FIXME (#54943) NLL doesn't enforce WF condition in unreachable code if
- // `_x` is changed to `_`
- let _x: &'a WithAssoc<TheType<'b>> = loop { };
+ let _: &'a WithAssoc<TheType<'b>> = loop { };
//~^ ERROR reference has a longer lifetime
}
error[E0491]: in type `&'a WithAssoc<TheType<'b>>`, reference has a longer lifetime than the data it references
- --> $DIR/regions-outlives-projection-container-wc.rs:36:13
+ --> $DIR/regions-outlives-projection-container-wc.rs:34:12
|
-LL | let _x: &'a WithAssoc<TheType<'b>> = loop { };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | let _: &'a WithAssoc<TheType<'b>> = loop { };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: the pointer is valid for the lifetime 'a as defined on the function body at 28:15
--> $DIR/regions-outlives-projection-container-wc.rs:28:15