From 65fe2516346f10dc8d670e9fdfbd4e4f99a5b34b Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 12 Jan 2019 14:55:23 +0000 Subject: [PATCH] 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. --- src/librustc/ich/impls_ty.rs | 2 +- src/librustc/mir/tcx.rs | 13 +- src/librustc/mir/visit.rs | 4 + .../traits/query/type_op/ascribe_user_type.rs | 15 +-- src/librustc/ty/context.rs | 5 +- .../borrow_check/nll/constraint_generation.rs | 11 +- src/librustc_mir/borrow_check/nll/renumber.rs | 17 +-- .../borrow_check/nll/type_check/mod.rs | 118 +++++++++--------- src/librustc_mir/build/expr/as_constant.rs | 5 +- src/librustc_mir/build/expr/as_place.rs | 12 +- src/librustc_mir/build/expr/as_rvalue.rs | 2 + src/librustc_mir/build/matches/mod.rs | 13 +- src/librustc_mir/hair/pattern/mod.rs | 17 +-- src/librustc_traits/type_op.rs | 43 +------ src/test/ui/issue-54943.rs | 6 +- src/test/ui/issue-54943.stderr | 11 ++ ...ection-where-clause-env-wrong-bound.stderr | 2 +- .../projection-where-clause-none.stderr | 2 +- src/test/ui/nll/ty-outlives/wf-unreachable.rs | 54 ++++++++ .../ui/nll/ty-outlives/wf-unreachable.stderr | 73 +++++++++++ .../ui/nll/user-annotations/downcast-infer.rs | 11 ++ ...n-supertrait-outlives-container.ast.stderr | 20 +++ ...n-supertrait-outlives-container.mir.stderr | 13 ++ ...c-type-in-supertrait-outlives-container.rs | 6 +- ...ons-free-region-ordering-caller.ast.stderr | 32 +++++ ...ons-free-region-ordering-caller.mir.stderr | 33 +++++ .../regions-free-region-ordering-caller.rs | 12 +- ...ns-free-region-ordering-caller1.nll.stderr | 19 ++- ...lives-projection-container-hrtb.ast.stderr | 37 ++++++ ...lives-projection-container-hrtb.mir.stderr | 24 ++++ ...ions-outlives-projection-container-hrtb.rs | 9 +- ...utlives-projection-container-wc.ast.stderr | 20 +++ ...utlives-projection-container-wc.mir.stderr | 13 ++ ...egions-outlives-projection-container-wc.rs | 6 +- 34 files changed, 514 insertions(+), 166 deletions(-) create mode 100644 src/test/ui/issue-54943.stderr create mode 100644 src/test/ui/nll/ty-outlives/wf-unreachable.rs create mode 100644 src/test/ui/nll/ty-outlives/wf-unreachable.stderr create mode 100644 src/test/ui/nll/user-annotations/downcast-infer.rs create mode 100644 src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.ast.stderr create mode 100644 src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.mir.stderr create mode 100644 src/test/ui/regions/regions-free-region-ordering-caller.ast.stderr create mode 100644 src/test/ui/regions/regions-free-region-ordering-caller.mir.stderr create mode 100644 src/test/ui/regions/regions-outlives-projection-container-hrtb.ast.stderr create mode 100644 src/test/ui/regions/regions-outlives-projection-container-hrtb.mir.stderr create mode 100644 src/test/ui/regions/regions-outlives-projection-container-wc.ast.stderr create mode 100644 src/test/ui/regions/regions-outlives-projection-container-wc.mir.stderr diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 9b613e3e1ab..79c2b89522d 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -1242,7 +1242,7 @@ impl_stable_hash_for!( impl_stable_hash_for!( struct ty::CanonicalUserTypeAnnotation<'tcx> { - user_ty, span + user_ty, span, inferred_ty } ); diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index c5b884525da..649370059f0 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -75,8 +75,7 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> { elem: &PlaceElem<'tcx>) -> PlaceTy<'tcx> { - self.projection_ty_core(tcx, elem, |_, _, ty| -> Result, ()> { Ok(ty) }) - .unwrap() + self.projection_ty_core(tcx, elem, |_, _, ty| ty) } /// `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. /// The `handle_field` callback must map a `Field` to its `Ty`, /// (which should be trivial when `T` = `Ty`). - pub fn projection_ty_core( + pub fn projection_ty_core( self, tcx: TyCtxt<'a, 'gcx, 'tcx>, elem: &ProjectionElem<'tcx, V, T>, - mut handle_field: impl FnMut(&Self, &Field, &T) -> Result, E>) - -> Result, E> + mut handle_field: impl FnMut(&Self, &Field, &T) -> Ty<'tcx>) + -> PlaceTy<'tcx> where V: ::std::fmt::Debug, T: ::std::fmt::Debug { @@ -140,10 +139,10 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> { } }, 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 } } diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 49a1e5046aa..598303f2932 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -887,6 +887,7 @@ macro_rules! make_mir_visitor { 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>) { @@ -967,6 +968,9 @@ pub enum TyContext { source_info: SourceInfo, }, + /// The inferred type of a user type annotation. + UserTy(Span), + /// The return type of the function. ReturnTy(SourceInfo), diff --git a/src/librustc/traits/query/type_op/ascribe_user_type.rs b/src/librustc/traits/query/type_op/ascribe_user_type.rs index b2f30564de9..15f627b3ee8 100644 --- a/src/librustc/traits/query/type_op/ascribe_user_type.rs +++ b/src/librustc/traits/query/type_op/ascribe_user_type.rs @@ -1,28 +1,23 @@ 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>, } 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>, ) -> 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! { 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 } } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 59835afc841..4c8f8141116 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -813,18 +813,19 @@ pub type CanonicalUserTypeAnnotations<'tcx> = 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 + user_ty, span, inferred_ty } } BraceStructLiftImpl! { impl<'a, 'tcx> Lift<'tcx> for CanonicalUserTypeAnnotation<'a> { type Lifted = CanonicalUserTypeAnnotation<'tcx>; - user_ty, span + user_ty, span, inferred_ty } } diff --git a/src/librustc_mir/borrow_check/nll/constraint_generation.rs b/src/librustc_mir/borrow_check/nll/constraint_generation.rs index e1c2b611d01..588f46cb77f 100644 --- a/src/librustc_mir/borrow_check/nll/constraint_generation.rs +++ b/src/librustc_mir/borrow_check/nll/constraint_generation.rs @@ -7,7 +7,7 @@ use rustc::infer::InferCtxt; 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; @@ -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. 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 ); diff --git a/src/librustc_mir/borrow_check/nll/renumber.rs b/src/librustc_mir/borrow_check/nll/renumber.rs index ade06bce469..e6a974fd8cc 100644 --- a/src/librustc_mir/borrow_check/nll/renumber.rs +++ b/src/librustc_mir/borrow_check/nll/renumber.rs @@ -1,8 +1,5 @@ use rustc::ty::subst::Substs; -use rustc::ty::{ - self, ClosureSubsts, GeneratorSubsts, Ty, TypeFoldable, - UserTypeAnnotationIndex, CanonicalUserTypeAnnotation -}; +use rustc::ty::{self, ClosureSubsts, GeneratorSubsts, Ty, TypeFoldable}; use rustc::mir::{Location, Mir}; use rustc::mir::visit::{MutVisitor, TyContext}; 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); } - 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) { debug!("visit_substs(substs={:?}, location={:?})", substs, location); diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 82ffafa4ce9..9ed1d49d05b 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -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 /// WF criteria on the types even if the code that referenced them is dead /// code (see #54943). - instantiated_type_annotations: FxHashMap>, + instantiated_type_annotations: FxHashMap>, } struct BorrowCheckContext<'a, 'tcx: 'a> { @@ -920,17 +920,58 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { self.mir.user_type_annotations ); 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]; - let (mut annotation, _) = self.infcx.instantiate_canonical_with_fresh_inference_vars( + let (annotation, _) = self.infcx.instantiate_canonical_with_fresh_inference_vars( span, user_ty ); match annotation { - UserType::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, + 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!( "instantiate_user_type_annotations: instantiated_type_annotations={:?}", @@ -1067,58 +1108,23 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { a, v, user_ty, locations, ); - let type_annotation = self.instantiated_type_annotations[&user_ty.base]; - match type_annotation { - 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; + let annotated_type = self.instantiated_type_annotations[&user_ty.base]; + 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; + let tcx = self.infcx.tcx; - 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); - - 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, - )), - )?; - } + 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(()) } diff --git a/src/librustc_mir/build/expr/as_constant.rs b/src/librustc_mir/build/expr/as_constant.rs index 4f812f53745..31e0c0daa3f 100644 --- a/src/librustc_mir/build/expr/as_constant.rs +++ b/src/librustc_mir/build/expr/as_constant.rs @@ -31,10 +31,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { value, } => this.as_constant(value), 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 { span, - user_ty: ty, + user_ty, + inferred_ty: ty, }) }); Constant { diff --git a/src/librustc_mir/build/expr/as_place.rs b/src/librustc_mir/build/expr/as_place.rs index 5429ce2a2e3..6bd61ab53fd 100644 --- a/src/librustc_mir/build/expr/as_place.rs +++ b/src/librustc_mir/build/expr/as_place.rs @@ -134,7 +134,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { 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( - CanonicalUserTypeAnnotation { span: source_info.span, user_ty } + CanonicalUserTypeAnnotation { + span: source_info.span, + user_ty, + inferred_ty: expr.ty, + } ); this.cfg.push( block, @@ -157,7 +161,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ); if let Some(user_ty) = user_ty { 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( block, diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index 501a10cfbb9..3de2f475786 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -331,10 +331,12 @@ 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(CanonicalUserTypeAnnotation { span: source_info.span, user_ty: ty, + inferred_ty, }) }); let adt = box AggregateKind::Adt( diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index 61d1216fd3e..2f1e8c03f2f 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -303,7 +303,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { 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, @@ -572,11 +574,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // of `user_ty` on any bindings contained with subpattern. let annotation = CanonicalUserTypeAnnotation { span: user_ty_span, - user_ty: user_ty.base, + 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) @@ -1340,7 +1343,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ); 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, diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 8a5e6a581b3..9dcccba1a06 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -12,7 +12,7 @@ use hair::util::UserAnnotatedTyHelpers; 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, UserType}; use rustc::ty::{CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations}; @@ -60,26 +60,29 @@ pub struct Pattern<'tcx> { #[derive(Clone, Debug)] pub struct PatternTypeProjection<'tcx> { - pub base: CanonicalUserType<'tcx>, - pub projs: Vec>, + pub user_ty: CanonicalUserType<'tcx>, } impl<'tcx> PatternTypeProjection<'tcx> { 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(CanonicalUserTypeAnnotation{ span, user_ty: self.base }), - projs: self.projs + base: annotations.push(CanonicalUserTypeAnnotation { + span, + user_ty: self.user_ty, + inferred_ty, + }), + projs: Vec::new(), } } } diff --git a/src/librustc_traits/type_op.rs b/src/librustc_traits/type_op.rs index 52fcb5b80f4..526637e108d 100644 --- a/src/librustc_traits/type_op.rs +++ b/src/librustc_traits/type_op.rs @@ -2,8 +2,6 @@ use rustc::infer::at::ToTrace; 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; @@ -44,17 +42,16 @@ fn type_op_ascribe_user_type<'tcx>( 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(()) }) @@ -112,10 +109,8 @@ impl AscribeUserTypeCx<'me, 'gcx, 'tcx> { 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, @@ -128,35 +123,7 @@ impl AscribeUserTypeCx<'me, 'gcx, 'tcx> { 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; - 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`. // diff --git a/src/test/ui/issue-54943.rs b/src/test/ui/issue-54943.rs index c720f627975..ce4e0106743 100644 --- a/src/test/ui/issue-54943.rs +++ b/src/test/ui/issue-54943.rs @@ -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)] #![allow(warnings)] @@ -11,7 +7,7 @@ fn boo<'a>() { 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() {} diff --git a/src/test/ui/issue-54943.stderr b/src/test/ui/issue-54943.stderr new file mode 100644 index 00000000000..aa68177bcdb --- /dev/null +++ b/src/test/ui/issue-54943.stderr @@ -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 + diff --git a/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.stderr b/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.stderr index acb978b5d5a..597b096dbe6 100644 --- a/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.stderr +++ b/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.stderr @@ -2,7 +2,7 @@ error[E0309]: the associated type `>::Output` may not live long --> $DIR/projection-where-clause-env-wrong-bound.rs:17:5 | LL | bar::() //~ ERROR may not live long enough - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ | = help: consider adding an explicit lifetime bound `>::Output: 'a`... diff --git a/src/test/ui/nll/ty-outlives/projection-where-clause-none.stderr b/src/test/ui/nll/ty-outlives/projection-where-clause-none.stderr index 2d171a98789..3c2ac474778 100644 --- a/src/test/ui/nll/ty-outlives/projection-where-clause-none.stderr +++ b/src/test/ui/nll/ty-outlives/projection-where-clause-none.stderr @@ -2,7 +2,7 @@ error[E0309]: the parameter type `T` may not live long enough --> $DIR/projection-where-clause-none.rs:16:5 | LL | bar::() //~ ERROR the parameter type `T` may not live long enough - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ | = help: consider adding an explicit lifetime bound `T: 'a`... diff --git a/src/test/ui/nll/ty-outlives/wf-unreachable.rs b/src/test/ui/nll/ty-outlives/wf-unreachable.rs new file mode 100644 index 00000000000..a2e3ab41614 --- /dev/null +++ b/src/test/ui/nll/ty-outlives/wf-unreachable.rs @@ -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() {} diff --git a/src/test/ui/nll/ty-outlives/wf-unreachable.stderr b/src/test/ui/nll/ty-outlives/wf-unreachable.stderr new file mode 100644 index 00000000000..14642a1e615 --- /dev/null +++ b/src/test/ui/nll/ty-outlives/wf-unreachable.stderr @@ -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 + diff --git a/src/test/ui/nll/user-annotations/downcast-infer.rs b/src/test/ui/nll/user-annotations/downcast-infer.rs new file mode 100644 index 00000000000..23b76bb1964 --- /dev/null +++ b/src/test/ui/nll/user-annotations/downcast-infer.rs @@ -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::>(Some(Some(v))) => (), + _ => (), + } +} diff --git a/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.ast.stderr b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.ast.stderr new file mode 100644 index 00000000000..76ead4e94ef --- /dev/null +++ b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.ast.stderr @@ -0,0 +1,20 @@ +error[E0491]: in type `&'a WithAssoc>`, 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> = 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`. diff --git a/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.mir.stderr b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.mir.stderr new file mode 100644 index 00000000000..ad94d375b5b --- /dev/null +++ b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.mir.stderr @@ -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> = loop { }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a` + +error: aborting due to previous error + diff --git a/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.rs b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.rs index df7c1e0c7c7..1d534921992 100644 --- a/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.rs +++ b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.rs @@ -3,6 +3,9 @@ // 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)] /////////////////////////////////////////////////////////////////////////// @@ -40,7 +43,8 @@ fn with_assoc<'a,'b>() { // FIXME (#54943) NLL doesn't enforce WF condition in unreachable code if // `_x` is changed to `_` let _x: &'a WithAssoc> = loop { }; - //~^ ERROR reference has a longer lifetime + //[ast]~^ ERROR reference has a longer lifetime + //[mir]~^^ ERROR lifetime may not live long enough } fn main() { diff --git a/src/test/ui/regions/regions-free-region-ordering-caller.ast.stderr b/src/test/ui/regions/regions-free-region-ordering-caller.ast.stderr new file mode 100644 index 00000000000..73266ab50fa --- /dev/null +++ b/src/test/ui/regions/regions-free-region-ordering-caller.ast.stderr @@ -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`. diff --git a/src/test/ui/regions/regions-free-region-ordering-caller.mir.stderr b/src/test/ui/regions/regions-free-region-ordering-caller.mir.stderr new file mode 100644 index 00000000000..abec468c9ea --- /dev/null +++ b/src/test/ui/regions/regions-free-region-ordering-caller.mir.stderr @@ -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 + diff --git a/src/test/ui/regions/regions-free-region-ordering-caller.rs b/src/test/ui/regions/regions-free-region-ordering-caller.rs index e26799fcc47..621e6e78b46 100644 --- a/src/test/ui/regions/regions-free-region-ordering-caller.rs +++ b/src/test/ui/regions/regions-free-region-ordering-caller.rs @@ -2,19 +2,25 @@ // 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() {} diff --git a/src/test/ui/regions/regions-free-region-ordering-caller1.nll.stderr b/src/test/ui/regions/regions-free-region-ordering-caller1.nll.stderr index 92c21fcb4ae..539343a6829 100644 --- a/src/test/ui/regions/regions-free-region-ordering-caller1.nll.stderr +++ b/src/test/ui/regions/regions-free-region-ordering-caller1.nll.stderr @@ -12,6 +12,21 @@ LL | let z: &'a & usize = &(&y); 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 -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`. diff --git a/src/test/ui/regions/regions-outlives-projection-container-hrtb.ast.stderr b/src/test/ui/regions/regions-outlives-projection-container-hrtb.ast.stderr new file mode 100644 index 00000000000..d8330184008 --- /dev/null +++ b/src/test/ui/regions/regions-outlives-projection-container-hrtb.ast.stderr @@ -0,0 +1,37 @@ +error[E0491]: in type `&'a WithHrAssoc>`, reference has a longer lifetime than the data it references + --> $DIR/regions-outlives-projection-container-hrtb.rs:35:12 + | +LL | let _: &'a WithHrAssoc> = 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>`, reference has a longer lifetime than the data it references + --> $DIR/regions-outlives-projection-container-hrtb.rs:57:12 + | +LL | let _: &'a WithHrAssocSub> = 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`. diff --git a/src/test/ui/regions/regions-outlives-projection-container-hrtb.mir.stderr b/src/test/ui/regions/regions-outlives-projection-container-hrtb.mir.stderr new file mode 100644 index 00000000000..5028663ba6d --- /dev/null +++ b/src/test/ui/regions/regions-outlives-projection-container-hrtb.mir.stderr @@ -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> = 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> = loop { }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a` + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/regions/regions-outlives-projection-container-hrtb.rs b/src/test/ui/regions/regions-outlives-projection-container-hrtb.rs index 3483f24ecbf..2871d962c42 100644 --- a/src/test/ui/regions/regions-outlives-projection-container-hrtb.rs +++ b/src/test/ui/regions/regions-outlives-projection-container-hrtb.rs @@ -1,6 +1,9 @@ // 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)] @@ -30,7 +33,8 @@ fn with_assoc<'a,'b>() { // We get an error because 'b:'a does not hold: let _: &'a WithHrAssoc> = 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. let _: &'a WithHrAssocSub> = loop { }; - //~^ ERROR reference has a longer lifetime + //[ast]~^ ERROR reference has a longer lifetime + //[mir]~^^ ERROR lifetime may not live long enough } diff --git a/src/test/ui/regions/regions-outlives-projection-container-wc.ast.stderr b/src/test/ui/regions/regions-outlives-projection-container-wc.ast.stderr new file mode 100644 index 00000000000..9e31065ca4e --- /dev/null +++ b/src/test/ui/regions/regions-outlives-projection-container-wc.ast.stderr @@ -0,0 +1,20 @@ +error[E0491]: in type `&'a WithAssoc>`, reference has a longer lifetime than the data it references + --> $DIR/regions-outlives-projection-container-wc.rs:37:12 + | +LL | let _: &'a WithAssoc> = 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`. diff --git a/src/test/ui/regions/regions-outlives-projection-container-wc.mir.stderr b/src/test/ui/regions/regions-outlives-projection-container-wc.mir.stderr new file mode 100644 index 00000000000..880fe17b740 --- /dev/null +++ b/src/test/ui/regions/regions-outlives-projection-container-wc.mir.stderr @@ -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> = loop { }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a` + +error: aborting due to previous error + diff --git a/src/test/ui/regions/regions-outlives-projection-container-wc.rs b/src/test/ui/regions/regions-outlives-projection-container-wc.rs index 91a0d8590ff..37622211327 100644 --- a/src/test/ui/regions/regions-outlives-projection-container-wc.rs +++ b/src/test/ui/regions/regions-outlives-projection-container-wc.rs @@ -3,6 +3,9 @@ // 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)] /////////////////////////////////////////////////////////////////////////// @@ -32,7 +35,8 @@ fn with_assoc<'a,'b>() { // which is &'b (), must outlive 'a. let _: &'a WithAssoc> = loop { }; - //~^ ERROR reference has a longer lifetime + //[ast]~^ ERROR reference has a longer lifetime + //[mir]~^^ ERROR lifetime may not live long enough } fn main() {