Skip to content

user annotations in patterns #54757

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Oct 9, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/librustc/mir/visit.rs
Original file line number Diff line number Diff line change
@@ -214,7 +214,7 @@ macro_rules! make_mir_visitor {
self.super_ty(ty);
}

fn visit_canonical_ty(&mut self, ty: & $($mutability)* CanonicalTy<'tcx>) {
fn visit_user_ty(&mut self, ty: & $($mutability)* CanonicalTy<'tcx>) {
self.super_canonical_ty(ty);
}

@@ -640,7 +640,7 @@ macro_rules! make_mir_visitor {
c_ty: & $($mutability)* CanonicalTy<'tcx>,
location: Location) {
self.visit_place(place, PlaceContext::Validate, location);
self.visit_canonical_ty(c_ty);
self.visit_user_ty(c_ty);
}

fn super_place(&mut self,
@@ -736,7 +736,7 @@ macro_rules! make_mir_visitor {
source_info: *source_info,
});
if let Some(user_ty) = user_ty {
self.visit_canonical_ty(user_ty);
self.visit_user_ty(user_ty);
}
self.visit_source_info(source_info);
self.visit_source_scope(visibility_scope);
23 changes: 9 additions & 14 deletions src/librustc_mir/borrow_check/nll/renumber.rs
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@

use rustc::ty::subst::Substs;
use rustc::ty::{self, CanonicalTy, ClosureSubsts, GeneratorSubsts, Ty, TypeFoldable};
use rustc::mir::{BasicBlock, Location, Mir, Place, Statement, StatementKind};
use rustc::mir::{BasicBlock, Location, Mir, Statement, StatementKind};
use rustc::mir::visit::{MutVisitor, TyContext};
use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};

@@ -65,6 +65,14 @@ impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> {
debug!("visit_ty: ty={:?}", ty);
}

fn visit_user_ty(&mut self, _ty: &mut CanonicalTy<'tcx>) {
// `user_ty` 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_ty: skipping renumber");
}

