Auto merge of #54757 - nikomatsakis:nll-issue-54573-user-annot, r=pnkfelix
user annotations in patterns Fixes https://github.com/rust-lang/rust/issues/54573 r? @pnkfelix
This commit is contained in:
commit
e1643a8968
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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,
|
||||
|
@ -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
src/librustc_mir/hair/util.rs
Normal file
56
src/librustc_mir/hair/util.rs
Normal file
@ -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
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
@ -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).
|
||||
|
@ -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)
|
||||
|
@ -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() { }
|
@ -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`.
|
@ -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() { }
|
@ -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`.
|
@ -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() { }
|
@ -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`.
|
@ -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() { }
|
@ -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`.
|
Loading…
Reference in New Issue
Block a user