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.
This commit is contained in:
parent
ed871cb368
commit
65fe251634
|
@ -1242,7 +1242,7 @@ impl_stable_hash_for!(
|
||||||
|
|
||||||
impl_stable_hash_for!(
|
impl_stable_hash_for!(
|
||||||
struct ty::CanonicalUserTypeAnnotation<'tcx> {
|
struct ty::CanonicalUserTypeAnnotation<'tcx> {
|
||||||
user_ty, span
|
user_ty, span, inferred_ty
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -75,8 +75,7 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> {
|
||||||
elem: &PlaceElem<'tcx>)
|
elem: &PlaceElem<'tcx>)
|
||||||
-> PlaceTy<'tcx>
|
-> PlaceTy<'tcx>
|
||||||
{
|
{
|
||||||
self.projection_ty_core(tcx, elem, |_, _, ty| -> Result<Ty<'tcx>, ()> { Ok(ty) })
|
self.projection_ty_core(tcx, elem, |_, _, ty| ty)
|
||||||
.unwrap()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `place_ty.projection_ty_core(tcx, elem, |...| { ... })`
|
/// `place_ty.projection_ty_core(tcx, elem, |...| { ... })`
|
||||||
|
@ -84,12 +83,12 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> {
|
||||||
/// `Ty` or downcast variant corresponding to that projection.
|
/// `Ty` or downcast variant corresponding to that projection.
|
||||||
/// The `handle_field` callback must map a `Field` to its `Ty`,
|
/// The `handle_field` callback must map a `Field` to its `Ty`,
|
||||||
/// (which should be trivial when `T` = `Ty`).
|
/// (which should be trivial when `T` = `Ty`).
|
||||||
pub fn projection_ty_core<V, T, E>(
|
pub fn projection_ty_core<V, T>(
|
||||||
self,
|
self,
|
||||||
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||||
elem: &ProjectionElem<'tcx, V, T>,
|
elem: &ProjectionElem<'tcx, V, T>,
|
||||||
mut handle_field: impl FnMut(&Self, &Field, &T) -> Result<Ty<'tcx>, E>)
|
mut handle_field: impl FnMut(&Self, &Field, &T) -> Ty<'tcx>)
|
||||||
-> Result<PlaceTy<'tcx>, E>
|
-> PlaceTy<'tcx>
|
||||||
where
|
where
|
||||||
V: ::std::fmt::Debug, T: ::std::fmt::Debug
|
V: ::std::fmt::Debug, T: ::std::fmt::Debug
|
||||||
{
|
{
|
||||||
|
@ -140,10 +139,10 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ProjectionElem::Field(ref f, ref fty) =>
|
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);
|
debug!("projection_ty self: {:?} elem: {:?} yields: {:?}", self, elem, answer);
|
||||||
Ok(answer)
|
answer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -887,6 +887,7 @@ macro_rules! make_mir_visitor {
|
||||||
ty: & $($mutability)* CanonicalUserTypeAnnotation<'tcx>,
|
ty: & $($mutability)* CanonicalUserTypeAnnotation<'tcx>,
|
||||||
) {
|
) {
|
||||||
self.visit_span(& $($mutability)* ty.span);
|
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>) {
|
fn super_ty(&mut self, _ty: & $($mutability)* Ty<'tcx>) {
|
||||||
|
@ -967,6 +968,9 @@ pub enum TyContext {
|
||||||
source_info: SourceInfo,
|
source_info: SourceInfo,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/// The inferred type of a user type annotation.
|
||||||
|
UserTy(Span),
|
||||||
|
|
||||||
/// The return type of the function.
|
/// The return type of the function.
|
||||||
ReturnTy(SourceInfo),
|
ReturnTy(SourceInfo),
|
||||||
|
|
||||||
|
|
|
@ -1,28 +1,23 @@
|
||||||
use infer::canonical::{Canonical, Canonicalized, CanonicalizedQueryResponse, QueryResponse};
|
use infer::canonical::{Canonical, Canonicalized, CanonicalizedQueryResponse, QueryResponse};
|
||||||
use traits::query::Fallible;
|
use traits::query::Fallible;
|
||||||
use hir::def_id::DefId;
|
use hir::def_id::DefId;
|
||||||
use mir::ProjectionKind;
|
use ty::{ParamEnvAnd, Ty, TyCtxt};
|
||||||
use ty::{self, ParamEnvAnd, Ty, TyCtxt};
|
|
||||||
use ty::subst::UserSubsts;
|
use ty::subst::UserSubsts;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
|
||||||
pub struct AscribeUserType<'tcx> {
|
pub struct AscribeUserType<'tcx> {
|
||||||
pub mir_ty: Ty<'tcx>,
|
pub mir_ty: Ty<'tcx>,
|
||||||
pub variance: ty::Variance,
|
|
||||||
pub def_id: DefId,
|
pub def_id: DefId,
|
||||||
pub user_substs: UserSubsts<'tcx>,
|
pub user_substs: UserSubsts<'tcx>,
|
||||||
pub projs: &'tcx ty::List<ProjectionKind<'tcx>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> AscribeUserType<'tcx> {
|
impl<'tcx> AscribeUserType<'tcx> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
mir_ty: Ty<'tcx>,
|
mir_ty: Ty<'tcx>,
|
||||||
variance: ty::Variance,
|
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
user_substs: UserSubsts<'tcx>,
|
user_substs: UserSubsts<'tcx>,
|
||||||
projs: &'tcx ty::List<ProjectionKind<'tcx>>,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self { mir_ty, variance, def_id, user_substs, projs }
|
Self { mir_ty, def_id, user_substs }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,19 +47,19 @@ impl<'gcx: 'tcx, 'tcx> super::QueryTypeOp<'gcx, 'tcx> for AscribeUserType<'tcx>
|
||||||
|
|
||||||
BraceStructTypeFoldableImpl! {
|
BraceStructTypeFoldableImpl! {
|
||||||
impl<'tcx> TypeFoldable<'tcx> for AscribeUserType<'tcx> {
|
impl<'tcx> TypeFoldable<'tcx> for AscribeUserType<'tcx> {
|
||||||
mir_ty, variance, def_id, user_substs, projs
|
mir_ty, def_id, user_substs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BraceStructLiftImpl! {
|
BraceStructLiftImpl! {
|
||||||
impl<'a, 'tcx> Lift<'tcx> for AscribeUserType<'a> {
|
impl<'a, 'tcx> Lift<'tcx> for AscribeUserType<'a> {
|
||||||
type Lifted = AscribeUserType<'tcx>;
|
type Lifted = AscribeUserType<'tcx>;
|
||||||
mir_ty, variance, def_id, user_substs, projs
|
mir_ty, def_id, user_substs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_stable_hash_for! {
|
impl_stable_hash_for! {
|
||||||
struct AscribeUserType<'tcx> {
|
struct AscribeUserType<'tcx> {
|
||||||
mir_ty, variance, def_id, user_substs, projs
|
mir_ty, def_id, user_substs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -813,18 +813,19 @@ pub type CanonicalUserTypeAnnotations<'tcx> =
|
||||||
pub struct CanonicalUserTypeAnnotation<'tcx> {
|
pub struct CanonicalUserTypeAnnotation<'tcx> {
|
||||||
pub user_ty: CanonicalUserType<'tcx>,
|
pub user_ty: CanonicalUserType<'tcx>,
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
|
pub inferred_ty: Ty<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
BraceStructTypeFoldableImpl! {
|
BraceStructTypeFoldableImpl! {
|
||||||
impl<'tcx> TypeFoldable<'tcx> for CanonicalUserTypeAnnotation<'tcx> {
|
impl<'tcx> TypeFoldable<'tcx> for CanonicalUserTypeAnnotation<'tcx> {
|
||||||
user_ty, span
|
user_ty, span, inferred_ty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BraceStructLiftImpl! {
|
BraceStructLiftImpl! {
|
||||||
impl<'a, 'tcx> Lift<'tcx> for CanonicalUserTypeAnnotation<'a> {
|
impl<'a, 'tcx> Lift<'tcx> for CanonicalUserTypeAnnotation<'a> {
|
||||||
type Lifted = CanonicalUserTypeAnnotation<'tcx>;
|
type Lifted = CanonicalUserTypeAnnotation<'tcx>;
|
||||||
user_ty, span
|
user_ty, span, inferred_ty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ use rustc::infer::InferCtxt;
|
||||||
use rustc::mir::visit::TyContext;
|
use rustc::mir::visit::TyContext;
|
||||||
use rustc::mir::visit::Visitor;
|
use rustc::mir::visit::Visitor;
|
||||||
use rustc::mir::{BasicBlock, BasicBlockData, Location, Mir, Place, Rvalue};
|
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::mir::UserTypeProjection;
|
||||||
use rustc::ty::fold::TypeFoldable;
|
use rustc::ty::fold::TypeFoldable;
|
||||||
use rustc::ty::subst::Substs;
|
use rustc::ty::subst::Substs;
|
||||||
|
@ -66,11 +66,12 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx
|
||||||
/// call. Make them live at the location where they appear.
|
/// call. Make them live at the location where they appear.
|
||||||
fn visit_ty(&mut self, ty: &ty::Ty<'tcx>, ty_context: TyContext) {
|
fn visit_ty(&mut self, ty: &ty::Ty<'tcx>, ty_context: TyContext) {
|
||||||
match ty_context {
|
match ty_context {
|
||||||
TyContext::ReturnTy(source_info)
|
TyContext::ReturnTy(SourceInfo { span, .. })
|
||||||
| TyContext::YieldTy(source_info)
|
| TyContext::YieldTy(SourceInfo { span, .. })
|
||||||
| TyContext::LocalDecl { source_info, .. } => {
|
| TyContext::UserTy(span)
|
||||||
|
| TyContext::LocalDecl { source_info: SourceInfo { span, .. }, .. } => {
|
||||||
span_bug!(
|
span_bug!(
|
||||||
source_info.span,
|
span,
|
||||||
"should not be visiting outside of the CFG: {:?}",
|
"should not be visiting outside of the CFG: {:?}",
|
||||||
ty_context
|
ty_context
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
use rustc::ty::subst::Substs;
|
use rustc::ty::subst::Substs;
|
||||||
use rustc::ty::{
|
use rustc::ty::{self, ClosureSubsts, GeneratorSubsts, Ty, TypeFoldable};
|
||||||
self, ClosureSubsts, GeneratorSubsts, Ty, TypeFoldable,
|
|
||||||
UserTypeAnnotationIndex, CanonicalUserTypeAnnotation
|
|
||||||
};
|
|
||||||
use rustc::mir::{Location, Mir};
|
use rustc::mir::{Location, Mir};
|
||||||
use rustc::mir::visit::{MutVisitor, TyContext};
|
use rustc::mir::visit::{MutVisitor, TyContext};
|
||||||
use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
|
use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
|
||||||
|
@ -58,18 +55,6 @@ impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> {
|
||||||
debug!("visit_ty: ty={:?}", ty);
|
debug!("visit_ty: ty={:?}", ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_user_type_annotation(
|
|
||||||
&mut self,
|
|
||||||
_index: UserTypeAnnotationIndex,
|
|
||||||
_ty: &mut CanonicalUserTypeAnnotation,
|
|
||||||
) {
|
|
||||||
// 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) {
|
fn visit_substs(&mut self, substs: &mut &'tcx Substs<'tcx>, location: Location) {
|
||||||
debug!("visit_substs(substs={:?}, location={:?})", substs, location);
|
debug!("visit_substs(substs={:?}, location={:?})", substs, location);
|
||||||
|
|
||||||
|
|
|
@ -748,7 +748,7 @@ struct TypeChecker<'a, 'gcx: 'tcx, 'tcx: 'a> {
|
||||||
/// annotations. Part of the reason for this setup is that it allows us to enforce basic
|
/// 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
|
/// WF criteria on the types even if the code that referenced them is dead
|
||||||
/// code (see #54943).
|
/// code (see #54943).
|
||||||
instantiated_type_annotations: FxHashMap<UserTypeAnnotationIndex, UserType<'tcx>>,
|
instantiated_type_annotations: FxHashMap<UserTypeAnnotationIndex, Ty<'tcx>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct BorrowCheckContext<'a, 'tcx: 'a> {
|
struct BorrowCheckContext<'a, 'tcx: 'a> {
|
||||||
|
@ -920,17 +920,58 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
||||||
self.mir.user_type_annotations
|
self.mir.user_type_annotations
|
||||||
);
|
);
|
||||||
for annotation_index in self.mir.user_type_annotations.indices() {
|
for annotation_index in self.mir.user_type_annotations.indices() {
|
||||||
let CanonicalUserTypeAnnotation { span, ref user_ty } =
|
let CanonicalUserTypeAnnotation { span, ref user_ty, inferred_ty } =
|
||||||
self.mir.user_type_annotations[annotation_index];
|
self.mir.user_type_annotations[annotation_index];
|
||||||
let (mut annotation, _) = self.infcx.instantiate_canonical_with_fresh_inference_vars(
|
let (annotation, _) = self.infcx.instantiate_canonical_with_fresh_inference_vars(
|
||||||
span, user_ty
|
span, user_ty
|
||||||
);
|
);
|
||||||
match annotation {
|
match annotation {
|
||||||
UserType::Ty(ref mut ty) =>
|
UserType::Ty(mut ty) => {
|
||||||
*ty = self.normalize(ty, Locations::All(span)),
|
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,
|
||||||
|
self.mir.user_type_annotations[annotation_index],
|
||||||
|
"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,
|
||||||
|
self.mir.user_type_annotations[annotation_index],
|
||||||
|
"bad user type AscribeUserType({:?}, {:?} {:?}): {:?}",
|
||||||
|
inferred_ty,
|
||||||
|
def_id,
|
||||||
|
user_substs,
|
||||||
|
terr
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
self.instantiated_type_annotations.insert(annotation_index, annotation);
|
self.instantiated_type_annotations.insert(annotation_index, inferred_ty);
|
||||||
}
|
}
|
||||||
debug!(
|
debug!(
|
||||||
"instantiate_user_type_annotations: instantiated_type_annotations={:?}",
|
"instantiate_user_type_annotations: instantiated_type_annotations={:?}",
|
||||||
|
@ -1067,58 +1108,23 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
||||||
a, v, user_ty, locations,
|
a, v, user_ty, locations,
|
||||||
);
|
);
|
||||||
|
|
||||||
let type_annotation = self.instantiated_type_annotations[&user_ty.base];
|
let annotated_type = self.instantiated_type_annotations[&user_ty.base];
|
||||||
match type_annotation {
|
let mut curr_projected_ty = PlaceTy::from_ty(annotated_type);
|
||||||
UserType::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;
|
|
||||||
|
|
||||||
// We need to follow any provided projetions into the type.
|
let tcx = self.infcx.tcx;
|
||||||
//
|
|
||||||
// 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 {
|
||||||
for proj in &user_ty.projs {
|
let projected_ty = curr_projected_ty.projection_ty_core(tcx, proj, |this, field, &()| {
|
||||||
let projected_ty = if let Ok(projected_ty) = curr_projected_ty {
|
let ty = this.field_ty(tcx, field);
|
||||||
projected_ty
|
self.normalize(ty, locations)
|
||||||
} else {
|
});
|
||||||
break;
|
curr_projected_ty = projected_ty;
|
||||||
};
|
|
||||||
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);
|
|
||||||
|
|
||||||
if let Ok(projected_ty) = curr_projected_ty {
|
|
||||||
let ty = projected_ty.to_ty(tcx);
|
|
||||||
self.relate_types(ty, v1, a, locations, category)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
UserType::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,
|
|
||||||
)),
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,10 +31,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
value,
|
value,
|
||||||
} => this.as_constant(value),
|
} => this.as_constant(value),
|
||||||
ExprKind::Literal { literal, user_ty } => {
|
ExprKind::Literal { literal, user_ty } => {
|
||||||
let user_ty = user_ty.map(|ty| {
|
let user_ty = user_ty.map(|user_ty| {
|
||||||
this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
|
this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
|
||||||
span,
|
span,
|
||||||
user_ty: ty,
|
user_ty,
|
||||||
|
inferred_ty: ty,
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
Constant {
|
Constant {
|
||||||
|
|
|
@ -134,7 +134,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
let place = unpack!(block = this.as_place(block, source));
|
let place = unpack!(block = this.as_place(block, source));
|
||||||
if let Some(user_ty) = user_ty {
|
if let Some(user_ty) = user_ty {
|
||||||
let annotation_index = this.canonical_user_type_annotations.push(
|
let annotation_index = this.canonical_user_type_annotations.push(
|
||||||
CanonicalUserTypeAnnotation { span: source_info.span, user_ty }
|
CanonicalUserTypeAnnotation {
|
||||||
|
span: source_info.span,
|
||||||
|
user_ty,
|
||||||
|
inferred_ty: expr.ty,
|
||||||
|
}
|
||||||
);
|
);
|
||||||
this.cfg.push(
|
this.cfg.push(
|
||||||
block,
|
block,
|
||||||
|
@ -157,7 +161,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
);
|
);
|
||||||
if let Some(user_ty) = user_ty {
|
if let Some(user_ty) = user_ty {
|
||||||
let annotation_index = this.canonical_user_type_annotations.push(
|
let annotation_index = this.canonical_user_type_annotations.push(
|
||||||
CanonicalUserTypeAnnotation { span: source_info.span, user_ty }
|
CanonicalUserTypeAnnotation {
|
||||||
|
span: source_info.span,
|
||||||
|
user_ty,
|
||||||
|
inferred_ty: expr.ty,
|
||||||
|
}
|
||||||
);
|
);
|
||||||
this.cfg.push(
|
this.cfg.push(
|
||||||
block,
|
block,
|
||||||
|
|
|
@ -331,10 +331,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
.collect()
|
.collect()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let inferred_ty = expr.ty;
|
||||||
let user_ty = user_ty.map(|ty| {
|
let user_ty = user_ty.map(|ty| {
|
||||||
this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
|
this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
|
||||||
span: source_info.span,
|
span: source_info.span,
|
||||||
user_ty: ty,
|
user_ty: ty,
|
||||||
|
inferred_ty,
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
let adt = box AggregateKind::Adt(
|
let adt = box AggregateKind::Adt(
|
||||||
|
|
|
@ -303,7 +303,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
let ty_source_info = self.source_info(user_ty_span);
|
let ty_source_info = self.source_info(user_ty_span);
|
||||||
let user_ty = box pat_ascription_ty.user_ty(
|
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(
|
self.cfg.push(
|
||||||
block,
|
block,
|
||||||
|
@ -572,11 +574,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
// of `user_ty` on any bindings contained with subpattern.
|
// of `user_ty` on any bindings contained with subpattern.
|
||||||
let annotation = CanonicalUserTypeAnnotation {
|
let annotation = CanonicalUserTypeAnnotation {
|
||||||
span: user_ty_span,
|
span: user_ty_span,
|
||||||
user_ty: user_ty.base,
|
user_ty: user_ty.user_ty,
|
||||||
|
inferred_ty: subpattern.ty,
|
||||||
};
|
};
|
||||||
let projection = UserTypeProjection {
|
let projection = UserTypeProjection {
|
||||||
base: self.canonical_user_type_annotations.push(annotation),
|
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);
|
let subpattern_user_ty = pattern_user_ty.push_projection(&projection, user_ty_span);
|
||||||
self.visit_bindings(subpattern, subpattern_user_ty, f)
|
self.visit_bindings(subpattern, subpattern_user_ty, f)
|
||||||
|
@ -1340,7 +1343,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
);
|
);
|
||||||
|
|
||||||
let user_ty = box ascription.user_ty.clone().user_ty(
|
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(
|
self.cfg.push(
|
||||||
block,
|
block,
|
||||||
|
|
|
@ -12,7 +12,7 @@ use hair::util::UserAnnotatedTyHelpers;
|
||||||
use hair::constant::*;
|
use hair::constant::*;
|
||||||
|
|
||||||
use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability};
|
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::mir::interpret::{Scalar, GlobalId, ConstValue, sign_extend};
|
||||||
use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty, Lift, UserType};
|
use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty, Lift, UserType};
|
||||||
use rustc::ty::{CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations};
|
use rustc::ty::{CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations};
|
||||||
|
@ -60,26 +60,29 @@ pub struct Pattern<'tcx> {
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct PatternTypeProjection<'tcx> {
|
pub struct PatternTypeProjection<'tcx> {
|
||||||
pub base: CanonicalUserType<'tcx>,
|
pub user_ty: CanonicalUserType<'tcx>,
|
||||||
pub projs: Vec<ProjectionElem<'tcx, (), ()>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> PatternTypeProjection<'tcx> {
|
impl<'tcx> PatternTypeProjection<'tcx> {
|
||||||
pub(crate) fn from_user_type(user_annotation: CanonicalUserType<'tcx>) -> Self {
|
pub(crate) fn from_user_type(user_annotation: CanonicalUserType<'tcx>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
base: user_annotation,
|
user_ty: user_annotation,
|
||||||
projs: Vec::new(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn user_ty(
|
pub(crate) fn user_ty(
|
||||||
self,
|
self,
|
||||||
annotations: &mut CanonicalUserTypeAnnotations<'tcx>,
|
annotations: &mut CanonicalUserTypeAnnotations<'tcx>,
|
||||||
|
inferred_ty: Ty<'tcx>,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> UserTypeProjection<'tcx> {
|
) -> UserTypeProjection<'tcx> {
|
||||||
UserTypeProjection {
|
UserTypeProjection {
|
||||||
base: annotations.push(CanonicalUserTypeAnnotation{ span, user_ty: self.base }),
|
base: annotations.push(CanonicalUserTypeAnnotation {
|
||||||
projs: self.projs
|
span,
|
||||||
|
user_ty: self.user_ty,
|
||||||
|
inferred_ty,
|
||||||
|
}),
|
||||||
|
projs: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,6 @@ use rustc::infer::at::ToTrace;
|
||||||
use rustc::infer::canonical::{Canonical, QueryResponse};
|
use rustc::infer::canonical::{Canonical, QueryResponse};
|
||||||
use rustc::infer::InferCtxt;
|
use rustc::infer::InferCtxt;
|
||||||
use rustc::hir::def_id::DefId;
|
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;
|
||||||
use rustc::traits::query::type_op::eq::Eq;
|
use rustc::traits::query::type_op::eq::Eq;
|
||||||
use rustc::traits::query::type_op::normalize::Normalize;
|
use rustc::traits::query::type_op::normalize::Normalize;
|
||||||
|
@ -44,17 +42,16 @@ fn type_op_ascribe_user_type<'tcx>(
|
||||||
tcx.infer_ctxt()
|
tcx.infer_ctxt()
|
||||||
.enter_canonical_trait_query(&canonicalized, |infcx, fulfill_cx, key| {
|
.enter_canonical_trait_query(&canonicalized, |infcx, fulfill_cx, key| {
|
||||||
let (
|
let (
|
||||||
param_env, AscribeUserType { mir_ty, variance, def_id, user_substs, projs }
|
param_env, AscribeUserType { mir_ty, def_id, user_substs }
|
||||||
) = key.into_parts();
|
) = key.into_parts();
|
||||||
|
|
||||||
debug!(
|
debug!(
|
||||||
"type_op_ascribe_user_type: mir_ty={:?} variance={:?} def_id={:?} \
|
"type_op_ascribe_user_type: mir_ty={:?} def_id={:?} user_substs={:?}",
|
||||||
user_substs={:?} projs={:?}",
|
mir_ty, def_id, user_substs
|
||||||
mir_ty, variance, def_id, user_substs, projs
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut cx = AscribeUserTypeCx { infcx, param_env, fulfill_cx };
|
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(())
|
Ok(())
|
||||||
})
|
})
|
||||||
|
@ -112,10 +109,8 @@ impl AscribeUserTypeCx<'me, 'gcx, 'tcx> {
|
||||||
fn relate_mir_and_user_ty(
|
fn relate_mir_and_user_ty(
|
||||||
&mut self,
|
&mut self,
|
||||||
mir_ty: Ty<'tcx>,
|
mir_ty: Ty<'tcx>,
|
||||||
variance: Variance,
|
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
user_substs: UserSubsts<'tcx>,
|
user_substs: UserSubsts<'tcx>,
|
||||||
projs: &[ProjectionKind<'tcx>],
|
|
||||||
) -> Result<(), NoSolution> {
|
) -> Result<(), NoSolution> {
|
||||||
let UserSubsts {
|
let UserSubsts {
|
||||||
user_self_ty,
|
user_self_ty,
|
||||||
|
@ -128,35 +123,7 @@ impl AscribeUserTypeCx<'me, 'gcx, 'tcx> {
|
||||||
debug!("relate_type_and_user_type: ty of def-id is {:?}", ty);
|
debug!("relate_type_and_user_type: ty of def-id is {:?}", ty);
|
||||||
let ty = self.normalize(ty);
|
let ty = self.normalize(ty);
|
||||||
|
|
||||||
// We need to follow any provided projetions into the type.
|
self.relate(mir_ty, Variance::Invariant, ty)?;
|
||||||
//
|
|
||||||
// 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)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prove the predicates coming along with `def_id`.
|
// Prove the predicates coming along with `def_id`.
|
||||||
//
|
//
|
||||||
|
|
|
@ -1,7 +1,3 @@
|
||||||
// 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)]
|
#![feature(nll)]
|
||||||
#![allow(warnings)]
|
#![allow(warnings)]
|
||||||
|
|
||||||
|
@ -11,7 +7,7 @@ fn boo<'a>() {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
let x = foo::<&'a u32>();
|
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() {}
|
fn main() {}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
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
|
||||||
|
|
|
@ -2,7 +2,7 @@ error[E0309]: the associated type `<T as MyTrait<'_>>::Output` may not live long
|
||||||
--> $DIR/projection-where-clause-env-wrong-bound.rs:17:5
|
--> $DIR/projection-where-clause-env-wrong-bound.rs:17:5
|
||||||
|
|
|
|
||||||
LL | bar::<T::Output>() //~ ERROR may not live long enough
|
LL | bar::<T::Output>() //~ ERROR may not live long enough
|
||||||
| ^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= help: consider adding an explicit lifetime bound `<T as MyTrait<'_>>::Output: 'a`...
|
= help: consider adding an explicit lifetime bound `<T as MyTrait<'_>>::Output: 'a`...
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ error[E0309]: the parameter type `T` may not live long enough
|
||||||
--> $DIR/projection-where-clause-none.rs:16:5
|
--> $DIR/projection-where-clause-none.rs:16:5
|
||||||
|
|
|
|
||||||
LL | bar::<T::Output>() //~ ERROR the parameter type `T` may not live long enough
|
LL | bar::<T::Output>() //~ ERROR the parameter type `T` may not live long enough
|
||||||
| ^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= help: consider adding an explicit lifetime bound `T: 'a`...
|
= help: consider adding an explicit lifetime bound `T: 'a`...
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
// 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() {}
|
|
@ -0,0 +1,73 @@
|
||||||
|
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
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
// 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))) => (),
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
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`.
|
|
@ -0,0 +1,13 @@
|
||||||
|
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
|
||||||
|
|
|
@ -3,6 +3,9 @@
|
||||||
// outlive the location in which the type appears, even when the
|
// outlive the location in which the type appears, even when the
|
||||||
// associted type is in a supertype. Issue #22246.
|
// associted type is in a supertype. Issue #22246.
|
||||||
|
|
||||||
|
// revisions: ast mir
|
||||||
|
//[mir]compile-flags: -Z borrowck=mir
|
||||||
|
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -40,7 +43,8 @@ fn with_assoc<'a,'b>() {
|
||||||
// FIXME (#54943) NLL doesn't enforce WF condition in unreachable code if
|
// FIXME (#54943) NLL doesn't enforce WF condition in unreachable code if
|
||||||
// `_x` is changed to `_`
|
// `_x` is changed to `_`
|
||||||
let _x: &'a WithAssoc<TheType<'b>> = loop { };
|
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() {
|
fn main() {
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
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`.
|
|
@ -0,0 +1,33 @@
|
||||||
|
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
|
||||||
|
|
|
@ -2,19 +2,25 @@
|
||||||
// than the thing it points at and ensure that they result in
|
// than the thing it points at and ensure that they result in
|
||||||
// errors. See also regions-free-region-ordering-callee.rs
|
// errors. See also regions-free-region-ordering-callee.rs
|
||||||
|
|
||||||
|
// revisions: ast mir
|
||||||
|
//[mir]compile-flags: -Z borrowck=mir
|
||||||
|
|
||||||
struct Paramd<'a> { x: &'a usize }
|
struct Paramd<'a> { x: &'a usize }
|
||||||
|
|
||||||
fn call2<'a, 'b>(a: &'a usize, b: &'b 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) {
|
fn call3<'a, 'b>(a: &'a usize, b: &'b usize) {
|
||||||
let y: Paramd<'a> = Paramd { x: a };
|
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) {
|
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() {}
|
fn main() {}
|
||||||
|
|
|
@ -12,6 +12,21 @@ LL | let z: &'a & usize = &(&y);
|
||||||
LL | }
|
LL | }
|
||||||
| - temporary value is freed at the end of this statement
|
| - 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
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0716`.
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
Some errors occurred: E0597, E0716.
|
||||||
|
For more information about an error, try `rustc --explain E0597`.
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
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`.
|
|
@ -0,0 +1,24 @@
|
||||||
|
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
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
// Test that structs with higher-ranked where clauses don't generate
|
// Test that structs with higher-ranked where clauses don't generate
|
||||||
// "outlives" requirements. Issue #22246.
|
// "outlives" requirements. Issue #22246.
|
||||||
|
|
||||||
|
// revisions: ast mir
|
||||||
|
//[mir]compile-flags: -Z borrowck=mir
|
||||||
|
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,7 +33,8 @@ fn with_assoc<'a,'b>() {
|
||||||
// We get an error because 'b:'a does not hold:
|
// We get an error because 'b:'a does not hold:
|
||||||
|
|
||||||
let _: &'a WithHrAssoc<TheType<'b>> = loop { };
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -51,7 +55,8 @@ fn with_assoc_sub<'a,'b>() {
|
||||||
// below to be well-formed, it is not related to the HR relation.
|
// below to be well-formed, it is not related to the HR relation.
|
||||||
|
|
||||||
let _: &'a WithHrAssocSub<TheType<'b>> = loop { };
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
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`.
|
|
@ -0,0 +1,13 @@
|
||||||
|
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
|
||||||
|
|
|
@ -3,6 +3,9 @@
|
||||||
// outlive the location in which the type appears, even when the
|
// outlive the location in which the type appears, even when the
|
||||||
// constraint is in a where clause not a bound. Issue #22246.
|
// constraint is in a where clause not a bound. Issue #22246.
|
||||||
|
|
||||||
|
// revisions: ast mir
|
||||||
|
//[mir]compile-flags: -Z borrowck=mir
|
||||||
|
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -32,7 +35,8 @@ fn with_assoc<'a,'b>() {
|
||||||
// which is &'b (), must outlive 'a.
|
// which is &'b (), must outlive 'a.
|
||||||
|
|
||||||
let _: &'a WithAssoc<TheType<'b>> = loop { };
|
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() {
|
fn main() {
|
||||||
|
|
Loading…
Reference in New Issue