fn visit_substs(&mut self, substs: &mut &'tcx Substs<'tcx>, location: Location) {
debug!("visit_substs(substs={:?}, location={:?})", substs, location);

@@ -112,19 +120,6 @@ impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> {
debug!("visit_closure_substs: substs={:?}", substs);
}

fn visit_ascribe_user_ty(
&mut self,
_place: &mut Place<'tcx>,
_variance: &mut ty::Variance,
_c_ty: &mut CanonicalTy<'tcx>,
_location: Location,
) {
// User-assert-ty statements represent types that the user added explicitly.
// 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_assert_ty: skipping renumber");
}

fn visit_statement(
&mut self,
block: BasicBlock,
8 changes: 8 additions & 0 deletions src/librustc_mir/build/matches/mod.rs
Original file line number Diff line number Diff line change
@@ -1307,6 +1307,14 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
) {
for ascription in ascriptions {
let source_info = self.source_info(ascription.span);

debug!(
"adding user ascription at span {:?} of place {:?} and {:?}",
source_info.span,
ascription.source,
ascription.user_ty,
);

self.cfg.push(
block,
Statement {
46 changes: 8 additions & 38 deletions src/librustc_mir/hair/cx/expr.rs
Original file line number Diff line number Diff line change
@@ -13,6 +13,7 @@ use rustc_data_structures::indexed_vec::Idx;
use hair::cx::Cx;
use hair::cx::block;
use hair::cx::to_ref::ToRef;
use hair::util::UserAnnotatedTyHelpers;
use rustc::hir::def::{Def, CtorKind};
use rustc::mir::interpret::GlobalId;
use rustc::ty::{self, AdtKind, Ty};
@@ -475,7 +476,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
adt_def: adt,
variant_index: 0,
substs,
user_ty: user_annotated_ty_for_adt(cx, expr.hir_id, adt),
user_ty: cx.user_substs_applied_to_adt(expr.hir_id, adt),
fields: field_refs(cx, fields),
base: base.as_ref().map(|base| {
FruInfo {
@@ -501,7 +502,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
adt_def: adt,
variant_index: index,
substs,
user_ty: user_annotated_ty_for_adt(cx, expr.hir_id, adt),
user_ty: cx.user_substs_applied_to_adt(expr.hir_id, adt),
fields: field_refs(cx, fields),
base: None,
}
@@ -787,48 +788,17 @@ fn user_annotated_ty_for_def(
// user.
Def::StructCtor(_def_id, CtorKind::Const) |
Def::VariantCtor(_def_id, CtorKind::Const) =>
match &cx.tables().node_id_to_type(hir_id).sty {
ty::Adt(adt_def, _) => user_annotated_ty_for_adt(cx, hir_id, adt_def),
sty => bug!("unexpected sty: {:?}", sty),
},
cx.user_substs_applied_to_ty_of_hir_id(hir_id),

// `Self` is used in expression as a tuple struct constructor or an unit struct constructor
Def::SelfCtor(_) => {
let sty = &cx.tables().node_id_to_type(hir_id).sty;
match sty {
ty::FnDef(ref def_id, _) => {
Some(cx.tables().user_substs(hir_id)?.unchecked_map(|user_substs| {
// Here, we just pair a `DefId` with the
// `user_substs`, so no new types etc are introduced.
cx.tcx().mk_fn_def(*def_id, user_substs)
}))
}
ty::Adt(ref adt_def, _) => {
user_annotated_ty_for_adt(cx, hir_id, adt_def)
}
_ => {
bug!("unexpected sty: {:?}", sty)
}
}
}
Def::SelfCtor(_) =>
cx.user_substs_applied_to_ty_of_hir_id(hir_id),

_ =>
bug!("user_annotated_ty_for_def: unexpected def {:?} at {:?}", def, hir_id)
}
}

fn user_annotated_ty_for_adt(
cx: &mut Cx<'a, 'gcx, 'tcx>,
hir_id: hir::HirId,
adt_def: &'tcx AdtDef,
) -> Option<CanonicalTy<'tcx>> {
let user_substs = cx.tables().user_substs(hir_id)?;
Some(user_substs.unchecked_map(|user_substs| {
// Here, we just pair an `AdtDef` with the
// `user_substs`, so no new types etc are introduced.
cx.tcx().mk_adt(adt_def, user_substs)
}))
}

fn method_callee<'a, 'gcx, 'tcx>(
cx: &mut Cx<'a, 'gcx, 'tcx>,
expr: &hir::Expr,
@@ -943,7 +913,7 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
adt_def,
variant_index: adt_def.variant_index_with_id(def_id),
substs,
user_ty: user_annotated_ty_for_adt(cx, expr.hir_id, adt_def),
user_ty: cx.user_substs_applied_to_adt(expr.hir_id, adt_def),
fields: vec![],
base: None,
}
11 changes: 11 additions & 0 deletions src/librustc_mir/hair/cx/mod.rs
Original file line number Diff line number Diff line change
@@ -15,6 +15,7 @@
//!
use hair::*;
use hair::util::UserAnnotatedTyHelpers;

use rustc_data_structures::indexed_vec::Idx;
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
@@ -272,6 +273,16 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
}
}

impl UserAnnotatedTyHelpers<'gcx, 'tcx> for Cx<'_, 'gcx, 'tcx> {
fn tcx(&self) -> TyCtxt<'_, 'gcx, 'tcx> {
self.tcx()
}

fn tables(&self) -> &ty::TypeckTables<'tcx> {
self.tables()
}
}

fn lint_level_for_hir_id(tcx: TyCtxt, mut id: ast::NodeId) -> ast::NodeId {
// Right now we insert a `with_ignore` node in the dep graph here to
// ignore the fact that `lint_levels` below depends on the entire crate.
2 changes: 2 additions & 0 deletions src/librustc_mir/hair/mod.rs
Original file line number Diff line number Diff line change
@@ -29,6 +29,8 @@ pub mod cx;
pub mod pattern;
pub use self::pattern::{BindingMode, Pattern, PatternKind, FieldPattern};

mod util;

#[derive(Copy, Clone, Debug)]
pub enum LintLevel {
Inherited,
47 changes: 39 additions & 8 deletions src/librustc_mir/hair/pattern/mod.rs
Original file line number Diff line number Diff line change
@@ -18,6 +18,8 @@ pub(crate) use self::check_match::check_match;

use const_eval::{const_field, const_variant_index};

use hair::util::UserAnnotatedTyHelpers;

use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability};
use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, sign_extend};
use rustc::ty::{self, CanonicalTy, TyCtxt, AdtDef, Ty, Region};
@@ -529,8 +531,9 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
field: Field::new(i),
pattern: self.lower_pattern(field),
})
.collect();
self.lower_variant_or_leaf(def, pat.span, ty, subpatterns)
.collect();

self.lower_variant_or_leaf(def, pat.hir_id, pat.span, ty, subpatterns)
}

PatKind::Struct(ref qpath, ref fields, _) => {
@@ -546,7 +549,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
})
.collect();

