提交 81bce529 编写于 作者: B bors

Auto merge of #22230 - nikomatsakis:object-lifetime-defaults-2, r=pnkfelix

Implement rules described in rust-lang/rfcs#599.

Fixes https://github.com/rust-lang/rust/issues/22211.

~~Based atop PR https://github.com/rust-lang/rust/pull/22182, so the first few commits (up to and including "Pacify the mercilous nrc") have already been reviewed.~~
......@@ -824,6 +824,7 @@ fn parse_type_param_def_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F)
assert_eq!(next(st), '|');
let bounds = parse_bounds_(st, conv);
let default = parse_opt(st, |st| parse_ty_(st, conv));
let object_lifetime_default = parse_object_lifetime_default(st, conv);
ty::TypeParameterDef {
name: name,
......@@ -831,7 +832,24 @@ fn parse_type_param_def_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F)
space: space,
index: index,
bounds: bounds,
default: default
default: default,
object_lifetime_default: object_lifetime_default,
}
}
fn parse_object_lifetime_default<'a,'tcx, F>(st: &mut PState<'a,'tcx>,
conv: &mut F)
-> Option<ty::ObjectLifetimeDefault>
where F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
{
match next(st) {
'n' => None,
'a' => Some(ty::ObjectLifetimeDefault::Ambiguous),
's' => {
let region = parse_region_(st, conv);
Some(ty::ObjectLifetimeDefault::Specific(region))
}
_ => panic!("parse_object_lifetime_default: bad input")
}
}
......
......@@ -414,6 +414,21 @@ pub fn enc_type_param_def<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tc
v.space.to_uint(), v.index);
enc_bounds(w, cx, &v.bounds);
enc_opt(w, v.default, |w, t| enc_ty(w, cx, t));
enc_object_lifetime_default(w, cx, v.object_lifetime_default);
}
fn enc_object_lifetime_default<'a, 'tcx>(w: &mut SeekableMemWriter,
cx: &ctxt<'a, 'tcx>,
default: Option<ty::ObjectLifetimeDefault>)
{
match default {
None => mywrite!(w, "n"),
Some(ty::ObjectLifetimeDefault::Ambiguous) => mywrite!(w, "a"),
Some(ty::ObjectLifetimeDefault::Specific(r)) => {
mywrite!(w, "s");
enc_region(w, cx, r);
}
}
}
pub fn enc_predicate<'a, 'tcx>(w: &mut SeekableMemWriter,
......
......@@ -619,7 +619,7 @@ fn report_concrete_failure(&self,
infer::RelateRegionParamBound(span) => {
self.tcx.sess.span_err(
span,
"declared lifetime bound not satisfied");
"lifetime bound not satisfied");
note_and_explain_region(
self.tcx,
"lifetime parameter instantiated with ",
......@@ -1628,7 +1628,7 @@ fn note_region_origin(&self, origin: &SubregionOrigin<'tcx>) {
self.tcx.sess.span_note(
span,
&format!("...so that the type `{}` \
will meet the declared lifetime bounds",
will meet its required lifetime bounds",
self.ty_to_string(t))[]);
}
infer::RelateDefaultParamBound(span, t) => {
......
......@@ -1762,6 +1762,21 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
}
}
/// Default region to use for the bound of objects that are
/// supplied as the value for this type parameter. This is derived
/// from `T:'a` annotations appearing in the type definition. If
/// this is `None`, then the default is inherited from the
/// surrounding context. See RFC #599 for details.
#[derive(Copy, Clone, Debug)]
pub enum ObjectLifetimeDefault {
/// Require an explicit annotation. Occurs when multiple
/// `T:'a` constraints are found.
Ambiguous,
/// Use the given region as the default.
Specific(Region),
}
#[derive(Clone, Debug)]
pub struct TypeParameterDef<'tcx> {
pub name: ast::Name,
......@@ -1770,6 +1785,7 @@ pub struct TypeParameterDef<'tcx> {
pub index: u32,
pub bounds: ParamBounds<'tcx>,
pub default: Option<Ty<'tcx>>,
pub object_lifetime_default: Option<ObjectLifetimeDefault>,
}
#[derive(RustcEncodable, RustcDecodable, Clone, Debug)]
......@@ -5884,42 +5900,13 @@ pub fn each_bound_trait_and_supertraits<'tcx, F>(tcx: &ctxt<'tcx>,
return true;
}
pub fn object_region_bounds<'tcx>(
tcx: &ctxt<'tcx>,
opt_principal: Option<&PolyTraitRef<'tcx>>, // None for closures
others: BuiltinBounds)
-> Vec<ty::Region>
{
// Since we don't actually *know* the self type for an object,
// this "open(err)" serves as a kind of dummy standin -- basically
// a skolemized type.
let open_ty = ty::mk_infer(tcx, FreshTy(0));
let opt_trait_ref = opt_principal.map_or(Vec::new(), |principal| {
// Note that we preserve the overall binding levels here.
assert!(!open_ty.has_escaping_regions());
let substs = tcx.mk_substs(principal.0.substs.with_self_ty(open_ty));
vec!(ty::Binder(Rc::new(ty::TraitRef::new(principal.0.def_id, substs))))
});
let param_bounds = ty::ParamBounds {
region_bounds: Vec::new(),
builtin_bounds: others,
trait_bounds: opt_trait_ref,
projection_bounds: Vec::new(), // not relevant to computing region bounds
};
let predicates = ty::predicates(tcx, open_ty, &param_bounds);
ty::required_region_bounds(tcx, open_ty, predicates)
}
/// Given a set of predicates that apply to an object type, returns
/// the region bounds that the (erased) `Self` type must
/// outlive. Precisely *because* the `Self` type is erased, the
/// parameter `erased_self_ty` must be supplied to indicate what type
/// has been used to represent `Self` in the predicates
/// themselves. This should really be a unique type; `FreshTy(0)` is a
/// popular choice (see `object_region_bounds` above).
/// popular choice.
///
/// Requires that trait definitions have been processed so that we can
/// elaborate predicates and walk supertraits.
......@@ -7390,3 +7377,12 @@ fn repr(&self, tcx: &ctxt<'tcx>) -> String {
self.caller_bounds.repr(tcx))
}
}
impl<'tcx> Repr<'tcx> for ObjectLifetimeDefault {
fn repr(&self, tcx: &ctxt<'tcx>) -> String {
match *self {
ObjectLifetimeDefault::Ambiguous => format!("Ambiguous"),
ObjectLifetimeDefault::Specific(ref r) => r.repr(tcx),
}
}
}
......@@ -379,6 +379,19 @@ fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::TypeParameterDef
index: self.index,
bounds: self.bounds.fold_with(folder),
default: self.default.fold_with(folder),
object_lifetime_default: self.object_lifetime_default.fold_with(folder),
}
}
}
impl<'tcx> TypeFoldable<'tcx> for ty::ObjectLifetimeDefault {
fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ObjectLifetimeDefault {
match *self {
ty::ObjectLifetimeDefault::Ambiguous =>
ty::ObjectLifetimeDefault::Ambiguous,
ty::ObjectLifetimeDefault::Specific(r) =>
ty::ObjectLifetimeDefault::Specific(r.fold_with(folder)),
}
}
}
......
此差异已折叠。
......@@ -1890,7 +1890,14 @@ pub fn lookup_tup_field_ty(&self,
}
impl<'a, 'tcx> RegionScope for FnCtxt<'a, 'tcx> {
fn default_region_bound(&self, span: Span) -> Option<ty::Region> {
fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
// RFC #599 specifies that object lifetime defaults take
// precedence over other defaults. But within a fn body we
// don't have a *default* region, rather we use inference to
// find the *correct* region, which is strictly more general
// (and anyway, within a fn body the right region may not even
// be something the user can write explicitly, since it might
// be some expression).
Some(self.infcx().next_region_var(infer::MiscVariable(span)))
}
......
......@@ -154,7 +154,7 @@ pub fn regionck_ensure_component_tys_wf<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
// empty region is a subregion of all others, this can't fail
// unless the type does not meet the well-formedness
// requirements.
type_must_outlive(&mut rcx, infer::RelateRegionParamBound(span),
type_must_outlive(&mut rcx, infer::RelateParamBound(span, component_ty),
component_ty, ty::ReEmpty);
}
}
......@@ -305,7 +305,7 @@ fn visit_region_obligations(&mut self, node_id: ast::NodeId)
debug!("visit_region_obligations: r_o={}",
r_o.repr(self.tcx()));
let sup_type = self.resolve_type(r_o.sup_type);
let origin = infer::RelateRegionParamBound(r_o.cause.span);
let origin = infer::RelateParamBound(r_o.cause.span, sup_type);
type_must_outlive(self, origin, sup_type, r_o.sub_region);
}
......
......@@ -12,6 +12,7 @@
pub use self::WfConstraint::*;
use astconv::object_region_bounds;
use middle::infer::GenericKind;
use middle::subst::{ParamSpace, Subst, Substs};
use middle::ty::{self, Ty};
......@@ -95,7 +96,7 @@ fn accumulate_from_ty(&mut self, ty: Ty<'tcx>) {
ty::ty_trait(ref t) => {
let required_region_bounds =
ty::object_region_bounds(self.tcx, Some(&t.principal), t.bounds.builtin_bounds);
object_region_bounds(self.tcx, &t.principal, t.bounds.builtin_bounds);
self.accumulate_from_object_ty(ty, t.bounds.region_bound, required_region_bounds)
}
......
......@@ -86,6 +86,7 @@ trait hierarchy is only necessary for shorthands like `T::X` or
*/
use astconv::{self, AstConv, ty_of_arg, ast_ty_to_ty, ast_region_to_region};
use middle::def;
use middle::lang_items::SizedTraitLangItem;
use middle::region;
use middle::resolve_lifetime;
......@@ -1199,8 +1200,23 @@ fn convert_typed_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
predicates.clone());
assert!(prev_predicates.is_none());
return (scheme, predicates);
// Debugging aid.
if ty::has_attr(tcx, local_def(it.id), "rustc_object_lifetime_default") {
let object_lifetime_default_reprs: String =
scheme.generics.types.iter()
.map(|t| match t.object_lifetime_default {
Some(ty::ObjectLifetimeDefault::Specific(r)) =>
r.user_string(tcx),
d =>
d.repr(ccx.tcx()),
})
.collect::<Vec<String>>()
.connect(",");
tcx.sess.span_err(it.span, &object_lifetime_default_reprs);
}
return (scheme, predicates);
}
fn type_scheme_of_foreign_item<'a, 'tcx>(
......@@ -1269,6 +1285,7 @@ fn ty_generics_for_type_or_impl<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
subst::TypeSpace,
&generics.lifetimes[],
&generics.ty_params[],
&generics.where_clause,
ty::Generics::empty())
}
......@@ -1298,6 +1315,7 @@ fn ty_generics_for_trait<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
subst::TypeSpace,
&ast_generics.lifetimes[],
&ast_generics.ty_params[],
&ast_generics.where_clause,
ty::Generics::empty());
// Add in the self type parameter.
......@@ -1321,7 +1339,8 @@ fn ty_generics_for_trait<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
trait_bounds: vec!(ty::Binder(self_trait_ref.clone())),
projection_bounds: vec!(),
},
default: None
default: None,
object_lifetime_default: None,
};
ccx.tcx.ty_param_defs.borrow_mut().insert(param_id, def.clone());
......@@ -1341,6 +1360,7 @@ fn ty_generics_for_fn_or_method<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
subst::FnSpace,
&early_lifetimes[],
&generics.ty_params[],
&generics.where_clause,
base_generics)
}
......@@ -1487,6 +1507,7 @@ fn ty_generics<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
space: subst::ParamSpace,
lifetime_defs: &[ast::LifetimeDef],
types: &[ast::TyParam],
where_clause: &ast::WhereClause,
base_generics: ty::Generics<'tcx>)
-> ty::Generics<'tcx>
{
......@@ -1511,7 +1532,7 @@ fn ty_generics<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
// Now create the real type parameters.
for (i, param) in types.iter().enumerate() {
let def = get_or_create_type_parameter_def(ccx, space, param, i as u32);
let def = get_or_create_type_parameter_def(ccx, space, param, i as u32, where_clause);
debug!("ty_generics: def for type param: {:?}, {:?}", def, space);
result.types.push(space, def);
}
......@@ -1522,7 +1543,8 @@ fn ty_generics<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
space: subst::ParamSpace,
param: &ast::TyParam,
index: u32)
index: u32,
where_clause: &ast::WhereClause)
-> ty::TypeParameterDef<'tcx>
{
let tcx = ccx.tcx;
......@@ -1558,13 +1580,17 @@ fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
}
};
let object_lifetime_default =
compute_object_lifetime_default(ccx, space, index, &param.bounds, where_clause);
let def = ty::TypeParameterDef {
space: space,
index: index,
name: param.ident.name,
def_id: local_def(param.id),
bounds: bounds,
default: default
default: default,
object_lifetime_default: object_lifetime_default,
};
tcx.ty_param_defs.borrow_mut().insert(param.id, def.clone());
......@@ -1572,6 +1598,99 @@ fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
def
}
/// Scan the bounds and where-clauses on a parameter to extract bounds
/// of the form `T:'a` so as to determine the `ObjectLifetimeDefault`.
/// This runs as part of computing the minimal type scheme, so we
/// intentionally avoid just asking astconv to convert all the where
/// clauses into a `ty::Predicate`. This is because that could induce
/// artificial cycles.
fn compute_object_lifetime_default<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
space: subst::ParamSpace,
index: u32,
param_bounds: &[ast::TyParamBound],
where_clause: &ast::WhereClause)
-> Option<ty::ObjectLifetimeDefault>
{
let inline_bounds = from_bounds(ccx, param_bounds);
let where_bounds = from_predicates(ccx, space, index, &where_clause.predicates);
let all_bounds: HashSet<_> = inline_bounds.into_iter()
.chain(where_bounds.into_iter())
.collect();
return if all_bounds.len() > 1 {
Some(ty::ObjectLifetimeDefault::Ambiguous)
} else {
all_bounds.into_iter()
.next()
.map(ty::ObjectLifetimeDefault::Specific)
};
fn from_bounds<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
bounds: &[ast::TyParamBound])
-> Vec<ty::Region>
{
bounds.iter()
.filter_map(|bound| {
match *bound {
ast::TraitTyParamBound(..) =>
None,
ast::RegionTyParamBound(ref lifetime) =>
Some(astconv::ast_region_to_region(ccx.tcx(), lifetime)),
}
})
.collect()
}
fn from_predicates<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
space: subst::ParamSpace,
index: u32,
predicates: &[ast::WherePredicate])
-> Vec<ty::Region>
{
predicates.iter()
.flat_map(|predicate| {
match *predicate {
ast::WherePredicate::BoundPredicate(ref data) => {
if data.bound_lifetimes.len() == 0 &&
is_param(ccx, &data.bounded_ty, space, index)
{
from_bounds(ccx, &data.bounds).into_iter()
} else {
Vec::new().into_iter()
}
}
ast::WherePredicate::RegionPredicate(..) |
ast::WherePredicate::EqPredicate(..) => {
Vec::new().into_iter()
}
}
})
.collect()
}
fn is_param(ccx: &CollectCtxt,
ast_ty: &ast::Ty,
space: subst::ParamSpace,
index: u32)
-> bool
{
match ast_ty.node {
ast::TyPath(_, id) => {
match ccx.tcx.def_map.borrow()[id] {
def::DefTyParam(s, i, _, _) => {
space == s && index == i
}
_ => {
false
}
}
}
_ => {
false
}
}
}
}
enum SizedByDefault { Yes, No }
/// Translate the AST's notion of ty param bounds (which are an enum consisting of a newtyped Ty or
......
......@@ -32,7 +32,10 @@ fn anon_regions(&self,
count: uint)
-> Result<Vec<ty::Region>, Option<Vec<(String, uint)>>>;
fn default_region_bound(&self, span: Span) -> Option<ty::Region>;
/// If an object omits any explicit lifetime bound, and none can
/// be derived from the object traits, what should we use? If
/// `None` is returned, an explicit annotation is required.
fn object_lifetime_default(&self, span: Span) -> Option<ty::Region>;
}
// A scope in which all regions must be explicitly named. This is used
......@@ -41,8 +44,8 @@ fn anon_regions(&self,
pub struct ExplicitRscope;
impl RegionScope for ExplicitRscope {
fn default_region_bound(&self, _span: Span) -> Option<ty::Region> {
None
fn object_lifetime_default(&self, _span: Span) -> Option<ty::Region> {
Some(ty::ReStatic)
}
fn anon_regions(&self,
......@@ -63,8 +66,8 @@ pub fn new(v: Vec<(String, uint)>) -> UnelidableRscope {
}
impl RegionScope for UnelidableRscope {
fn default_region_bound(&self, _span: Span) -> Option<ty::Region> {
None
fn object_lifetime_default(&self, _span: Span) -> Option<ty::Region> {
Some(ty::ReStatic)
}
fn anon_regions(&self,
......@@ -76,22 +79,26 @@ fn anon_regions(&self,
}
}
// A scope in which any omitted region defaults to `default`. This is
// used after the `->` in function signatures, but also for backwards
// compatibility with object types. The latter use may go away.
pub struct SpecificRscope {
default: ty::Region
// A scope in which omitted anonymous region defaults to
// `default`. This is used after the `->` in function signatures. The
// latter use may go away. Note that object-lifetime defaults work a
// bit differently, as specified in RFC #599.
pub struct ElidableRscope {
default: ty::Region,
}
impl SpecificRscope {
pub fn new(r: ty::Region) -> SpecificRscope {
SpecificRscope { default: r }
impl ElidableRscope {
pub fn new(r: ty::Region) -> ElidableRscope {
ElidableRscope { default: r }
}
}
impl RegionScope for SpecificRscope {
fn default_region_bound(&self, _span: Span) -> Option<ty::Region> {
Some(self.default)
impl RegionScope for ElidableRscope {
fn object_lifetime_default(&self, _span: Span) -> Option<ty::Region> {
// Per RFC #599, object-lifetimes default to 'static unless
// overridden by context, and this takes precedence over
// lifetime elision.
Some(ty::ReStatic)
}
fn anon_regions(&self,
......@@ -124,9 +131,11 @@ fn next_region(&self) -> ty::Region {
}
impl RegionScope for BindingRscope {
fn default_region_bound(&self, _span: Span) -> Option<ty::Region>
{
Some(self.next_region())
fn object_lifetime_default(&self, _span: Span) -> Option<ty::Region> {
// Per RFC #599, object-lifetimes default to 'static unless
// overridden by context, and this takes precedence over the
// binding defaults.
Some(ty::ReStatic)
}
fn anon_regions(&self,
......@@ -138,6 +147,42 @@ fn anon_regions(&self,
}
}
/// A scope which overrides the default object lifetime but has no other effect.
pub struct ObjectLifetimeDefaultRscope<'r> {
base_scope: &'r (RegionScope+'r),
default: Option<ty::ObjectLifetimeDefault>,
}
impl<'r> ObjectLifetimeDefaultRscope<'r> {
pub fn new(base_scope: &'r (RegionScope+'r),
default: Option<ty::ObjectLifetimeDefault>)
-> ObjectLifetimeDefaultRscope<'r>
{
ObjectLifetimeDefaultRscope {
base_scope: base_scope,
default: default,
}
}
}
impl<'r> RegionScope for ObjectLifetimeDefaultRscope<'r> {
fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
match self.default {
None => self.base_scope.object_lifetime_default(span),
Some(ty::ObjectLifetimeDefault::Ambiguous) => None,
Some(ty::ObjectLifetimeDefault::Specific(r)) => Some(r),
}
}
fn anon_regions(&self,
span: Span,
count: uint)
-> Result<Vec<ty::Region>, Option<Vec<(String, uint)>>>
{
self.base_scope.anon_regions(span, count)
}
}
/// A scope which simply shifts the Debruijn index of other scopes
/// to account for binding levels.
pub struct ShiftedRscope<'r> {
......@@ -151,9 +196,8 @@ pub fn new(base_scope: &'r (RegionScope+'r)) -> ShiftedRscope<'r> {
}
impl<'r> RegionScope for ShiftedRscope<'r> {
fn default_region_bound(&self, span: Span) -> Option<ty::Region>
{
self.base_scope.default_region_bound(span)
fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
self.base_scope.object_lifetime_default(span)
.map(|r| ty_fold::shift_region(r, 1))
}
......
......@@ -35,18 +35,18 @@ fn expand(&self,
sp: Span,
meta_item: &ast::MetaItem,
item: &ast::Item,
push: Box<FnMut(P<ast::Item>)>);
push: &mut FnMut(P<ast::Item>));
}
impl<F> ItemDecorator for F
where F : Fn(&mut ExtCtxt, Span, &ast::MetaItem, &ast::Item, Box<FnMut(P<ast::Item>)>)
where F : Fn(&mut ExtCtxt, Span, &ast::MetaItem, &ast::Item, &mut FnMut(P<ast::Item>))
{
fn expand(&self,
ecx: &mut ExtCtxt,
sp: Span,
meta_item: &ast::MetaItem,
item: &ast::Item,
push: Box<FnMut(P<ast::Item>)>) {
push: &mut FnMut(P<ast::Item>)) {
(*self)(ecx, sp, meta_item, item, push)
}
}
......
......@@ -72,7 +72,7 @@ pub fn expand_deprecated_deriving(cx: &mut ExtCtxt,
span: Span,
_: &MetaItem,
_: &Item,
_: Box<FnMut(P<Item>)>) {
_: &mut FnMut(P<Item>)) {
cx.span_err(span, "`deriving` has been renamed to `derive`");
}
......@@ -80,7 +80,7 @@ pub fn expand_meta_derive(cx: &mut ExtCtxt,
_span: Span,
mitem: &MetaItem,
item: &Item,
mut push: Box<FnMut(P<Item>)>) {
push: &mut FnMut(P<Item>)) {
match mitem.node {
MetaNameValue(_, ref l) => {
cx.span_err(l.span, "unexpected value in `derive`");
......
......@@ -363,7 +363,7 @@ fn expand_mac_invoc<T, F, G>(mac: ast::Mac, span: codemap::Span,
mark_thunk: G,
fld: &mut MacroExpander)
-> Option<T> where
F: FnOnce(Box<MacResult>) -> Option<T>,
F: for<'a> FnOnce(Box<MacResult+'a>) -> Option<T>,
G: FnOnce(T, Mrk) -> T,
{
match mac.node {
......@@ -1102,9 +1102,10 @@ fn expand_annotatable(a: Annotatable,
// but that double-mut-borrows fld
let mut items: SmallVector<P<ast::Item>> = SmallVector::zero();
dec.expand(fld.cx, attr.span, &*attr.node.value, &**it,
box |item| items.push(item));
decorator_items.extend(items.into_iter()
.flat_map(|item| expand_item(item, fld).into_iter()));
&mut |item| items.push(item));
decorator_items.extend(
items.into_iter()
.flat_map(|item| expand_item(item, fld).into_iter()));
fld.cx.bt_pop();
}
......
......@@ -14,6 +14,6 @@
trait Foo : Send { }
impl <'a> Foo for &'a mut () { }
//~^ ERROR declared lifetime bound not satisfied
//~^ ERROR the type `&'a mut ()` does not fulfill the required lifetime
fn main() { }
......@@ -12,7 +12,7 @@
use std::vec;
pub struct Container<'a> {
reader: &'a mut Reader //~ ERROR explicit lifetime bound required
reader: &'a mut Reader
}
impl<'a> Container<'a> {
......@@ -33,5 +33,5 @@ pub fn for_stdin<'a>() -> Container<'a> {
fn main() {
let mut c = for_stdin();
let mut v = Vec::new();
c.read_to(v);
c.read_to(v); //~ ERROR mismatched types
}
......@@ -9,12 +9,12 @@
// except according to those terms.
fn f() { }
struct S(Box<FnMut()>); //~ ERROR explicit lifetime bound required
pub static C: S = S(f);
struct S(Box<FnMut()>);
pub static C: S = S(f); //~ ERROR mismatched types
fn g() { }
type T = Box<FnMut()>; //~ ERROR explicit lifetime bound required
pub static D: T = g;
type T = Box<FnMut()>;
pub static D: T = g; //~ ERROR mismatched types
fn main() {}
......@@ -36,7 +36,7 @@ fn g<T>(val: T) {
fn foo<'a>() {
let t: S<&'a isize> = S;
let a = &t as &Gettable<&'a isize>;
//~^ ERROR declared lifetime bound not satisfied
//~^ ERROR the type `&'a isize` does not fulfill the required lifetime
}
fn foo2<'a>() {
......
......@@ -22,7 +22,7 @@ fn test51<'a>() {
}
fn test52<'a>() {
assert_send::<&'a (Dummy+Send)>();
//~^ ERROR declared lifetime bound not satisfied
//~^ ERROR does not fulfill the required lifetime
}
// ...unless they are properly bounded
......
......@@ -19,7 +19,7 @@ fn assert_send<T:Send>() { }
// but not if they own a bad thing
fn test40<'a>(_: &'a isize) {
assert_send::<Box<&'a isize>>(); //~ ERROR declared lifetime bound not satisfied
assert_send::<Box<&'a isize>>(); //~ ERROR does not fulfill the required lifetime
}
fn main() { }
......@@ -22,13 +22,13 @@ fn assert_send<T:Send>() { }
// otherwise lifetime pointers are not ok
fn test20<'a>(_: &'a isize) {
assert_send::<&'a isize>(); //~ ERROR declared lifetime bound not satisfied
assert_send::<&'a isize>(); //~ ERROR does not fulfill the required lifetime
}
fn test21<'a>(_: &'a isize) {
assert_send::<&'a str>(); //~ ERROR declared lifetime bound not satisfied
assert_send::<&'a str>(); //~ ERROR does not fulfill the required lifetime
}
fn test22<'a>(_: &'a isize) {
assert_send::<&'a [isize]>(); //~ ERROR declared lifetime bound not satisfied
assert_send::<&'a [isize]>(); //~ ERROR does not fulfill the required lifetime
}
fn main() { }
// Copyright 2015 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.
// Test that if a struct declares multiple region bounds for a given
// type parameter, an explicit lifetime bound is required on object
// lifetimes within.
#![allow(dead_code)]
trait Test {
fn foo(&self) { }
}
struct Ref0<T:?Sized> {
r: *mut T
}
struct Ref1<'a,T:'a+?Sized> {
r: &'a T
}
struct Ref2<'a,'b:'a,T:'a+'b+?Sized> {
r: &'a &'b T
}
fn a<'a,'b>(t: Ref2<'a,'b,Test>) {
//~^ ERROR lifetime bound for this object type cannot be deduced from context
}
fn b(t: Ref2<Test>) {
//~^ ERROR lifetime bound for this object type cannot be deduced from context
}
fn c(t: Ref2<&Test>) {
// In this case, the &'a overrides.
}
fn d(t: Ref2<Ref1<Test>>) {
// In this case, the lifetime parameter from the Ref1 overrides.
}
fn e(t: Ref2<Ref0<Test>>) {
//~^ ERROR lifetime bound for this object type cannot be deduced from context
//
// In this case, Ref2 is ambiguous, and Ref0 inherits the
// ambiguity.
}
fn f(t: &Ref2<Test>) {
//~^ ERROR lifetime bound for this object type cannot be deduced from context
}
fn main() {
}
// Copyright 2015 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.
// Test various cases where the old rules under lifetime elision
// yield slightly different results than the new rules.
#![allow(dead_code)]
trait SomeTrait {
fn dummy(&self) { }
}
struct SomeStruct<'a> {
r: Box<SomeTrait+'a>
}
fn deref<T>(ss: &T) -> T {
// produces the type of a deref without worrying about whether a
// move out would actually be legal
loop { }
}
fn load0<'a>(ss: &'a Box<SomeTrait>) -> Box<SomeTrait> {
// Under old rules, the fully elaborated types of input/output were:
//
// for<'a,'b> fn(&'a Box<SomeTrait+'b>) -> Box<SomeTrait+'a>
//
// Under new rules the result is:
//
// for<'a> fn(&'a Box<SomeTrait+'a>) -> Box<SomeTrait+'static>
//
// Therefore, we get a type error attempting to return `deref(ss)`
// since `SomeTrait+'a <: SomeTrait+'static` does not hold.
deref(ss)
//~^ ERROR cannot infer
}
fn load1(ss: &SomeTrait) -> &SomeTrait {
// Under old rules, the fully elaborated types of input/output were:
//
// for<'a,'b> fn(&'a (SomeTrait+'b)) -> &'a (SomeTrait+'a)
//
// Under new rules the result is:
//
// for<'a> fn(&'a (SomeTrait+'a)) -> &'a (SomeTrait+'a)
//
// In both cases, returning `ss` is legal.
ss
}
fn load2<'a>(ss: &'a SomeTrait) -> &SomeTrait {
// Same as `load1` but with an explicit name thrown in for fun.
ss
}
fn load3<'a,'b>(ss: &'a SomeTrait) -> &'b SomeTrait {
// Under old rules, the fully elaborated types of input/output were:
//
// for<'a,'b,'c>fn(&'a (SomeTrait+'c)) -> &'b (SomeTrait+'a)
//
// Based on the input/output types, the compiler could infer that
// 'c : 'a
// 'b : 'a
// must hold, and therefore it permitted `&'a (Sometrait+'c)` to be
// coerced to `&'b (SomeTrait+'a)`.
//
// Under the newer defaults, though, we get:
//
// for<'a,'b> fn(&'a (SomeTrait+'a)) -> &'b (SomeTrait+'b)
//
// which fails to type check.
ss
//~^ ERROR cannot infer
//~| ERROR mismatched types
}
fn main() {
}
// Copyright 2015 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.
// Test various cases where the defaults should lead to errors being
// reported.
#![allow(dead_code)]
trait SomeTrait {
fn dummy(&self) { }
}
struct SomeStruct<'a> {
r: Box<SomeTrait+'a>
}
fn load(ss: &mut SomeStruct) -> Box<SomeTrait> {
// `Box<SomeTrait>` defaults to a `'static` bound, so this return
// is illegal.
ss.r //~ ERROR mismatched types
}
fn store(ss: &mut SomeStruct, b: Box<SomeTrait>) {
// No error: b is bounded by 'static which outlives the
// (anonymous) lifetime on the struct.
ss.r = b;
}
fn store1<'b>(ss: &mut SomeStruct, b: Box<SomeTrait+'b>) {
// Here we override the lifetimes explicitly, and so naturally we get an error.
ss.r = b; //~ ERROR mismatched types
}
fn main() {
}
// Copyright 2015 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.
// Test a "pass-through" object-lifetime-default that produces errors.
#![allow(dead_code)]
trait SomeTrait {
fn dummy(&self) { }
}
struct MyBox<T:?Sized> {
r: Box<T>
}
fn deref<T>(ss: &T) -> T {
// produces the type of a deref without worrying about whether a
// move out would actually be legal
loop { }
}
fn load0(ss: &MyBox<SomeTrait>) -> MyBox<SomeTrait> {
deref(ss) //~ ERROR cannot infer
}
fn load1<'a,'b>(a: &'a MyBox<SomeTrait>,
b: &'b MyBox<SomeTrait>)
-> &'b MyBox<SomeTrait>
{
a
//~^ ERROR cannot infer
//~| ERROR mismatched types
//~| ERROR mismatched types
}
fn main() {
}
// Copyright 2015 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.
#[rustc_object_lifetime_default]
struct A<T>(T); //~ ERROR None
#[rustc_object_lifetime_default]
struct B<'a,T>(&'a (), T); //~ ERROR None
#[rustc_object_lifetime_default]
struct C<'a,T:'a>(&'a T); //~ ERROR 'a
#[rustc_object_lifetime_default]
struct D<'a,'b,T:'a+'b>(&'a T, &'b T); //~ ERROR Ambiguous
#[rustc_object_lifetime_default]
struct E<'a,'b:'a,T:'b>(&'a T, &'b T); //~ ERROR 'b
#[rustc_object_lifetime_default]
struct F<'a,'b,T:'a,U:'b>(&'a T, &'b U); //~ ERROR 'a,'b
#[rustc_object_lifetime_default]
struct G<'a,'b,T:'a,U:'a+'b>(&'a T, &'b U); //~ ERROR 'a,Ambiguous
fn main() { }
......@@ -25,7 +25,7 @@ struct Foo<'a,'b,'c> {
c: Box<Is<'a>>,
d: Box<IsSend>,
e: Box<Is<'a>+Send>, // we can derive two bounds, but one is 'static, so ok
f: Box<SomeTrait>, //~ ERROR explicit lifetime bound required
f: Box<SomeTrait>, // OK, defaults to 'static due to RFC 599.
g: Box<SomeTrait+'a>,
z: Box<Is<'a>+'b+'c>, //~ ERROR only a single explicit lifetime bound is permitted
......
......@@ -11,6 +11,8 @@
// Various tests related to testing how region inference works
// with respect to the object receivers.
#![allow(warnings)]
trait Foo {
fn borrowed<'a>(&'a self) -> &'a ();
}
......@@ -21,29 +23,6 @@ fn borrowed_receiver_same_lifetime<'a>(x: &'a Foo) -> &'a () {
x.borrowed()
}
// Borrowed receiver but two distinct lifetimes, we get an error.
fn borrowed_receiver_different_lifetimes<'a,'b>(x: &'a Foo) -> &'b () {
x.borrowed() //~ ERROR cannot infer
}
// Borrowed receiver with two distinct lifetimes, but we know that
// 'b:'a, hence &'a () is permitted.
fn borrowed_receiver_related_lifetimes<'a,'b>(x: &'a (Foo+'b)) -> &'a () {
x.borrowed()
}
// Here we have two distinct lifetimes, but we try to return a pointer
// with the longer lifetime when (from the signature) we only know
// that it lives as long as the shorter lifetime. Therefore, error.
fn borrowed_receiver_related_lifetimes2<'a,'b>(x: &'a (Foo+'b)) -> &'b () {
x.borrowed() //~ ERROR cannot infer
}
// Here, the object is bounded by an anonymous lifetime and returned
// as `&'static`, so you get an error.
fn owned_receiver(x: Box<Foo>) -> &'static () {
x.borrowed() //~ ERROR cannot infer
}
fn main() {}
#[rustc_error]
fn main() {} //~ ERROR compilation successful
// Copyright 2012-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 <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.
// Various tests related to testing how region inference works
// with respect to the object receivers.
trait Foo {
fn borrowed<'a>(&'a self) -> &'a ();
}
// Borrowed receiver but two distinct lifetimes, we get an error.
fn borrowed_receiver_different_lifetimes<'a,'b>(x: &'a Foo) -> &'b () {
x.borrowed() //~ ERROR cannot infer
}
fn main() {}
// Copyright 2012-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 <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.
// Various tests related to testing how region inference works
// with respect to the object receivers.
#![allow(warnings)]
trait Foo {
fn borrowed<'a>(&'a self) -> &'a ();
}
// Borrowed receiver with two distinct lifetimes, but we know that
// 'b:'a, hence &'a () is permitted.
fn borrowed_receiver_related_lifetimes<'a,'b>(x: &'a (Foo+'b)) -> &'a () {
x.borrowed()
}
#[rustc_error]
fn main() {} //~ ERROR compilation successful
// Copyright 2012-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 <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.
// Various tests related to testing how region inference works
// with respect to the object receivers.
trait Foo {
fn borrowed<'a>(&'a self) -> &'a ();
}
// Here we have two distinct lifetimes, but we try to return a pointer
// with the longer lifetime when (from the signature) we only know
// that it lives as long as the shorter lifetime. Therefore, error.
fn borrowed_receiver_related_lifetimes2<'a,'b>(x: &'a (Foo+'b)) -> &'b () {
x.borrowed() //~ ERROR cannot infer
}
fn main() {}
// Copyright 2012-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 <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.
// Various tests related to testing how region inference works
// with respect to the object receivers.
trait Foo {
fn borrowed<'a>(&'a self) -> &'a ();
}
// Here, the object is bounded by an anonymous lifetime and returned
// as `&'static`, so you get an error.
fn owned_receiver(x: Box<Foo>) -> &'static () {
x.borrowed() //~ ERROR `*x` does not live long enough
}
fn main() {}
......@@ -17,20 +17,22 @@ trait Foo {}
impl<'a> Foo for &'a [u8] {}
fn a(v: &[u8]) -> Box<Foo + 'static> {
let x: Box<Foo + 'static> = box v; //~ ERROR declared lifetime bound not satisfied
let x: Box<Foo + 'static> = box v; //~ ERROR does not fulfill the required lifetime
x
}
fn b(v: &[u8]) -> Box<Foo + 'static> {
box v //~ ERROR declared lifetime bound not satisfied
box v //~ ERROR does not fulfill the required lifetime
}
fn c(v: &[u8]) -> Box<Foo> {
box v // OK thanks to lifetime elision
// same as previous case due to RFC 599
box v //~ ERROR does not fulfill the required lifetime
}
fn d<'a,'b>(v: &'a [u8]) -> Box<Foo+'b> {
box v //~ ERROR declared lifetime bound not satisfied
box v //~ ERROR does not fulfill the required lifetime
}
fn e<'a:'b,'b>(v: &'a [u8]) -> Box<Foo+'b> {
......
......@@ -32,15 +32,15 @@ fn static_lifime_ok<'a,T,U:Send>(_: &'a isize) {
// otherwise lifetime pointers are not ok
fn param_not_ok<'a>(x: &'a isize) {
assert_send::<&'a isize>(); //~ ERROR declared lifetime bound not satisfied
assert_send::<&'a isize>(); //~ ERROR does not fulfill the required lifetime
}
fn param_not_ok1<'a>(_: &'a isize) {
assert_send::<&'a str>(); //~ ERROR declared lifetime bound not satisfied
assert_send::<&'a str>(); //~ ERROR does not fulfill the required lifetime
}
fn param_not_ok2<'a>(_: &'a isize) {
assert_send::<&'a [isize]>(); //~ ERROR declared lifetime bound not satisfied
assert_send::<&'a [isize]>(); //~ ERROR does not fulfill the required lifetime
}
// boxes are ok
......@@ -54,7 +54,7 @@ fn box_ok() {
// but not if they own a bad thing
fn box_with_region_not_ok<'a>() {
assert_send::<Box<&'a isize>>(); //~ ERROR declared lifetime bound not satisfied
assert_send::<Box<&'a isize>>(); //~ ERROR does not fulfill the required lifetime
}
// objects with insufficient bounds no ok
......@@ -66,7 +66,7 @@ fn object_with_random_bound_not_ok<'a>() {
fn object_with_send_bound_not_ok<'a>() {
assert_send::<&'a (Dummy+Send)>();
//~^ ERROR declared lifetime bound not satisfied
//~^ ERROR does not fulfill the required lifetime
}
// unsafe pointers are ok unless they point at unsendable things
......
......@@ -29,15 +29,15 @@ fn static_lifime_ok<'a,T,U:Send>(_: &'a isize) {
// otherwise lifetime pointers are not ok
fn param_not_ok<'a>(x: &'a isize) {
assert_send::<&'a isize>(); //~ ERROR declared lifetime bound not satisfied
assert_send::<&'a isize>(); //~ ERROR does not fulfill the required lifetime
}
fn param_not_ok1<'a>(_: &'a isize) {
assert_send::<&'a str>(); //~ ERROR declared lifetime bound not satisfied
assert_send::<&'a str>(); //~ ERROR does not fulfill the required lifetime
}
fn param_not_ok2<'a>(_: &'a isize) {
assert_send::<&'a [isize]>(); //~ ERROR declared lifetime bound not satisfied
assert_send::<&'a [isize]>(); //~ ERROR does not fulfill the required lifetime
}
// boxes are ok
......@@ -51,7 +51,7 @@ fn box_ok() {
// but not if they own a bad thing
fn box_with_region_not_ok<'a>() {
assert_send::<Box<&'a isize>>(); //~ ERROR declared lifetime bound not satisfied
assert_send::<Box<&'a isize>>(); //~ ERROR does not fulfill the required lifetime
}
// unsafe pointers are ok unless they point at unsendable things
......@@ -62,11 +62,11 @@ fn unsafe_ok1<'a>(_: &'a isize) {
}
fn unsafe_ok2<'a>(_: &'a isize) {
assert_send::<*const &'a isize>(); //~ ERROR declared lifetime bound not satisfied
assert_send::<*const &'a isize>(); //~ ERROR does not fulfill the required lifetime
}
fn unsafe_ok3<'a>(_: &'a isize) {
assert_send::<*mut &'a isize>(); //~ ERROR declared lifetime bound not satisfied
assert_send::<*mut &'a isize>(); //~ ERROR does not fulfill the required lifetime
}
fn main() {
......
......@@ -20,7 +20,7 @@ fn some_method<A:'static>(self) { }
fn caller<'a>(x: &isize) {
Foo.some_method::<&'a isize>();
//~^ ERROR declared lifetime bound not satisfied
//~^ ERROR does not fulfill the required lifetime
}
fn main() { }
......@@ -9,6 +9,7 @@
// except according to those terms.
#![feature(box_syntax)]
#![allow(warnings)]
trait A<T> {}
struct B<'a, T>(&'a (A<T>+'a));
......@@ -17,19 +18,7 @@ trait X {}
impl<'a, T> X for B<'a, T> {}
fn f<'a, T, U>(v: Box<A<T>+'static>) -> Box<X+'static> {
box B(&*v) as Box<X>
}
fn g<'a, T: 'static>(v: Box<A<T>>) -> Box<X+'static> {
box B(&*v) as Box<X> //~ ERROR cannot infer
}
fn h<'a, T, U>(v: Box<A<U>+'static>) -> Box<X+'static> {
box B(&*v) as Box<X>
}
fn i<'a, T, U>(v: Box<A<U>>) -> Box<X+'static> {
box B(&*v) as Box<X> //~ ERROR cannot infer
box B(&*v) as Box<X> //~ ERROR `*v` does not live long enough
}
fn main() {}
......
// 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 <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.
#![feature(box_syntax)]
trait A<T> {}
struct B<'a, T>(&'a (A<T>+'a));
trait X {}
impl<'a, T> X for B<'a, T> {}
fn g<'a, T: 'static>(v: Box<A<T>+'a>) -> Box<X+'static> {
box B(&*v) as Box<X> //~ ERROR cannot infer
}
fn main() { }
// 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 <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.
#![feature(box_syntax)]
#![allow(warnings)]
trait A<T> {}
struct B<'a, T>(&'a (A<T>+'a));
trait X {}
impl<'a, T> X for B<'a, T> {}
fn h<'a, T, U>(v: Box<A<U>+'static>) -> Box<X+'static> {
box B(&*v) as Box<X> //~ ERROR `*v` does not live long enough
}
fn main() {}
// 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 <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.
#![feature(box_syntax)]
trait A<T> {}
struct B<'a, T>(&'a (A<T>+'a));
trait X {}
impl<'a, T> X for B<'a, T> {}
fn i<'a, T, U>(v: Box<A<U>+'a>) -> Box<X+'static> {
box B(&*v) as Box<X> //~ ERROR cannot infer
}
fn main() {}
......@@ -14,7 +14,7 @@ trait seq { }
impl<T> seq<T> for Vec<T> { //~ ERROR wrong number of type arguments
/* ... */
}
impl seq<bool> for u32 {
impl seq<bool> for u32 { //~ ERROR wrong number of type arguments
/* Treat the integer as a sequence of bits */
}
......
......@@ -57,6 +57,7 @@ fn main() {
let pt3 = PointF::<i32> {
//~^ ERROR wrong number of type arguments
//~| ERROR structure constructor specifies a structure of type
x: 9i32,
y: 10i32,
};
......
......@@ -22,7 +22,7 @@ fn c(x: Box<Foo+Sync+Send>) {
fn d(x: Box<Foo>) {
a(x); //~ ERROR mismatched types
//~| expected `Box<Foo + Send>`
//~| found `Box<Foo>`
//~| found `Box<Foo + 'static>`
//~| expected bounds `Send`
//~| found no bounds
}
......
......@@ -24,8 +24,7 @@ fn c(x: Box<Foo+Sync>) {
}
fn d(x: &'static (Foo+Sync)) {
b(x); //~ ERROR cannot infer
//~^ ERROR mismatched types
b(x);
}
fn main() {}
......@@ -12,7 +12,9 @@
trait Three<A,B,C> { fn dummy(&self) -> (A,B,C); }
fn foo(_: &Three()) //~ ERROR wrong number of type arguments
fn foo(_: &Three())
//~^ ERROR wrong number of type arguments
//~| ERROR no associated type `Output`
{}
fn main() { }
......@@ -12,7 +12,9 @@
trait Zero { fn dummy(&self); }
fn foo(_: Zero()) //~ ERROR wrong number of type arguments
fn foo(_: Zero())
//~^ ERROR wrong number of type arguments
//~| ERROR no associated type `Output` defined in `Zero`
{}
fn main() { }
......@@ -14,6 +14,7 @@ trait Trait {}
fn f<F:Trait(isize) -> isize>(x: F) {}
//~^ ERROR wrong number of type arguments: expected 0, found 1
//~| ERROR no associated type `Output`
fn main() {}
// Copyright 2015 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.
// Test that `Box<Test>` is equivalent to `Box<Test+'static>`, both in
// fields and fn arguments.
#![allow(dead_code)]
trait Test {
fn foo(&self) { }
}
struct SomeStruct {
t: Box<Test>,
u: Box<Test+'static>,
}
fn a(t: Box<Test>, mut ss: SomeStruct) {
ss.t = t;
}
fn b(t: Box<Test+'static>, mut ss: SomeStruct) {
ss.t = t;
}
fn c(t: Box<Test>, mut ss: SomeStruct) {
ss.u = t;
}
fn d(t: Box<Test+'static>, mut ss: SomeStruct) {
ss.u = t;
}
fn main() {
}
// Copyright 2015 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.
// Test that the lifetime of the enclosing `&` is used for the object
// lifetime bound.
#![allow(dead_code)]
trait Test {
fn foo(&self) { }
}
struct Ref<'a,T:'a+?Sized> {
r: &'a T
}
struct SomeStruct<'a> {
t: Ref<'a,Test>,
u: Ref<'a,Test+'a>,
}
fn a<'a>(t: Ref<'a,Test>, mut ss: SomeStruct<'a>) {
ss.t = t;
}
fn b<'a>(t: Ref<'a,Test>, mut ss: SomeStruct<'a>) {
ss.u = t;
}
fn c<'a>(t: Ref<'a,Test+'a>, mut ss: SomeStruct<'a>) {
ss.t = t;
}
fn d<'a>(t: Ref<'a,Test+'a>, mut ss: SomeStruct<'a>) {
ss.u = t;
}
fn main() {
}
// Copyright 2015 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.
// Test that the lifetime from the enclosing `&` is "inherited"
// through the `Box` struct.
#![allow(dead_code)]
trait Test {
fn foo(&self) { }
}
struct SomeStruct<'a> {
t: &'a Box<Test>,
u: &'a Box<Test+'a>,
}
fn a<'a>(t: &'a Box<Test>, mut ss: SomeStruct<'a>) {
ss.t = t;
}
fn b<'a>(t: &'a Box<Test>, mut ss: SomeStruct<'a>) {
ss.u = t;
}
fn c<'a>(t: &'a Box<Test+'a>, mut ss: SomeStruct<'a>) {
ss.t = t;
}
fn d<'a>(t: &'a Box<Test+'a>, mut ss: SomeStruct<'a>) {
ss.u = t;
}
fn main() {
}
// Copyright 2015 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.
// Test that the lifetime of the enclosing `&` is used for the object
// lifetime bound.
#![allow(dead_code)]
trait Test {
fn foo(&self) { }
}
struct SomeStruct<'a> {
t: &'a mut Test,
u: &'a mut (Test+'a),
}
fn a<'a>(t: &'a mut Test, mut ss: SomeStruct<'a>) {
ss.t = t;
}
fn b<'a>(t: &'a mut Test, mut ss: SomeStruct<'a>) {
ss.u = t;
}
fn c<'a>(t: &'a mut (Test+'a), mut ss: SomeStruct<'a>) {
ss.t = t;
}
fn d<'a>(t: &'a mut (Test+'a), mut ss: SomeStruct<'a>) {
ss.u = t;
}
fn main() {
}
// Copyright 2015 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.
// Test that the lifetime from the enclosing `&` is "inherited"
// through the `MyBox` struct.
#![allow(dead_code)]
trait Test {
fn foo(&self) { }
}
struct SomeStruct<'a> {
t: &'a MyBox<Test>,
u: &'a MyBox<Test+'a>,
}
struct MyBox<T:?Sized> {
b: Box<T>
}
fn a<'a>(t: &'a MyBox<Test>, mut ss: SomeStruct<'a>) {
ss.t = t;
}
fn b<'a>(t: &'a MyBox<Test>, mut ss: SomeStruct<'a>) {
ss.u = t;
}
fn c<'a>(t: &'a MyBox<Test+'a>, mut ss: SomeStruct<'a>) {
ss.t = t;
}
fn d<'a>(t: &'a MyBox<Test+'a>, mut ss: SomeStruct<'a>) {
ss.u = t;
}
fn main() {
}
// Copyright 2015 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.
// Test that the lifetime of the enclosing `&` is used for the object
// lifetime bound.
#![allow(dead_code)]
trait Test {
fn foo(&self) { }
}
struct SomeStruct<'a> {
t: &'a Test,
u: &'a (Test+'a),
}
fn a<'a>(t: &'a Test, mut ss: SomeStruct<'a>) {
ss.t = t;
}
fn b<'a>(t: &'a Test, mut ss: SomeStruct<'a>) {
ss.u = t;
}
fn c<'a>(t: &'a (Test+'a), mut ss: SomeStruct<'a>) {
ss.t = t;
}
fn d<'a>(t: &'a (Test+'a), mut ss: SomeStruct<'a>) {
ss.u = t;
}
fn main() {
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册