support user-given types in adts

This commit is contained in:
Niko Matsakis 2018-08-09 11:56:53 -04:00
parent 2d1d3fef62
commit 56506cfa25
27 changed files with 686 additions and 40 deletions

View File

@ -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) => {

View File

@ -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<usize>),
Adt(&'tcx AdtDef, usize, &'tcx Substs<'tcx>, Option<CanonicalTy<'tcx>>, Option<usize>),
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)

View File

@ -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) => {

View File

@ -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);
}

View File

@ -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)

View File

@ -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<CanonicalTy<'tcx>> {
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)
}

View File

@ -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 { .. } |

View File

@ -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<CanonicalTy<'tcx>> {
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<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>(
@ -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,
}

View File

@ -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::<T> { ... }`.
user_ty: Option<CanonicalTy<'tcx>>,
fields: Vec<FieldExprRef<'tcx>>,
base: Option<FruInfo<'tcx>>
},

View File

@ -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)

View File

@ -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()

View File

@ -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 {

View File

@ -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])
}

View File

@ -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;

View File

@ -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
}

View File

@ -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 <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.
// Unit test for the "user substitutions" that are annotated on each
// node.
#![feature(nll)]
enum SomeEnum<T> {
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() { }

View File

@ -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`.

View File

@ -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 <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.
// Unit test for the "user substitutions" that are annotated on each
// node.
#![feature(nll)]
struct SomeStruct<T> { 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() { }

View File

@ -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`.

View File

@ -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 <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.
// Unit test for the "user substitutions" that are annotated on each
// node.
#![feature(nll)]
#![allow(warnings)]
use std::cell::Cell;
enum SomeEnum<T> {
SomeVariant(T),
SomeOtherVariant,
}
fn combine<T>(_: 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::<Cell<_>>);
}
fn annot_reference_any_lifetime() {
let c = 66;
combine(SomeEnum::SomeVariant(Cell::new(&c)), SomeEnum::SomeOtherVariant::<Cell<&u32>>);
}
fn annot_reference_static_lifetime() {
let c = 66;
combine(SomeEnum::SomeVariant(Cell::new(&c)), SomeEnum::SomeOtherVariant::<Cell<&'static u32>>); //~ ERROR
}
fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
let c = 66;
combine(SomeEnum::SomeVariant(Cell::new(&c)), SomeEnum::SomeOtherVariant::<Cell<&'a u32>>); //~ ERROR
}
fn annot_reference_named_lifetime_ok<'a>(c: &'a u32) {
combine(SomeEnum::SomeVariant(Cell::new(c)), SomeEnum::SomeOtherVariant::<Cell<&'a u32>>);
}
fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
let _closure = || {
let c = 66;
combine(SomeEnum::SomeVariant(Cell::new(&c)), SomeEnum::SomeOtherVariant::<Cell<&'a u32>>); //~ ERROR
};
}
fn annot_reference_named_lifetime_in_closure_ok<'a>(c: &'a u32) {
let _closure = || {
combine(SomeEnum::SomeVariant(Cell::new(c)), SomeEnum::SomeOtherVariant::<Cell<&'a u32>>);
};
}
fn main() { }

View File

@ -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::<Cell<&'static u32>>); //~ 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::<Cell<&'a u32>>); //~ 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::<Cell<&'a u32>>); //~ 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`.

View File

@ -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 <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.
// Unit test for the "user substitutions" that are annotated on each
// node.
#![feature(nll)]
#![allow(warnings)]
enum SomeEnum<T> {
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() { }

View File

@ -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`.

View File

@ -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 <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.
// 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(&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() { }

View File

@ -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`.

View File

@ -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 <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.
// 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: T }
#[rustc_dump_user_substs]
fn main() {
SomeStruct { t: 22 }; // Nothing given, no annotation.
SomeStruct::<_> { t: 22 }; // Nothing interesting given, no annotation.
SomeStruct::<u32> { t: 22 }; //~ ERROR [u32]
}

View File

@ -0,0 +1,8 @@
error: user substs: Canonical { variables: [], value: [u32] }
--> $DIR/dump-adt-brace-struct.rs:28:5
|
LL | SomeStruct::<u32> { t: 22 }; //~ ERROR [u32]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error