self.lower_variant_or_leaf(def, pat.span, ty, subpatterns)
self.lower_variant_or_leaf(def, pat.hir_id, pat.span, ty, subpatterns)
}
};

@@ -637,12 +640,12 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
fn lower_variant_or_leaf(
&mut self,
def: Def,
hir_id: hir::HirId,
span: Span,
ty: Ty<'tcx>,
subpatterns: Vec<FieldPattern<'tcx>>)
-> PatternKind<'tcx>
{
match def {
subpatterns: Vec<FieldPattern<'tcx>>,
) -> PatternKind<'tcx> {
let mut kind = match def {
Def::Variant(variant_id) | Def::VariantCtor(variant_id, ..) => {
let enum_id = self.tcx.parent_def_id(variant_id).unwrap();
let adt_def = self.tcx.adt_def(enum_id);
@@ -675,7 +678,24 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
self.errors.push(PatternError::NonConstPath(span));
PatternKind::Wild
}
};

if let Some(user_ty) = self.user_substs_applied_to_ty_of_hir_id(hir_id) {
let subpattern = Pattern {
span,
ty,
kind: Box::new(kind),
};

debug!("pattern user_ty = {:?} for pattern at {:?}", user_ty, span);

kind = PatternKind::AscribeUserType {
subpattern,
user_ty,
};
}

kind
}

/// Takes a HIR Path. If the path is a constant, evaluates it and feeds
@@ -729,7 +749,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
},
}
}
_ => self.lower_variant_or_leaf(def, span, ty, vec![]),
_ => self.lower_variant_or_leaf(def, id, span, ty, vec![]),
};

Pattern {
@@ -894,6 +914,17 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
}
}

impl UserAnnotatedTyHelpers<'tcx, 'tcx> for PatternContext<'_, 'tcx> {
fn tcx(&self) -> TyCtxt<'_, 'tcx, 'tcx> {
self.tcx
}

fn tables(&self) -> &ty::TypeckTables<'tcx> {
self.tables
}
}


pub trait PatternFoldable<'tcx> : Sized {
fn fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
self.super_fold_with(folder)
56 changes: 56 additions & 0 deletions src/librustc_mir/hair/util.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use rustc::hir;
use rustc::ty::{self, AdtDef, CanonicalTy, TyCtxt};

crate trait UserAnnotatedTyHelpers<'gcx: 'tcx, 'tcx> {
fn tcx(&self) -> TyCtxt<'_, 'gcx, 'tcx>;

fn tables(&self) -> &ty::TypeckTables<'tcx>;

fn user_substs_applied_to_adt(
&self,
hir_id: hir::HirId,
adt_def: &'tcx AdtDef,
) -> Option<CanonicalTy<'tcx>> {
let user_substs = self.tables().user_substs(hir_id)?;
Some(user_substs.unchecked_map(|user_substs| {
// Here, we just pair an `AdtDef` with the
// `user_substs`, so no new types etc are introduced.
self.tcx().mk_adt(adt_def, user_substs)
}))
}

/// Looks up the type associated with this hir-id and applies the
/// user-given substitutions; the hir-id must map to a suitable
/// type.
fn user_substs_applied_to_ty_of_hir_id(&self, hir_id: hir::HirId) -> Option<CanonicalTy<'tcx>> {
let user_substs = self.tables().user_substs(hir_id)?;
match &self.tables().node_id_to_type(hir_id).sty {
ty::Adt(adt_def, _) => Some(user_substs.unchecked_map(|user_substs| {
// Ok to call `unchecked_map` because we just pair an
// `AdtDef` with the `user_substs`, so no new types
// etc are introduced.
self.tcx().mk_adt(adt_def, user_substs)
})),
ty::FnDef(def_id, _) => Some(user_substs.unchecked_map(|user_substs| {
// Here, we just pair a `DefId` with the
// `user_substs`, so no new types etc are introduced.
self.tcx().mk_fn_def(*def_id, user_substs)
})),
sty => bug!(
"sty: {:?} should not have user-substs {:?} recorded ",
sty,
user_substs
),
}
}
}
43 changes: 33 additions & 10 deletions src/librustc_typeck/astconv.rs
Original file line number Diff line number Diff line change
@@ -402,21 +402,44 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
}

