From f4b711516d0ef53957c1f65590051ed9e43cb4a9 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 2 Oct 2018 11:00:57 -0400 Subject: [PATCH 1/6] move `user_annotated_ty_for_adt` into a helper trait --- src/librustc_mir/hair/cx/expr.rs | 24 ++++++------------------ src/librustc_mir/hair/cx/mod.rs | 11 +++++++++++ src/librustc_mir/hair/mod.rs | 2 ++ src/librustc_mir/hair/util.rs | 31 +++++++++++++++++++++++++++++++ 4 files changed, 50 insertions(+), 18 deletions(-) create mode 100644 src/librustc_mir/hair/util.rs diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 8d50fbbdc6b..ef7be184ab0 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -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_annotated_ty_for_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_annotated_ty_for_adt(expr.hir_id, adt), fields: field_refs(cx, fields), base: None, } @@ -788,7 +789,7 @@ fn user_annotated_ty_for_def( 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), + ty::Adt(adt_def, _) => cx.user_annotated_ty_for_adt(hir_id, adt_def), sty => bug!("unexpected sty: {:?}", sty), }, @@ -804,7 +805,7 @@ fn user_annotated_ty_for_def( })) } ty::Adt(ref adt_def, _) => { - user_annotated_ty_for_adt(cx, hir_id, adt_def) + cx.user_annotated_ty_for_adt(hir_id, adt_def) } _ => { bug!("unexpected sty: {:?}", sty) @@ -816,19 +817,6 @@ fn user_annotated_ty_for_def( } } -fn user_annotated_ty_for_adt( - cx: &mut Cx<'a, 'gcx, 'tcx>, - hir_id: hir::HirId, - adt_def: &'tcx AdtDef, -) -> Option> { - 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 +931,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_annotated_ty_for_adt(expr.hir_id, adt_def), fields: vec![], base: None, } diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index 4d4a89fca8b..5f798135966 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -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. diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs index eb73a202148..e4f88e4fcc3 100644 --- a/src/librustc_mir/hair/mod.rs +++ b/src/librustc_mir/hair/mod.rs @@ -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, diff --git a/src/librustc_mir/hair/util.rs b/src/librustc_mir/hair/util.rs new file mode 100644 index 00000000000..803ce615747 --- /dev/null +++ b/src/librustc_mir/hair/util.rs @@ -0,0 +1,31 @@ +// 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 or the MIT license +// , 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_annotated_ty_for_adt( + &self, + hir_id: hir::HirId, + adt_def: &'tcx AdtDef, + ) -> Option> { + 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) + })) + } +} From 71fed065f7006f4102ac8130896a407aabb5de82 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 5 Oct 2018 10:40:35 -0400 Subject: [PATCH 2/6] extract more helper fns around user substs --- src/librustc_mir/hair/cx/expr.rs | 32 +++++++------------------------- src/librustc_mir/hair/util.rs | 27 ++++++++++++++++++++++++++- 2 files changed, 33 insertions(+), 26 deletions(-) diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index ef7be184ab0..c969a3ef348 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -476,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: cx.user_annotated_ty_for_adt(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 { @@ -502,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: cx.user_annotated_ty_for_adt(expr.hir_id, adt), + user_ty: cx.user_substs_applied_to_adt(expr.hir_id, adt), fields: field_refs(cx, fields), base: None, } @@ -788,30 +788,12 @@ 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, _) => cx.user_annotated_ty_for_adt(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, _) => { - cx.user_annotated_ty_for_adt(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) } @@ -931,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: cx.user_annotated_ty_for_adt(expr.hir_id, adt_def), + user_ty: cx.user_substs_applied_to_adt(expr.hir_id, adt_def), fields: vec![], base: None, } diff --git a/src/librustc_mir/hair/util.rs b/src/librustc_mir/hair/util.rs index 803ce615747..48a2e67a3dc 100644 --- a/src/librustc_mir/hair/util.rs +++ b/src/librustc_mir/hair/util.rs @@ -16,7 +16,7 @@ crate trait UserAnnotatedTyHelpers<'gcx: 'tcx, 'tcx> { fn tables(&self) -> &ty::TypeckTables<'tcx>; - fn user_annotated_ty_for_adt( + fn user_substs_applied_to_adt( &self, hir_id: hir::HirId, adt_def: &'tcx AdtDef, @@ -28,4 +28,29 @@ crate trait UserAnnotatedTyHelpers<'gcx: 'tcx, 'tcx> { 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> { + 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 + ), + } + } } From a609384561944c24b076dcecbcd84adb0243c0fb Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 8 Oct 2018 18:03:43 -0400 Subject: [PATCH 3/6] do not skip renumbering the place in place-type-ascriptions --- src/librustc/mir/visit.rs | 6 ++--- src/librustc_mir/borrow_check/nll/renumber.rs | 23 ++++++++----------- 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 7d8227053b3..d2b0a6a37a7 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -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); diff --git a/src/librustc_mir/borrow_check/nll/renumber.rs b/src/librustc_mir/borrow_check/nll/renumber.rs index d77863d598f..15a60badc93 100644 --- a/src/librustc_mir/borrow_check/nll/renumber.rs +++ b/src/librustc_mir/borrow_check/nll/renumber.rs @@ -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, From 40ab41fd1898e44328108295df3f17074a253dcf Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 8 Oct 2018 19:03:24 -0400 Subject: [PATCH 4/6] add pattern type ascriptions for tuple/brace structs/enums --- src/librustc_mir/build/matches/mod.rs | 8 ++++ src/librustc_mir/hair/pattern/mod.rs | 47 +++++++++++++++---- src/librustc_typeck/check/mod.rs | 7 +++ .../pattern_substs_on_brace_enum_variant.rs | 24 ++++++++++ ...attern_substs_on_brace_enum_variant.stderr | 25 ++++++++++ .../pattern_substs_on_brace_struct.rs | 22 +++++++++ .../pattern_substs_on_brace_struct.stderr | 25 ++++++++++ .../pattern_substs_on_tuple_enum_variant.rs | 24 ++++++++++ ...attern_substs_on_tuple_enum_variant.stderr | 25 ++++++++++ .../pattern_substs_on_tuple_struct.rs | 22 +++++++++ .../pattern_substs_on_tuple_struct.stderr | 25 ++++++++++ 11 files changed, 246 insertions(+), 8 deletions(-) create mode 100644 src/test/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.rs create mode 100644 src/test/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.stderr create mode 100644 src/test/ui/nll/user-annotations/pattern_substs_on_brace_struct.rs create mode 100644 src/test/ui/nll/user-annotations/pattern_substs_on_brace_struct.stderr create mode 100644 src/test/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.rs create mode 100644 src/test/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.stderr create mode 100644 src/test/ui/nll/user-annotations/pattern_substs_on_tuple_struct.rs create mode 100644 src/test/ui/nll/user-annotations/pattern_substs_on_tuple_struct.stderr diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index 656c78a46ed..c2a7172d54c 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -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 { diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index b22cc4a1a42..04090e5087f 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -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>) - -> PatternKind<'tcx> - { - match def { + subpatterns: Vec>, + ) -> 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>(&self, folder: &mut F) -> Self { self.super_fold_with(folder) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 529f1e6161b..52ed279b853 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -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); diff --git a/src/test/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.rs b/src/test/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.rs new file mode 100644 index 00000000000..526134b6e4b --- /dev/null +++ b/src/test/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.rs @@ -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() { } diff --git a/src/test/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.stderr b/src/test/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.stderr new file mode 100644 index 00000000000..5dbbf7c5b48 --- /dev/null +++ b/src/test/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.stderr @@ -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`. diff --git a/src/test/ui/nll/user-annotations/pattern_substs_on_brace_struct.rs b/src/test/ui/nll/user-annotations/pattern_substs_on_brace_struct.rs new file mode 100644 index 00000000000..1c92858eb3a --- /dev/null +++ b/src/test/ui/nll/user-annotations/pattern_substs_on_brace_struct.rs @@ -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() { } diff --git a/src/test/ui/nll/user-annotations/pattern_substs_on_brace_struct.stderr b/src/test/ui/nll/user-annotations/pattern_substs_on_brace_struct.stderr new file mode 100644 index 00000000000..0108a185b1f --- /dev/null +++ b/src/test/ui/nll/user-annotations/pattern_substs_on_brace_struct.stderr @@ -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`. diff --git a/src/test/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.rs b/src/test/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.rs new file mode 100644 index 00000000000..d6c364f8e3f --- /dev/null +++ b/src/test/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.rs @@ -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() { } diff --git a/src/test/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.stderr b/src/test/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.stderr new file mode 100644 index 00000000000..b18fdc30ac2 --- /dev/null +++ b/src/test/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.stderr @@ -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`. diff --git a/src/test/ui/nll/user-annotations/pattern_substs_on_tuple_struct.rs b/src/test/ui/nll/user-annotations/pattern_substs_on_tuple_struct.rs new file mode 100644 index 00000000000..626ca908797 --- /dev/null +++ b/src/test/ui/nll/user-annotations/pattern_substs_on_tuple_struct.rs @@ -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() { } diff --git a/src/test/ui/nll/user-annotations/pattern_substs_on_tuple_struct.stderr b/src/test/ui/nll/user-annotations/pattern_substs_on_tuple_struct.stderr new file mode 100644 index 00000000000..b72fda95580 --- /dev/null +++ b/src/test/ui/nll/user-annotations/pattern_substs_on_tuple_struct.stderr @@ -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`. From 16e1aaf09da5d516487118e048bf37e8c44f1b77 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 2 Oct 2018 14:05:23 -0400 Subject: [PATCH 5/6] document `create_substs_for_generic_args` --- src/librustc_typeck/astconv.rs | 43 ++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 28d2ae413de..e4ad02595d1 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -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 `::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>, - 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). From ccba716099c61816734f8daa7459001f6fdea0af Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 2 Oct 2018 14:05:39 -0400 Subject: [PATCH 6/6] add some `debug!` to type checking --- src/librustc_typeck/check/mod.rs | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 52ed279b853..be8b16dd2f5 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3759,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 { @@ -4988,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); @@ -5201,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)