diff --git a/src/librustc/middle/infer/error_reporting.rs b/src/librustc/middle/infer/error_reporting.rs index c015c2307f6..e58ff53b00c 100644 --- a/src/librustc/middle/infer/error_reporting.rs +++ b/src/librustc/middle/infer/error_reporting.rs @@ -66,7 +66,8 @@ use super::region_inference::RegionResolutionError; use super::region_inference::ConcreteFailure; use super::region_inference::SubSupConflict; use super::region_inference::SupSupConflict; -use super::region_inference::ParamBoundFailure; +use super::region_inference::GenericBoundFailure; +use super::region_inference::GenericKind; use super::region_inference::ProcessedErrors; use super::region_inference::SameRegions; @@ -120,11 +121,11 @@ pub trait ErrorReporting<'tcx> { sub: Region, sup: Region); - fn report_param_bound_failure(&self, - origin: SubregionOrigin<'tcx>, - param_ty: ty::ParamTy, - sub: Region, - sups: Vec); + fn report_generic_bound_failure(&self, + origin: SubregionOrigin<'tcx>, + kind: GenericKind<'tcx>, + sub: Region, + sups: Vec); fn report_sub_sup_conflict(&self, var_origin: RegionVariableOrigin, @@ -175,8 +176,8 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { self.report_concrete_failure(origin, sub, sup); } - ParamBoundFailure(origin, param_ty, sub, sups) => { - self.report_param_bound_failure(origin, param_ty, sub, sups); + GenericBoundFailure(kind, param_ty, sub, sups) => { + self.report_generic_bound_failure(kind, param_ty, sub, sups); } SubSupConflict(var_origin, @@ -421,30 +422,35 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { found.user_string(self.tcx))) } - fn report_param_bound_failure(&self, - origin: SubregionOrigin<'tcx>, - param_ty: ty::ParamTy, - sub: Region, - _sups: Vec) { - + fn report_generic_bound_failure(&self, + origin: SubregionOrigin<'tcx>, + bound_kind: GenericKind<'tcx>, + sub: Region, + _sups: Vec) + { // FIXME: it would be better to report the first error message // with the span of the parameter itself, rather than the span // where the error was detected. But that span is not readily // accessible. + let labeled_user_string = match bound_kind { + GenericKind::Param(ref p) => + format!("the parameter type `{}`", p.user_string(self.tcx)), + GenericKind::Projection(ref p) => + format!("the associated type `{}`", p.user_string(self.tcx)), + }; + match sub { ty::ReFree(ty::FreeRegion {bound_region: ty::BrNamed(..), ..}) => { // Does the required lifetime have a nice name we can print? self.tcx.sess.span_err( origin.span(), - format!( - "the parameter type `{}` may not live long enough", - param_ty.user_string(self.tcx))[]); + format!("{} may not live long enough", labeled_user_string)[]); self.tcx.sess.span_help( origin.span(), format!( "consider adding an explicit lifetime bound `{}: {}`...", - param_ty.user_string(self.tcx), + bound_kind.user_string(self.tcx), sub.user_string(self.tcx))[]); } @@ -452,14 +458,12 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { // Does the required lifetime have a nice name we can print? self.tcx.sess.span_err( origin.span(), - format!( - "the parameter type `{}` may not live long enough", - param_ty.user_string(self.tcx))[]); + format!("{} may not live long enough", labeled_user_string)[]); self.tcx.sess.span_help( origin.span(), format!( "consider adding an explicit lifetime bound `{}: 'static`...", - param_ty.user_string(self.tcx))[]); + bound_kind.user_string(self.tcx))[]); } _ => { @@ -467,17 +471,16 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { self.tcx.sess.span_err( origin.span(), format!( - "the parameter type `{}` may not live long enough", - param_ty.user_string(self.tcx))[]); + "{} may not live long enough", + labeled_user_string)[]); self.tcx.sess.span_help( origin.span(), format!( - "consider adding an explicit lifetime bound to `{}`", - param_ty.user_string(self.tcx))[]); + "consider adding an explicit lifetime bound for `{}`", + bound_kind.user_string(self.tcx))[]); note_and_explain_region( self.tcx, - format!("the parameter type `{}` must be valid for ", - param_ty.user_string(self.tcx))[], + format!("{} must be valid for ", labeled_user_string)[], sub, "..."); } diff --git a/src/librustc/middle/infer/mod.rs b/src/librustc/middle/infer/mod.rs index e1401898f7a..c2db81d3114 100644 --- a/src/librustc/middle/infer/mod.rs +++ b/src/librustc/middle/infer/mod.rs @@ -20,6 +20,7 @@ pub use self::ValuePairs::*; pub use self::fixup_err::*; pub use middle::ty::IntVarValue; pub use self::freshen::TypeFreshener; +pub use self::region_inference::GenericKind; use middle::subst; use middle::subst::Substs; @@ -382,19 +383,6 @@ pub fn mk_subr<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, cx.region_vars.commit(snapshot); } -pub fn verify_param_bound<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, - origin: SubregionOrigin<'tcx>, - param_ty: ty::ParamTy, - a: ty::Region, - bs: Vec) { - debug!("verify_param_bound({}, {} <: {})", - param_ty.repr(cx.tcx), - a.repr(cx.tcx), - bs.repr(cx.tcx)); - - cx.region_vars.verify_param_bound(origin, param_ty, a, bs); -} - pub fn mk_eqty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, a_is_expected: bool, origin: TypeOrigin, @@ -1070,6 +1058,20 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { value, |br, _| self.next_region_var(LateBoundRegion(span, br, lbrct))) } + + /// See `verify_generic_bound` method in `region_inference` + pub fn verify_generic_bound(&self, + origin: SubregionOrigin<'tcx>, + kind: GenericKind<'tcx>, + a: ty::Region, + bs: Vec) { + debug!("verify_generic_bound({}, {} <: {})", + kind.repr(self.tcx), + a.repr(self.tcx), + bs.repr(self.tcx)); + + self.region_vars.verify_generic_bound(origin, kind, a, bs); + } } impl<'tcx> TypeTrace<'tcx> { diff --git a/src/librustc/middle/infer/region_inference/mod.rs b/src/librustc/middle/infer/region_inference/mod.rs index f0ee63c08e8..23e96dafa61 100644 --- a/src/librustc/middle/infer/region_inference/mod.rs +++ b/src/librustc/middle/infer/region_inference/mod.rs @@ -22,7 +22,7 @@ use super::cres; use super::{RegionVariableOrigin, SubregionOrigin, TypeTrace, MiscVariable}; use middle::region; -use middle::ty; +use middle::ty::{mod, Ty}; use middle::ty::{BoundRegion, FreeRegion, Region, RegionVid}; use middle::ty::{ReEmpty, ReStatic, ReInfer, ReFree, ReEarlyBound}; use middle::ty::{ReLateBound, ReScope, ReVar, ReSkolemized, BrFresh}; @@ -30,7 +30,7 @@ use middle::graph; use middle::graph::{Direction, NodeIndex}; use util::common::indenter; use util::nodemap::{FnvHashMap, FnvHashSet}; -use util::ppaux::Repr; +use util::ppaux::{Repr, UserString}; use std::cell::{Cell, RefCell}; use std::cmp::Ordering::{self, Less, Greater, Equal}; @@ -61,12 +61,18 @@ pub enum Verify<'tcx> { // `b` are inference variables. VerifyRegSubReg(SubregionOrigin<'tcx>, Region, Region), - // VerifyParamBound(T, _, R, RS): The parameter type `T` must - // outlive the region `R`. `T` is known to outlive `RS`. Therefore - // verify that `R <= RS[i]` for some `i`. Inference variables may - // be involved (but this verification step doesn't influence - // inference). - VerifyParamBound(ty::ParamTy, SubregionOrigin<'tcx>, Region, Vec), + // VerifyGenericBound(T, _, R, RS): The parameter type `T` (or + // associated type) must outlive the region `R`. `T` is known to + // outlive `RS`. Therefore verify that `R <= RS[i]` for some + // `i`. Inference variables may be involved (but this verification + // step doesn't influence inference). + VerifyGenericBound(GenericKind<'tcx>, SubregionOrigin<'tcx>, Region, Vec), +} + +#[deriving(Clone, Show, PartialEq, Eq)] +pub enum GenericKind<'tcx> { + Param(ty::ParamTy), + Projection(ty::ProjectionTy<'tcx>), } #[derive(Copy, PartialEq, Eq, Hash)] @@ -98,12 +104,12 @@ pub enum RegionResolutionError<'tcx> { /// `o` requires that `a <= b`, but this does not hold ConcreteFailure(SubregionOrigin<'tcx>, Region, Region), - /// `ParamBoundFailure(p, s, a, bs) + /// `GenericBoundFailure(p, s, a, bs) /// - /// The parameter type `p` must be known to outlive the lifetime + /// The parameter/assocated-type `p` must be known to outlive the lifetime /// `a`, but it is only known to outlive `bs` (and none of the /// regions in `bs` outlive `a`). - ParamBoundFailure(SubregionOrigin<'tcx>, ty::ParamTy, Region, Vec), + GenericBoundFailure(SubregionOrigin<'tcx>, GenericKind<'tcx>, Region, Vec), /// `SubSupConflict(v, sub_origin, sub_r, sup_origin, sup_r)`: /// @@ -489,12 +495,13 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { } } - pub fn verify_param_bound(&self, - origin: SubregionOrigin<'tcx>, - param_ty: ty::ParamTy, - sub: Region, - sups: Vec) { - self.add_verify(VerifyParamBound(param_ty, origin, sub, sups)); + /// See `Verify::VerifyGenericBound` + pub fn verify_generic_bound(&self, + origin: SubregionOrigin<'tcx>, + kind: GenericKind<'tcx>, + sub: Region, + sups: Vec) { + self.add_verify(VerifyGenericBound(kind, origin, sub, sups)); } pub fn lub_regions(&self, @@ -660,7 +667,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { &mut result_set, r, a, b); } - VerifyParamBound(_, _, a, ref bs) => { + VerifyGenericBound(_, _, a, ref bs) => { for &b in bs.iter() { consider_adding_bidirectional_edges( &mut result_set, r, @@ -1211,7 +1218,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { errors.push(ConcreteFailure((*origin).clone(), sub, sup)); } - VerifyParamBound(ref param_ty, ref origin, sub, ref sups) => { + VerifyGenericBound(ref kind, ref origin, sub, ref sups) => { let sub = normalize(values, sub); if sups.iter() .map(|&sup| normalize(values, sup)) @@ -1223,8 +1230,8 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { let sups = sups.iter().map(|&sup| normalize(values, sup)) .collect(); errors.push( - ParamBoundFailure( - (*origin).clone(), *param_ty, sub, sups)); + GenericBoundFailure( + (*origin).clone(), kind.clone(), sub, sups)); } } } @@ -1584,8 +1591,8 @@ impl<'tcx> Repr<'tcx> for Verify<'tcx> { VerifyRegSubReg(_, ref a, ref b) => { format!("VerifyRegSubReg({}, {})", a.repr(tcx), b.repr(tcx)) } - VerifyParamBound(_, ref p, ref a, ref bs) => { - format!("VerifyParamBound({}, {}, {})", + VerifyGenericBound(_, ref p, ref a, ref bs) => { + format!("VerifyGenericBound({}, {}, {})", p.repr(tcx), a.repr(tcx), bs.repr(tcx)) } } @@ -1624,3 +1631,32 @@ impl<'tcx> Repr<'tcx> for RegionAndOrigin<'tcx> { self.origin.repr(tcx)) } } + +impl<'tcx> Repr<'tcx> for GenericKind<'tcx> { + fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String { + match *self { + GenericKind::Param(ref p) => p.repr(tcx), + GenericKind::Projection(ref p) => p.repr(tcx), + } + } +} + +impl<'tcx> UserString<'tcx> for GenericKind<'tcx> { + fn user_string(&self, tcx: &ty::ctxt<'tcx>) -> String { + match *self { + GenericKind::Param(ref p) => p.user_string(tcx), + GenericKind::Projection(ref p) => p.user_string(tcx), + } + } +} + +impl<'tcx> GenericKind<'tcx> { + pub fn to_ty(&self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx> { + match *self { + GenericKind::Param(ref p) => + p.to_ty(tcx), + GenericKind::Projection(ref p) => + ty::mk_projection(tcx, p.trait_ref.clone(), p.item_name), + } + } +} diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index b5ddb528c2f..99216930dfe 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -92,7 +92,7 @@ use middle::region::CodeExtent; use middle::traits; use middle::ty::{ReScope}; use middle::ty::{self, Ty, MethodCall}; -use middle::infer; +use middle::infer::{mod, GenericKind}; use middle::pat_util; use util::ppaux::{ty_to_string, Repr}; @@ -164,7 +164,7 @@ pub fn regionck_ensure_component_tys_wf<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, pub struct Rcx<'a, 'tcx: 'a> { fcx: &'a FnCtxt<'a, 'tcx>, - region_param_pairs: Vec<(ty::Region, ty::ParamTy)>, + region_bound_pairs: Vec<(ty::Region, GenericKind<'tcx>)>, // id of innermost fn or loop repeating_scope: ast::NodeId, @@ -205,7 +205,7 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> { Rcx { fcx: fcx, repeating_scope: initial_repeating_scope, subject: subject, - region_param_pairs: Vec::new() } + region_bound_pairs: Vec::new() } } pub fn tcx(&self) -> &'a ty::ctxt<'tcx> { @@ -286,12 +286,12 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> { } }; - let len = self.region_param_pairs.len(); + let len = self.region_bound_pairs.len(); self.relate_free_regions(fn_sig[], body.id); link_fn_args(self, CodeExtent::from_node_id(body.id), fn_decl.inputs[]); self.visit_block(body); self.visit_region_obligations(body.id); - self.region_param_pairs.truncate(len); + self.region_bound_pairs.truncate(len); } fn visit_region_obligations(&mut self, node_id: ast::NodeId) @@ -357,11 +357,11 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> { // relationship that arises here, but // presently we do not.) } - regionmanip::RegionSubParamConstraint(_, r_a, p_b) => { - debug!("RegionSubParamConstraint: {} <= {}", - r_a.repr(tcx), p_b.repr(tcx)); + regionmanip::RegionSubGenericConstraint(_, r_a, ref generic_b) => { + debug!("RegionSubGenericConstraint: {} <= {}", + r_a.repr(tcx), generic_b.repr(tcx)); - self.region_param_pairs.push((r_a, p_b)); + self.region_bound_pairs.push((r_a, generic_b.clone())); } } } @@ -1477,31 +1477,31 @@ fn type_must_outlive<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>, let o1 = infer::ReferenceOutlivesReferent(ty, origin.span()); rcx.fcx.mk_subr(o1, r_a, r_b); } - regionmanip::RegionSubParamConstraint(None, r_a, param_b) => { - param_must_outlive(rcx, origin.clone(), r_a, param_b); + regionmanip::RegionSubGenericConstraint(None, r_a, ref generic_b) => { + generic_must_outlive(rcx, origin.clone(), r_a, generic_b); } - regionmanip::RegionSubParamConstraint(Some(ty), r_a, param_b) => { + regionmanip::RegionSubGenericConstraint(Some(ty), r_a, ref generic_b) => { let o1 = infer::ReferenceOutlivesReferent(ty, origin.span()); - param_must_outlive(rcx, o1, r_a, param_b); + generic_must_outlive(rcx, o1, r_a, generic_b); } } } } -fn param_must_outlive<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>, - origin: infer::SubregionOrigin<'tcx>, - region: ty::Region, - param_ty: ty::ParamTy) { +fn generic_must_outlive<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>, + origin: infer::SubregionOrigin<'tcx>, + region: ty::Region, + generic: &GenericKind<'tcx>) { let param_env = &rcx.fcx.inh.param_env; - debug!("param_must_outlive(region={}, param_ty={})", + debug!("param_must_outlive(region={}, generic={})", region.repr(rcx.tcx()), - param_ty.repr(rcx.tcx())); + generic.repr(rcx.tcx())); // To start, collect bounds from user: let mut param_bounds = ty::required_region_bounds(rcx.tcx(), - param_ty.to_ty(rcx.tcx()), + generic.to_ty(rcx.tcx()), param_env.caller_bounds.predicates.as_slice().to_vec()); // Add in the default bound of fn body that applies to all in @@ -1517,22 +1517,21 @@ fn param_must_outlive<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>, // fn foo<'a, A>(x: &'a A) { x.bar() } // // The problem is that the type of `x` is `&'a A`. To be - // well-formed, then, A must be lower-bounded by `'a`, but we + // well-formed, then, A must be lower-generic by `'a`, but we // don't know that this holds from first principles. - for &(ref r, ref p) in rcx.region_param_pairs.iter() { - debug!("param_ty={} p={}", - param_ty.repr(rcx.tcx()), + for &(ref r, ref p) in rcx.region_bound_pairs.iter() { + debug!("generic={} p={}", + generic.repr(rcx.tcx()), p.repr(rcx.tcx())); - if param_ty == *p { + if generic == p { param_bounds.push(*r); } } - // Inform region inference that this parameter type must be - // properly bounded. - infer::verify_param_bound(rcx.fcx.infcx(), - origin, - param_ty, - region, - param_bounds); + // Inform region inference that this generic must be properly + // bounded. + rcx.fcx.infcx().verify_generic_bound(origin, + generic.clone(), + region, + param_bounds); } diff --git a/src/librustc_typeck/check/regionmanip.rs b/src/librustc_typeck/check/regionmanip.rs index 66cf077d4c2..eb03e7bec07 100644 --- a/src/librustc_typeck/check/regionmanip.rs +++ b/src/librustc_typeck/check/regionmanip.rs @@ -12,6 +12,7 @@ pub use self::WfConstraint::*; +use middle::infer::GenericKind; use middle::subst::{ParamSpace, Subst, Substs}; use middle::ty::{self, Ty}; use middle::ty_fold::{TypeFolder}; @@ -24,7 +25,7 @@ use util::ppaux::Repr; pub enum WfConstraint<'tcx> { RegionSubRegionConstraint(Option>, ty::Region, ty::Region), - RegionSubParamConstraint(Option>, ty::Region, ty::ParamTy), + RegionSubGenericConstraint(Option>, ty::Region, GenericKind<'tcx>), } struct Wf<'a, 'tcx: 'a> { @@ -125,8 +126,7 @@ impl<'a, 'tcx> Wf<'a, 'tcx> { ty::ty_projection(ref data) => { // `>::Name` - // FIXME(#20303) -- gain ability to require that ty_projection : in-scope region, - // like a type parameter + self.push_projection_constraint_from_top(data); // this seems like a minimal requirement: let trait_def = ty::lookup_trait_def(self.tcx, data.trait_ref.def_id); @@ -215,12 +215,21 @@ impl<'a, 'tcx> Wf<'a, 'tcx> { self.push_param_constraint(region, opt_ty, param_ty); } + /// Pushes a constraint that `projection_ty` must outlive the top region on the stack. + fn push_projection_constraint_from_top(&mut self, + projection_ty: &ty::ProjectionTy<'tcx>) { + let &(region, opt_ty) = self.stack.last().unwrap(); + self.out.push(RegionSubGenericConstraint( + opt_ty, region, GenericKind::Projection(projection_ty.clone()))); + } + /// Pushes a constraint that `region <= param_ty`, due to `opt_ty` fn push_param_constraint(&mut self, region: ty::Region, opt_ty: Option>, param_ty: ty::ParamTy) { - self.out.push(RegionSubParamConstraint(opt_ty, region, param_ty)); + self.out.push(RegionSubGenericConstraint( + opt_ty, region, GenericKind::Param(param_ty))); } fn accumulate_from_adt(&mut self, @@ -393,16 +402,16 @@ impl<'a, 'tcx> Wf<'a, 'tcx> { } impl<'tcx> Repr<'tcx> for WfConstraint<'tcx> { - fn repr(&self, tcx: &ty::ctxt) -> String { + fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String { match *self { - RegionSubRegionConstraint(_, r_a, r_b) => { + RegionSubRegionConstraint(_, ref r_a, ref r_b) => { format!("RegionSubRegionConstraint({}, {})", r_a.repr(tcx), r_b.repr(tcx)) } - RegionSubParamConstraint(_, r, p) => { - format!("RegionSubParamConstraint({}, {})", + RegionSubGenericConstraint(_, ref r, ref p) => { + format!("RegionSubGenericConstraint({}, {})", r.repr(tcx), p.repr(tcx)) } diff --git a/src/test/compile-fail/regions-close-associated-type-into-object.rs b/src/test/compile-fail/regions-close-associated-type-into-object.rs new file mode 100644 index 00000000000..84664078d56 --- /dev/null +++ b/src/test/compile-fail/regions-close-associated-type-into-object.rs @@ -0,0 +1,83 @@ +// Copyright 2014 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. + +#![feature(associated_types)] + +trait X {} + +trait Iter { + type Item: X; + + fn into_item(self) -> Self::Item; + fn as_item(&self) -> &Self::Item; +} + +fn bad1(v: T) -> Box +{ + let item = v.into_item(); + box item //~ ERROR associated type `::Item` may not live long enough +} + +fn bad2(v: T) -> Box + where Box : X +{ + let item = box v.into_item(); + box item //~ ERROR associated type `::Item` may not live long enough +} + +fn bad3<'a, T: Iter>(v: T) -> Box +{ + let item = v.into_item(); + box item //~ ERROR associated type `::Item` may not live long enough +} + +fn bad4<'a, T: Iter>(v: T) -> Box + where Box : X +{ + let item = box v.into_item(); + box item //~ ERROR associated type `::Item` may not live long enough +} + +fn ok1<'a, T: Iter>(v: T) -> Box + where T::Item : 'a +{ + let item = v.into_item(); + box item // OK, T::Item : 'a is declared +} + +fn ok2<'a, T: Iter>(v: &T, w: &'a T::Item) -> Box + where T::Item : Clone +{ + let item = Clone::clone(w); + box item // OK, T::Item : 'a is implied +} + +fn ok3<'a, T: Iter>(v: &'a T) -> Box + where T::Item : Clone + 'a +{ + let item = Clone::clone(v.as_item()); + box item // OK, T::Item : 'a was declared +} + +fn meh1<'a, T: Iter>(v: &'a T) -> Box + where T::Item : Clone +{ + // This case is kind of interesting. It's the same as `ok3` but + // without the explicit declaration. In principle, it seems like + // we ought to be able to infer that `T::Item : 'a` because we + // invoked `v.as_self()` which yielded a value of type `&'a + // T::Item`. But we're not that smart at present. + + let item = Clone::clone(v.as_item()); + box item //~ ERROR associated type `::Item` may not live +} + +fn main() {} + diff --git a/src/test/compile-fail/regions-close-param-into-object.rs b/src/test/compile-fail/regions-close-param-into-object.rs new file mode 100644 index 00000000000..3e91d090c31 --- /dev/null +++ b/src/test/compile-fail/regions-close-param-into-object.rs @@ -0,0 +1,39 @@ +// Copyright 2014 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. + + +trait X {} + +fn p1(v: T) -> Box + where T : X +{ + box v //~ ERROR parameter type `T` may not live long enough +} + +fn p2(v: Box) -> Box + where Box : X +{ + box v //~ ERROR parameter type `T` may not live long enough +} + +fn p3<'a,T>(v: T) -> Box + where T : X +{ + box v //~ ERROR parameter type `T` may not live long enough +} + +fn p4<'a,T>(v: Box) -> Box + where Box : X +{ + box v //~ ERROR parameter type `T` may not live long enough +} + +fn main() {} +