/// Creates the relevant generic argument substitutions
/// corresponding to a set of generic parameters.
pub fn create_substs_for_generic_args<'a, 'b, A, P, I>(
/// corresponding to a set of generic parameters. This is a
/// rather complex little function. Let me try to explain the
/// role of each of its parameters:
///
/// To start, we are given the `def_id` of the thing we are
/// creating the substitutions for, and a partial set of
/// substitutions `parent_substs`. In general, the substitutions
/// for an item begin with substitutions for all the "parents" of
/// that item -- so e.g. for a method it might include the
/// parameters from the impl.
///
/// Therefore, the method begins by walking down these parents,
/// starting with the outermost parent and proceed inwards until
/// it reaches `def_id`. For each parent P, it will check `parent_substs`
/// first to see if the parent's substitutions are listed in there. If so,
/// we can append those and move on. Otherwise, it invokes the
/// three callback functions:
///
/// - `args_for_def_id`: given the def-id P, supplies back the
/// generic arguments that were given to that parent from within
/// the path; so e.g. if you have `<T as Foo>::Bar`, the def-id
/// might refer to the trait `Foo`, and the arguments might be
/// `[T]`. The boolean value indicates whether to infer values
/// for arguments whose values were not explicitly provided.
/// - `provided_kind`: given the generic parameter and the value from `args_for_def_id`,
/// instantiate a `Kind`
/// - `inferred_kind`: if no parameter was provided, and inference is enabled, then
/// creates a suitable inference variable.
pub fn create_substs_for_generic_args<'a, 'b>(
tcx: TyCtxt<'a, 'gcx, 'tcx>,
def_id: DefId,
parent_substs: &[Kind<'tcx>],
has_self: bool,
self_ty: Option<Ty<'tcx>>,
args_for_def_id: A,
provided_kind: P,
inferred_kind: I,
) -> &'tcx Substs<'tcx> where
A: Fn(DefId) -> (Option<&'b GenericArgs>, bool),
P: Fn(&GenericParamDef, &GenericArg) -> Kind<'tcx>,
I: Fn(Option<&[Kind<'tcx>]>, &GenericParamDef, bool) -> Kind<'tcx>
{
args_for_def_id: impl Fn(DefId) -> (Option<&'b GenericArgs>, bool),
provided_kind: impl Fn(&GenericParamDef, &GenericArg) -> Kind<'tcx>,
inferred_kind: impl Fn(Option<&[Kind<'tcx>]>, &GenericParamDef, bool) -> Kind<'tcx>,
) -> &'tcx Substs<'tcx> {
// Collect the segments of the path: we need to substitute arguments
// for parameters throughout the entire path (wherever there are
// generic parameters).
30 changes: 26 additions & 4 deletions src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
@@ -2164,6 +2164,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
/// occurred**, so that annotations like `Vec<_>` are preserved
/// properly.
pub fn write_user_substs_from_substs(&self, hir_id: hir::HirId, substs: &'tcx Substs<'tcx>) {
debug!(
"write_user_substs_from_substs({:?}, {:?}) in fcx {}",
hir_id,
substs,
self.tag(),
);

if !substs.is_noop() {
let user_substs = self.infcx.canonicalize_response(&substs);
debug!("instantiate_value_path: user_substs = {:?}", user_substs);
@@ -3752,6 +3759,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
expected: Expectation<'tcx>,
needs: Needs
) -> Ty<'tcx> {
debug!(
"check_expr_kind(expr={:?}, expected={:?}, needs={:?})",
expr,
expected,
needs,
);

let tcx = self.tcx;
let id = expr.id;
match expr.node {
@@ -4981,10 +4995,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
span: Span,
node_id: ast::NodeId)
-> (Ty<'tcx>, Def) {
debug!("instantiate_value_path(path={:?}, def={:?}, node_id={})",
segments,
def,
node_id);
debug!(
"instantiate_value_path(segments={:?}, self_ty={:?}, def={:?}, node_id={})",
segments,
self_ty,
def,
node_id,
);

let path_segs = self.def_ids_for_path_segments(segments, def);

@@ -5194,6 +5211,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
let hir_id = self.tcx.hir.node_to_hir_id(node_id);
self.write_substs(hir_id, substs);

debug!(
"instantiate_value_path: id={:?} substs={:?}",
node_id,
substs,
);
self.write_user_substs_from_substs(hir_id, substs);

(ty_substituted, new_def)
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#![feature(nll)]

enum Foo<'a> {
Bar { field: &'a u32 }
}

fn in_let() {
let y = 22;
let foo = Foo::Bar { field: &y };
//~^ ERROR `y` does not live long enough
let Foo::Bar::<'static> { field: _z } = foo;
}

fn in_match() {
let y = 22;
let foo = Foo::Bar { field: &y };
//~^ ERROR `y` does not live long enough
match foo {
Foo::Bar::<'static> { field: _z } => {
}
}
}

fn main() { }
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
error[E0597]: `y` does not live long enough
--> $DIR/pattern_substs_on_brace_enum_variant.rs:9:33
|
LL | let foo = Foo::Bar { field: &y };
| ^^ borrowed value does not live long enough
...
LL | }
| - `y` dropped here while still borrowed
|
= note: borrowed value must be valid for the static lifetime...

error[E0597]: `y` does not live long enough
--> $DIR/pattern_substs_on_brace_enum_variant.rs:16:33
|
LL | let foo = Foo::Bar { field: &y };
| ^^ borrowed value does not live long enough
...
LL | }
| - `y` dropped here while still borrowed
|
= note: borrowed value must be valid for the static lifetime...

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0597`.
22 changes: 22 additions & 0 deletions src/test/ui/nll/user-annotations/pattern_substs_on_brace_struct.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#![feature(nll)]

struct Foo<'a> { field: &'a u32 }

fn in_let() {
let y = 22;
let foo = Foo { field: &y };
//~^ ERROR `y` does not live long enough
let Foo::<'static> { field: _z } = foo;
}

fn in_main() {
let y = 22;
let foo = Foo { field: &y };
//~^ ERROR `y` does not live long enough
match foo {
Foo::<'static> { field: _z } => {
}
}
}

fn main() { }
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
error[E0597]: `y` does not live long enough
--> $DIR/pattern_substs_on_brace_struct.rs:7:28
|
LL | let foo = Foo { field: &y };
| ^^ borrowed value does not live long enough
...
LL | }
| - `y` dropped here while still borrowed
|
= note: borrowed value must be valid for the static lifetime...

error[E0597]: `y` does not live long enough
--> $DIR/pattern_substs_on_brace_struct.rs:14:28
|
LL | let foo = Foo { field: &y };
| ^^ borrowed value does not live long enough
...
LL | }
| - `y` dropped here while still borrowed
|
= note: borrowed value must be valid for the static lifetime...

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0597`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#![feature(nll)]

enum Foo<'a> {
Bar(&'a u32)
}

fn in_let() {
let y = 22;
let foo = Foo::Bar(&y);
//~^ ERROR `y` does not live long enough
let Foo::Bar::<'static>(_z) = foo;
}

fn in_match() {
let y = 22;
let foo = Foo::Bar(&y);
//~^ ERROR `y` does not live long enough
match foo {
Foo::Bar::<'static>(_z) => {
}
}
}

fn main() { }
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
error[E0597]: `y` does not live long enough
--> $DIR/pattern_substs_on_tuple_enum_variant.rs:9:24
|
LL | let foo = Foo::Bar(&y);
| ^^ borrowed value does not live long enough
...
LL | }
| - `y` dropped here while still borrowed
|
= note: borrowed value must be valid for the static lifetime...

error[E0597]: `y` does not live long enough
--> $DIR/pattern_substs_on_tuple_enum_variant.rs:16:24
|
LL | let foo = Foo::Bar(&y);
| ^^ borrowed value does not live long enough
...
LL | }
| - `y` dropped here while still borrowed
|
= note: borrowed value must be valid for the static lifetime...

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0597`.
22 changes: 22 additions & 0 deletions src/test/ui/nll/user-annotations/pattern_substs_on_tuple_struct.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#![feature(nll)]

struct Foo<'a>(&'a u32);

fn in_let() {
let y = 22;
let foo = Foo(&y);
//~^ ERROR `y` does not live long enough
let Foo::<'static>(_z) = foo;
}

fn in_match() {
let y = 22;
let foo = Foo(&y);
//~^ ERROR `y` does not live long enough
match foo {
Foo::<'static>(_z) => {
}
}
}

fn main() { }
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
error[E0597]: `y` does not live long enough
--> $DIR/pattern_substs_on_tuple_struct.rs:7:19
|
LL | let foo = Foo(&y);
| ^^ borrowed value does not live long enough
...
LL | }
| - `y` dropped here while still borrowed
|
= note: borrowed value must be valid for the static lifetime...

error[E0597]: `y` does not live long enough
--> $DIR/pattern_substs_on_tuple_struct.rs:14:19
|
LL | let foo = Foo(&y);
| ^^ borrowed value does not live long enough
...
LL | }
| - `y` dropped here while still borrowed
|
= note: borrowed value must be valid for the static lifetime...

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0597`.