}
);
-impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for ty::UserTypeAnnotation<'gcx> {
+impl_stable_hash_for!(
+ struct ty::CanonicalUserTypeAnnotation<'tcx> {
+ user_ty, span, inferred_ty
+ }
+);
+
+impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for ty::UserType<'gcx> {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a>,
hasher: &mut StableHasher<W>) {
mem::discriminant(self).hash_stable(hcx, hasher);
match *self {
- ty::UserTypeAnnotation::Ty(ref ty) => {
+ ty::UserType::Ty(ref ty) => {
ty.hash_stable(hcx, hasher);
}
- ty::UserTypeAnnotation::TypeOf(ref def_id, ref substs) => {
+ ty::UserType::TypeOf(ref def_id, ref substs) => {
def_id.hash_stable(hcx, hasher);
substs.hash_stable(hcx, hasher);
}
use ty::layout::VariantIdx;
use ty::{
self, AdtDef, CanonicalUserTypeAnnotations, ClosureSubsts, GeneratorSubsts, Region, Ty, TyCtxt,
- UserTypeAnnotationIndex, UserTypeAnnotation,
+ UserTypeAnnotationIndex,
};
use util::ppaux;
elem: &PlaceElem<'tcx>)
-> PlaceTy<'tcx>
{
- self.projection_ty_core(tcx, elem, |_, _, ty| -> Result<Ty<'tcx>, ()> { Ok(ty) })
- .unwrap()
+ self.projection_ty_core(tcx, elem, |_, _, ty| ty)
}
/// `place_ty.projection_ty_core(tcx, elem, |...| { ... })`
/// `Ty` or downcast variant corresponding to that projection.
/// The `handle_field` callback must map a `Field` to its `Ty`,
/// (which should be trivial when `T` = `Ty`).
- pub fn projection_ty_core<V, T, E>(
+ pub fn projection_ty_core<V, T>(
self,
tcx: TyCtxt<'a, 'gcx, 'tcx>,
elem: &ProjectionElem<'tcx, V, T>,
- mut handle_field: impl FnMut(&Self, &Field, &T) -> Result<Ty<'tcx>, E>)
- -> Result<PlaceTy<'tcx>, E>
+ mut handle_field: impl FnMut(&Self, &Field, &T) -> Ty<'tcx>)
+ -> PlaceTy<'tcx>
where
V: ::std::fmt::Debug, T: ::std::fmt::Debug
{
}
},
ProjectionElem::Field(ref f, ref fty) =>
- PlaceTy::Ty { ty: handle_field(&self, f, fty)? },
+ PlaceTy::Ty { ty: handle_field(&self, f, fty) },
};
debug!("projection_ty self: {:?} elem: {:?} yields: {:?}", self, elem, answer);
- Ok(answer)
+ answer
}
}
use hir::def_id::DefId;
-use infer::canonical::Canonical;
use ty::subst::Substs;
-use ty::{ClosureSubsts, GeneratorSubsts, Region, Ty};
+use ty::{CanonicalUserTypeAnnotation, ClosureSubsts, GeneratorSubsts, Region, Ty};
use mir::*;
use syntax_pos::Span;
fn visit_user_type_annotation(
&mut self,
index: UserTypeAnnotationIndex,
- ty: & $($mutability)* Canonical<'tcx, UserTypeAnnotation<'tcx>>,
+ ty: & $($mutability)* CanonicalUserTypeAnnotation<'tcx>,
) {
self.super_user_type_annotation(index, ty);
}
self.visit_local_decl(local, & $($mutability)* mir.local_decls[local]);
}
- for index in mir.user_type_annotations.indices() {
- let (span, annotation) = & $($mutability)* mir.user_type_annotations[index];
+ macro_rules! type_annotations {
+ (mut) => (mir.user_type_annotations.iter_enumerated_mut());
+ () => (mir.user_type_annotations.iter_enumerated());
+ };
+
+ for (index, annotation) in type_annotations!($($mutability)*) {
self.visit_user_type_annotation(
index, annotation
);
- self.visit_span(span);
}
self.visit_span(&$($mutability)* mir.span);
fn super_user_type_annotation(
&mut self,
_index: UserTypeAnnotationIndex,
- _ty: & $($mutability)* Canonical<'tcx, UserTypeAnnotation<'tcx>>,
+ ty: & $($mutability)* CanonicalUserTypeAnnotation<'tcx>,
) {
+ self.visit_span(& $($mutability)* ty.span);
+ self.visit_ty(& $($mutability)* ty.inferred_ty, TyContext::UserTy(ty.span));
}
fn super_ty(&mut self, _ty: & $($mutability)* Ty<'tcx>) {
source_info: SourceInfo,
},
+ /// The inferred type of a user type annotation.
+ UserTy(Span),
+
/// The return type of the function.
ReturnTy(SourceInfo),
use infer::canonical::{Canonical, Canonicalized, CanonicalizedQueryResponse, QueryResponse};
use traits::query::Fallible;
use hir::def_id::DefId;
-use mir::ProjectionKind;
-use ty::{self, ParamEnvAnd, Ty, TyCtxt};
+use ty::{ParamEnvAnd, Ty, TyCtxt};
use ty::subst::UserSubsts;
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
pub struct AscribeUserType<'tcx> {
pub mir_ty: Ty<'tcx>,
- pub variance: ty::Variance,
pub def_id: DefId,
pub user_substs: UserSubsts<'tcx>,
- pub projs: &'tcx ty::List<ProjectionKind<'tcx>>,
}
impl<'tcx> AscribeUserType<'tcx> {
pub fn new(
mir_ty: Ty<'tcx>,
- variance: ty::Variance,
def_id: DefId,
user_substs: UserSubsts<'tcx>,
- projs: &'tcx ty::List<ProjectionKind<'tcx>>,
) -> Self {
- Self { mir_ty, variance, def_id, user_substs, projs }
+ Self { mir_ty, def_id, user_substs }
}
}
BraceStructTypeFoldableImpl! {
impl<'tcx> TypeFoldable<'tcx> for AscribeUserType<'tcx> {
- mir_ty, variance, def_id, user_substs, projs
+ mir_ty, def_id, user_substs
}
}
BraceStructLiftImpl! {
impl<'a, 'tcx> Lift<'tcx> for AscribeUserType<'a> {
type Lifted = AscribeUserType<'tcx>;
- mir_ty, variance, def_id, user_substs, projs
+ mir_ty, def_id, user_substs
}
}
impl_stable_hash_for! {
struct AscribeUserType<'tcx> {
- mir_ty, variance, def_id, user_substs, projs
+ mir_ty, def_id, user_substs
}
}
/// canonical substitutions would include only `for<X> { Vec<X> }`.
///
/// See also `AscribeUserType` statement in MIR.
- user_provided_types: ItemLocalMap<CanonicalUserTypeAnnotation<'tcx>>,
+ user_provided_types: ItemLocalMap<CanonicalUserType<'tcx>>,
/// Stores the canonicalized types provided by the user. See also
/// `AscribeUserType` statement in MIR.
pub fn user_provided_types(
&self
- ) -> LocalTableInContext<'_, CanonicalUserTypeAnnotation<'tcx>> {
+ ) -> LocalTableInContext<'_, CanonicalUserType<'tcx>> {
LocalTableInContext {
local_id_root: self.local_id_root,
data: &self.user_provided_types
pub fn user_provided_types_mut(
&mut self
- ) -> LocalTableInContextMut<'_, CanonicalUserTypeAnnotation<'tcx>> {
+ ) -> LocalTableInContextMut<'_, CanonicalUserType<'tcx>> {
LocalTableInContextMut {
local_id_root: self.local_id_root,
data: &mut self.user_provided_types
newtype_index! {
pub struct UserTypeAnnotationIndex {
- DEBUG_FORMAT = "UserTypeAnnotation({})",
+ DEBUG_FORMAT = "UserType({})",
const START_INDEX = 0,
}
}
/// Mapping of type annotation indices to canonical user type annotations.
pub type CanonicalUserTypeAnnotations<'tcx> =
- IndexVec<UserTypeAnnotationIndex, (Span, CanonicalUserTypeAnnotation<'tcx>)>;
+ IndexVec<UserTypeAnnotationIndex, CanonicalUserTypeAnnotation<'tcx>>;
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
+pub struct CanonicalUserTypeAnnotation<'tcx> {
+ pub user_ty: CanonicalUserType<'tcx>,
+ pub span: Span,
+ pub inferred_ty: Ty<'tcx>,
+}
+
+BraceStructTypeFoldableImpl! {
+ impl<'tcx> TypeFoldable<'tcx> for CanonicalUserTypeAnnotation<'tcx> {
+ user_ty, span, inferred_ty
+ }
+}
+
+BraceStructLiftImpl! {
+ impl<'a, 'tcx> Lift<'tcx> for CanonicalUserTypeAnnotation<'a> {
+ type Lifted = CanonicalUserTypeAnnotation<'tcx>;
+ user_ty, span, inferred_ty
+ }
+}
+
/// Canonicalized user type annotation.
-pub type CanonicalUserTypeAnnotation<'gcx> = Canonical<'gcx, UserTypeAnnotation<'gcx>>;
+pub type CanonicalUserType<'gcx> = Canonical<'gcx, UserType<'gcx>>;
-impl CanonicalUserTypeAnnotation<'gcx> {
+impl CanonicalUserType<'gcx> {
/// Returns `true` if this represents a substitution of the form `[?0, ?1, ?2]`,
/// i.e. each thing is mapped to a canonical variable with the same index.
pub fn is_identity(&self) -> bool {
match self.value {
- UserTypeAnnotation::Ty(_) => false,
- UserTypeAnnotation::TypeOf(_, user_substs) => {
+ UserType::Ty(_) => false,
+ UserType::TypeOf(_, user_substs) => {
if user_substs.user_self_ty.is_some() {
return false;
}
/// from constants that are named via paths, like `Foo::<A>::new` and
/// so forth.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
-pub enum UserTypeAnnotation<'tcx> {
+pub enum UserType<'tcx> {
Ty(Ty<'tcx>),
/// The canonical type is the result of `type_of(def_id)` with the
}
EnumTypeFoldableImpl! {
- impl<'tcx> TypeFoldable<'tcx> for UserTypeAnnotation<'tcx> {
- (UserTypeAnnotation::Ty)(ty),
- (UserTypeAnnotation::TypeOf)(def, substs),
+ impl<'tcx> TypeFoldable<'tcx> for UserType<'tcx> {
+ (UserType::Ty)(ty),
+ (UserType::TypeOf)(def, substs),
}
}
EnumLiftImpl! {
- impl<'a, 'tcx> Lift<'tcx> for UserTypeAnnotation<'a> {
- type Lifted = UserTypeAnnotation<'tcx>;
- (UserTypeAnnotation::Ty)(ty),
- (UserTypeAnnotation::TypeOf)(def, substs),
+ impl<'a, 'tcx> Lift<'tcx> for UserType<'a> {
+ type Lifted = UserType<'tcx>;
+ (UserType::Ty)(ty),
+ (UserType::TypeOf)(def, substs),
}
}
pub use self::context::{TyCtxt, FreeRegionInfo, GlobalArenas, AllArenas, tls, keep_local};
pub use self::context::{Lift, TypeckTables, CtxtInterners};
pub use self::context::{
- UserTypeAnnotationIndex, UserTypeAnnotation, CanonicalUserTypeAnnotation,
- CanonicalUserTypeAnnotations,
+ UserTypeAnnotationIndex, UserType, CanonicalUserType,
+ CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
};
pub use self::instance::{Instance, InstanceDef};
use rustc::mir::visit::TyContext;
use rustc::mir::visit::Visitor;
use rustc::mir::{BasicBlock, BasicBlockData, Location, Mir, Place, Rvalue};
-use rustc::mir::{Statement, Terminator};
+use rustc::mir::{SourceInfo, Statement, Terminator};
use rustc::mir::UserTypeProjection;
use rustc::ty::fold::TypeFoldable;
use rustc::ty::subst::Substs;
/// call. Make them live at the location where they appear.
fn visit_ty(&mut self, ty: &ty::Ty<'tcx>, ty_context: TyContext) {
match ty_context {
- TyContext::ReturnTy(source_info)
- | TyContext::YieldTy(source_info)
- | TyContext::LocalDecl { source_info, .. } => {
+ TyContext::ReturnTy(SourceInfo { span, .. })
+ | TyContext::YieldTy(SourceInfo { span, .. })
+ | TyContext::UserTy(span)
+ | TyContext::LocalDecl { source_info: SourceInfo { span, .. }, .. } => {
span_bug!(
- source_info.span,
+ span,
"should not be visiting outside of the CFG: {:?}",
ty_context
);
-use rustc::infer::canonical::Canonical;
use rustc::ty::subst::Substs;
-use rustc::ty::{
- self, ClosureSubsts, GeneratorSubsts, Ty, TypeFoldable, UserTypeAnnotation,
- UserTypeAnnotationIndex,
-};
+use rustc::ty::{self, ClosureSubsts, GeneratorSubsts, Ty, TypeFoldable};
use rustc::mir::{Location, Mir};
use rustc::mir::visit::{MutVisitor, TyContext};
use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
debug!("visit_ty: ty={:?}", ty);
}
- fn visit_user_type_annotation(
- &mut self,
- _index: UserTypeAnnotationIndex,
- _ty: &mut Canonical<'tcx, UserTypeAnnotation<'tcx>>,
- ) {
- // User type annotations represent the types that the user
- // wrote in the progarm. We don't want to erase the regions
- // from these types: rather, we want to add them as
- // constraints at type-check time.
- debug!("visit_user_type_annotation: skipping renumber");
- }
-
fn visit_substs(&mut self, substs: &mut &'tcx Substs<'tcx>, location: Location) {
debug!("visit_substs(substs={:?}, location={:?})", substs, location);
use rustc::traits::query::{Fallible, NoSolution};
use rustc::traits::{ObligationCause, PredicateObligations};
use rustc::ty::fold::TypeFoldable;
-use rustc::ty::subst::{Subst, Substs, UnpackedKind};
+use rustc::ty::subst::{Subst, Substs, UnpackedKind, UserSubsts};
use rustc::ty::{
- self, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind, UserTypeAnnotation,
- UserTypeAnnotationIndex,
+ self, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind, UserType,
+ CanonicalUserTypeAnnotation, UserTypeAnnotationIndex,
};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
location.to_locations(),
ConstraintCategory::Boring,
) {
- let annotation = self.cx.instantiated_type_annotations[&annotation_index];
+ let annotation = &self.mir.user_type_annotations[annotation_index];
span_mirbug!(
self,
constant,
terr,
);
}
+ } else {
+ match *constant.literal {
+ ty::LazyConst::Unevaluated(def_id, substs) => {
+ if let Err(terr) = self.cx.fully_perform_op(
+ location.to_locations(),
+ ConstraintCategory::Boring,
+ self.cx.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(
+ constant.ty, def_id, UserSubsts { substs, user_self_ty: None },
+ )),
+ ) {
+ span_mirbug!(
+ self,
+ constant,
+ "bad constant type {:?} ({:?})",
+ constant,
+ terr
+ );
+ }
+ }
+ ty::LazyConst::Evaluated(lit) => {
+ if let ty::FnDef(def_id, substs) = lit.ty.sty {
+ let tcx = self.tcx();
+
+ let instantiated_predicates = tcx
+ .predicates_of(def_id)
+ .instantiate(tcx, substs);
+ self.cx.normalize_and_prove_instantiated_predicates(
+ instantiated_predicates,
+ location.to_locations(),
+ );
+ }
+ }
+ }
}
}
}
}
- /// Checks that the constant's `ty` field matches up with what
- /// would be expected from its literal.
+ /// Checks that the constant's `ty` field matches up with what would be
+ /// expected from its literal. Unevaluated constants and well-formed
+ /// constraints are checked by `visit_constant`.
fn sanitize_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
debug!(
"sanitize_constant(constant={:?}, location={:?})",
ty::LazyConst::Unevaluated(..) => return,
};
- // FIXME(#46702) -- We need some way to get the predicates
- // associated with the "pre-evaluated" form of the
- // constant. For example, consider that the constant
- // may have associated constant projections (`<Foo as
- // Trait<'a, 'b>>::SOME_CONST`) that impose
- // constraints on `'a` and `'b`. These constraints
- // would be lost if we just look at the normalized
- // value.
- if let ty::FnDef(def_id, substs) = literal.ty.sty {
- let tcx = self.tcx();
- let type_checker = &mut self.cx;
-
- // FIXME -- For now, use the substitutions from
- // `value.ty` rather than `value.val`. The
- // renumberer will rewrite them to independent
- // sets of regions; in principle, we ought to
- // derive the type of the `value.val` from "first
- // principles" and equate with value.ty, but as we
- // are transitioning to the miri-based system, we
- // don't have a handy function for that, so for
- // now we just ignore `value.val` regions.
-
- let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, substs);
- type_checker.normalize_and_prove_instantiated_predicates(
- instantiated_predicates,
- location.to_locations(),
- );
- }
-
debug!("sanitize_constant: expected_ty={:?}", literal.ty);
if let Err(terr) = self.cx.eq_types(
reported_errors: FxHashSet<(Ty<'tcx>, Span)>,
borrowck_context: Option<&'a mut BorrowCheckContext<'a, 'tcx>>,
universal_region_relations: Option<&'a UniversalRegionRelations<'tcx>>,
- /// For each user-type annotation (identified by a UserTypeAnnotationIndex), we create
- /// an "instantiated" version at the beginning of type check, which replaces each
- /// canonical variable with a fresh inference variable. These instantiated versions are
- /// stored either in this field or in user_substs, depending on the kind of user-type
- /// annotation. They are then referenced by the code which has the job of enforcing these
- /// annotations. Part of the reason for this setup is that it allows us to enforce basic
- /// WF criteria on the types even if the code that referenced them is dead
- /// code (see #54943).
- instantiated_type_annotations: FxHashMap<UserTypeAnnotationIndex, UserTypeAnnotation<'tcx>>,
}
struct BorrowCheckContext<'a, 'tcx: 'a> {
borrowck_context,
reported_errors: Default::default(),
universal_region_relations,
- instantiated_type_annotations: Default::default(),
};
- checker.instantiate_user_type_annotations();
+ checker.check_user_type_annotations();
checker
}
- /// Instantiate canonical types from user type annotations in the `Mir` into the
- /// `TypeChecker`. Used when relating user type annotations and when checking if
- /// annotations are well-formed.
- fn instantiate_user_type_annotations(&mut self) {
+ /// Equate the inferred type and the annotated type for user type annotations
+ fn check_user_type_annotations(&mut self) {
debug!(
- "instantiate_user_type_annotations: user_type_annotations={:?}",
+ "check_user_type_annotations: user_type_annotations={:?}",
self.mir.user_type_annotations
);
- for annotation_index in self.mir.user_type_annotations.indices() {
- let (span, canonical_annotation) = &self.mir.user_type_annotations[annotation_index];
- let (mut annotation, _) = self.infcx.instantiate_canonical_with_fresh_inference_vars(
- *span, &canonical_annotation
+ for user_annotation in &self.mir.user_type_annotations {
+ let CanonicalUserTypeAnnotation { span, ref user_ty, inferred_ty } = *user_annotation;
+ let (annotation, _) = self.infcx.instantiate_canonical_with_fresh_inference_vars(
+ span, user_ty
);
match annotation {
- UserTypeAnnotation::Ty(ref mut ty) =>
- *ty = self.normalize(ty, Locations::All(*span)),
- _ => {},
+ UserType::Ty(mut ty) => {
+ ty = self.normalize(ty, Locations::All(span));
+
+ if let Err(terr) = self.eq_types(
+ ty,
+ inferred_ty,
+ Locations::All(span),
+ ConstraintCategory::BoringNoLocation,
+ ) {
+ span_mirbug!(
+ self,
+ user_annotation,
+ "bad user type ({:?} = {:?}): {:?}",
+ ty,
+ inferred_ty,
+ terr
+ );
+ }
+
+ self.prove_predicate(
+ ty::Predicate::WellFormed(inferred_ty),
+ Locations::All(span),
+ ConstraintCategory::TypeAnnotation,
+ );
+ },
+ UserType::TypeOf(def_id, user_substs) => {
+ if let Err(terr) = self.fully_perform_op(
+ Locations::All(span),
+ ConstraintCategory::BoringNoLocation,
+ self.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(
+ inferred_ty, def_id, user_substs,
+ )),
+ ) {
+ span_mirbug!(
+ self,
+ user_annotation,
+ "bad user type AscribeUserType({:?}, {:?} {:?}): {:?}",
+ inferred_ty,
+ def_id,
+ user_substs,
+ terr
+ );
+ }
+ },
}
- self.instantiated_type_annotations.insert(annotation_index, annotation);
}
- debug!(
- "instantiate_user_type_annotations: instantiated_type_annotations={:?}",
- self.instantiated_type_annotations,
- );
}
/// Given some operation `op` that manipulates types, proves
a, v, user_ty, locations,
);
- let type_annotation = self.instantiated_type_annotations[&user_ty.base];
- match type_annotation {
- UserTypeAnnotation::Ty(ty) => {
- // The `TypeRelating` code assumes that "unresolved inference
- // variables" appear in the "a" side, so flip `Contravariant`
- // ambient variance to get the right relationship.
- let v1 = ty::Contravariant.xform(v);
- let tcx = self.infcx.tcx;
+ let annotated_type = self.mir.user_type_annotations[user_ty.base].inferred_ty;
+ let mut curr_projected_ty = PlaceTy::from_ty(annotated_type);
- // We need to follow any provided projetions into the type.
- //
- // if we hit a ty var as we descend, then just skip the
- // attempt to relate the mir local with any type.
- #[derive(Debug)] struct HitTyVar;
- let mut curr_projected_ty: Result<PlaceTy, HitTyVar>;
-
- curr_projected_ty = Ok(PlaceTy::from_ty(ty));
- for proj in &user_ty.projs {
- let projected_ty = if let Ok(projected_ty) = curr_projected_ty {
- projected_ty
- } else {
- break;
- };
- curr_projected_ty = projected_ty.projection_ty_core(
- tcx, proj, |this, field, &()| {
- if this.to_ty(tcx).is_ty_var() {
- Err(HitTyVar)
- } else {
- let ty = this.field_ty(tcx, field);
- Ok(self.normalize(ty, locations))
- }
- });
- }
- debug!("user_ty base: {:?} freshened: {:?} projs: {:?} yields: {:?}",
- user_ty.base, ty, user_ty.projs, curr_projected_ty);
+ let tcx = self.infcx.tcx;
- if let Ok(projected_ty) = curr_projected_ty {
- let ty = projected_ty.to_ty(tcx);
- self.relate_types(ty, v1, a, locations, category)?;
- }
- }
- UserTypeAnnotation::TypeOf(def_id, user_substs) => {
- let projs = self.infcx.tcx.intern_projs(&user_ty.projs);
- self.fully_perform_op(
- locations,
- category,
- self.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(
- a, v, def_id, user_substs, projs,
- )),
- )?;
- }
+ for proj in &user_ty.projs {
+ let projected_ty = curr_projected_ty.projection_ty_core(tcx, proj, |this, field, &()| {
+ let ty = this.field_ty(tcx, field);
+ self.normalize(ty, locations)
+ });
+ curr_projected_ty = projected_ty;
}
+ debug!("user_ty base: {:?} freshened: {:?} projs: {:?} yields: {:?}",
+ user_ty.base, annotated_type, user_ty.projs, curr_projected_ty);
+
+ let ty = curr_projected_ty.to_ty(tcx);
+ self.relate_types(a, v, ty, locations, category)?;
Ok(())
}
location.to_locations(),
ConstraintCategory::Boring,
) {
- let annotation = self.instantiated_type_annotations[&annotation_index];
+ let annotation = &mir.user_type_annotations[annotation_index];
span_mirbug!(
self,
stmt,
Locations::All(stmt.source_info.span),
ConstraintCategory::TypeAnnotation,
) {
- let annotation = self.instantiated_type_annotations[&projection.base];
+ let annotation = &mir.user_type_annotations[projection.base];
span_mirbug!(
self,
stmt,
use build::Builder;
use hair::*;
use rustc::mir::*;
+use rustc::ty::CanonicalUserTypeAnnotation;
impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
/// Compile `expr`, yielding a compile-time constant. Assumes that
value,
} => this.as_constant(value),
ExprKind::Literal { literal, user_ty } => {
- let user_ty = user_ty.map(|ty| {
- this.canonical_user_type_annotations.push((span, ty))
+ let user_ty = user_ty.map(|user_ty| {
+ this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
+ span,
+ user_ty,
+ inferred_ty: ty,
+ })
});
Constant {
span,
use hair::*;
use rustc::mir::interpret::EvalErrorKind::BoundsCheck;
use rustc::mir::*;
-use rustc::ty::Variance;
+use rustc::ty::{CanonicalUserTypeAnnotation, Variance};
use rustc_data_structures::indexed_vec::Idx;
let place = unpack!(block = this.as_place(block, source));
if let Some(user_ty) = user_ty {
let annotation_index = this.canonical_user_type_annotations.push(
- (source_info.span, user_ty)
+ CanonicalUserTypeAnnotation {
+ span: source_info.span,
+ user_ty,
+ inferred_ty: expr.ty,
+ }
);
this.cfg.push(
block,
);
if let Some(user_ty) = user_ty {
let annotation_index = this.canonical_user_type_annotations.push(
- (source_info.span, user_ty)
+ CanonicalUserTypeAnnotation {
+ span: source_info.span,
+ user_ty,
+ inferred_ty: expr.ty,
+ }
);
this.cfg.push(
block,
use rustc::middle::region;
use rustc::mir::interpret::EvalErrorKind;
use rustc::mir::*;
-use rustc::ty::{self, Ty, UpvarSubsts};
+use rustc::ty::{self, CanonicalUserTypeAnnotation, Ty, UpvarSubsts};
use syntax_pos::Span;
impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
.collect()
};
+ let inferred_ty = expr.ty;
let user_ty = user_ty.map(|ty| {
- this.canonical_user_type_annotations.push((expr_span, ty))
+ this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
+ span: source_info.span,
+ user_ty: ty,
+ inferred_ty,
+ })
});
let adt = box AggregateKind::Adt(
adt_def,
use build::{GuardFrame, GuardFrameLocal, LocalsForNode};
use hair::*;
use rustc::mir::*;
-use rustc::ty::{self, Ty};
+use rustc::ty::{self, CanonicalUserTypeAnnotation, Ty};
use rustc::ty::layout::VariantIdx;
use rustc_data_structures::bit_set::BitSet;
use rustc_data_structures::fx::FxHashMap;
let ty_source_info = self.source_info(user_ty_span);
let user_ty = box pat_ascription_ty.user_ty(
- &mut self.canonical_user_type_annotations, ty_source_info.span
+ &mut self.canonical_user_type_annotations,
+ place.ty(&self.local_decls, self.hir.tcx()).to_ty(self.hir.tcx()),
+ ty_source_info.span,
);
self.cfg.push(
block,
//
// Note that the variance doesn't apply here, as we are tracking the effect
// of `user_ty` on any bindings contained with subpattern.
- let annotation = (user_ty_span, user_ty.base);
+ let annotation = CanonicalUserTypeAnnotation {
+ span: user_ty_span,
+ user_ty: user_ty.user_ty,
+ inferred_ty: subpattern.ty,
+ };
let projection = UserTypeProjection {
base: self.canonical_user_type_annotations.push(annotation),
- projs: user_ty.projs.clone(),
+ projs: Vec::new(),
};
let subpattern_user_ty = pattern_user_ty.push_projection(&projection, user_ty_span);
self.visit_bindings(subpattern, subpattern_user_ty, f)
);
let user_ty = box ascription.user_ty.clone().user_ty(
- &mut self.canonical_user_type_annotations, source_info.span
+ &mut self.canonical_user_type_annotations,
+ ascription.source.ty(&self.local_decls, self.hir.tcx()).to_ty(self.hir.tcx()),
+ source_info.span
);
self.cfg.push(
block,
let user_ty = user_provided_types.get(fun.hir_id)
.map(|u_ty| *u_ty)
.map(|mut u_ty| {
- if let UserTypeAnnotation::TypeOf(ref mut did, _) = &mut u_ty.value {
+ if let UserType::TypeOf(ref mut did, _) = &mut u_ty.value {
*did = adt_def.did;
}
u_ty
cx: &mut Cx<'a, 'gcx, 'tcx>,
hir_id: hir::HirId,
def: &Def,
-) -> Option<ty::CanonicalUserTypeAnnotation<'tcx>> {
+) -> Option<ty::CanonicalUserType<'tcx>> {
debug!("user_substs_applied_to_def: def={:?}", def);
let user_provided_type = match def {
// A reference to something callable -- e.g., a fn, method, or
use rustc::infer::canonical::Canonical;
use rustc::middle::region;
use rustc::ty::subst::Substs;
-use rustc::ty::{AdtDef, UpvarSubsts, Ty, Const, LazyConst, UserTypeAnnotation};
+use rustc::ty::{AdtDef, UpvarSubsts, Ty, Const, LazyConst, UserType};
use rustc::ty::layout::VariantIdx;
use rustc::hir;
use syntax::ast;
/// Optional user-given substs: for something like `let x =
/// Bar::<T> { ... }`.
- user_ty: Option<Canonical<'tcx, UserTypeAnnotation<'tcx>>>,
+ user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
fields: Vec<FieldExprRef<'tcx>>,
base: Option<FruInfo<'tcx>>
PlaceTypeAscription {
source: ExprRef<'tcx>,
/// Type that the user gave to this expression
- user_ty: Option<Canonical<'tcx, UserTypeAnnotation<'tcx>>>,
+ user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
},
ValueTypeAscription {
source: ExprRef<'tcx>,
/// Type that the user gave to this expression
- user_ty: Option<Canonical<'tcx, UserTypeAnnotation<'tcx>>>,
+ user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
},
Closure {
closure_id: DefId,
},
Literal {
literal: &'tcx LazyConst<'tcx>,
- user_ty: Option<Canonical<'tcx, UserTypeAnnotation<'tcx>>>,
+ user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
},
InlineAsm {
asm: &'tcx hir::InlineAsm,
use hair::constant::*;
use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability};
-use rustc::mir::{ProjectionElem, UserTypeProjection};
+use rustc::mir::{UserTypeProjection};
use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, sign_extend};
-use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty, Lift};
-use rustc::ty::{CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, UserTypeAnnotation};
+use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty, Lift, UserType};
+use rustc::ty::{CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations};
use rustc::ty::subst::{Substs, Kind};
use rustc::ty::layout::VariantIdx;
use rustc::hir::{self, PatKind, RangeEnd};
#[derive(Clone, Debug)]
pub struct PatternTypeProjection<'tcx> {
- pub base: CanonicalUserTypeAnnotation<'tcx>,
- pub projs: Vec<ProjectionElem<'tcx, (), ()>>,
+ pub user_ty: CanonicalUserType<'tcx>,
}
impl<'tcx> PatternTypeProjection<'tcx> {
- pub(crate) fn from_user_type(user_annotation: CanonicalUserTypeAnnotation<'tcx>) -> Self {
+ pub(crate) fn from_user_type(user_annotation: CanonicalUserType<'tcx>) -> Self {
Self {
- base: user_annotation,
- projs: Vec::new(),
+ user_ty: user_annotation,
}
}
pub(crate) fn user_ty(
self,
annotations: &mut CanonicalUserTypeAnnotations<'tcx>,
+ inferred_ty: Ty<'tcx>,
span: Span,
) -> UserTypeProjection<'tcx> {
UserTypeProjection {
- base: annotations.push((span, self.base)),
- projs: self.projs
+ base: annotations.push(CanonicalUserTypeAnnotation {
+ span,
+ user_ty: self.user_ty,
+ inferred_ty,
+ }),
+ projs: Vec::new(),
}
}
}
CloneImpls!{ <'tcx>
Span, Field, Mutability, ast::Name, ast::NodeId, usize, ty::Const<'tcx>,
Region<'tcx>, Ty<'tcx>, BindingMode, &'tcx AdtDef,
- &'tcx Substs<'tcx>, &'tcx Kind<'tcx>, UserTypeAnnotation<'tcx>,
+ &'tcx Substs<'tcx>, &'tcx Kind<'tcx>, UserType<'tcx>,
UserTypeProjection<'tcx>, PatternTypeProjection<'tcx>
}
use rustc::hir;
-use rustc::ty::{self, CanonicalUserTypeAnnotation, TyCtxt, UserTypeAnnotation};
+use rustc::ty::{self, CanonicalUserType, TyCtxt, UserType};
crate trait UserAnnotatedTyHelpers<'gcx: 'tcx, 'tcx> {
fn tcx(&self) -> TyCtxt<'_, 'gcx, 'tcx>;
fn user_substs_applied_to_ty_of_hir_id(
&self,
hir_id: hir::HirId,
- ) -> Option<CanonicalUserTypeAnnotation<'tcx>> {
+ ) -> Option<CanonicalUserType<'tcx>> {
let user_provided_types = self.tables().user_provided_types();
let mut user_ty = *user_provided_types.get(hir_id)?;
debug!("user_subts_applied_to_ty_of_hir_id: user_ty={:?}", user_ty);
match &self.tables().node_id_to_type(hir_id).sty {
ty::Adt(adt_def, ..) => {
- if let UserTypeAnnotation::TypeOf(ref mut did, _) = &mut user_ty.value {
+ if let UserType::TypeOf(ref mut did, _) = &mut user_ty.value {
*did = adt_def.did;
}
Some(user_ty)
if !mir.user_type_annotations.is_empty() {
writeln!(w, "| User Type Annotations")?;
}
- for (index, (span, annotation)) in mir.user_type_annotations.iter_enumerated() {
- writeln!(w, "| {:?}: {:?} at {:?}", index.index(), annotation, span)?;
+ for (index, annotation) in mir.user_type_annotations.iter_enumerated() {
+ writeln!(w, "| {:?}: {:?} at {:?}", index.index(), annotation.user_ty, annotation.span)?;
}
if !mir.user_type_annotations.is_empty() {
writeln!(w, "|")?;
use rustc::infer::canonical::{Canonical, QueryResponse};
use rustc::infer::InferCtxt;
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::eq::Eq;
use rustc::traits::query::type_op::normalize::Normalize;
tcx.infer_ctxt()
.enter_canonical_trait_query(&canonicalized, |infcx, fulfill_cx, key| {
let (
- param_env, AscribeUserType { mir_ty, variance, def_id, user_substs, projs }
+ param_env, AscribeUserType { mir_ty, def_id, user_substs }
) = key.into_parts();
debug!(
- "type_op_ascribe_user_type: mir_ty={:?} variance={:?} def_id={:?} \
- user_substs={:?} projs={:?}",
- mir_ty, variance, def_id, user_substs, projs
+ "type_op_ascribe_user_type: mir_ty={:?} def_id={:?} user_substs={:?}",
+ mir_ty, def_id, user_substs
);
let mut cx = AscribeUserTypeCx { infcx, param_env, fulfill_cx };
- cx.relate_mir_and_user_ty(mir_ty, variance, def_id, user_substs, projs)?;
+ cx.relate_mir_and_user_ty(mir_ty, def_id, user_substs)?;
Ok(())
})
fn relate_mir_and_user_ty(
&mut self,
mir_ty: Ty<'tcx>,
- variance: Variance,
def_id: DefId,
user_substs: UserSubsts<'tcx>,
- projs: &[ProjectionKind<'tcx>],
) -> Result<(), NoSolution> {
let UserSubsts {
user_self_ty,
debug!("relate_type_and_user_type: ty of def-id is {:?}", ty);
let ty = self.normalize(ty);
- // We need to follow any provided projetions into the type.
- //
- // if we hit a ty var as we descend, then just skip the
- // attempt to relate the mir local with any type.
-
- struct HitTyVar;
- let mut curr_projected_ty: Result<PlaceTy, HitTyVar>;
- curr_projected_ty = Ok(PlaceTy::from_ty(ty));
- for proj in projs {
- let projected_ty = if let Ok(projected_ty) = curr_projected_ty {
- projected_ty
- } else {
- break;
- };
- curr_projected_ty = projected_ty.projection_ty_core(
- tcx, proj, |this, field, &()| {
- if this.to_ty(tcx).is_ty_var() {
- Err(HitTyVar)
- } else {
- let ty = this.field_ty(tcx, field);
- Ok(self.normalize(ty))
- }
- });
- }
-
- if let Ok(projected_ty) = curr_projected_ty {
- let ty = projected_ty.to_ty(tcx);
- self.relate(mir_ty, variance, ty)?;
- }
+ self.relate(mir_ty, Variance::Invariant, ty)?;
// Prove the predicates coming along with `def_id`.
//
use rustc::mir::interpret::{ConstValue, GlobalId};
use rustc::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine};
use rustc::ty::{
- self, AdtKind, CanonicalUserTypeAnnotation, Ty, TyCtxt, GenericParamDefKind, Visibility,
- ToPolyTraitRef, ToPredicate, RegionKind, UserTypeAnnotation
+ self, AdtKind, CanonicalUserType, Ty, TyCtxt, GenericParamDefKind, Visibility,
+ ToPolyTraitRef, ToPredicate, RegionKind, UserType
};
use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
use rustc::ty::fold::TypeFoldable;
};
let c_ty = self.fcx.inh.infcx.canonicalize_user_type_annotation(
- &UserTypeAnnotation::Ty(revealed_ty)
+ &UserType::Ty(revealed_ty)
);
debug!("visit_local: ty.hir_id={:?} o_ty={:?} revealed_ty={:?} c_ty={:?}",
ty.hir_id, o_ty, revealed_ty, c_ty);
user_self_ty: None, // not relevant here
};
- self.infcx.canonicalize_user_type_annotation(&UserTypeAnnotation::TypeOf(
+ self.infcx.canonicalize_user_type_annotation(&UserType::TypeOf(
method.def_id,
user_substs,
))
if !substs.is_noop() {
let canonicalized = self.infcx.canonicalize_user_type_annotation(
- &UserTypeAnnotation::TypeOf(def_id, UserSubsts {
+ &UserType::TypeOf(def_id, UserSubsts {
substs,
user_self_ty,
})
pub fn write_user_type_annotation(
&self,
hir_id: hir::HirId,
- canonical_user_type_annotation: CanonicalUserTypeAnnotation<'tcx>,
+ canonical_user_type_annotation: CanonicalUserType<'tcx>,
) {
debug!(
"write_user_type_annotation: hir_id={:?} canonical_user_type_annotation={:?} tag={}",
// types that involve projections, since those can resolve to
// `'static` bounds (modulo #54940, which hopefully will be
// fixed by the time you see this comment, dear reader,
- // although I have my doubts). Other sorts of things are
- // already sufficiently enforced with erased regions. =)
- if ty.has_free_regions() || ty.has_projections() {
- let c_ty = self.infcx.canonicalize_response(&UserTypeAnnotation::Ty(ty));
+ // although I have my doubts). Also pass in types with inference
+ // types, because they may be repeated. Other sorts of things
+ // are already sufficiently enforced with erased regions. =)
+ if ty.has_free_regions() || ty.has_projections() || ty.has_infer_types() {
+ let c_ty = self.infcx.canonicalize_response(&UserType::Ty(ty));
debug!("to_ty_saving_user_provided_ty: c_ty={:?}", c_ty);
self.tables.borrow_mut().user_provided_types_mut().insert(ast_ty.hir_id, c_ty);
}
.user_provided_types_mut()
.insert(hir_id, c_ty.clone());
- if let ty::UserTypeAnnotation::TypeOf(_, user_substs) = c_ty.value {
+ if let ty::UserType::TypeOf(_, user_substs) = c_ty.value {
if self.rustc_dump_user_substs {
// This is a unit-testing mechanism.
let node_id = self.tcx().hir().hir_to_node_id(hir_id);
// StorageLive(_4);
// _4 = std::option::Option<std::boxed::Box<u32>>::None;
// FakeRead(ForLet, _4);
-// AscribeUserType(_4, o, UserTypeProjection { base: UserTypeAnnotation(1), projs: [] });
+// AscribeUserType(_4, o, UserTypeProjection { base: UserType(1), projs: [] });
// StorageLive(_5);
// StorageLive(_6);
// _6 = move _4;
// _10 = move _8;
// Retag(_10);
// ...
-// _14 = &mut (*_10);
-// Retag(_14);
-// _13 = move _14 as *mut i32 (Misc);
-// Retag([raw] _13);
+// _15 = &mut (*_10);
+// Retag(_15);
+// _14 = move _15 as *mut i32 (Misc);
+// Retag([raw] _14);
// ...
-// _17 = move _18(move _19) -> bb2;
+// _18 = move _19(move _20) -> bb2;
// }
//
// bb2: {
-// Retag(_17);
+// Retag(_18);
// ...
-// _21 = const Test::foo_shr(move _22, move _24) -> bb3;
+// _22 = const Test::foo_shr(move _23, move _25) -> bb3;
// }
//
// bb3: {
-// compile-pass
-// FIXME(#54943) This test targets the scenario where proving the WF requirements of a user
-// type annotation requires checking dead code. This test should actually fail to compile.
-
#![feature(nll)]
#![allow(warnings)]
return;
let x = foo::<&'a u32>();
- //~^ ERROR the type `&'a u32` does not fulfill the required lifetime [E0477]
+ //~^ ERROR lifetime may not live long enough
}
fn main() {}
--- /dev/null
+error: lifetime may not live long enough
+ --> $DIR/issue-54943.rs:9:13
+ |
+LL | fn boo<'a>() {
+ | -- lifetime `'a` defined here
+...
+LL | let x = foo::<&'a u32>();
+ | ^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+
+error: aborting due to previous error
+
--- /dev/null
+// compile-pass
+
+#![feature(type_alias_enum_variants)]
+
+enum Outer<T> {
+ A(T)
+}
+
+enum Inner {
+ A(i32)
+}
+
+type OuterAlias = Outer<Inner>;
+
+fn ice(x: OuterAlias) {
+ // Fine
+ match x {
+ OuterAlias::A(Inner::A(_)) => (),
+ }
+ // Not fine
+ match x {
+ OuterAlias::A(Inner::A(y)) => (),
+ }
+}
+
+fn main() {}
--> $DIR/projection-where-clause-env-wrong-bound.rs:17:5
|
LL | bar::<T::Output>() //~ ERROR may not live long enough
- | ^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^
|
= help: consider adding an explicit lifetime bound `<T as MyTrait<'_>>::Output: 'a`...
--> $DIR/projection-where-clause-none.rs:16:5
|
LL | bar::<T::Output>() //~ ERROR the parameter type `T` may not live long enough
- | ^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^
|
= help: consider adding an explicit lifetime bound `T: 'a`...
--- /dev/null
+// Test that we check that user type annotations are well-formed, even in dead
+// code.
+
+#![feature(nll)]
+
+fn uninit<'a>() {
+ return;
+ let x: &'static &'a (); //~ ERROR lifetime may not live long enough
+}
+
+fn var_type<'a>() {
+ return;
+ let x: &'static &'a () = &&(); //~ ERROR lifetime may not live long enough
+}
+
+fn uninit_infer<'a>() {
+ let x: &'static &'a _; //~ ERROR lifetime may not live long enough
+ x = && ();
+}
+
+fn infer<'a>() {
+ return;
+ let x: &'static &'a _ = &&(); //~ ERROR lifetime may not live long enough
+}
+
+fn uninit_no_var<'a>() {
+ return;
+ let _: &'static &'a (); //~ ERROR lifetime may not live long enough
+}
+
+fn no_var<'a>() {
+ return;
+ let _: &'static &'a () = &&(); //~ ERROR lifetime may not live long enough
+}
+
+fn infer_no_var<'a>() {
+ return;
+ let _: &'static &'a _ = &&(); //~ ERROR lifetime may not live long enough
+}
+
+trait X<'a, 'b> {}
+
+struct C<'a, 'b, T: X<'a, 'b>>(T, &'a (), &'b ());
+
+impl X<'_, '_> for i32 {}
+impl<'a> X<'a, 'a> for () {}
+
+// This type annotation is not well-formed because we substitute `()` for `_`.
+fn required_substs<'a>() {
+ return;
+ let _: C<'static, 'a, _> = C((), &(), &()); //~ ERROR lifetime may not live long enough
+}
+
+fn main() {}
--- /dev/null
+error: lifetime may not live long enough
+ --> $DIR/wf-unreachable.rs:8:12
+ |
+LL | fn uninit<'a>() {
+ | -- lifetime `'a` defined here
+LL | return;
+LL | let x: &'static &'a (); //~ ERROR lifetime may not live long enough
+ | ^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+ --> $DIR/wf-unreachable.rs:13:12
+ |
+LL | fn var_type<'a>() {
+ | -- lifetime `'a` defined here
+LL | return;
+LL | let x: &'static &'a () = &&(); //~ ERROR lifetime may not live long enough
+ | ^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+ --> $DIR/wf-unreachable.rs:17:12
+ |
+LL | fn uninit_infer<'a>() {
+ | -- lifetime `'a` defined here
+LL | let x: &'static &'a _; //~ ERROR lifetime may not live long enough
+ | ^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+ --> $DIR/wf-unreachable.rs:23:12
+ |
+LL | fn infer<'a>() {
+ | -- lifetime `'a` defined here
+LL | return;
+LL | let x: &'static &'a _ = &&(); //~ ERROR lifetime may not live long enough
+ | ^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+ --> $DIR/wf-unreachable.rs:28:12
+ |
+LL | fn uninit_no_var<'a>() {
+ | -- lifetime `'a` defined here
+LL | return;
+LL | let _: &'static &'a (); //~ ERROR lifetime may not live long enough
+ | ^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+ --> $DIR/wf-unreachable.rs:33:12
+ |
+LL | fn no_var<'a>() {
+ | -- lifetime `'a` defined here
+LL | return;
+LL | let _: &'static &'a () = &&(); //~ ERROR lifetime may not live long enough
+ | ^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+ --> $DIR/wf-unreachable.rs:38:12
+ |
+LL | fn infer_no_var<'a>() {
+ | -- lifetime `'a` defined here
+LL | return;
+LL | let _: &'static &'a _ = &&(); //~ ERROR lifetime may not live long enough
+ | ^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+ --> $DIR/wf-unreachable.rs:51:12
+ |
+LL | fn required_substs<'a>() {
+ | -- lifetime `'a` defined here
+LL | return;
+LL | let _: C<'static, 'a, _> = C((), &(), &()); //~ ERROR lifetime may not live long enough
+ | ^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
+error: aborting due to 8 previous errors
+
--- /dev/null
+// Test that we still check constants are well-formed, even when we there's no
+// type annotation to check.
+
+#![feature(nll)]
+
+const FUN: fn(&'static ()) = |_| {};
+struct A;
+impl A {
+ const ASSOCIATED_FUN: fn(&'static ()) = |_| {};
+}
+
+struct B<'a>(&'a ());
+impl B<'static> {
+ const ALSO_ASSOCIATED_FUN: fn(&'static ()) = |_| {};
+}
+
+trait Z: 'static {
+ const TRAIT_ASSOCIATED_FUN: fn(&'static Self) = |_| ();
+}
+
+impl Z for () {}
+
+fn main() {
+ let x = ();
+ FUN(&x); //~ ERROR `x` does not live long enough
+ A::ASSOCIATED_FUN(&x); //~ ERROR `x` does not live long enough
+ B::ALSO_ASSOCIATED_FUN(&x); //~ ERROR `x` does not live long enough
+ <_>::TRAIT_ASSOCIATED_FUN(&x); //~ ERROR `x` does not live long enough
+}
--- /dev/null
+error[E0597]: `x` does not live long enough
+ --> $DIR/constant-in-expr-inherent-2.rs:25:9
+ |
+LL | FUN(&x); //~ ERROR `x` does not live long enough
+ | ----^^-
+ | | |
+ | | borrowed value does not live long enough
+ | argument requires that `x` is borrowed for `'static`
+...
+LL | }
+ | - `x` dropped here while still borrowed
+
+error[E0597]: `x` does not live long enough
+ --> $DIR/constant-in-expr-inherent-2.rs:26:23
+ |
+LL | A::ASSOCIATED_FUN(&x); //~ ERROR `x` does not live long enough
+ | ------------------^^-
+ | | |
+ | | borrowed value does not live long enough
+ | argument requires that `x` is borrowed for `'static`
+...
+LL | }
+ | - `x` dropped here while still borrowed
+
+error[E0597]: `x` does not live long enough
+ --> $DIR/constant-in-expr-inherent-2.rs:27:28
+ |
+LL | B::ALSO_ASSOCIATED_FUN(&x); //~ ERROR `x` does not live long enough
+ | -----------------------^^-
+ | | |
+ | | borrowed value does not live long enough
+ | argument requires that `x` is borrowed for `'static`
+LL | <_>::TRAIT_ASSOCIATED_FUN(&x); //~ ERROR `x` does not live long enough
+LL | }
+ | - `x` dropped here while still borrowed
+
+error[E0597]: `x` does not live long enough
+ --> $DIR/constant-in-expr-inherent-2.rs:28:31
+ |
+LL | <_>::TRAIT_ASSOCIATED_FUN(&x); //~ ERROR `x` does not live long enough
+ | --------------------------^^-
+ | | |
+ | | borrowed value does not live long enough
+ | argument requires that `x` is borrowed for `'static`
+LL | }
+ | - `x` dropped here while still borrowed
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
--- /dev/null
+// compile-pass
+
+// Check that we don't try to downcast `_` when type-checking the annotation.
+fn main() {
+ let x = Some(Some(Some(1)));
+
+ match x {
+ Some::<Option<_>>(Some(Some(v))) => (),
+ _ => (),
+ }
+}
--- /dev/null
+// Check that repeated type variables are correctly handled
+
+#![allow(unused)]
+#![feature(nll, type_ascription)]
+
+type PairUncoupled<'a, 'b, T> = (&'a T, &'b T);
+type PairCoupledTypes<T> = (T, T);
+type PairCoupledRegions<'a, T> = (&'a T, &'a T);
+
+fn uncoupled_wilds_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+ let ((y, _z),) = ((s, _x),): (PairUncoupled<_>,);
+ y // OK
+}
+
+fn coupled_wilds_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+ let ((y, _z),) = ((s, _x),): (PairCoupledTypes<_>,);
+ y //~ ERROR lifetime may not live long enough
+}
+
+fn coupled_regions_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+ let ((y, _z),) = ((s, _x),): (PairCoupledRegions<_>,);
+ y //~ ERROR lifetime may not live long enough
+}
+
+fn cast_uncoupled_wilds_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+ let ((y, _z),) = ((s, _x),) as (PairUncoupled<_>,);
+ y // OK
+}
+
+fn cast_coupled_wilds_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+ let ((y, _z),) = ((s, _x),) as (PairCoupledTypes<_>,);
+ y //~ ERROR lifetime may not live long enough
+}
+
+fn cast_coupled_regions_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+ let ((y, _z),) = ((s, _x),) as (PairCoupledRegions<_>,);
+ y //~ ERROR lifetime may not live long enough
+}
+
+fn main() {}
--- /dev/null
+error: lifetime may not live long enough
+ --> $DIR/issue-57731-ascibed-coupled-types.rs:17:5
+ |
+LL | fn coupled_wilds_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+ | -- lifetime `'a` defined here
+LL | let ((y, _z),) = ((s, _x),): (PairCoupledTypes<_>,);
+LL | y //~ ERROR lifetime may not live long enough
+ | ^ returning this value requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+ --> $DIR/issue-57731-ascibed-coupled-types.rs:22:5
+ |
+LL | fn coupled_regions_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+ | -- lifetime `'a` defined here
+LL | let ((y, _z),) = ((s, _x),): (PairCoupledRegions<_>,);
+LL | y //~ ERROR lifetime may not live long enough
+ | ^ returning this value requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+ --> $DIR/issue-57731-ascibed-coupled-types.rs:32:5
+ |
+LL | fn cast_coupled_wilds_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+ | -- lifetime `'a` defined here
+LL | let ((y, _z),) = ((s, _x),) as (PairCoupledTypes<_>,);
+LL | y //~ ERROR lifetime may not live long enough
+ | ^ returning this value requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+ --> $DIR/issue-57731-ascibed-coupled-types.rs:37:5
+ |
+LL | fn cast_coupled_regions_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+ | -- lifetime `'a` defined here
+LL | let ((y, _z),) = ((s, _x),) as (PairCoupledRegions<_>,);
+LL | y //~ ERROR lifetime may not live long enough
+ | ^ returning this value requires that `'a` must outlive `'static`
+
+error: aborting due to 4 previous errors
+
--- /dev/null
+error[E0491]: in type `&'a WithAssoc<TheType<'b>>`, reference has a longer lifetime than the data it references
+ --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:45:13
+ |
+LL | let _x: &'a WithAssoc<TheType<'b>> = loop { };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: the pointer is valid for the lifetime 'a as defined on the function body at 37:15
+ --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:37:15
+ |
+LL | fn with_assoc<'a,'b>() {
+ | ^^
+note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 37:18
+ --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:37:18
+ |
+LL | fn with_assoc<'a,'b>() {
+ | ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0491`.
--- /dev/null
+error: lifetime may not live long enough
+ --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:45:13
+ |
+LL | fn with_assoc<'a,'b>() {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+...
+LL | let _x: &'a WithAssoc<TheType<'b>> = loop { };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
+
+error: aborting due to previous error
+
// outlive the location in which the type appears, even when the
// associted type is in a supertype. Issue #22246.
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
#![allow(dead_code)]
///////////////////////////////////////////////////////////////////////////
// FIXME (#54943) NLL doesn't enforce WF condition in unreachable code if
// `_x` is changed to `_`
let _x: &'a WithAssoc<TheType<'b>> = loop { };
- //~^ ERROR reference has a longer lifetime
+ //[ast]~^ ERROR reference has a longer lifetime
+ //[mir]~^^ ERROR lifetime may not live long enough
}
fn main() {
--- /dev/null
+error[E0623]: lifetime mismatch
+ --> $DIR/regions-free-region-ordering-caller.rs:11:12
+ |
+LL | fn call2<'a, 'b>(a: &'a usize, b: &'b usize) {
+ | --------- ---------
+ | |
+ | these two types are declared with different lifetimes...
+LL | let z: Option<&'b &'a usize> = None;//[ast]~ ERROR E0623
+ | ^^^^^^^^^^^^^^^^^^^^^ ...but data from `a` flows into `b` here
+
+error[E0623]: lifetime mismatch
+ --> $DIR/regions-free-region-ordering-caller.rs:17:12
+ |
+LL | fn call3<'a, 'b>(a: &'a usize, b: &'b usize) {
+ | --------- ---------
+ | |
+ | these two types are declared with different lifetimes...
+LL | let y: Paramd<'a> = Paramd { x: a };
+LL | let z: Option<&'b Paramd<'a>> = None;//[ast]~ ERROR E0623
+ | ^^^^^^^^^^^^^^^^^^^^^^ ...but data from `a` flows into `b` here
+
+error[E0623]: lifetime mismatch
+ --> $DIR/regions-free-region-ordering-caller.rs:22:12
+ |
+LL | fn call4<'a, 'b>(a: &'a usize, b: &'b usize) {
+ | --------- --------- these two types are declared with different lifetimes...
+LL | let z: Option<&'a &'b usize> = None;//[ast]~ ERROR E0623
+ | ^^^^^^^^^^^^^^^^^^^^^ ...but data from `b` flows into `a` here
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0623`.
--- /dev/null
+error: lifetime may not live long enough
+ --> $DIR/regions-free-region-ordering-caller.rs:11:12
+ |
+LL | fn call2<'a, 'b>(a: &'a usize, b: &'b usize) {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+LL | let z: Option<&'b &'a usize> = None;//[ast]~ ERROR E0623
+ | ^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'b`
+
+error: lifetime may not live long enough
+ --> $DIR/regions-free-region-ordering-caller.rs:17:12
+ |
+LL | fn call3<'a, 'b>(a: &'a usize, b: &'b usize) {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+LL | let y: Paramd<'a> = Paramd { x: a };
+LL | let z: Option<&'b Paramd<'a>> = None;//[ast]~ ERROR E0623
+ | ^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'b`
+
+error: lifetime may not live long enough
+ --> $DIR/regions-free-region-ordering-caller.rs:22:12
+ |
+LL | fn call4<'a, 'b>(a: &'a usize, b: &'b usize) {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+LL | let z: Option<&'a &'b usize> = None;//[ast]~ ERROR E0623
+ | ^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
+
+error: aborting due to 3 previous errors
+
// than the thing it points at and ensure that they result in
// errors. See also regions-free-region-ordering-callee.rs
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
struct Paramd<'a> { x: &'a usize }
fn call2<'a, 'b>(a: &'a usize, b: &'b usize) {
- let z: Option<&'b &'a usize> = None;//~ ERROR E0623
+ let z: Option<&'b &'a usize> = None;//[ast]~ ERROR E0623
+ //[mir]~^ ERROR lifetime may not live long enough
}
fn call3<'a, 'b>(a: &'a usize, b: &'b usize) {
let y: Paramd<'a> = Paramd { x: a };
- let z: Option<&'b Paramd<'a>> = None;//~ ERROR E0623
+ let z: Option<&'b Paramd<'a>> = None;//[ast]~ ERROR E0623
+ //[mir]~^ ERROR lifetime may not live long enough
}
fn call4<'a, 'b>(a: &'a usize, b: &'b usize) {
- let z: Option<&'a &'b usize> = None;//~ ERROR E0623
+ let z: Option<&'a &'b usize> = None;//[ast]~ ERROR E0623
+ //[mir]~^ ERROR lifetime may not live long enough
}
fn main() {}
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
+ | |
+ | type annotation 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`.
--- /dev/null
+error[E0491]: in type `&'a WithHrAssoc<TheType<'b>>`, reference has a longer lifetime than the data it references
+ --> $DIR/regions-outlives-projection-container-hrtb.rs:35:12
+ |
+LL | let _: &'a WithHrAssoc<TheType<'b>> = loop { };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: the pointer is valid for the lifetime 'a as defined on the function body at 32:15
+ --> $DIR/regions-outlives-projection-container-hrtb.rs:32:15
+ |
+LL | fn with_assoc<'a,'b>() {
+ | ^^
+note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 32:18
+ --> $DIR/regions-outlives-projection-container-hrtb.rs:32:18
+ |
+LL | fn with_assoc<'a,'b>() {
+ | ^^
+
+error[E0491]: in type `&'a WithHrAssocSub<TheType<'b>>`, reference has a longer lifetime than the data it references
+ --> $DIR/regions-outlives-projection-container-hrtb.rs:57:12
+ |
+LL | let _: &'a WithHrAssocSub<TheType<'b>> = loop { };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: the pointer is valid for the lifetime 'a as defined on the function body at 53:19
+ --> $DIR/regions-outlives-projection-container-hrtb.rs:53:19
+ |
+LL | fn with_assoc_sub<'a,'b>() {
+ | ^^
+note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 53:22
+ --> $DIR/regions-outlives-projection-container-hrtb.rs:53:22
+ |
+LL | fn with_assoc_sub<'a,'b>() {
+ | ^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0491`.
--- /dev/null
+error: lifetime may not live long enough
+ --> $DIR/regions-outlives-projection-container-hrtb.rs:35:12
+ |
+LL | fn with_assoc<'a,'b>() {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+...
+LL | let _: &'a WithHrAssoc<TheType<'b>> = loop { };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
+
+error: lifetime may not live long enough
+ --> $DIR/regions-outlives-projection-container-hrtb.rs:57:12
+ |
+LL | fn with_assoc_sub<'a,'b>() {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+...
+LL | let _: &'a WithHrAssocSub<TheType<'b>> = loop { };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
+
+error: aborting due to 2 previous errors
+
// Test that structs with higher-ranked where clauses don't generate
// "outlives" requirements. Issue #22246.
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
#![allow(dead_code)]
// We get an error because 'b:'a does not hold:
let _: &'a WithHrAssoc<TheType<'b>> = loop { };
- //~^ ERROR reference has a longer lifetime
+ //[ast]~^ ERROR reference has a longer lifetime
+ //[mir]~^^ ERROR lifetime may not live long enough
}
///////////////////////////////////////////////////////////////////////////
// below to be well-formed, it is not related to the HR relation.
let _: &'a WithHrAssocSub<TheType<'b>> = loop { };
- //~^ ERROR reference has a longer lifetime
+ //[ast]~^ ERROR reference has a longer lifetime
+ //[mir]~^^ ERROR lifetime may not live long enough
}
--- /dev/null
+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:37:12
+ |
+LL | let _: &'a WithAssoc<TheType<'b>> = loop { };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: the pointer is valid for the lifetime 'a as defined on the function body at 31:15
+ --> $DIR/regions-outlives-projection-container-wc.rs:31:15
+ |
+LL | fn with_assoc<'a,'b>() {
+ | ^^
+note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 31:18
+ --> $DIR/regions-outlives-projection-container-wc.rs:31:18
+ |
+LL | fn with_assoc<'a,'b>() {
+ | ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0491`.
--- /dev/null
+error: lifetime may not live long enough
+ --> $DIR/regions-outlives-projection-container-wc.rs:37:12
+ |
+LL | fn with_assoc<'a,'b>() {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+...
+LL | let _: &'a WithAssoc<TheType<'b>> = loop { };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
+
+error: aborting due to previous error
+
// outlive the location in which the type appears, even when the
// constraint is in a where clause not a bound. Issue #22246.
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
#![allow(dead_code)]
///////////////////////////////////////////////////////////////////////////
// which is &'b (), must outlive 'a.
let _: &'a WithAssoc<TheType<'b>> = loop { };
- //~^ ERROR reference has a longer lifetime
+ //[ast]~^ ERROR reference has a longer lifetime
+ //[mir]~^^ ERROR lifetime may not live long enough
}
fn main() {