diff --git a/src/librustc/ich/impls_mir.rs b/src/librustc/ich/impls_mir.rs index 724481da6813..274a2df283cb 100644 --- a/src/librustc/ich/impls_mir.rs +++ b/src/librustc/ich/impls_mir.rs @@ -607,5 +607,5 @@ impl<'a, 'gcx> HashStable> for mir::UserTypeAnnotation< } } -impl_stable_hash_for!(struct mir::UserTypeProjection<'tcx> { base }); +impl_stable_hash_for!(struct mir::UserTypeProjection<'tcx> { base, projs }); impl_stable_hash_for!(struct mir::UserTypeProjections<'tcx> { contents }); diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index f96c3b432d60..142dc40e5b12 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2456,6 +2456,31 @@ EnumLiftImpl! { /// /// Its a collection because there can be multiple type ascriptions on /// the path from the root of the pattern down to the binding itself. +/// +/// An example: +/// +/// ```rust +/// struct S<'a>((i32, &'a str), String); +/// let S((_, w): (i32, &'static str), _): S = ...; +/// // ------ ^^^^^^^^^^^^^^^^^^^ (1) +/// // --------------------------------- ^ (2) +/// ``` +/// +/// The highlights labelled `(1)` show the subpattern `(_, w)` being +/// ascribed the type `(i32, &'static str)`. +/// +/// The highlights labelled `(2)` show the whole pattern being +/// ascribed the type `S`. +/// +/// In this example, when we descend to `w`, we will have built up the +/// following two projected types: +/// +/// * base: `S`, projection: `(base.0).1` +/// * base: `(i32, &'static str)`, projection: `base.1` +/// +/// The first will lead to the constraint `w: &'1 str` (for some +/// inferred region `'1`). The second will lead to the constraint `w: +/// &'static str`. #[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub struct UserTypeProjections<'tcx> { pub(crate) contents: Vec<(UserTypeProjection<'tcx>, Span)>, @@ -2485,14 +2510,49 @@ impl<'tcx> UserTypeProjections<'tcx> { } } -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] +/// Encodes the effect of a user-supplied type annotation on the +/// subcomponents of a pattern. The effect is determined by applying the +/// given list of proejctions to some underlying base type. Often, +/// the projection element list `projs` is empty, in which case this +/// directly encodes a type in `base`. But in the case of complex patterns with +/// subpatterns and bindings, we want to apply only a *part* of the type to a variable, +/// in which case the `projs` vector is used. +/// +/// Examples: +/// +/// * `let x: T = ...` -- here, the `projs` vector is empty. +/// +/// * `let (x, _): T = ...` -- here, the `projs` vector would contain +/// `field[0]` (aka `.0`), indicating that the type of `s` is +/// determined by finding the type of the `.0` field from `T`. +#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub struct UserTypeProjection<'tcx> { pub base: UserTypeAnnotation<'tcx>, + pub projs: Vec>, } -BraceStructTypeFoldableImpl! { - impl<'tcx> TypeFoldable<'tcx> for UserTypeProjection<'tcx> { - base +impl<'tcx> TypeFoldable<'tcx> for UserTypeProjection<'tcx> { + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { + use mir::ProjectionElem::*; + + let base = self.base.fold_with(folder); + let projs: Vec<_> = self.projs + .iter() + .map(|elem| { + match elem { + Deref => Deref, + Field(f, ()) => Field(f.clone(), ()), + Index(()) => Index(()), + elem => elem.clone(), + }}) + .collect(); + + UserTypeProjection { base, projs } + } + + fn super_visit_with>(&self, visitor: &mut Vs) -> bool { + self.base.visit_with(visitor) + // Note: there's nothing in `self.proj` to visit. } } diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index fc7b4862b0ae..473730c54899 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -44,11 +44,59 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> { } } + /// `place_ty.field_ty(tcx, f)` computes the type at a given field + /// of a record or enum-variant. (Most clients of `PlaceTy` can + /// instead just extract the relevant type directly from their + /// `PlaceElem`, but some instances of `ProjectionElem` do + /// not carry a `Ty` for `T`.) + /// + /// Note that the resulting type has not been normalized. + pub fn field_ty(self, tcx: TyCtxt<'a, 'gcx, 'tcx>, f: &Field) -> Ty<'tcx> + { + // Pass `0` here so it can be used as a "default" variant_index in first arm below + let answer = match (self, 0) { + (PlaceTy::Ty { + ty: &ty::TyS { sty: ty::TyKind::Adt(adt_def, substs), .. } }, variant_index) | + (PlaceTy::Downcast { adt_def, substs, variant_index }, _) => { + let variant_def = &adt_def.variants[variant_index]; + let field_def = &variant_def.fields[f.index()]; + field_def.ty(tcx, substs) + } + (PlaceTy::Ty { ty }, _) => { + match ty.sty { + ty::Tuple(ref tys) => tys[f.index()], + _ => bug!("extracting field of non-tuple non-adt: {:?}", self), + } + } + }; + debug!("field_ty self: {:?} f: {:?} yields: {:?}", self, f, answer); + answer + } + + /// Convenience wrapper around `projection_ty_core` for + /// `PlaceElem`, where we can just use the `Ty` that is already + /// stored inline on field projection elems. pub fn projection_ty(self, tcx: TyCtxt<'a, 'gcx, 'tcx>, elem: &PlaceElem<'tcx>) -> PlaceTy<'tcx> { - match *elem { + self.projection_ty_core(tcx, elem, |_, _, ty| ty) + } + + /// `place_ty.projection_ty_core(tcx, elem, |...| { ... })` + /// projects `place_ty` onto `elem`, returning the appropriate + /// `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(self, + tcx: TyCtxt<'a, 'gcx, 'tcx>, + elem: &ProjectionElem<'tcx, V, T>, + mut handle_field: impl FnMut(&Self, &Field, &T) -> Ty<'tcx>) + -> PlaceTy<'tcx> + where + V: ::std::fmt::Debug, T: ::std::fmt::Debug + { + let answer = match *elem { ProjectionElem::Deref => { let ty = self.to_ty(tcx) .builtin_deref(true) @@ -94,8 +142,10 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> { bug!("cannot downcast non-ADT type: `{:?}`", self) } }, - ProjectionElem::Field(_, fty) => PlaceTy::Ty { ty: fty } - } + ProjectionElem::Field(ref f, ref fty) => PlaceTy::Ty { ty: handle_field(&self, f, fty) } + }; + debug!("projection_ty self: {:?} elem: {:?} yields: {:?}", self, elem, answer); + answer } } diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 61eb565fb9a9..bfc03923f601 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -797,8 +797,9 @@ macro_rules! make_mir_visitor { ) { let UserTypeProjection { ref $($mutability)* base, + projs: _, // Note: Does not visit projection elems! } = *ty; - self.visit_user_type_annotation(base) + self.visit_user_type_annotation(base); } fn super_user_type_annotation( diff --git a/src/librustc_codegen_llvm/mir/analyze.rs b/src/librustc_codegen_llvm/mir/analyze.rs index a0d6cc462958..1602ef3c5b79 100644 --- a/src/librustc_codegen_llvm/mir/analyze.rs +++ b/src/librustc_codegen_llvm/mir/analyze.rs @@ -168,7 +168,9 @@ impl Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'll, 'tcx> { let base_ty = self.fx.monomorphize(&base_ty); // ZSTs don't require any actual memory access. - let elem_ty = base_ty.projection_ty(cx.tcx, &proj.elem).to_ty(cx.tcx); + let elem_ty = base_ty + .projection_ty(cx.tcx, &proj.elem) + .to_ty(cx.tcx); let elem_ty = self.fx.monomorphize(&elem_ty); if cx.layout_of(elem_ty).is_zst() { return; diff --git a/src/librustc_codegen_llvm/mir/place.rs b/src/librustc_codegen_llvm/mir/place.rs index e7b6f5908a4d..062f7174680d 100644 --- a/src/librustc_codegen_llvm/mir/place.rs +++ b/src/librustc_codegen_llvm/mir/place.rs @@ -517,7 +517,8 @@ impl FunctionCx<'a, 'll, 'tcx> { let mut subslice = cg_base.project_index(bx, C_usize(bx.cx, from as u64)); let projected_ty = PlaceTy::Ty { ty: cg_base.layout.ty } - .projection_ty(tcx, &projection.elem).to_ty(bx.tcx()); + .projection_ty(tcx, &projection.elem) + .to_ty(bx.tcx()); subslice.layout = bx.cx.layout_of(self.monomorphize(&projected_ty)); if subslice.layout.is_unsized() { 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 828907ddc63a..4d1eea4724be 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -284,7 +284,7 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> { if let Err(terr) = self.cx.relate_type_and_user_type( constant.ty, ty::Variance::Invariant, - &UserTypeProjection { base: user_ty }, + &UserTypeProjection { base: user_ty, projs: vec![], }, location.to_locations(), ConstraintCategory::Boring, ) { @@ -980,7 +980,6 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { a, v, user_ty, locations, ); - // FIXME match user_ty.base { UserTypeAnnotation::Ty(canonical_ty) => { let (ty, _) = self.infcx @@ -991,6 +990,20 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { // ambient variance to get the right relationship. let v1 = ty::Contravariant.xform(v); + let tcx = self.infcx.tcx; + let mut projected_ty = PlaceTy::from_ty(ty); + for proj in &user_ty.projs { + projected_ty = projected_ty.projection_ty_core( + tcx, proj, |this, field, &()| { + let ty = this.field_ty(tcx, field); + self.normalize(ty, locations) + }); + } + debug!("user_ty base: {:?} freshened: {:?} projs: {:?} yields: {:?}", + user_ty.base, ty, user_ty.projs, projected_ty); + + let ty = projected_ty.to_ty(tcx); + self.relate_types(ty, v1, a, locations, category)?; } UserTypeAnnotation::TypeOf(def_id, canonical_substs) => { @@ -1000,6 +1013,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { ) = self.infcx .instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &canonical_substs); + // FIXME: add user_ty.projs support to `AscribeUserType`. self.fully_perform_op( locations, category, @@ -1173,7 +1187,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { if let Err(terr) = self.relate_type_and_user_type( rv_ty, ty::Variance::Invariant, - &UserTypeProjection { base: user_ty }, + &UserTypeProjection { base: user_ty, projs: vec![], }, location.to_locations(), ConstraintCategory::Boring, ) { diff --git a/src/librustc_mir/build/expr/as_place.rs b/src/librustc_mir/build/expr/as_place.rs index bc03b6a5dd04..77746e5538d6 100644 --- a/src/librustc_mir/build/expr/as_place.rs +++ b/src/librustc_mir/build/expr/as_place.rs @@ -147,7 +147,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { kind: StatementKind::AscribeUserType( place.clone(), Variance::Invariant, - box UserTypeProjection { base: user_ty }, + box UserTypeProjection { base: user_ty, projs: vec![], }, ), }, ); @@ -167,7 +167,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { kind: StatementKind::AscribeUserType( Place::Local(temp.clone()), Variance::Invariant, - box UserTypeProjection { base: user_ty }, + box UserTypeProjection { base: user_ty, projs: vec![], }, ), }, ); diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index 5479ccb2d84d..b92f270255af 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -32,6 +32,8 @@ mod simplify; mod test; mod util; +use std::convert::TryFrom; + /// ArmHasGuard is isomorphic to a boolean flag. It indicates whether /// a match arm has a guard expression attached to it. #[derive(Copy, Clone, Debug)] @@ -541,11 +543,13 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ref slice, ref suffix, } => { + let from = u32::try_from(prefix.len()).unwrap(); + let to = u32::try_from(suffix.len()).unwrap(); for subpattern in prefix { self.visit_bindings(subpattern, &pattern_user_ty.index(), f); } for subpattern in slice { - self.visit_bindings(subpattern, &pattern_user_ty.subslice(), f); + self.visit_bindings(subpattern, &pattern_user_ty.subslice(from, to), f); } for subpattern in suffix { self.visit_bindings(subpattern, &pattern_user_ty.index(), f); @@ -555,25 +559,28 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { PatternKind::Deref { ref subpattern } => { self.visit_bindings(subpattern, &pattern_user_ty.deref(), f); } - PatternKind::AscribeUserType { ref subpattern, user_ty, user_ty_span } => { + PatternKind::AscribeUserType { ref subpattern, ref user_ty, user_ty_span } => { // This corresponds to something like // // ``` // let A::<'a>(_): A<'static> = ...; // ``` - let pattern_user_ty = pattern_user_ty.add_user_type(user_ty, user_ty_span); - self.visit_bindings(subpattern, &pattern_user_ty, f) + let subpattern_user_ty = pattern_user_ty.add_user_type(user_ty, user_ty_span); + self.visit_bindings(subpattern, &subpattern_user_ty, f) } PatternKind::Leaf { ref subpatterns } => { - for (j, subpattern) in subpatterns.iter().enumerate() { - self.visit_bindings(&subpattern.pattern, &pattern_user_ty.leaf(j), f); + for subpattern in subpatterns { + let subpattern_user_ty = pattern_user_ty.leaf(subpattern.field); + self.visit_bindings(&subpattern.pattern, &subpattern_user_ty, f); } } - PatternKind::Variant { ref subpatterns, .. } => { - for (j, subpattern) in subpatterns.iter().enumerate() { - self.visit_bindings(&subpattern.pattern, &pattern_user_ty.variant(j), f); + PatternKind::Variant { adt_def, substs: _, variant_index, ref subpatterns } => { + for subpattern in subpatterns { + let subpattern_user_ty = pattern_user_ty.variant( + adt_def, variant_index, subpattern.field); + self.visit_bindings(&subpattern.pattern, &subpattern_user_ty, f); } } } @@ -1329,7 +1336,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { kind: StatementKind::AscribeUserType( ascription.source.clone(), ty::Variance::Covariant, - box ascription.user_ty.user_ty(), + box ascription.user_ty.clone().user_ty(), ), }, ); diff --git a/src/librustc_mir/build/matches/simplify.rs b/src/librustc_mir/build/matches/simplify.rs index 494e7c03c3e6..349d877d5247 100644 --- a/src/librustc_mir/build/matches/simplify.rs +++ b/src/librustc_mir/build/matches/simplify.rs @@ -63,10 +63,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { candidate: &mut Candidate<'pat, 'tcx>) -> Result<(), MatchPair<'pat, 'tcx>> { match *match_pair.pattern.kind { - PatternKind::AscribeUserType { ref subpattern, user_ty, user_ty_span } => { + PatternKind::AscribeUserType { ref subpattern, ref user_ty, user_ty_span } => { candidate.ascriptions.push(Ascription { span: user_ty_span, - user_ty, + user_ty: user_ty.clone(), source: match_pair.place.clone(), }); diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 7a04c6e39df0..bff87da9c771 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -21,7 +21,7 @@ use const_eval::{const_field, const_variant_index}; use hair::util::UserAnnotatedTyHelpers; use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability}; -use rustc::mir::{UserTypeAnnotation, UserTypeProjection, UserTypeProjections}; +use rustc::mir::{ProjectionElem, UserTypeAnnotation, UserTypeProjection, UserTypeProjections}; use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, sign_extend}; use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty}; use rustc::ty::subst::{Substs, Kind}; @@ -86,43 +86,87 @@ impl<'tcx> PatternTypeProjections<'tcx> { PatternTypeProjections { contents: vec![] } } - pub(crate) fn index(&self) -> Self { - unimplemented!() + fn map_projs(&self, + mut f: impl FnMut(&PatternTypeProjection<'tcx>) -> PatternTypeProjection<'tcx>) + -> Self + { + PatternTypeProjections { + contents: self.contents + .iter() + .map(|(proj, span)| (f(proj), *span)) + .collect(), } } - pub(crate) fn subslice(&self) -> Self { - unimplemented!() + pub(crate) fn index(&self) -> Self { self.map_projs(|pat_ty_proj| pat_ty_proj.index()) } + + pub(crate) fn subslice(&self, from: u32, to: u32) -> Self { + self.map_projs(|pat_ty_proj| pat_ty_proj.subslice(from, to)) } - pub(crate) fn deref(&self) -> Self { - unimplemented!() + pub(crate) fn deref(&self) -> Self { self.map_projs(|pat_ty_proj| pat_ty_proj.deref()) } + + pub(crate) fn leaf(&self, field: Field) -> Self { + self.map_projs(|pat_ty_proj| pat_ty_proj.leaf(field)) } - pub(crate) fn add_user_type(&self, user_ty: PatternTypeProjection<'tcx>, sp: Span) -> Self { + pub(crate) fn variant(&self, + adt_def: &'tcx AdtDef, + variant_index: usize, + field: Field) -> Self { + self.map_projs(|pat_ty_proj| pat_ty_proj.variant(adt_def, variant_index, field)) + } + + pub(crate) fn add_user_type(&self, user_ty: &PatternTypeProjection<'tcx>, sp: Span) -> Self { let mut new = self.clone(); - new.contents.push((user_ty, sp)); + new.contents.push((user_ty.clone(), sp)); new } - - pub(crate) fn leaf(&self, _index: usize) -> Self { - unimplemented!() - } - - pub(crate) fn variant(&self, _index: usize) -> Self { - unimplemented!() - } } -#[derive(Copy, Clone, Debug)] +#[derive(Clone, Debug)] pub struct PatternTypeProjection<'tcx>(UserTypeProjection<'tcx>); impl<'tcx> PatternTypeProjection<'tcx> { + pub(crate) fn index(&self) -> Self { + let mut new = self.clone(); + new.0.projs.push(ProjectionElem::Index(())); + new + } + + pub(crate) fn subslice(&self, from: u32, to: u32) -> Self { + let mut new = self.clone(); + new.0.projs.push(ProjectionElem::Subslice { from, to }); + new + } + + pub(crate) fn deref(&self) -> Self { + let mut new = self.clone(); + new.0.projs.push(ProjectionElem::Deref); + new + } + + pub(crate) fn leaf(&self, field: Field) -> Self { + let mut new = self.clone(); + new.0.projs.push(ProjectionElem::Field(field, ())); + new + } + + pub(crate) fn variant(&self, + adt_def: &'tcx AdtDef, + variant_index: usize, + field: Field) -> Self { + let mut new = self.clone(); + new.0.projs.push(ProjectionElem::Downcast(adt_def, variant_index)); + new.0.projs.push(ProjectionElem::Field(field, ())); + new + } + pub(crate) fn from_canonical_ty(c_ty: ty::CanonicalTy<'tcx>) -> Self { Self::from_user_type(UserTypeAnnotation::Ty(c_ty)) } pub(crate) fn from_user_type(u_ty: UserTypeAnnotation<'tcx>) -> Self { - Self::from_user_type_proj(UserTypeProjection { base: u_ty }) + Self::from_user_type_proj(UserTypeProjection { base: u_ty, projs: vec![], }) } pub(crate) fn from_user_type_proj(u_ty: UserTypeProjection<'tcx>) -> Self { @@ -1086,7 +1130,7 @@ impl<'tcx> PatternFoldable<'tcx> for PatternKind<'tcx> { PatternKind::Wild => PatternKind::Wild, PatternKind::AscribeUserType { ref subpattern, - user_ty, + ref user_ty, user_ty_span, } => PatternKind::AscribeUserType { subpattern: subpattern.fold_with(folder), diff --git a/src/test/ui/nll/user-annotations/patterns.rs b/src/test/ui/nll/user-annotations/patterns.rs index e3bac513fa87..643231b39b42 100644 --- a/src/test/ui/nll/user-annotations/patterns.rs +++ b/src/test/ui/nll/user-annotations/patterns.rs @@ -9,11 +9,11 @@ fn variable_no_initializer() { } fn tuple_no_initializer() { - // FIXME(#47187): We are not propagating ascribed type through tuples. + let x = 22; let (y, z): (&'static u32, &'static u32); - y = &x; + y = &x; //~ ERROR } fn ref_with_ascribed_static_type() -> u32 { @@ -34,11 +34,11 @@ fn ref_with_ascribed_any_type() -> u32 { struct Single { value: T } fn struct_no_initializer() { - // FIXME(#47187): We are not propagating ascribed type through patterns. + let x = 22; let Single { value: y }: Single<&'static u32>; - y = &x; + y = &x; //~ ERROR } fn variable_with_initializer() { @@ -91,26 +91,26 @@ fn struct_double_field_underscore_with_initializer() { } fn static_to_a_to_static_through_variable<'a>(x: &'a u32) -> &'static u32 { - // The error in this test is inconsistency with - // `static_to_a_to_static_through_tuple`, but "feels right" to - // me. It occurs because we special case the single binding case - // and force the type of `y` to be `&'a u32`, even though the - // right-hand side has type `&'static u32`. + + + + + let y: &'a u32 = &22; y //~ ERROR } fn static_to_a_to_static_through_tuple<'a>(x: &'a u32) -> &'static u32 { - // FIXME(#47187): The fact that this type-checks is perhaps surprising. - // What happens is that the right-hand side is constrained to have - // type `&'a u32`, which is possible, because it has type - // `&'static u32`. The variable `y` is then forced to have type - // `&'static u32`, but it is constrained only by the right-hand - // side, not the ascribed type, and hence it passes. + + + + + + let (y, _z): (&'a u32, u32) = (&22, 44); - y + y //~ ERROR } fn a_to_static_then_static<'a>(x: &'a u32) -> &'static u32 { diff --git a/src/test/ui/nll/user-annotations/patterns.stderr b/src/test/ui/nll/user-annotations/patterns.stderr index 0c50b98ee271..58b708fcb1b5 100644 --- a/src/test/ui/nll/user-annotations/patterns.stderr +++ b/src/test/ui/nll/user-annotations/patterns.stderr @@ -8,6 +8,16 @@ LL | y = &x; //~ ERROR LL | } | - `x` dropped here while still borrowed +error[E0597]: `x` does not live long enough + --> $DIR/patterns.rs:16:9 + | +LL | let (y, z): (&'static u32, &'static u32); + | ---------------------------- type annotation requires that `x` is borrowed for `'static` +LL | y = &x; //~ ERROR + | ^^ borrowed value does not live long enough +LL | } + | - `x` dropped here while still borrowed + error[E0597]: `x` does not live long enough --> $DIR/patterns.rs:22:13 | @@ -19,6 +29,16 @@ LL | **z LL | } | - `x` dropped here while still borrowed +error[E0597]: `x` does not live long enough + --> $DIR/patterns.rs:41:9 + | +LL | let Single { value: y }: Single<&'static u32>; + | -------------------- type annotation requires that `x` is borrowed for `'static` +LL | y = &x; //~ ERROR + | ^^ borrowed value does not live long enough +LL | } + | - `x` dropped here while still borrowed + error[E0597]: `x` does not live long enough --> $DIR/patterns.rs:46:27 | @@ -127,6 +147,15 @@ LL | fn static_to_a_to_static_through_variable<'a>(x: &'a u32) -> &'static u32 { LL | y //~ ERROR | ^ returning this value requires that `'a` must outlive `'static` +error: unsatisfied lifetime constraints + --> $DIR/patterns.rs:113:5 + | +LL | fn static_to_a_to_static_through_tuple<'a>(x: &'a u32) -> &'static u32 { + | -- lifetime `'a` defined here +... +LL | y //~ ERROR + | ^ returning this value requires that `'a` must outlive `'static` + error: unsatisfied lifetime constraints --> $DIR/patterns.rs:117:18 | @@ -135,7 +164,7 @@ LL | fn a_to_static_then_static<'a>(x: &'a u32) -> &'static u32 { LL | let (y, _z): (&'static u32, u32) = (x, 44); //~ ERROR | ^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` -error: aborting due to 14 previous errors +error: aborting due to 17 previous errors Some errors occurred: E0597, E0716. For more information about an error, try `rustc --explain E0597`.