diff --git a/src/librustc/ich/impls_mir.rs b/src/librustc/ich/impls_mir.rs index ad20bab2b87..1c9387d02d5 100644 --- a/src/librustc/ich/impls_mir.rs +++ b/src/librustc/ich/impls_mir.rs @@ -479,10 +479,11 @@ for mir::AggregateKind<'gcx> { mir::AggregateKind::Array(t) => { t.hash_stable(hcx, hasher); } - mir::AggregateKind::Adt(adt_def, idx, substs, active_field) => { + mir::AggregateKind::Adt(adt_def, idx, substs, user_substs, active_field) => { adt_def.hash_stable(hcx, hasher); idx.hash_stable(hcx, hasher); substs.hash_stable(hcx, hasher); + user_substs.hash_stable(hcx, hasher); active_field.hash_stable(hcx, hasher); } mir::AggregateKind::Closure(def_id, ref substs) => { diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index efe2e352138..7f292f6167f 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2009,7 +2009,7 @@ pub enum AggregateKind<'tcx> { /// active field number and is present only for union expressions /// -- e.g. for a union expression `SomeUnion { c: .. }`, the /// active field index would identity the field `c` - Adt(&'tcx AdtDef, usize, &'tcx Substs<'tcx>, Option), + Adt(&'tcx AdtDef, usize, &'tcx Substs<'tcx>, Option>, Option), Closure(DefId, ClosureSubsts<'tcx>), Generator(DefId, GeneratorSubsts<'tcx>, hir::GeneratorMovability), @@ -2135,7 +2135,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { _ => fmt_tuple(fmt, places), }, - AggregateKind::Adt(adt_def, variant, substs, _) => { + AggregateKind::Adt(adt_def, variant, substs, _user_ty, _) => { let variant_def = &adt_def.variants[variant]; ppaux::parameterized(fmt, substs, variant_def.did, &[])?; @@ -2813,8 +2813,14 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> { let kind = box match **kind { AggregateKind::Array(ty) => AggregateKind::Array(ty.fold_with(folder)), AggregateKind::Tuple => AggregateKind::Tuple, - AggregateKind::Adt(def, v, substs, n) => { - AggregateKind::Adt(def, v, substs.fold_with(folder), n) + AggregateKind::Adt(def, v, substs, user_ty, n) => { + AggregateKind::Adt( + def, + v, + substs.fold_with(folder), + user_ty.fold_with(folder), + n, + ) } AggregateKind::Closure(id, substs) => { AggregateKind::Closure(id, substs.fold_with(folder)) @@ -2846,7 +2852,8 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> { (match **kind { AggregateKind::Array(ty) => ty.visit_with(visitor), AggregateKind::Tuple => false, - AggregateKind::Adt(_, _, substs, _) => substs.visit_with(visitor), + AggregateKind::Adt(_, _, substs, user_ty, _) => + substs.visit_with(visitor) || user_ty.visit_with(visitor), AggregateKind::Closure(_, substs) => substs.visit_with(visitor), AggregateKind::Generator(_, substs, _) => substs.visit_with(visitor), }) || fields.visit_with(visitor) diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index ec395478ec6..c928be4f9df 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -216,7 +216,7 @@ impl<'tcx> Rvalue<'tcx> { AggregateKind::Tuple => { tcx.mk_tup(ops.iter().map(|op| op.ty(local_decls, tcx))) } - AggregateKind::Adt(def, _, substs, _) => { + AggregateKind::Adt(def, _, substs, _, _) => { tcx.type_of(def.did).subst(tcx, substs) } AggregateKind::Closure(did, substs) => { diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 1eaecf7a522..c7723fdf191 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -589,6 +589,7 @@ macro_rules! make_mir_visitor { AggregateKind::Adt(_adt_def, _variant_index, ref $($mutability)* substs, + _user_substs, _active_field_index) => { self.visit_substs(substs, location); } diff --git a/src/librustc_codegen_llvm/mir/rvalue.rs b/src/librustc_codegen_llvm/mir/rvalue.rs index 25f32360815..e301e5ae70b 100644 --- a/src/librustc_codegen_llvm/mir/rvalue.rs +++ b/src/librustc_codegen_llvm/mir/rvalue.rs @@ -148,7 +148,7 @@ impl FunctionCx<'a, 'll, 'tcx> { mir::Rvalue::Aggregate(ref kind, ref operands) => { let (dest, active_field_index) = match **kind { - mir::AggregateKind::Adt(adt_def, variant_index, _, active_field_index) => { + mir::AggregateKind::Adt(adt_def, variant_index, _, _, active_field_index) => { dest.codegen_set_discr(&bx, variant_index); if adt_def.is_enum() { (dest.project_downcast(&bx, variant_index), active_field_index) 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 67c7dfdafaa..1393045e75d 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -917,6 +917,20 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { terr ); } + + if let Some(user_ty) = self.rvalue_user_ty(rv) { + if let Err(terr) = self.eq_canonical_type_and_type(user_ty, rv_ty, location.boring()) { + span_mirbug!( + self, + stmt, + "bad user type on rvalue ({:?} = {:?}): {:?}", + user_ty, + rv_ty, + terr + ); + } + } + self.check_rvalue(mir, rv, location); if !self.tcx().features().unsized_locals { let trait_ref = ty::TraitRef { @@ -1391,7 +1405,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { let tcx = self.tcx(); match *ak { - AggregateKind::Adt(def, variant_index, substs, active_field_index) => { + AggregateKind::Adt(def, variant_index, substs, _, active_field_index) => { let variant = &def.variants[variant_index]; let adj_field_index = active_field_index.unwrap_or(field_index); if let Some(field) = variant.fields.get(adj_field_index) { @@ -1557,6 +1571,36 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { } } + /// If this rvalue supports a user-given type annotation, then + /// extract and return it. This represents the final type of the + /// rvalue and will be unified with the inferred type. + fn rvalue_user_ty( + &self, + rvalue: &Rvalue<'tcx>, + ) -> Option> { + match rvalue { + Rvalue::Use(_) | + Rvalue::Repeat(..) | + Rvalue::Ref(..) | + Rvalue::Len(..) | + Rvalue::Cast(..) | + Rvalue::BinaryOp(..) | + Rvalue::CheckedBinaryOp(..) | + Rvalue::NullaryOp(..) | + Rvalue::UnaryOp(..) | + Rvalue::Discriminant(..) => + None, + + Rvalue::Aggregate(aggregate, _) => match **aggregate { + AggregateKind::Adt(_, _, _, user_ty, _) => user_ty, + AggregateKind::Array(_) => None, + AggregateKind::Tuple => None, + AggregateKind::Closure(_, _) => None, + AggregateKind::Generator(_, _, _) => None, + } + } + } + fn check_aggregate_rvalue( &mut self, mir: &Mir<'tcx>, @@ -1750,7 +1794,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { ); let instantiated_predicates = match aggregate_kind { - AggregateKind::Adt(def, _, substs, _) => { + AggregateKind::Adt(def, _, substs, _, _) => { tcx.predicates_of(def.did).instantiate(tcx, substs) } diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index fab4f77a095..ad3862aca35 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -255,7 +255,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { block.and(Rvalue::Aggregate(result, operands)) } ExprKind::Adt { - adt_def, variant_index, substs, fields, base + adt_def, variant_index, substs, user_ty, fields, base } => { // see (*) above let is_union = adt_def.is_union(); let active_field_index = if is_union { Some(fields[0].name.index()) } else { None }; @@ -286,7 +286,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { }; let adt = - box AggregateKind::Adt(adt_def, variant_index, substs, active_field_index); + box AggregateKind::Adt(adt_def, variant_index, substs, user_ty, active_field_index); block.and(Rvalue::Aggregate(adt, fields)) } ExprKind::Assign { .. } | diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 9a771e3d451..7153a388467 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -256,6 +256,16 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, }; if let Some((adt_def, index)) = adt_data { let substs = cx.tables().node_substs(fun.hir_id); + + let user_ty = cx.tables().user_substs(fun.hir_id) + .map(|user_substs| { + 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) + }) + }); + let field_refs = args.iter() .enumerate() .map(|(idx, e)| { @@ -265,12 +275,12 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } }) .collect(); - // FIXME(#47184) -- user given type annot on ADTs ExprKind::Adt { adt_def, substs, variant_index: index, fields: field_refs, + user_ty, base: None, } } else { @@ -424,11 +434,11 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, ty::Adt(adt, substs) => { match adt.adt_kind() { AdtKind::Struct | AdtKind::Union => { - // FIXME(#47184) -- user given type annot on ADTs ExprKind::Adt { adt_def: adt, variant_index: 0, substs, + user_ty: user_annotated_ty_for_adt(cx, expr.hir_id, adt), fields: field_refs(cx, fields), base: base.as_ref().map(|base| { FruInfo { @@ -450,11 +460,11 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, assert!(base.is_none()); let index = adt.variant_index_with_id(variant_id); - // FIXME(#47184) -- user given type annot on ADTs ExprKind::Adt { adt_def: adt, variant_index: index, substs, + user_ty: user_annotated_ty_for_adt(cx, expr.hir_id, adt), fields: field_refs(cx, fields), base: None, } @@ -694,8 +704,7 @@ fn user_annotated_ty_for_def( hir_id: hir::HirId, def: &Def, ) -> Option> { - let user_substs = cx.tables().user_substs(hir_id)?; - Some(match def { + match def { // A reference to something callable -- e.g., a fn, method, or // a tuple-struct or tuple-variant. This has the type of a // `Fn` but with the user-given substitutions. @@ -703,11 +712,11 @@ fn user_annotated_ty_for_def( Def::Method(_) | Def::StructCtor(_, CtorKind::Fn) | Def::VariantCtor(_, CtorKind::Fn) => - user_substs.unchecked_map(|user_substs| { + 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.def_id(), user_substs) - }), + })), Def::Const(_def_id) | Def::AssociatedConst(_def_id) => @@ -720,18 +729,26 @@ 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::TyAdt(adt_def, _) => - 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) - }), + ty::Adt(adt_def, _) => user_annotated_ty_for_adt(cx, hir_id, adt_def), sty => bug!("unexpected sty: {:?}", sty), }, _ => 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> { + 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>( @@ -835,7 +852,6 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, Def::StructCtor(def_id, CtorKind::Const) | Def::VariantCtor(def_id, CtorKind::Const) => { - // FIXME(#47184) -- user given type annot on ADTs match cx.tables().node_id_to_type(expr.hir_id).sty { // A unit struct/variant which is used as a value. // We return a completely different ExprKind here to account for this special case. @@ -844,6 +860,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), fields: vec![], base: None, } diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs index 5539db609c4..d6037adb53b 100644 --- a/src/librustc_mir/hair/mod.rs +++ b/src/librustc_mir/hair/mod.rs @@ -261,6 +261,11 @@ pub enum ExprKind<'tcx> { adt_def: &'tcx AdtDef, variant_index: usize, substs: &'tcx Substs<'tcx>, + + /// Optional user-given substs: for something like `let x = + /// Bar:: { ... }`. + user_ty: Option>, + fields: Vec>, base: Option> }, diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs index f39a5ee3e4e..db556db2417 100644 --- a/src/librustc_mir/interpret/step.rs +++ b/src/librustc_mir/interpret/step.rs @@ -208,7 +208,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { Aggregate(ref kind, ref operands) => { let (dest, active_field_index) = match **kind { - mir::AggregateKind::Adt(adt_def, variant_index, _, active_field_index) => { + mir::AggregateKind::Adt(adt_def, variant_index, _, _, active_field_index) => { self.write_discriminant_value(variant_index, dest)?; if adt_def.is_enum() { (self.place_downcast(dest, variant_index)?, active_field_index) diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index e6b480a27d1..7e7e7cfade6 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -850,7 +850,7 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>, kind: StatementKind::Assign( Place::Local(RETURN_PLACE), Rvalue::Aggregate( - box AggregateKind::Adt(adt_def, variant_no, substs, None), + box AggregateKind::Adt(adt_def, variant_no, substs, None, None), (1..sig.inputs().len()+1).map(|i| { Operand::Move(Place::Local(Local::new(i))) }).collect() diff --git a/src/librustc_mir/transform/deaggregator.rs b/src/librustc_mir/transform/deaggregator.rs index 8b2b9ef7e81..cff098c7b73 100644 --- a/src/librustc_mir/transform/deaggregator.rs +++ b/src/librustc_mir/transform/deaggregator.rs @@ -48,7 +48,7 @@ impl MirPass for Deaggregator { let mut set_discriminant = None; let active_field_index = match *kind { - AggregateKind::Adt(adt_def, variant_index, _, active_field_index) => { + AggregateKind::Adt(adt_def, variant_index, _, _, active_field_index) => { if adt_def.is_enum() { set_discriminant = Some(Statement { kind: StatementKind::SetDiscriminant { diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index a7d6c08ec1f..db588884d8e 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -157,7 +157,7 @@ struct TransformVisitor<'a, 'tcx: 'a> { impl<'a, 'tcx> TransformVisitor<'a, 'tcx> { // Make a GeneratorState rvalue fn make_state(&self, idx: usize, val: Operand<'tcx>) -> Rvalue<'tcx> { - let adt = AggregateKind::Adt(self.state_adt_ref, idx, self.state_substs, None); + let adt = AggregateKind::Adt(self.state_adt_ref, idx, self.state_substs, None, None); Rvalue::Aggregate(box adt, vec![val]) } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index a528c8e9b4f..37f4f22cb02 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1367,7 +1367,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { -> Ty<'tcx> { let tcx = self.tcx(); - debug!("base_def_to_ty(def={:?}, opt_self_ty={:?}, path_segments={:?})", + debug!("def_to_ty(def={:?}, opt_self_ty={:?}, path_segments={:?})", path.def, opt_self_ty, path.segments); let span = path.span; diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 16894478df0..54acdd8c552 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2113,16 +2113,31 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } - pub fn write_user_substs(&self, node_id: hir::HirId, substs: CanonicalSubsts<'tcx>) { + /// Given the substs that we just converted from the HIR, try to + /// canonicalize them and store them as user-given substitutions + /// (i.e., substitutions that must be respected by the NLL check). + /// + /// This should be invoked **before any unifications have + /// 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>) { + if !substs.is_noop() { + let user_substs = self.infcx.canonicalize_response(&substs); + debug!("instantiate_value_path: user_substs = {:?}", user_substs); + self.write_user_substs(hir_id, user_substs); + } + } + + pub fn write_user_substs(&self, hir_id: hir::HirId, substs: CanonicalSubsts<'tcx>) { debug!( "write_user_substs({:?}, {:?}) in fcx {}", - node_id, + hir_id, substs, self.tag(), ); if !substs.is_identity() { - self.tables.borrow_mut().user_substs_mut().insert(node_id, substs); + self.tables.borrow_mut().user_substs_mut().insert(hir_id, substs); } else { debug!("write_user_substs: skipping identity substs"); } @@ -3596,6 +3611,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }; if let Some((variant, did, substs)) = variant { + debug!("check_struct_path: did={:?} substs={:?}", did, substs); + let hir_id = self.tcx.hir.node_to_hir_id(node_id); + self.write_user_substs_from_substs(hir_id, substs); + // Check bounds on type arguments used in the path. let bounds = self.instantiate_bounds(path_span, did, substs); let cause = traits::ObligationCause::new(path_span, self.body_id, @@ -5138,11 +5157,7 @@ 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); - if !substs.is_noop() { - let user_substs = self.infcx.canonicalize_response(&substs); - debug!("instantiate_value_path: user_substs = {:?}", user_substs); - self.write_user_substs(hir_id, user_substs); - } + self.write_user_substs_from_substs(hir_id, substs); ty_substituted } diff --git a/src/test/ui/nll/user-annotations/adt-brace-enums.rs b/src/test/ui/nll/user-annotations/adt-brace-enums.rs new file mode 100644 index 00000000000..4465be414bc --- /dev/null +++ b/src/test/ui/nll/user-annotations/adt-brace-enums.rs @@ -0,0 +1,62 @@ +// Copyright 2017 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. + +// Unit test for the "user substitutions" that are annotated on each +// node. + +#![feature(nll)] + +enum SomeEnum { + SomeVariant { t: T } +} + +fn no_annot() { + let c = 66; + SomeEnum::SomeVariant { t: &c }; +} + +fn annot_underscore() { + let c = 66; + SomeEnum::SomeVariant::<_> { t: &c }; +} + +fn annot_reference_any_lifetime() { + let c = 66; + SomeEnum::SomeVariant::<&u32> { t: &c }; +} + +fn annot_reference_static_lifetime() { + let c = 66; + SomeEnum::SomeVariant::<&'static u32> { t: &c }; //~ ERROR +} + +fn annot_reference_named_lifetime<'a>(_d: &'a u32) { + let c = 66; + SomeEnum::SomeVariant::<&'a u32> { t: &c }; //~ ERROR +} + +fn annot_reference_named_lifetime_ok<'a>(c: &'a u32) { + SomeEnum::SomeVariant::<&'a u32> { t: c }; +} + +fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) { + let _closure = || { + let c = 66; + SomeEnum::SomeVariant::<&'a u32> { t: &c }; //~ ERROR + }; +} + +fn annot_reference_named_lifetime_in_closure_ok<'a>(c: &'a u32) { + let _closure = || { + SomeEnum::SomeVariant::<&'a u32> { t: c }; + }; +} + +fn main() { } diff --git a/src/test/ui/nll/user-annotations/adt-brace-enums.stderr b/src/test/ui/nll/user-annotations/adt-brace-enums.stderr new file mode 100644 index 00000000000..842bb622bc3 --- /dev/null +++ b/src/test/ui/nll/user-annotations/adt-brace-enums.stderr @@ -0,0 +1,41 @@ +error[E0597]: `c` does not live long enough + --> $DIR/adt-brace-enums.rs:37:48 + | +LL | SomeEnum::SomeVariant::<&'static u32> { t: &c }; //~ ERROR + | ^^ borrowed value does not live long enough +LL | } + | - `c` dropped here while still borrowed + | + = note: borrowed value must be valid for the static lifetime... + +error[E0597]: `c` does not live long enough + --> $DIR/adt-brace-enums.rs:42:43 + | +LL | SomeEnum::SomeVariant::<&'a u32> { t: &c }; //~ ERROR + | ^^ borrowed value does not live long enough +LL | } + | - `c` dropped here while still borrowed + | +note: borrowed value must be valid for the lifetime 'a as defined on the function body at 40:35... + --> $DIR/adt-brace-enums.rs:40:35 + | +LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) { + | ^^ + +error[E0597]: `c` does not live long enough + --> $DIR/adt-brace-enums.rs:52:47 + | +LL | SomeEnum::SomeVariant::<&'a u32> { t: &c }; //~ ERROR + | ^^ borrowed value does not live long enough +LL | }; + | - `c` dropped here while still borrowed + | +note: borrowed value must be valid for the lifetime 'a as defined on the function body at 49:46... + --> $DIR/adt-brace-enums.rs:49:46 + | +LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) { + | ^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/nll/user-annotations/adt-brace-structs.rs b/src/test/ui/nll/user-annotations/adt-brace-structs.rs new file mode 100644 index 00000000000..c479e050564 --- /dev/null +++ b/src/test/ui/nll/user-annotations/adt-brace-structs.rs @@ -0,0 +1,60 @@ +// Copyright 2017 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. + +// Unit test for the "user substitutions" that are annotated on each +// node. + +#![feature(nll)] + +struct SomeStruct { t: T } + +fn no_annot() { + let c = 66; + SomeStruct { t: &c }; +} + +fn annot_underscore() { + let c = 66; + SomeStruct::<_> { t: &c }; +} + +fn annot_reference_any_lifetime() { + let c = 66; + SomeStruct::<&u32> { t: &c }; +} + +fn annot_reference_static_lifetime() { + let c = 66; + SomeStruct::<&'static u32> { t: &c }; //~ ERROR +} + +fn annot_reference_named_lifetime<'a>(_d: &'a u32) { + let c = 66; + SomeStruct::<&'a u32> { t: &c }; //~ ERROR +} + +fn annot_reference_named_lifetime_ok<'a>(c: &'a u32) { + SomeStruct::<&'a u32> { t: c }; +} + +fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) { + let _closure = || { + let c = 66; + SomeStruct::<&'a u32> { t: &c }; //~ ERROR + }; +} + +fn annot_reference_named_lifetime_in_closure_ok<'a>(c: &'a u32) { + let _closure = || { + SomeStruct::<&'a u32> { t: c }; + }; +} + +fn main() { } diff --git a/src/test/ui/nll/user-annotations/adt-brace-structs.stderr b/src/test/ui/nll/user-annotations/adt-brace-structs.stderr new file mode 100644 index 00000000000..7ba76212dc5 --- /dev/null +++ b/src/test/ui/nll/user-annotations/adt-brace-structs.stderr @@ -0,0 +1,41 @@ +error[E0597]: `c` does not live long enough + --> $DIR/adt-brace-structs.rs:35:37 + | +LL | SomeStruct::<&'static u32> { t: &c }; //~ ERROR + | ^^ borrowed value does not live long enough +LL | } + | - `c` dropped here while still borrowed + | + = note: borrowed value must be valid for the static lifetime... + +error[E0597]: `c` does not live long enough + --> $DIR/adt-brace-structs.rs:40:32 + | +LL | SomeStruct::<&'a u32> { t: &c }; //~ ERROR + | ^^ borrowed value does not live long enough +LL | } + | - `c` dropped here while still borrowed + | +note: borrowed value must be valid for the lifetime 'a as defined on the function body at 38:35... + --> $DIR/adt-brace-structs.rs:38:35 + | +LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) { + | ^^ + +error[E0597]: `c` does not live long enough + --> $DIR/adt-brace-structs.rs:50:36 + | +LL | SomeStruct::<&'a u32> { t: &c }; //~ ERROR + | ^^ borrowed value does not live long enough +LL | }; + | - `c` dropped here while still borrowed + | +note: borrowed value must be valid for the lifetime 'a as defined on the function body at 47:46... + --> $DIR/adt-brace-structs.rs:47:46 + | +LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) { + | ^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/nll/user-annotations/adt-nullary-enums.rs b/src/test/ui/nll/user-annotations/adt-nullary-enums.rs new file mode 100644 index 00000000000..d4ffba10cb6 --- /dev/null +++ b/src/test/ui/nll/user-annotations/adt-nullary-enums.rs @@ -0,0 +1,68 @@ +// Copyright 2017 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. + +// Unit test for the "user substitutions" that are annotated on each +// node. + +#![feature(nll)] +#![allow(warnings)] + +use std::cell::Cell; + +enum SomeEnum { + SomeVariant(T), + SomeOtherVariant, +} + +fn combine(_: T, _: T) { } + +fn no_annot() { + let c = 66; + combine(SomeEnum::SomeVariant(Cell::new(&c)), SomeEnum::SomeOtherVariant); +} + +fn annot_underscore() { + let c = 66; + combine(SomeEnum::SomeVariant(Cell::new(&c)), SomeEnum::SomeOtherVariant::>); +} + +fn annot_reference_any_lifetime() { + let c = 66; + combine(SomeEnum::SomeVariant(Cell::new(&c)), SomeEnum::SomeOtherVariant::>); +} + +fn annot_reference_static_lifetime() { + let c = 66; + combine(SomeEnum::SomeVariant(Cell::new(&c)), SomeEnum::SomeOtherVariant::>); //~ ERROR +} + +fn annot_reference_named_lifetime<'a>(_d: &'a u32) { + let c = 66; + combine(SomeEnum::SomeVariant(Cell::new(&c)), SomeEnum::SomeOtherVariant::>); //~ ERROR +} + +fn annot_reference_named_lifetime_ok<'a>(c: &'a u32) { + combine(SomeEnum::SomeVariant(Cell::new(c)), SomeEnum::SomeOtherVariant::>); +} + +fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) { + let _closure = || { + let c = 66; + combine(SomeEnum::SomeVariant(Cell::new(&c)), SomeEnum::SomeOtherVariant::>); //~ ERROR + }; +} + +fn annot_reference_named_lifetime_in_closure_ok<'a>(c: &'a u32) { + let _closure = || { + combine(SomeEnum::SomeVariant(Cell::new(c)), SomeEnum::SomeOtherVariant::>); + }; +} + +fn main() { } diff --git a/src/test/ui/nll/user-annotations/adt-nullary-enums.stderr b/src/test/ui/nll/user-annotations/adt-nullary-enums.stderr new file mode 100644 index 00000000000..b120d6c4e5d --- /dev/null +++ b/src/test/ui/nll/user-annotations/adt-nullary-enums.stderr @@ -0,0 +1,41 @@ +error[E0597]: `c` does not live long enough + --> $DIR/adt-nullary-enums.rs:43:45 + | +LL | combine(SomeEnum::SomeVariant(Cell::new(&c)), SomeEnum::SomeOtherVariant::>); //~ ERROR + | ^^ borrowed value does not live long enough +LL | } + | - `c` dropped here while still borrowed + | + = note: borrowed value must be valid for the static lifetime... + +error[E0597]: `c` does not live long enough + --> $DIR/adt-nullary-enums.rs:48:45 + | +LL | combine(SomeEnum::SomeVariant(Cell::new(&c)), SomeEnum::SomeOtherVariant::>); //~ ERROR + | ^^ borrowed value does not live long enough +LL | } + | - `c` dropped here while still borrowed + | +note: borrowed value must be valid for the lifetime 'a as defined on the function body at 46:35... + --> $DIR/adt-nullary-enums.rs:46:35 + | +LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) { + | ^^ + +error[E0597]: `c` does not live long enough + --> $DIR/adt-nullary-enums.rs:58:49 + | +LL | combine(SomeEnum::SomeVariant(Cell::new(&c)), SomeEnum::SomeOtherVariant::>); //~ ERROR + | ^^ borrowed value does not live long enough +LL | }; + | - `c` dropped here while still borrowed + | +note: borrowed value must be valid for the lifetime 'a as defined on the function body at 55:46... + --> $DIR/adt-nullary-enums.rs:55:46 + | +LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) { + | ^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/nll/user-annotations/adt-tuple-enums.rs b/src/test/ui/nll/user-annotations/adt-tuple-enums.rs new file mode 100644 index 00000000000..ae75a54f649 --- /dev/null +++ b/src/test/ui/nll/user-annotations/adt-tuple-enums.rs @@ -0,0 +1,64 @@ +// Copyright 2017 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. + +// Unit test for the "user substitutions" that are annotated on each +// node. + +#![feature(nll)] +#![allow(warnings)] + +enum SomeEnum { + SomeVariant(T), + SomeOtherVariant, +} + +fn no_annot() { + let c = 66; + SomeEnum::SomeVariant(&c); +} + +fn annot_underscore() { + let c = 66; + SomeEnum::SomeVariant::<_>(&c); +} + +fn annot_reference_any_lifetime() { + let c = 66; + SomeEnum::SomeVariant::<&u32>(&c); +} + +fn annot_reference_static_lifetime() { + let c = 66; + SomeEnum::SomeVariant::<&'static u32>(&c); //~ ERROR +} + +fn annot_reference_named_lifetime<'a>(_d: &'a u32) { + let c = 66; + SomeEnum::SomeVariant::<&'a u32>(&c); //~ ERROR +} + +fn annot_reference_named_lifetime_ok<'a>(c: &'a u32) { + SomeEnum::SomeVariant::<&'a u32>(c); +} + +fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) { + let _closure = || { + let c = 66; + SomeEnum::SomeVariant::<&'a u32>(&c); //~ ERROR + }; +} + +fn annot_reference_named_lifetime_in_closure_ok<'a>(c: &'a u32) { + let _closure = || { + SomeEnum::SomeVariant::<&'a u32>(c); + }; +} + +fn main() { } diff --git a/src/test/ui/nll/user-annotations/adt-tuple-enums.stderr b/src/test/ui/nll/user-annotations/adt-tuple-enums.stderr new file mode 100644 index 00000000000..18d1cc7e087 --- /dev/null +++ b/src/test/ui/nll/user-annotations/adt-tuple-enums.stderr @@ -0,0 +1,41 @@ +error[E0597]: `c` does not live long enough + --> $DIR/adt-tuple-enums.rs:39:43 + | +LL | SomeEnum::SomeVariant::<&'static u32>(&c); //~ ERROR + | ^^ borrowed value does not live long enough +LL | } + | - `c` dropped here while still borrowed + | + = note: borrowed value must be valid for the static lifetime... + +error[E0597]: `c` does not live long enough + --> $DIR/adt-tuple-enums.rs:44:38 + | +LL | SomeEnum::SomeVariant::<&'a u32>(&c); //~ ERROR + | ^^ borrowed value does not live long enough +LL | } + | - `c` dropped here while still borrowed + | +note: borrowed value must be valid for the lifetime 'a as defined on the function body at 42:35... + --> $DIR/adt-tuple-enums.rs:42:35 + | +LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) { + | ^^ + +error[E0597]: `c` does not live long enough + --> $DIR/adt-tuple-enums.rs:54:42 + | +LL | SomeEnum::SomeVariant::<&'a u32>(&c); //~ ERROR + | ^^ borrowed value does not live long enough +LL | }; + | - `c` dropped here while still borrowed + | +note: borrowed value must be valid for the lifetime 'a as defined on the function body at 51:46... + --> $DIR/adt-tuple-enums.rs:51:46 + | +LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) { + | ^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/nll/user-annotations/adt-tuple-struct.rs b/src/test/ui/nll/user-annotations/adt-tuple-struct.rs new file mode 100644 index 00000000000..401a71c1fe5 --- /dev/null +++ b/src/test/ui/nll/user-annotations/adt-tuple-struct.rs @@ -0,0 +1,60 @@ +// Copyright 2017 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. + +// Unit test for the "user substitutions" that are annotated on each +// node. + +#![feature(nll)] + +struct SomeStruct(T); + +fn no_annot() { + let c = 66; + SomeStruct(&c); +} + +fn annot_underscore() { + let c = 66; + SomeStruct::<_>(&c); +} + +fn annot_reference_any_lifetime() { + let c = 66; + SomeStruct::<&u32>(&c); +} + +fn annot_reference_static_lifetime() { + let c = 66; + SomeStruct::<&'static u32>(&c); //~ ERROR +} + +fn annot_reference_named_lifetime<'a>(_d: &'a u32) { + let c = 66; + SomeStruct::<&'a u32>(&c); //~ ERROR +} + +fn annot_reference_named_lifetime_ok<'a>(c: &'a u32) { + SomeStruct::<&'a u32>(c); +} + +fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) { + let _closure = || { + let c = 66; + SomeStruct::<&'a u32>(&c); //~ ERROR + }; +} + +fn annot_reference_named_lifetime_in_closure_ok<'a>(c: &'a u32) { + let _closure = || { + SomeStruct::<&'a u32>(c); + }; +} + +fn main() { } diff --git a/src/test/ui/nll/user-annotations/adt-tuple-struct.stderr b/src/test/ui/nll/user-annotations/adt-tuple-struct.stderr new file mode 100644 index 00000000000..397016e52d0 --- /dev/null +++ b/src/test/ui/nll/user-annotations/adt-tuple-struct.stderr @@ -0,0 +1,41 @@ +error[E0597]: `c` does not live long enough + --> $DIR/adt-tuple-struct.rs:35:32 + | +LL | SomeStruct::<&'static u32>(&c); //~ ERROR + | ^^ borrowed value does not live long enough +LL | } + | - `c` dropped here while still borrowed + | + = note: borrowed value must be valid for the static lifetime... + +error[E0597]: `c` does not live long enough + --> $DIR/adt-tuple-struct.rs:40:27 + | +LL | SomeStruct::<&'a u32>(&c); //~ ERROR + | ^^ borrowed value does not live long enough +LL | } + | - `c` dropped here while still borrowed + | +note: borrowed value must be valid for the lifetime 'a as defined on the function body at 38:35... + --> $DIR/adt-tuple-struct.rs:38:35 + | +LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) { + | ^^ + +error[E0597]: `c` does not live long enough + --> $DIR/adt-tuple-struct.rs:50:31 + | +LL | SomeStruct::<&'a u32>(&c); //~ ERROR + | ^^ borrowed value does not live long enough +LL | }; + | - `c` dropped here while still borrowed + | +note: borrowed value must be valid for the lifetime 'a as defined on the function body at 47:46... + --> $DIR/adt-tuple-struct.rs:47:46 + | +LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) { + | ^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/nll/user-annotations/dump-adt-brace-struct.rs b/src/test/ui/nll/user-annotations/dump-adt-brace-struct.rs new file mode 100644 index 00000000000..970fbf98af4 --- /dev/null +++ b/src/test/ui/nll/user-annotations/dump-adt-brace-struct.rs @@ -0,0 +1,29 @@ +// Copyright 2017 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. + +// Unit test for the "user substitutions" that are annotated on each +// node. + +// compile-flags:-Zverbose + +#![allow(warnings)] +#![feature(nll)] +#![feature(rustc_attrs)] + +struct SomeStruct { t: T } + +#[rustc_dump_user_substs] +fn main() { + SomeStruct { t: 22 }; // Nothing given, no annotation. + + SomeStruct::<_> { t: 22 }; // Nothing interesting given, no annotation. + + SomeStruct:: { t: 22 }; //~ ERROR [u32] +} diff --git a/src/test/ui/nll/user-annotations/dump-adt-brace-struct.stderr b/src/test/ui/nll/user-annotations/dump-adt-brace-struct.stderr new file mode 100644 index 00000000000..2b0e5039d8d --- /dev/null +++ b/src/test/ui/nll/user-annotations/dump-adt-brace-struct.stderr @@ -0,0 +1,8 @@ +error: user substs: Canonical { variables: [], value: [u32] } + --> $DIR/dump-adt-brace-struct.rs:28:5 + | +LL | SomeStruct:: { t: 22 }; //~ ERROR [u32] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error +