auto merge of #18743 : nikomatsakis/rust/hrtb-refactor-2, r=pcwalton
Various miscellaneous changes pushing towards HRTB support: 1. Update parser and adjust ast to support `for<'a,'b>` syntax, both in closures and trait bounds. Warn on the old syntax (not error, for stage0). 2. Refactor TyTrait representation to include a TraitRef. 3. Purge `once_fns` feature gate and `once` keyword. r? @pcwalton This is a [breaking-change]: - The `once_fns` feature is now officially deprecated. Rewrite using normal closures or unboxed closures. - The new `for`-based syntax now issues warnings (but not yet errors): - `fn<'a>(T) -> U` becomes `for<'a> fn(T) -> U` - `<'a> |T| -> U` becomes `for<'a> |T| -> U`
This commit is contained in:
commit
a2f303ad09
@ -1690,8 +1690,8 @@ impl LintPass for Stability {
|
||||
for t in supertraits.iter() {
|
||||
match *t {
|
||||
ast::TraitTyParamBound(ref t) => {
|
||||
let id = ty::trait_ref_to_def_id(cx.tcx, t);
|
||||
self.lint(cx, id, t.path.span);
|
||||
let id = ty::trait_ref_to_def_id(cx.tcx, &t.trait_ref);
|
||||
self.lint(cx, id, t.trait_ref.path.span);
|
||||
}
|
||||
_ => (/* pass */)
|
||||
}
|
||||
|
@ -389,11 +389,10 @@ fn parse_ty(st: &mut PState, conv: conv_did) -> ty::t {
|
||||
}
|
||||
'x' => {
|
||||
assert_eq!(next(st), '[');
|
||||
let def = parse_def(st, NominalType, |x,y| conv(x,y));
|
||||
let substs = parse_substs(st, |x,y| conv(x,y));
|
||||
let trait_ref = parse_trait_ref(st, |x,y| conv(x,y));
|
||||
let bounds = parse_existential_bounds(st, |x,y| conv(x,y));
|
||||
assert_eq!(next(st), ']');
|
||||
return ty::mk_trait(st.tcx, def, substs, bounds);
|
||||
return ty::mk_trait(st.tcx, trait_ref, bounds);
|
||||
}
|
||||
'p' => {
|
||||
let did = parse_def(st, TypeParameter, |x,y| conv(x,y));
|
||||
|
@ -231,13 +231,10 @@ fn enc_sty(w: &mut SeekableMemWriter, cx: &ctxt, st: &ty::sty) {
|
||||
enc_substs(w, cx, substs);
|
||||
mywrite!(w, "]");
|
||||
}
|
||||
ty::ty_trait(box ty::TyTrait {
|
||||
def_id,
|
||||
ref substs,
|
||||
ref bounds
|
||||
}) => {
|
||||
mywrite!(w, "x[{}|", (cx.ds)(def_id));
|
||||
enc_substs(w, cx, substs);
|
||||
ty::ty_trait(box ty::TyTrait { ref principal,
|
||||
ref bounds }) => {
|
||||
mywrite!(w, "x[");
|
||||
enc_trait_ref(w, cx, principal);
|
||||
enc_existential_bounds(w, cx, bounds);
|
||||
mywrite!(w, "]");
|
||||
}
|
||||
|
@ -1085,16 +1085,19 @@ impl<'a> rbml_writer_helpers for Encoder<'a> {
|
||||
this.emit_enum_variant_arg(1, |this| idx.encode(this))
|
||||
})
|
||||
}
|
||||
ty::UnsizeVtable(ty::TyTrait { def_id,
|
||||
bounds: ref b,
|
||||
ref substs },
|
||||
ty::UnsizeVtable(ty::TyTrait { ref principal,
|
||||
bounds: ref b },
|
||||
self_ty) => {
|
||||
this.emit_enum_variant("UnsizeVtable", 2, 4, |this| {
|
||||
this.emit_enum_variant_arg(
|
||||
0, |this| Ok(this.emit_existential_bounds(ecx, b)));
|
||||
this.emit_enum_variant_arg(1, |this| def_id.encode(this));
|
||||
this.emit_enum_variant_arg(2, |this| Ok(this.emit_ty(ecx, self_ty)));
|
||||
this.emit_enum_variant_arg(3, |this| Ok(this.emit_substs(ecx, substs)))
|
||||
this.emit_enum_variant_arg(0, |this| {
|
||||
try!(this.emit_struct_field("principal", 0, |this| {
|
||||
Ok(this.emit_trait_ref(ecx, &*principal))
|
||||
}));
|
||||
this.emit_struct_field("bounds", 1, |this| {
|
||||
Ok(this.emit_existential_bounds(ecx, b))
|
||||
})
|
||||
});
|
||||
this.emit_enum_variant_arg(1, |this| Ok(this.emit_ty(ecx, self_ty)))
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -1693,18 +1696,19 @@ impl<'a> rbml_decoder_decoder_helpers for reader::Decoder<'a> {
|
||||
ty::UnsizeStruct(box uk, idx)
|
||||
}
|
||||
2 => {
|
||||
let b =
|
||||
this.read_enum_variant_arg(
|
||||
0, |this| Ok(this.read_existential_bounds(dcx))).unwrap();
|
||||
let def_id: ast::DefId =
|
||||
this.read_enum_variant_arg(1, |this| Decodable::decode(this)).unwrap();
|
||||
let ty_trait = try!(this.read_enum_variant_arg(0, |this| {
|
||||
let principal = try!(this.read_struct_field("principal", 0, |this| {
|
||||
Ok(this.read_trait_ref(dcx))
|
||||
}));
|
||||
Ok(ty::TyTrait {
|
||||
principal: (*principal).clone(),
|
||||
bounds: try!(this.read_struct_field("bounds", 1, |this| {
|
||||
Ok(this.read_existential_bounds(dcx))
|
||||
})),
|
||||
})
|
||||
}));
|
||||
let self_ty =
|
||||
this.read_enum_variant_arg(2, |this| Ok(this.read_ty(dcx))).unwrap();
|
||||
let substs = this.read_enum_variant_arg(3,
|
||||
|this| Ok(this.read_substs(dcx))).unwrap();
|
||||
let ty_trait = ty::TyTrait { def_id: def_id.tr(dcx),
|
||||
bounds: b,
|
||||
substs: substs };
|
||||
this.read_enum_variant_arg(1, |this| Ok(this.read_ty(dcx))).unwrap();
|
||||
ty::UnsizeVtable(ty_trait, self_ty)
|
||||
}
|
||||
_ => panic!("bad enum variant for ty::UnsizeKind")
|
||||
|
@ -1291,7 +1291,7 @@ impl<'a, 'tcx> VisiblePrivateTypesVisitor<'a, 'tcx> {
|
||||
match *ty_param_bound {
|
||||
ast::TraitTyParamBound(ref trait_ref) => {
|
||||
if !self.tcx.sess.features.borrow().visible_private_types &&
|
||||
self.path_is_private_type(trait_ref.ref_id) {
|
||||
self.path_is_private_type(trait_ref.trait_ref.ref_id) {
|
||||
self.tcx.sess.span_err(span,
|
||||
"private type in exported type \
|
||||
parameter bound");
|
||||
@ -1432,7 +1432,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
|
||||
//
|
||||
// Those in 2. are warned via walk_generics and this
|
||||
// call here.
|
||||
visit::walk_trait_ref_helper(self, tr)
|
||||
self.visit_trait_ref(tr)
|
||||
}
|
||||
}
|
||||
} else if trait_ref.is_none() && self_is_public_path {
|
||||
|
@ -33,12 +33,12 @@ use syntax::ast::{ItemTrait, ItemTy, LOCAL_CRATE, Local, ItemConst};
|
||||
use syntax::ast::{MethodImplItem, Mod, Name, NamedField, NodeId};
|
||||
use syntax::ast::{Pat, PatEnum, PatIdent, PatLit};
|
||||
use syntax::ast::{PatRange, PatStruct, Path, PathListIdent, PathListMod};
|
||||
use syntax::ast::{PrimTy, Public, SelfExplicit, SelfStatic};
|
||||
use syntax::ast::{PolyTraitRef, PrimTy, Public, SelfExplicit, SelfStatic};
|
||||
use syntax::ast::{RegionTyParamBound, StmtDecl, StructField};
|
||||
use syntax::ast::{StructVariantKind, TraitRef, TraitTyParamBound};
|
||||
use syntax::ast::{TupleVariantKind, Ty, TyBool, TyChar, TyClosure, TyF32};
|
||||
use syntax::ast::{TyF64, TyFloat, TyI, TyI8, TyI16, TyI32, TyI64, TyInt};
|
||||
use syntax::ast::{TyParam, TyParamBound, TyPath, TyPtr, TyProc, TyQPath};
|
||||
use syntax::ast::{TyParam, TyParamBound, TyPath, TyPtr, TyPolyTraitRef, TyProc, TyQPath};
|
||||
use syntax::ast::{TyRptr, TyStr, TyU, TyU8, TyU16, TyU32, TyU64, TyUint};
|
||||
use syntax::ast::{TypeImplItem, UnnamedField};
|
||||
use syntax::ast::{Variant, ViewItem, ViewItemExternCrate};
|
||||
@ -607,6 +607,7 @@ enum TraitReferenceType {
|
||||
TraitImplementation, // impl SomeTrait for T { ... }
|
||||
TraitDerivation, // trait T : SomeTrait { ... }
|
||||
TraitBoundingTypeParameter, // fn f<T:SomeTrait>() { ... }
|
||||
TraitObject, // Box<for<'a> SomeTrait>
|
||||
}
|
||||
|
||||
impl NameBindings {
|
||||
@ -4244,11 +4245,11 @@ impl<'a> Resolver<'a> {
|
||||
this.resolve_type_parameter_bounds(item.id, bounds,
|
||||
TraitDerivation);
|
||||
|
||||
match unbound {
|
||||
&Some(ast::TraitTyParamBound(ref tpb)) => {
|
||||
match *unbound {
|
||||
Some(ref tpb) => {
|
||||
this.resolve_trait_reference(item.id, tpb, TraitDerivation);
|
||||
}
|
||||
_ => {}
|
||||
None => {}
|
||||
}
|
||||
|
||||
for trait_item in (*trait_items).iter() {
|
||||
@ -4495,7 +4496,7 @@ impl<'a> Resolver<'a> {
|
||||
}
|
||||
match &type_parameter.unbound {
|
||||
&Some(ref unbound) =>
|
||||
self.resolve_type_parameter_bound(
|
||||
self.resolve_trait_reference(
|
||||
type_parameter.id, unbound, TraitBoundingTypeParameter),
|
||||
&None => {}
|
||||
}
|
||||
@ -4521,12 +4522,19 @@ impl<'a> Resolver<'a> {
|
||||
reference_type: TraitReferenceType) {
|
||||
match *type_parameter_bound {
|
||||
TraitTyParamBound(ref tref) => {
|
||||
self.resolve_trait_reference(id, tref, reference_type)
|
||||
self.resolve_poly_trait_reference(id, tref, reference_type)
|
||||
}
|
||||
RegionTyParamBound(..) => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_poly_trait_reference(&mut self,
|
||||
id: NodeId,
|
||||
poly_trait_reference: &PolyTraitRef,
|
||||
reference_type: TraitReferenceType) {
|
||||
self.resolve_trait_reference(id, &poly_trait_reference.trait_ref, reference_type)
|
||||
}
|
||||
|
||||
fn resolve_trait_reference(&mut self,
|
||||
id: NodeId,
|
||||
trait_reference: &TraitRef,
|
||||
@ -4538,6 +4546,7 @@ impl<'a> Resolver<'a> {
|
||||
TraitBoundingTypeParameter => "bound type parameter with",
|
||||
TraitImplementation => "implement",
|
||||
TraitDerivation => "derive",
|
||||
TraitObject => "reference",
|
||||
};
|
||||
|
||||
let msg = format!("attempt to {} a nonexistent trait `{}`", usage_str, path_str);
|
||||
@ -5044,6 +5053,13 @@ impl<'a> Resolver<'a> {
|
||||
visit::walk_ty(self, ty);
|
||||
}
|
||||
|
||||
TyPolyTraitRef(ref poly_trait_ref) => {
|
||||
self.resolve_poly_trait_reference(
|
||||
ty.id,
|
||||
&**poly_trait_ref,
|
||||
TraitObject);
|
||||
visit::walk_ty(self, ty);
|
||||
}
|
||||
_ => {
|
||||
// Just resolve embedded types.
|
||||
visit::walk_ty(self, ty);
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
use driver::session::Session;
|
||||
use middle::subst;
|
||||
use std::fmt;
|
||||
use syntax::ast;
|
||||
use syntax::codemap::Span;
|
||||
use syntax::owned_slice::OwnedSlice;
|
||||
@ -46,18 +47,12 @@ pub enum DefRegion {
|
||||
// that it corresponds to
|
||||
pub type NamedRegionMap = NodeMap<DefRegion>;
|
||||
|
||||
// Returns an instance of some type that implements std::fmt::Show
|
||||
fn lifetime_show(lt_name: &ast::Name) -> token::InternedString {
|
||||
token::get_name(*lt_name)
|
||||
}
|
||||
|
||||
struct LifetimeContext<'a> {
|
||||
sess: &'a Session,
|
||||
named_region_map: &'a mut NamedRegionMap,
|
||||
scope: Scope<'a>
|
||||
}
|
||||
|
||||
#[deriving(Show)]
|
||||
enum ScopeChain<'a> {
|
||||
/// EarlyScope(i, ['a, 'b, ...], s) extends s with early-bound
|
||||
/// lifetimes, assigning indexes 'a => i, 'b => i+1, ... etc.
|
||||
@ -88,42 +83,32 @@ pub fn krate(sess: &Session, krate: &ast::Crate) -> NamedRegionMap {
|
||||
|
||||
impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
|
||||
fn visit_item(&mut self, item: &ast::Item) {
|
||||
let lifetimes = match item.node {
|
||||
ast::ItemFn(..) | // fn lifetimes get added in visit_fn below
|
||||
match item.node {
|
||||
ast::ItemFn(..) => {
|
||||
// Fn lifetimes get added in visit_fn below:
|
||||
self.with(RootScope, |this| visit::walk_item(this, item));
|
||||
}
|
||||
ast::ItemMod(..) |
|
||||
ast::ItemMac(..) |
|
||||
ast::ItemForeignMod(..) |
|
||||
ast::ItemStatic(..) | ast::ItemConst(..) => {
|
||||
self.with(|_, f| f(RootScope), |v| visit::walk_item(v, item));
|
||||
return;
|
||||
ast::ItemStatic(..) |
|
||||
ast::ItemConst(..) => {
|
||||
// These sorts of items have no lifetime parameters at all.
|
||||
self.with(RootScope, |this| visit::walk_item(this, item));
|
||||
}
|
||||
ast::ItemTy(_, ref generics) |
|
||||
ast::ItemEnum(_, ref generics) |
|
||||
ast::ItemStruct(_, ref generics) |
|
||||
ast::ItemTrait(ref generics, _, _, _) => {
|
||||
self.with(|scope, f| {
|
||||
f(EarlyScope(subst::TypeSpace,
|
||||
&generics.lifetimes,
|
||||
scope))
|
||||
}, |v| v.check_lifetime_defs(&generics.lifetimes));
|
||||
&generics.lifetimes
|
||||
}
|
||||
ast::ItemTrait(ref generics, _, _, _) |
|
||||
ast::ItemImpl(ref generics, _, _, _) => {
|
||||
self.with(|scope, f| {
|
||||
f(EarlyScope(subst::TypeSpace,
|
||||
&generics.lifetimes,
|
||||
scope))
|
||||
}, |v| v.check_lifetime_defs(&generics.lifetimes));
|
||||
&generics.lifetimes
|
||||
// These kinds of items have only early bound lifetime parameters.
|
||||
let lifetimes = &generics.lifetimes;
|
||||
self.with(EarlyScope(subst::TypeSpace, lifetimes, &ROOT_SCOPE), |this| {
|
||||
this.check_lifetime_defs(lifetimes);
|
||||
visit::walk_item(this, item);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
self.with(|_, f| f(EarlyScope(subst::TypeSpace, lifetimes, &ROOT_SCOPE)), |v| {
|
||||
debug!("entering scope {}", v.scope);
|
||||
v.check_lifetime_defs(lifetimes);
|
||||
visit::walk_item(v, item);
|
||||
debug!("exiting scope {}", v.scope);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_fn(&mut self, fk: visit::FnKind<'v>, fd: &'v ast::FnDecl,
|
||||
@ -131,7 +116,9 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
|
||||
match fk {
|
||||
visit::FkItemFn(_, generics, _, _) |
|
||||
visit::FkMethod(_, generics, _) => {
|
||||
self.visit_fn_decl(n, generics, |v| visit::walk_fn(v, fk, fd, b, s))
|
||||
self.visit_early_late(
|
||||
subst::FnSpace, n, generics,
|
||||
|this| visit::walk_fn(this, fk, fd, b, s))
|
||||
}
|
||||
visit::FkFnBlock(..) => {
|
||||
visit::walk_fn(self, fk, fd, b, s)
|
||||
@ -146,22 +133,20 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
|
||||
_ => return visit::walk_ty(self, ty)
|
||||
};
|
||||
|
||||
self.with(|scope, f| f(LateScope(ty.id, lifetimes, scope)), |v| {
|
||||
v.check_lifetime_defs(lifetimes);
|
||||
debug!("pushing fn scope id={} due to type", ty.id);
|
||||
visit::walk_ty(v, ty);
|
||||
debug!("popping fn scope id={} due to type", ty.id);
|
||||
self.with(LateScope(ty.id, lifetimes, self.scope), |this| {
|
||||
this.check_lifetime_defs(lifetimes);
|
||||
visit::walk_ty(this, ty);
|
||||
});
|
||||
}
|
||||
|
||||
fn visit_ty_method(&mut self, m: &ast::TypeMethod) {
|
||||
self.visit_fn_decl(m.id, &m.generics, |v| visit::walk_ty_method(v, m))
|
||||
self.visit_early_late(
|
||||
subst::FnSpace, m.id, &m.generics,
|
||||
|this| visit::walk_ty_method(this, m))
|
||||
}
|
||||
|
||||
fn visit_block(&mut self, b: &ast::Block) {
|
||||
debug!("pushing block scope {}", b.id);
|
||||
self.with(|scope, f| f(BlockScope(b.id, scope)), |v| visit::walk_block(v, b));
|
||||
debug!("popping block scope {}", b.id);
|
||||
self.with(BlockScope(b.id, self.scope), |this| visit::walk_block(this, b));
|
||||
}
|
||||
|
||||
fn visit_lifetime_ref(&mut self, lifetime_ref: &ast::Lifetime) {
|
||||
@ -188,13 +173,16 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
|
||||
}
|
||||
|
||||
impl<'a> LifetimeContext<'a> {
|
||||
fn with(&mut self, wrap_scope: |Scope, |ScopeChain||, f: |&mut LifetimeContext|) {
|
||||
let LifetimeContext { sess, ref mut named_region_map, scope} = *self;
|
||||
wrap_scope(scope, |scope1| f(&mut LifetimeContext {
|
||||
fn with(&mut self, wrap_scope: ScopeChain, f: |&mut LifetimeContext|) {
|
||||
let LifetimeContext {sess, ref mut named_region_map, ..} = *self;
|
||||
let mut this = LifetimeContext {
|
||||
sess: sess,
|
||||
named_region_map: *named_region_map,
|
||||
scope: &scope1
|
||||
}))
|
||||
scope: &wrap_scope
|
||||
};
|
||||
debug!("entering scope {}", this.scope);
|
||||
f(&mut this);
|
||||
debug!("exiting scope {}", this.scope);
|
||||
}
|
||||
|
||||
fn visit_ty_param_bounds(&mut self,
|
||||
@ -202,7 +190,7 @@ impl<'a> LifetimeContext<'a> {
|
||||
for bound in bounds.iter() {
|
||||
match *bound {
|
||||
ast::TraitTyParamBound(ref trait_ref) => {
|
||||
self.visit_trait_ref(trait_ref);
|
||||
self.visit_poly_trait_ref(trait_ref);
|
||||
}
|
||||
ast::RegionTyParamBound(ref lifetime) => {
|
||||
self.visit_lifetime_ref(lifetime);
|
||||
@ -211,23 +199,27 @@ impl<'a> LifetimeContext<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_trait_ref(&mut self, trait_ref: &ast::TraitRef) {
|
||||
self.with(|scope, f| {
|
||||
f(LateScope(trait_ref.ref_id, &trait_ref.lifetimes, scope))
|
||||
}, |v| {
|
||||
v.check_lifetime_defs(&trait_ref.lifetimes);
|
||||
for lifetime in trait_ref.lifetimes.iter() {
|
||||
v.visit_lifetime_decl(lifetime);
|
||||
fn visit_poly_trait_ref(&mut self, trait_ref: &ast::PolyTraitRef) {
|
||||
let ref_id = trait_ref.trait_ref.ref_id;
|
||||
self.with(LateScope(ref_id, &trait_ref.bound_lifetimes, self.scope), |this| {
|
||||
this.check_lifetime_defs(&trait_ref.bound_lifetimes);
|
||||
for lifetime in trait_ref.bound_lifetimes.iter() {
|
||||
this.visit_lifetime_decl(lifetime);
|
||||
}
|
||||
v.visit_path(&trait_ref.path, trait_ref.ref_id);
|
||||
this.visit_trait_ref(&trait_ref.trait_ref)
|
||||
})
|
||||
}
|
||||
|
||||
fn visit_trait_ref(&mut self, trait_ref: &ast::TraitRef) {
|
||||
self.visit_path(&trait_ref.path, trait_ref.ref_id);
|
||||
}
|
||||
|
||||
/// Visits self by adding a scope and handling recursive walk over the contents with `walk`.
|
||||
fn visit_fn_decl(&mut self,
|
||||
n: ast::NodeId,
|
||||
generics: &ast::Generics,
|
||||
walk: |&mut LifetimeContext|) {
|
||||
fn visit_early_late(&mut self,
|
||||
early_space: subst::ParamSpace,
|
||||
binder_id: ast::NodeId,
|
||||
generics: &ast::Generics,
|
||||
walk: |&mut LifetimeContext|) {
|
||||
/*!
|
||||
* Handles visiting fns and methods. These are a bit
|
||||
* complicated because we must distinguish early- vs late-bound
|
||||
@ -248,33 +240,25 @@ impl<'a> LifetimeContext<'a> {
|
||||
* numbered sequentially, starting from the lowest index that
|
||||
* is already in scope (for a fn item, that will be 0, but for
|
||||
* a method it might not be). Late bound lifetimes are
|
||||
* resolved by name and associated with a binder id (`n`), so
|
||||
* resolved by name and associated with a binder id (`binder_id`), so
|
||||
* the ordering is not important there.
|
||||
*/
|
||||
|
||||
let referenced_idents = early_bound_lifetime_names(generics);
|
||||
debug!("pushing fn scope id={} due to fn item/method\
|
||||
referenced_idents={}",
|
||||
n,
|
||||
referenced_idents.iter().map(lifetime_show).collect::<Vec<token::InternedString>>());
|
||||
let lifetimes = &generics.lifetimes;
|
||||
if referenced_idents.is_empty() {
|
||||
self.with(|scope, f| f(LateScope(n, lifetimes, scope)), |v| {
|
||||
v.check_lifetime_defs(lifetimes);
|
||||
walk(v);
|
||||
});
|
||||
} else {
|
||||
let (early, late) = lifetimes.clone().partition(
|
||||
|l| referenced_idents.iter().any(|&i| i == l.lifetime.name));
|
||||
|
||||
self.with(|scope, f| f(EarlyScope(subst::FnSpace, &early, scope)), |v| {
|
||||
v.with(|scope1, f| f(LateScope(n, &late, scope1)), |v| {
|
||||
v.check_lifetime_defs(lifetimes);
|
||||
walk(v);
|
||||
});
|
||||
debug!("visit_early_late: binder_id={} referenced_idents={}",
|
||||
binder_id,
|
||||
referenced_idents);
|
||||
|
||||
let (early, late) = generics.lifetimes.clone().partition(
|
||||
|l| referenced_idents.iter().any(|&i| i == l.lifetime.name));
|
||||
|
||||
self.with(EarlyScope(early_space, &early, self.scope), |this| {
|
||||
this.with(LateScope(binder_id, &late, this.scope), |this| {
|
||||
this.check_lifetime_defs(&generics.lifetimes);
|
||||
walk(this);
|
||||
});
|
||||
}
|
||||
debug!("popping fn scope id={} due to fn item/method", n);
|
||||
});
|
||||
}
|
||||
|
||||
fn resolve_lifetime_ref(&mut self, lifetime_ref: &ast::Lifetime) {
|
||||
@ -525,3 +509,14 @@ fn early_bound_lifetime_names(generics: &ast::Generics) -> Vec<ast::Name> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> fmt::Show for ScopeChain<'a> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
EarlyScope(space, defs, _) => write!(fmt, "EarlyScope({}, {})", space, defs),
|
||||
LateScope(id, defs, _) => write!(fmt, "LateScope({}, {})", id, defs),
|
||||
BlockScope(id, _) => write!(fmt, "BlockScope({})", id),
|
||||
RootScope => write!(fmt, "RootScope"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -710,6 +710,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
|
||||
}
|
||||
};
|
||||
|
||||
let trait_ref = &trait_ref.trait_ref;
|
||||
match self.lookup_type_ref(trait_ref.ref_id) {
|
||||
Some(id) => {
|
||||
let sub_span = self.span.sub_span_for_type_name(trait_ref.path.span);
|
||||
@ -1068,7 +1069,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
|
||||
for bound in param.bounds.iter() {
|
||||
match *bound {
|
||||
ast::TraitTyParamBound(ref trait_ref) => {
|
||||
self.process_trait_ref(trait_ref, None);
|
||||
self.process_trait_ref(&trait_ref.trait_ref, None);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
@ -143,7 +143,7 @@ pub fn ty_is_local(tcx: &ty::ctxt,
|
||||
}
|
||||
|
||||
ty::ty_trait(ref tt) => {
|
||||
tt.def_id.krate == ast::LOCAL_CRATE
|
||||
tt.principal.def_id.krate == ast::LOCAL_CRATE
|
||||
}
|
||||
|
||||
// Type parameters may be bound to types that are not local to
|
||||
|
@ -423,8 +423,8 @@ impl TypeMap {
|
||||
|
||||
from_def_id_and_substs(self,
|
||||
cx,
|
||||
trait_data.def_id,
|
||||
&trait_data.substs,
|
||||
trait_data.principal.def_id,
|
||||
&trait_data.principal.substs,
|
||||
&mut unique_type_id);
|
||||
},
|
||||
ty::ty_bare_fn(ty::BareFnTy{ fn_style, abi, ref sig } ) => {
|
||||
@ -2813,7 +2813,7 @@ fn trait_pointer_metadata(cx: &CrateContext,
|
||||
// But it does not describe the trait's methods.
|
||||
|
||||
let def_id = match ty::get(trait_type).sty {
|
||||
ty::ty_trait(box ty::TyTrait { def_id, .. }) => def_id,
|
||||
ty::ty_trait(box ty::TyTrait { ref principal, .. }) => principal.def_id,
|
||||
_ => {
|
||||
let pp_type_name = ppaux::ty_to_string(cx.tcx(), trait_type);
|
||||
cx.sess().bug(format!("debuginfo: Unexpected trait-object type in \
|
||||
@ -3739,8 +3739,8 @@ fn push_debuginfo_type_name(cx: &CrateContext,
|
||||
output.push(']');
|
||||
},
|
||||
ty::ty_trait(ref trait_data) => {
|
||||
push_item_name(cx, trait_data.def_id, false, output);
|
||||
push_type_params(cx, &trait_data.substs, output);
|
||||
push_item_name(cx, trait_data.principal.def_id, false, output);
|
||||
push_type_params(cx, &trait_data.principal.substs, output);
|
||||
},
|
||||
ty::ty_bare_fn(ty::BareFnTy{ fn_style, abi, ref sig } ) => {
|
||||
if fn_style == ast::UnsafeFn {
|
||||
|
@ -324,10 +324,10 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
_ => bcx.sess().bug(format!("UnsizeStruct with bad sty: {}",
|
||||
bcx.ty_to_string(unsized_ty)).as_slice())
|
||||
},
|
||||
&ty::UnsizeVtable(ty::TyTrait { def_id, ref substs, .. }, _) => {
|
||||
let substs = substs.with_self_ty(unsized_ty);
|
||||
&ty::UnsizeVtable(ty::TyTrait { ref principal, .. }, _) => {
|
||||
let substs = principal.substs.with_self_ty(unsized_ty);
|
||||
let trait_ref =
|
||||
Rc::new(ty::TraitRef { def_id: def_id,
|
||||
Rc::new(ty::TraitRef { def_id: principal.def_id,
|
||||
substs: substs });
|
||||
let trait_ref =
|
||||
trait_ref.subst(bcx.tcx(), &bcx.fcx.param_substs.substs);
|
||||
|
@ -378,14 +378,14 @@ pub fn type_of_adjust(cx: &ctxt, adj: &AutoAdjustment) -> Option<t> {
|
||||
fn type_of_autoref(cx: &ctxt, autoref: &AutoRef) -> Option<t> {
|
||||
match autoref {
|
||||
&AutoUnsize(ref k) => match k {
|
||||
&UnsizeVtable(TyTrait { def_id, ref substs, bounds }, _) => {
|
||||
Some(mk_trait(cx, def_id, substs.clone(), bounds))
|
||||
&UnsizeVtable(TyTrait { ref principal, bounds }, _) => {
|
||||
Some(mk_trait(cx, (*principal).clone(), bounds))
|
||||
}
|
||||
_ => None
|
||||
},
|
||||
&AutoUnsizeUniq(ref k) => match k {
|
||||
&UnsizeVtable(TyTrait { def_id, ref substs, bounds }, _) => {
|
||||
Some(mk_uniq(cx, mk_trait(cx, def_id, substs.clone(), bounds)))
|
||||
&UnsizeVtable(TyTrait { ref principal, bounds }, _) => {
|
||||
Some(mk_uniq(cx, mk_trait(cx, (*principal).clone(), bounds)))
|
||||
}
|
||||
_ => None
|
||||
},
|
||||
@ -983,12 +983,12 @@ pub enum sty {
|
||||
|
||||
#[deriving(Clone, PartialEq, Eq, Hash, Show)]
|
||||
pub struct TyTrait {
|
||||
pub def_id: DefId,
|
||||
pub substs: Substs,
|
||||
// Principal trait reference.
|
||||
pub principal: TraitRef, // would use Rc<TraitRef>, but it runs afoul of some static rules
|
||||
pub bounds: ExistentialBounds
|
||||
}
|
||||
|
||||
#[deriving(PartialEq, Eq, Hash, Show)]
|
||||
#[deriving(Clone, PartialEq, Eq, Hash, Show)]
|
||||
pub struct TraitRef {
|
||||
pub def_id: DefId,
|
||||
pub substs: Substs,
|
||||
@ -1643,8 +1643,8 @@ pub fn mk_t(cx: &ctxt, st: sty) -> t {
|
||||
&ty_enum(_, ref substs) | &ty_struct(_, ref substs) => {
|
||||
flags = flags | sflags(substs);
|
||||
}
|
||||
&ty_trait(box TyTrait { ref substs, ref bounds, .. }) => {
|
||||
flags = flags | sflags(substs);
|
||||
&ty_trait(box TyTrait { ref principal, ref bounds }) => {
|
||||
flags = flags | sflags(&principal.substs);
|
||||
flags = flags | flags_for_bounds(bounds);
|
||||
}
|
||||
&ty_uniq(tt) | &ty_vec(tt, _) | &ty_open(tt) => {
|
||||
@ -1874,14 +1874,12 @@ pub fn mk_ctor_fn(cx: &ctxt,
|
||||
|
||||
|
||||
pub fn mk_trait(cx: &ctxt,
|
||||
did: ast::DefId,
|
||||
substs: Substs,
|
||||
principal: ty::TraitRef,
|
||||
bounds: ExistentialBounds)
|
||||
-> t {
|
||||
// take a copy of substs so that we own the vectors inside
|
||||
let inner = box TyTrait {
|
||||
def_id: did,
|
||||
substs: substs,
|
||||
principal: principal,
|
||||
bounds: bounds
|
||||
};
|
||||
mk_t(cx, ty_trait(inner))
|
||||
@ -1934,9 +1932,15 @@ pub fn maybe_walk_ty(ty: t, f: |t| -> bool) {
|
||||
ty_ptr(ref tm) | ty_rptr(_, ref tm) => {
|
||||
maybe_walk_ty(tm.ty, f);
|
||||
}
|
||||
ty_enum(_, ref substs) | ty_struct(_, ref substs) | ty_unboxed_closure(_, _, ref substs) |
|
||||
ty_trait(box TyTrait { ref substs, .. }) => {
|
||||
for subty in (*substs).types.iter() {
|
||||
ty_trait(box TyTrait { ref principal, .. }) => {
|
||||
for subty in principal.substs.types.iter() {
|
||||
maybe_walk_ty(*subty, |x| f(x));
|
||||
}
|
||||
}
|
||||
ty_enum(_, ref substs) |
|
||||
ty_struct(_, ref substs) |
|
||||
ty_unboxed_closure(_, _, ref substs) => {
|
||||
for subty in substs.types.iter() {
|
||||
maybe_walk_ty(*subty, |x| f(x));
|
||||
}
|
||||
}
|
||||
@ -3554,8 +3558,8 @@ pub fn unsize_ty(cx: &ctxt,
|
||||
format!("UnsizeStruct with bad sty: {}",
|
||||
ty_to_string(cx, ty)).as_slice())
|
||||
},
|
||||
&UnsizeVtable(TyTrait { def_id, ref substs, bounds }, _) => {
|
||||
mk_trait(cx, def_id, substs.clone(), bounds)
|
||||
&UnsizeVtable(TyTrait { ref principal, bounds }, _) => {
|
||||
mk_trait(cx, (*principal).clone(), bounds)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3808,7 +3812,7 @@ pub fn ty_sort_string(cx: &ctxt, t: t) -> String {
|
||||
ty_bare_fn(_) => "extern fn".to_string(),
|
||||
ty_closure(_) => "fn".to_string(),
|
||||
ty_trait(ref inner) => {
|
||||
format!("trait {}", item_path_str(cx, inner.def_id))
|
||||
format!("trait {}", item_path_str(cx, inner.principal.def_id))
|
||||
}
|
||||
ty_struct(id, _) => {
|
||||
format!("struct {}", item_path_str(cx, id))
|
||||
@ -4230,11 +4234,14 @@ pub fn try_add_builtin_trait(
|
||||
|
||||
pub fn ty_to_def_id(ty: t) -> Option<ast::DefId> {
|
||||
match get(ty).sty {
|
||||
ty_trait(box TyTrait { def_id: id, .. }) |
|
||||
ty_trait(ref tt) =>
|
||||
Some(tt.principal.def_id),
|
||||
ty_struct(id, _) |
|
||||
ty_enum(id, _) |
|
||||
ty_unboxed_closure(id, _, _) => Some(id),
|
||||
_ => None
|
||||
ty_unboxed_closure(id, _, _) =>
|
||||
Some(id),
|
||||
_ =>
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
@ -5213,9 +5220,9 @@ pub fn hash_crate_independent(tcx: &ctxt, t: t, svh: &Svh) -> u64 {
|
||||
}
|
||||
}
|
||||
}
|
||||
ty_trait(box TyTrait { def_id: d, bounds, .. }) => {
|
||||
ty_trait(box TyTrait { ref principal, bounds }) => {
|
||||
byte!(17);
|
||||
did(&mut state, d);
|
||||
did(&mut state, principal.def_id);
|
||||
hash!(bounds);
|
||||
}
|
||||
ty_struct(d, _) => {
|
||||
@ -5504,12 +5511,13 @@ pub fn accumulate_lifetimes_in_type(accumulator: &mut Vec<ty::Region>,
|
||||
typ: t) {
|
||||
walk_ty(typ, |typ| {
|
||||
match get(typ).sty {
|
||||
ty_rptr(region, _) => accumulator.push(region),
|
||||
ty_rptr(region, _) => {
|
||||
accumulator.push(region)
|
||||
}
|
||||
ty_trait(ref t) => {
|
||||
accumulator.push_all(t.principal.substs.regions().as_slice());
|
||||
}
|
||||
ty_enum(_, ref substs) |
|
||||
ty_trait(box TyTrait {
|
||||
ref substs,
|
||||
..
|
||||
}) |
|
||||
ty_struct(_, ref substs) => {
|
||||
accum_substs(accumulator, substs);
|
||||
}
|
||||
@ -5538,7 +5546,8 @@ pub fn accumulate_lifetimes_in_type(accumulator: &mut Vec<ty::Region>,
|
||||
ty_param(_) |
|
||||
ty_infer(_) |
|
||||
ty_open(_) |
|
||||
ty_err => {}
|
||||
ty_err => {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -373,12 +373,11 @@ impl TypeFoldable for ty::UnsizeKind {
|
||||
match *self {
|
||||
ty::UnsizeLength(len) => ty::UnsizeLength(len),
|
||||
ty::UnsizeStruct(box ref k, n) => ty::UnsizeStruct(box k.fold_with(folder), n),
|
||||
ty::UnsizeVtable(ty::TyTrait{bounds, def_id, ref substs}, self_ty) => {
|
||||
ty::UnsizeVtable(ty::TyTrait{ref principal, bounds}, self_ty) => {
|
||||
ty::UnsizeVtable(
|
||||
ty::TyTrait {
|
||||
principal: principal.fold_with(folder),
|
||||
bounds: bounds.fold_with(folder),
|
||||
def_id: def_id,
|
||||
substs: substs.fold_with(folder)
|
||||
},
|
||||
self_ty.fold_with(folder))
|
||||
}
|
||||
@ -531,15 +530,10 @@ pub fn super_fold_sty<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
|
||||
ty::ty_enum(tid, ref substs) => {
|
||||
ty::ty_enum(tid, substs.fold_with(this))
|
||||
}
|
||||
ty::ty_trait(box ty::TyTrait {
|
||||
def_id,
|
||||
ref substs,
|
||||
bounds
|
||||
}) => {
|
||||
ty::ty_trait(box ty::TyTrait { ref principal, bounds }) => {
|
||||
ty::ty_trait(box ty::TyTrait {
|
||||
def_id: def_id,
|
||||
substs: substs.fold_with(this),
|
||||
bounds: this.fold_existential_bounds(bounds),
|
||||
principal: (*principal).fold_with(this),
|
||||
bounds: bounds.fold_with(this),
|
||||
})
|
||||
}
|
||||
ty::ty_tup(ref ts) => {
|
||||
|
@ -51,8 +51,6 @@
|
||||
|
||||
use middle::const_eval;
|
||||
use middle::def;
|
||||
use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem};
|
||||
use middle::lang_items::{FnOnceTraitLangItem};
|
||||
use middle::resolve_lifetime as rl;
|
||||
use middle::subst::{FnSpace, TypeSpace, AssocSpace, SelfSpace, Subst, Substs};
|
||||
use middle::subst::{VecPerParamSpace};
|
||||
@ -398,6 +396,46 @@ fn ast_path_substs<'tcx,AC,RS>(
|
||||
}
|
||||
}
|
||||
|
||||
pub fn instantiate_trait_ref<'tcx,AC,RS>(this: &AC,
|
||||
rscope: &RS,
|
||||
ast_trait_ref: &ast::TraitRef,
|
||||
self_ty: Option<ty::t>,
|
||||
associated_type: Option<ty::t>)
|
||||
-> Rc<ty::TraitRef>
|
||||
where AC: AstConv<'tcx>,
|
||||
RS: RegionScope
|
||||
{
|
||||
/*!
|
||||
* Instantiates the path for the given trait reference, assuming that
|
||||
* it's bound to a valid trait type. Returns the def_id for the defining
|
||||
* trait. Fails if the type is a type other than a trait type.
|
||||
*/
|
||||
|
||||
match lookup_def_tcx(this.tcx(),
|
||||
ast_trait_ref.path.span,
|
||||
ast_trait_ref.ref_id) {
|
||||
def::DefTrait(trait_did) => {
|
||||
let trait_ref =
|
||||
Rc::new(ast_path_to_trait_ref(this,
|
||||
rscope,
|
||||
trait_did,
|
||||
self_ty,
|
||||
associated_type,
|
||||
&ast_trait_ref.path,
|
||||
ast_trait_ref.ref_id));
|
||||
|
||||
this.tcx().trait_refs.borrow_mut().insert(ast_trait_ref.ref_id,
|
||||
trait_ref.clone());
|
||||
trait_ref
|
||||
}
|
||||
_ => {
|
||||
this.tcx().sess.span_fatal(
|
||||
ast_trait_ref.path.span,
|
||||
format!("`{}` is not a trait", ast_trait_ref.path.user_string(this.tcx()))[]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ast_path_to_trait_ref<'tcx,AC,RS>(this: &AC,
|
||||
rscope: &RS,
|
||||
trait_def_id: ast::DefId,
|
||||
@ -405,11 +443,11 @@ pub fn ast_path_to_trait_ref<'tcx,AC,RS>(this: &AC,
|
||||
associated_type: Option<ty::t>,
|
||||
path: &ast::Path,
|
||||
binder_id: ast::NodeId)
|
||||
-> Rc<ty::TraitRef>
|
||||
-> ty::TraitRef
|
||||
where AC: AstConv<'tcx>,
|
||||
RS: RegionScope {
|
||||
let trait_def = this.get_trait_def(trait_def_id);
|
||||
Rc::new(ty::TraitRef {
|
||||
ty::TraitRef {
|
||||
def_id: trait_def_id,
|
||||
substs: ast_path_substs(this,
|
||||
rscope,
|
||||
@ -419,7 +457,7 @@ pub fn ast_path_to_trait_ref<'tcx,AC,RS>(this: &AC,
|
||||
associated_type,
|
||||
path,
|
||||
binder_id)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ast_path_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||
@ -620,41 +658,6 @@ enum PointerTy {
|
||||
Uniq
|
||||
}
|
||||
|
||||
pub fn trait_ref_for_unboxed_function<'tcx, AC: AstConv<'tcx>,
|
||||
RS:RegionScope>(
|
||||
this: &AC,
|
||||
rscope: &RS,
|
||||
kind: ast::UnboxedClosureKind,
|
||||
decl: &ast::FnDecl,
|
||||
self_ty: Option<ty::t>)
|
||||
-> ty::TraitRef {
|
||||
let lang_item = match kind {
|
||||
ast::FnUnboxedClosureKind => FnTraitLangItem,
|
||||
ast::FnMutUnboxedClosureKind => FnMutTraitLangItem,
|
||||
ast::FnOnceUnboxedClosureKind => FnOnceTraitLangItem,
|
||||
};
|
||||
let trait_did = this.tcx().lang_items.require(lang_item).unwrap();
|
||||
let input_types = decl.inputs
|
||||
.iter()
|
||||
.map(|input| {
|
||||
ast_ty_to_ty(this, rscope, &*input.ty)
|
||||
}).collect::<Vec<_>>();
|
||||
let input_tuple = ty::mk_tup_or_nil(this.tcx(), input_types);
|
||||
let output_type = ast_ty_to_ty(this, rscope, &*decl.output);
|
||||
let mut substs = Substs::new_type(vec!(input_tuple, output_type),
|
||||
Vec::new());
|
||||
|
||||
match self_ty {
|
||||
Some(s) => substs.types.push(SelfSpace, s),
|
||||
None => ()
|
||||
}
|
||||
|
||||
ty::TraitRef {
|
||||
def_id: trait_did,
|
||||
substs: substs,
|
||||
}
|
||||
}
|
||||
|
||||
// Handle `~`, `Box`, and `&` being able to mean strs and vecs.
|
||||
// If a_seq_ty is a str or a vec, make it a str/vec.
|
||||
// Also handle first-class trait types.
|
||||
@ -702,26 +705,17 @@ fn mk_pointer<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||
None,
|
||||
path,
|
||||
id);
|
||||
let bounds = match *opt_bounds {
|
||||
None => {
|
||||
conv_existential_bounds(this,
|
||||
rscope,
|
||||
path.span,
|
||||
[result.clone()].as_slice(),
|
||||
[].as_slice())
|
||||
}
|
||||
Some(ref bounds) => {
|
||||
conv_existential_bounds(this,
|
||||
rscope,
|
||||
path.span,
|
||||
[result.clone()].as_slice(),
|
||||
bounds.as_slice())
|
||||
}
|
||||
};
|
||||
let empty_vec = [];
|
||||
let bounds = match *opt_bounds { None => empty_vec.as_slice(),
|
||||
Some(ref bounds) => bounds.as_slice() };
|
||||
let existential_bounds = conv_existential_bounds(this,
|
||||
rscope,
|
||||
path.span,
|
||||
&[Rc::new(result.clone())],
|
||||
bounds);
|
||||
let tr = ty::mk_trait(tcx,
|
||||
result.def_id,
|
||||
result.substs.clone(),
|
||||
bounds);
|
||||
result,
|
||||
existential_bounds);
|
||||
return match ptr_ty {
|
||||
Uniq => {
|
||||
return ty::mk_uniq(tcx, tr);
|
||||
@ -907,6 +901,16 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||
|
||||
ty::mk_closure(tcx, fn_decl)
|
||||
}
|
||||
ast::TyPolyTraitRef(ref data) => {
|
||||
// FIXME(#18639) this is just a placeholder for code to come
|
||||
let principal = instantiate_trait_ref(this, rscope, &data.trait_ref, None, None);
|
||||
let bounds = conv_existential_bounds(this,
|
||||
rscope,
|
||||
ast_ty.span,
|
||||
&[principal.clone()],
|
||||
&[]);
|
||||
ty::mk_trait(tcx, (*principal).clone(), bounds)
|
||||
}
|
||||
ast::TyPath(ref path, ref bounds, id) => {
|
||||
let a_def = match tcx.def_map.borrow().get(&id) {
|
||||
None => {
|
||||
@ -943,11 +947,10 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||
let bounds = conv_existential_bounds(this,
|
||||
rscope,
|
||||
ast_ty.span,
|
||||
&[result.clone()],
|
||||
&[Rc::new(result.clone())],
|
||||
ast_bounds);
|
||||
ty::mk_trait(tcx,
|
||||
result.def_id,
|
||||
result.substs.clone(),
|
||||
result,
|
||||
bounds)
|
||||
}
|
||||
def::DefTy(did, _) | def::DefStruct(did) => {
|
||||
@ -1546,6 +1549,7 @@ pub fn partition_bounds<'a>(tcx: &ty::ctxt,
|
||||
for &ast_bound in ast_bounds.iter() {
|
||||
match *ast_bound {
|
||||
ast::TraitTyParamBound(ref b) => {
|
||||
let b = &b.trait_ref; // FIXME
|
||||
match lookup_def_tcx(tcx, b.path.span, b.ref_id) {
|
||||
def::DefTrait(trait_did) => {
|
||||
match trait_def_ids.get(&trait_did) {
|
||||
|
@ -632,9 +632,9 @@ impl<'a, 'tcx> LookupContext<'a, 'tcx> {
|
||||
let span = self.self_expr.map_or(self.span, |e| e.span);
|
||||
check::autoderef(self.fcx, span, self_ty, None, NoPreference, |self_ty, _| {
|
||||
match get(self_ty).sty {
|
||||
ty_trait(box TyTrait { def_id, ref substs, bounds, .. }) => {
|
||||
self.push_inherent_candidates_from_object(self_ty, def_id, substs, bounds);
|
||||
self.push_inherent_impl_candidates_for_type(def_id);
|
||||
ty_trait(box TyTrait { ref principal, bounds, .. }) => {
|
||||
self.push_inherent_candidates_from_object(self_ty, &*principal, bounds);
|
||||
self.push_inherent_impl_candidates_for_type(principal.def_id);
|
||||
}
|
||||
ty_enum(did, _) |
|
||||
ty_struct(did, _) |
|
||||
@ -744,24 +744,23 @@ impl<'a, 'tcx> LookupContext<'a, 'tcx> {
|
||||
|
||||
fn push_inherent_candidates_from_object(&mut self,
|
||||
self_ty: ty::t,
|
||||
did: DefId,
|
||||
substs: &subst::Substs,
|
||||
principal: &ty::TraitRef,
|
||||
_bounds: ty::ExistentialBounds) {
|
||||
debug!("push_inherent_candidates_from_object(self_ty={})",
|
||||
self_ty.repr(self.tcx()));
|
||||
|
||||
let tcx = self.tcx();
|
||||
|
||||
// It is illegal to invoke a method on a trait instance that refers to
|
||||
// the `Self` type. Here, we use a substitution that replaces `Self`
|
||||
// with the object type itself. Hence, a `&self` method will wind up
|
||||
// with an argument type like `&Trait`.
|
||||
let rcvr_substs = substs.with_self_ty(self_ty);
|
||||
|
||||
let trait_ref = Rc::new(TraitRef {
|
||||
def_id: did,
|
||||
substs: rcvr_substs.clone()
|
||||
});
|
||||
// It is illegal to invoke a method on a trait instance that
|
||||
// refers to the `Self` type. An error will be reported by
|
||||
// `enforce_object_limitations()` if the method refers to the
|
||||
// `Self` type anywhere other than the receiver. Here, we use
|
||||
// a substitution that replaces `Self` with the object type
|
||||
// itself. Hence, a `&self` method will wind up with an
|
||||
// argument type like `&Trait`.
|
||||
let rcvr_substs = principal.substs.with_self_ty(self_ty);
|
||||
let trait_ref = Rc::new(TraitRef { def_id: principal.def_id,
|
||||
substs: rcvr_substs.clone() });
|
||||
|
||||
self.push_inherent_candidates_from_bounds_inner(
|
||||
&[trait_ref.clone()],
|
||||
@ -796,7 +795,7 @@ impl<'a, 'tcx> LookupContext<'a, 'tcx> {
|
||||
method_ty: m,
|
||||
origin: MethodTraitObject(MethodObject {
|
||||
trait_ref: new_trait_ref,
|
||||
object_trait_id: did,
|
||||
object_trait_id: principal.def_id,
|
||||
method_num: method_num,
|
||||
real_index: vtable_index
|
||||
})
|
||||
@ -1151,17 +1150,19 @@ impl<'a, 'tcx> LookupContext<'a, 'tcx> {
|
||||
fn auto_slice_trait(&self, ty: ty::t, autoderefs: uint) -> Option<MethodResult> {
|
||||
debug!("auto_slice_trait");
|
||||
match ty::get(ty).sty {
|
||||
ty_trait(box ty::TyTrait {
|
||||
def_id: trt_did,
|
||||
substs: ref trt_substs,
|
||||
bounds: b,
|
||||
.. }) => {
|
||||
ty_trait(box ty::TyTrait { ref principal,
|
||||
bounds: b,
|
||||
.. }) => {
|
||||
let trt_did = principal.def_id;
|
||||
let trt_substs = &principal.substs;
|
||||
let tcx = self.tcx();
|
||||
self.search_for_some_kind_of_autorefd_method(
|
||||
|r, m| AutoPtr(r, m, None),
|
||||
autoderefs, [MutImmutable, MutMutable],
|
||||
|m, r| {
|
||||
let tr = ty::mk_trait(tcx, trt_did, trt_substs.clone(), b);
|
||||
let principal = ty::TraitRef::new(trt_did,
|
||||
trt_substs.clone());
|
||||
let tr = ty::mk_trait(tcx, principal, b);
|
||||
ty::mk_rptr(tcx, r, ty::mt{ ty: tr, mutbl: m })
|
||||
})
|
||||
}
|
||||
|
@ -140,11 +140,11 @@ pub fn check_object_safety(tcx: &ty::ctxt, object_trait: &ty::TyTrait, span: Spa
|
||||
// `call_once` which is the method which takes self by value. What could go
|
||||
// wrong?
|
||||
match tcx.lang_items.fn_once_trait() {
|
||||
Some(def_id) if def_id == object_trait.def_id => return,
|
||||
Some(def_id) if def_id == object_trait.principal.def_id => return,
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let trait_items = ty::trait_items(tcx, object_trait.def_id);
|
||||
let trait_items = ty::trait_items(tcx, object_trait.principal.def_id);
|
||||
|
||||
let mut errors = Vec::new();
|
||||
for item in trait_items.iter() {
|
||||
@ -158,7 +158,7 @@ pub fn check_object_safety(tcx: &ty::ctxt, object_trait: &ty::TyTrait, span: Spa
|
||||
|
||||
let mut errors = errors.iter().flat_map(|x| x.iter()).peekable();
|
||||
if errors.peek().is_some() {
|
||||
let trait_name = ty::item_path_str(tcx, object_trait.def_id);
|
||||
let trait_name = ty::item_path_str(tcx, object_trait.principal.def_id);
|
||||
span_err!(tcx.sess, span, E0038,
|
||||
"cannot convert to a trait object because trait `{}` is not object-safe",
|
||||
trait_name);
|
||||
@ -241,8 +241,7 @@ pub fn register_object_cast_obligations(fcx: &FnCtxt,
|
||||
// needs some refactoring so there is a more convenient type to pass around.
|
||||
let object_trait_ty =
|
||||
ty::mk_trait(fcx.tcx(),
|
||||
object_trait.def_id,
|
||||
object_trait.substs.clone(),
|
||||
object_trait.principal.clone(),
|
||||
object_trait.bounds);
|
||||
|
||||
debug!("register_object_cast_obligations: referent_ty={} object_trait_ty={}",
|
||||
@ -252,13 +251,13 @@ pub fn register_object_cast_obligations(fcx: &FnCtxt,
|
||||
// Take the type parameters from the object type, but set
|
||||
// the Self type (which is unknown, for the object type)
|
||||
// to be the type we are casting from.
|
||||
let mut object_substs = object_trait.substs.clone();
|
||||
let mut object_substs = object_trait.principal.substs.clone();
|
||||
assert!(object_substs.self_ty().is_none());
|
||||
object_substs.types.push(SelfSpace, referent_ty);
|
||||
|
||||
// Create the obligation for casting from T to Trait.
|
||||
let object_trait_ref =
|
||||
Rc::new(ty::TraitRef { def_id: object_trait.def_id,
|
||||
Rc::new(ty::TraitRef { def_id: object_trait.principal.def_id,
|
||||
substs: object_substs });
|
||||
let object_obligation =
|
||||
Obligation::new(
|
||||
|
@ -112,8 +112,8 @@ fn get_base_type_def_id(inference_context: &InferCtxt,
|
||||
ty_rptr(_, ty::mt {ty, ..}) |
|
||||
ty_uniq(ty) => {
|
||||
match ty::get(ty).sty {
|
||||
ty_trait(box ty::TyTrait { def_id, .. }) => {
|
||||
Some(def_id)
|
||||
ty_trait(box ty::TyTrait { ref principal, .. }) => {
|
||||
Some(principal.def_id)
|
||||
}
|
||||
_ => {
|
||||
panic!("get_base_type() returned a type that wasn't an \
|
||||
@ -121,8 +121,8 @@ fn get_base_type_def_id(inference_context: &InferCtxt,
|
||||
}
|
||||
}
|
||||
}
|
||||
ty_trait(box ty::TyTrait { def_id, .. }) => {
|
||||
Some(def_id)
|
||||
ty_trait(box ty::TyTrait { ref principal, .. }) => {
|
||||
Some(principal.def_id)
|
||||
}
|
||||
_ => {
|
||||
panic!("get_base_type() returned a type that wasn't an \
|
||||
|
@ -18,6 +18,7 @@ use middle::ty;
|
||||
use syntax::ast::{Item, ItemImpl};
|
||||
use syntax::ast;
|
||||
use syntax::ast_util;
|
||||
use syntax::codemap::Span;
|
||||
use syntax::visit;
|
||||
use util::ppaux::Repr;
|
||||
|
||||
@ -30,6 +31,17 @@ struct OrphanChecker<'cx, 'tcx:'cx> {
|
||||
tcx: &'cx ty::ctxt<'tcx>
|
||||
}
|
||||
|
||||
impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
|
||||
fn check_def_id(&self, span: Span, def_id: ast::DefId) {
|
||||
if def_id.krate != ast::LOCAL_CRATE {
|
||||
span_err!(self.tcx.sess, span, E0116,
|
||||
"cannot associate methods with a type outside the \
|
||||
crate the type is defined in; define and implement \
|
||||
a trait or new type instead");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> {
|
||||
fn visit_item(&mut self, item: &'v ast::Item) {
|
||||
let def_id = ast_util::local_def(item.id);
|
||||
@ -41,14 +53,11 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> {
|
||||
let self_ty = ty::lookup_item_type(self.tcx, def_id).ty;
|
||||
match ty::get(self_ty).sty {
|
||||
ty::ty_enum(def_id, _) |
|
||||
ty::ty_struct(def_id, _) |
|
||||
ty::ty_trait(box ty::TyTrait{ def_id, ..}) => {
|
||||
if def_id.krate != ast::LOCAL_CRATE {
|
||||
span_err!(self.tcx.sess, item.span, E0116,
|
||||
"cannot associate methods with a type outside the \
|
||||
crate the type is defined in; define and implement \
|
||||
a trait or new type instead");
|
||||
}
|
||||
ty::ty_struct(def_id, _) => {
|
||||
self.check_def_id(item.span, def_id);
|
||||
}
|
||||
ty::ty_trait(box ty::TyTrait{ ref principal, ..}) => {
|
||||
self.check_def_id(item.span, principal.def_id);
|
||||
}
|
||||
_ => {
|
||||
span_err!(self.tcx.sess, item.span, E0118,
|
||||
|
@ -61,7 +61,6 @@ use syntax::ast_util::{local_def, PostExpansionMethod};
|
||||
use syntax::codemap::Span;
|
||||
use syntax::parse::token::{special_idents};
|
||||
use syntax::parse::token;
|
||||
use syntax::print::pprust::{path_to_string};
|
||||
use syntax::ptr::P;
|
||||
use syntax::visit;
|
||||
|
||||
@ -633,24 +632,33 @@ pub fn ensure_no_ty_param_bounds(ccx: &CrateCtxt,
|
||||
span: Span,
|
||||
generics: &ast::Generics,
|
||||
thing: &'static str) {
|
||||
let mut warn = false;
|
||||
|
||||
for ty_param in generics.ty_params.iter() {
|
||||
let bounds = ty_param.bounds.iter();
|
||||
let mut bounds = bounds.chain(ty_param.unbound.iter());
|
||||
for bound in bounds {
|
||||
for bound in ty_param.bounds.iter() {
|
||||
match *bound {
|
||||
ast::TraitTyParamBound(..) => {
|
||||
// According to accepted RFC #XXX, we should
|
||||
// eventually accept these, but it will not be
|
||||
// part of this PR. Still, convert to warning to
|
||||
// make bootstrapping easier.
|
||||
span_warn!(ccx.tcx.sess, span, E0122,
|
||||
"trait bounds are not (yet) enforced \
|
||||
in {} definitions",
|
||||
thing);
|
||||
warn = true;
|
||||
}
|
||||
ast::RegionTyParamBound(..) => { }
|
||||
}
|
||||
}
|
||||
|
||||
match ty_param.unbound {
|
||||
Some(_) => { warn = true; }
|
||||
None => { }
|
||||
}
|
||||
}
|
||||
|
||||
if warn {
|
||||
// According to accepted RFC #XXX, we should
|
||||
// eventually accept these, but it will not be
|
||||
// part of this PR. Still, convert to warning to
|
||||
// make bootstrapping easier.
|
||||
span_warn!(ccx.tcx.sess, span, E0122,
|
||||
"trait bounds are not (yet) enforced \
|
||||
in {} definitions",
|
||||
thing);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1147,7 +1155,8 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
|
||||
parent_visibility);
|
||||
|
||||
for trait_ref in opt_trait_ref.iter() {
|
||||
instantiate_trait_ref(&icx, trait_ref, selfty, None);
|
||||
astconv::instantiate_trait_ref(&icx, &ExplicitRscope, trait_ref,
|
||||
Some(selfty), None);
|
||||
}
|
||||
},
|
||||
ast::ItemTrait(_, _, _, ref trait_methods) => {
|
||||
@ -1315,47 +1324,6 @@ pub fn convert_foreign(ccx: &CrateCtxt, i: &ast::ForeignItem) {
|
||||
ccx.tcx.tcache.borrow_mut().insert(local_def(i.id), pty);
|
||||
}
|
||||
|
||||
pub fn instantiate_trait_ref<'tcx,AC>(this: &AC,
|
||||
ast_trait_ref: &ast::TraitRef,
|
||||
self_ty: ty::t,
|
||||
associated_type: Option<ty::t>)
|
||||
-> Rc<ty::TraitRef>
|
||||
where AC: AstConv<'tcx> {
|
||||
/*!
|
||||
* Instantiates the path for the given trait reference, assuming that
|
||||
* it's bound to a valid trait type. Returns the def_id for the defining
|
||||
* trait. Fails if the type is a type other than a trait type.
|
||||
*/
|
||||
|
||||
// FIXME(#5121) -- distinguish early vs late lifetime params
|
||||
let rscope = ExplicitRscope;
|
||||
|
||||
match lookup_def_tcx(this.tcx(),
|
||||
ast_trait_ref.path.span,
|
||||
ast_trait_ref.ref_id) {
|
||||
def::DefTrait(trait_did) => {
|
||||
let trait_ref =
|
||||
astconv::ast_path_to_trait_ref(this,
|
||||
&rscope,
|
||||
trait_did,
|
||||
Some(self_ty),
|
||||
associated_type,
|
||||
&ast_trait_ref.path,
|
||||
ast_trait_ref.ref_id);
|
||||
|
||||
this.tcx().trait_refs.borrow_mut().insert(ast_trait_ref.ref_id,
|
||||
trait_ref.clone());
|
||||
trait_ref
|
||||
}
|
||||
_ => {
|
||||
this.tcx().sess.span_fatal(
|
||||
ast_trait_ref.path.span,
|
||||
format!("`{}` is not a trait",
|
||||
path_to_string(&ast_trait_ref.path)).as_slice());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_trait_def(ccx: &CrateCtxt, trait_id: ast::DefId) -> Rc<ty::TraitDef> {
|
||||
if trait_id.krate != ast::LOCAL_CRATE {
|
||||
return ty::lookup_trait_def(ccx.tcx, trait_id)
|
||||
@ -1720,14 +1688,14 @@ fn ty_generics_for_fn_or_method<'tcx,AC>(
|
||||
|
||||
// Add the Sized bound, unless the type parameter is marked as `Sized?`.
|
||||
fn add_unsized_bound<'tcx,AC>(this: &AC,
|
||||
unbound: &Option<ast::TyParamBound>,
|
||||
unbound: &Option<ast::TraitRef>,
|
||||
bounds: &mut ty::BuiltinBounds,
|
||||
desc: &str,
|
||||
span: Span)
|
||||
where AC: AstConv<'tcx> {
|
||||
let kind_id = this.tcx().lang_items.require(SizedTraitLangItem);
|
||||
match unbound {
|
||||
&Some(ast::TraitTyParamBound(ref tpb)) => {
|
||||
&Some(ref tpb) => {
|
||||
// FIXME(#8559) currently requires the unbound to be built-in.
|
||||
let trait_def_id = ty::trait_ref_to_def_id(this.tcx(), tpb);
|
||||
match kind_id {
|
||||
@ -1752,7 +1720,7 @@ fn add_unsized_bound<'tcx,AC>(this: &AC,
|
||||
ty::try_add_builtin_trait(this.tcx(), kind_id.unwrap(), bounds);
|
||||
}
|
||||
// No lang item for Sized, so we can't add it as a bound.
|
||||
_ => {}
|
||||
&None => {}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1870,11 +1838,11 @@ fn ty_generics<'tcx,AC>(this: &AC,
|
||||
|
||||
let trait_def_id =
|
||||
match lookup_def_tcx(this.tcx(),
|
||||
ast_trait_ref.path.span,
|
||||
ast_trait_ref.ref_id) {
|
||||
ast_trait_ref.trait_ref.path.span,
|
||||
ast_trait_ref.trait_ref.ref_id) {
|
||||
def::DefTrait(trait_def_id) => trait_def_id,
|
||||
_ => {
|
||||
this.tcx().sess.span_bug(ast_trait_ref.path.span,
|
||||
this.tcx().sess.span_bug(ast_trait_ref.trait_ref.path.span,
|
||||
"not a trait?!")
|
||||
}
|
||||
};
|
||||
@ -1972,7 +1940,7 @@ fn compute_bounds<'tcx,AC>(this: &AC,
|
||||
name_of_bounded_thing: ast::Name,
|
||||
param_ty: ty::ParamTy,
|
||||
ast_bounds: &[ast::TyParamBound],
|
||||
unbound: &Option<ast::TyParamBound>,
|
||||
unbound: &Option<ast::TraitRef>,
|
||||
span: Span,
|
||||
where_clause: &ast::WhereClause)
|
||||
-> ty::ParamBounds
|
||||
@ -2047,10 +2015,11 @@ fn conv_param_bounds<'tcx,AC>(this: &AC,
|
||||
let trait_bounds: Vec<Rc<ty::TraitRef>> =
|
||||
trait_bounds.into_iter()
|
||||
.map(|b| {
|
||||
instantiate_trait_ref(this,
|
||||
b,
|
||||
param_ty.to_ty(this.tcx()),
|
||||
Some(param_ty.to_ty(this.tcx())))
|
||||
astconv::instantiate_trait_ref(this,
|
||||
&ExplicitRscope,
|
||||
b,
|
||||
Some(param_ty.to_ty(this.tcx())),
|
||||
Some(param_ty.to_ty(this.tcx())))
|
||||
})
|
||||
.collect();
|
||||
let region_bounds: Vec<ty::Region> =
|
||||
|
@ -413,15 +413,14 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||
let ty = ty::mk_vec(tcx, t_a, None);
|
||||
Some((ty, ty::UnsizeLength(len)))
|
||||
}
|
||||
(&ty::ty_trait(..), &ty::ty_trait(..)) => None,
|
||||
(_, &ty::ty_trait(box ty::TyTrait { def_id, ref substs, bounds })) => {
|
||||
let ty = ty::mk_trait(tcx,
|
||||
def_id,
|
||||
substs.clone(),
|
||||
bounds);
|
||||
Some((ty, ty::UnsizeVtable(ty::TyTrait { def_id: def_id,
|
||||
bounds: bounds,
|
||||
substs: substs.clone() },
|
||||
(&ty::ty_trait(..), &ty::ty_trait(..)) => {
|
||||
None
|
||||
}
|
||||
(_, &ty::ty_trait(box ty::TyTrait { ref principal, bounds })) => {
|
||||
// FIXME what is the purpose of `ty`?
|
||||
let ty = ty::mk_trait(tcx, (*principal).clone(), bounds);
|
||||
Some((ty, ty::UnsizeVtable(ty::TyTrait { principal: (*principal).clone(),
|
||||
bounds: bounds },
|
||||
ty_a)))
|
||||
}
|
||||
(&ty::ty_struct(did_a, ref substs_a), &ty::ty_struct(did_b, ref substs_b))
|
||||
@ -524,16 +523,10 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||
|
||||
match *sty_a {
|
||||
ty::ty_rptr(_, ty::mt{ty, mutbl}) => match ty::get(ty).sty {
|
||||
ty::ty_trait(box ty::TyTrait {
|
||||
def_id,
|
||||
ref substs,
|
||||
bounds,
|
||||
..
|
||||
}) =>
|
||||
{
|
||||
ty::ty_trait(box ty::TyTrait { ref principal, bounds }) => {
|
||||
debug!("mutbl={} b_mutbl={}", mutbl, b_mutbl);
|
||||
|
||||
let tr = ty::mk_trait(tcx, def_id, substs.clone(), bounds);
|
||||
// FIXME what is purpose of this type `tr`?
|
||||
let tr = ty::mk_trait(tcx, (*principal).clone(), bounds);
|
||||
try!(self.subtype(mk_ty(tr), b));
|
||||
Ok(Some(AdjustDerefRef(AutoDerefRef {
|
||||
autoderefs: 1,
|
||||
|
@ -52,7 +52,6 @@ use middle::typeck::infer::type_variable::{RelationDir, EqTo,
|
||||
use middle::ty_fold::{TypeFoldable};
|
||||
use util::ppaux::Repr;
|
||||
|
||||
|
||||
use syntax::ast::{Onceness, FnStyle};
|
||||
use syntax::ast;
|
||||
use syntax::abi;
|
||||
@ -461,15 +460,11 @@ pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C, a: ty::t, b: ty::t) -> cres<t
|
||||
}
|
||||
|
||||
(&ty::ty_trait(ref a_),
|
||||
&ty::ty_trait(ref b_))
|
||||
if a_.def_id == b_.def_id => {
|
||||
&ty::ty_trait(ref b_)) => {
|
||||
debug!("Trying to match traits {} and {}", a, b);
|
||||
let substs = try!(this.substs(a_.def_id, &a_.substs, &b_.substs));
|
||||
let principal = try!(this.trait_refs(&a_.principal, &b_.principal));
|
||||
let bounds = try!(this.existential_bounds(a_.bounds, b_.bounds));
|
||||
Ok(ty::mk_trait(tcx,
|
||||
a_.def_id,
|
||||
substs.clone(),
|
||||
bounds))
|
||||
Ok(ty::mk_trait(tcx, principal, bounds))
|
||||
}
|
||||
|
||||
(&ty::ty_struct(a_id, ref a_substs), &ty::ty_struct(b_id, ref b_substs))
|
||||
|
@ -1102,7 +1102,8 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
|
||||
// be passing down a map.
|
||||
ast::RegionTyParamBound(lt)
|
||||
}
|
||||
&ast::TraitTyParamBound(ref tr) => {
|
||||
&ast::TraitTyParamBound(ref poly_tr) => {
|
||||
let tr = &poly_tr.trait_ref;
|
||||
let last_seg = tr.path.segments.last().unwrap();
|
||||
let mut insert = Vec::new();
|
||||
let lifetimes = last_seg.parameters.lifetimes();
|
||||
@ -1119,10 +1120,12 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
|
||||
region_names: region_names
|
||||
};
|
||||
let new_path = self.rebuild_path(rebuild_info, lifetime);
|
||||
ast::TraitTyParamBound(ast::TraitRef {
|
||||
path: new_path,
|
||||
ref_id: tr.ref_id,
|
||||
lifetimes: tr.lifetimes.clone(),
|
||||
ast::TraitTyParamBound(ast::PolyTraitRef {
|
||||
bound_lifetimes: poly_tr.bound_lifetimes.clone(),
|
||||
trait_ref: ast::TraitRef {
|
||||
path: new_path,
|
||||
ref_id: tr.ref_id,
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -856,16 +856,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
-> ty::TraitRef {
|
||||
// make up a dummy type just to reuse/abuse the resolve machinery
|
||||
let dummy0 = ty::mk_trait(self.tcx,
|
||||
trait_ref.def_id,
|
||||
trait_ref.substs.clone(),
|
||||
(*trait_ref).clone(),
|
||||
ty::region_existential_bound(ty::ReStatic));
|
||||
let dummy1 = self.resolve_type_vars_if_possible(dummy0);
|
||||
match ty::get(dummy1).sty {
|
||||
ty::ty_trait(box ty::TyTrait { ref def_id, ref substs, .. }) => {
|
||||
ty::TraitRef {
|
||||
def_id: *def_id,
|
||||
substs: (*substs).clone(),
|
||||
}
|
||||
ty::ty_trait(box ty::TyTrait { ref principal, .. }) => {
|
||||
(*principal).clone()
|
||||
}
|
||||
_ => {
|
||||
self.tcx.sess.bug(
|
||||
|
@ -778,14 +778,14 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
|
||||
variance);
|
||||
}
|
||||
|
||||
ty::ty_trait(box ty::TyTrait { def_id, ref substs, bounds }) => {
|
||||
let trait_def = ty::lookup_trait_def(self.tcx(), def_id);
|
||||
ty::ty_trait(box ty::TyTrait { ref principal, bounds }) => {
|
||||
let trait_def = ty::lookup_trait_def(self.tcx(), principal.def_id);
|
||||
let generics = &trait_def.generics;
|
||||
|
||||
// Traits DO have a Self type parameter, but it is
|
||||
// erased from object types.
|
||||
assert!(!generics.types.is_empty_in(subst::SelfSpace) &&
|
||||
substs.types.is_empty_in(subst::SelfSpace));
|
||||
principal.substs.types.is_empty_in(subst::SelfSpace));
|
||||
|
||||
// Traits never declare region parameters in the self
|
||||
// space.
|
||||
@ -801,10 +801,10 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
|
||||
self.add_constraints_from_region(bounds.region_bound, contra);
|
||||
|
||||
self.add_constraints_from_substs(
|
||||
def_id,
|
||||
principal.def_id,
|
||||
generics.types.get_slice(subst::TypeSpace),
|
||||
generics.regions.get_slice(subst::TypeSpace),
|
||||
substs,
|
||||
&principal.substs,
|
||||
variance);
|
||||
}
|
||||
|
||||
|
@ -435,12 +435,12 @@ pub fn ty_to_string(cx: &ctxt, typ: t) -> String {
|
||||
parameterized(cx, base.as_slice(), substs, &generics)
|
||||
}
|
||||
ty_trait(box ty::TyTrait {
|
||||
def_id: did, ref substs, ref bounds
|
||||
ref principal, ref bounds
|
||||
}) => {
|
||||
let base = ty::item_path_str(cx, did);
|
||||
let trait_def = ty::lookup_trait_def(cx, did);
|
||||
let base = ty::item_path_str(cx, principal.def_id);
|
||||
let trait_def = ty::lookup_trait_def(cx, principal.def_id);
|
||||
let ty = parameterized(cx, base.as_slice(),
|
||||
substs, &trait_def.generics);
|
||||
&principal.substs, &trait_def.generics);
|
||||
let bound_str = bounds.user_string(cx);
|
||||
let bound_sep = if bound_str.is_empty() { "" } else { "+" };
|
||||
format!("{}{}{}",
|
||||
|
@ -963,6 +963,12 @@ impl Clean<Type> for ast::TraitRef {
|
||||
}
|
||||
}
|
||||
|
||||
impl Clean<Type> for ast::PolyTraitRef {
|
||||
fn clean(&self, cx: &DocContext) -> Type {
|
||||
self.trait_ref.clean(cx)
|
||||
}
|
||||
}
|
||||
|
||||
#[deriving(Clone, Encodable, Decodable)]
|
||||
pub enum TraitMethod {
|
||||
RequiredMethod(Item),
|
||||
@ -1306,7 +1312,8 @@ impl Clean<Type> for ty::t {
|
||||
}
|
||||
ty::ty_struct(did, ref substs) |
|
||||
ty::ty_enum(did, ref substs) |
|
||||
ty::ty_trait(box ty::TyTrait { def_id: did, ref substs, .. }) => {
|
||||
ty::ty_trait(box ty::TyTrait { principal: ty::TraitRef { def_id: did, ref substs },
|
||||
.. }) => {
|
||||
let fqn = csearch::get_item_path(cx.tcx(), did);
|
||||
let fqn: Vec<String> = fqn.into_iter().map(|i| {
|
||||
i.to_string()
|
||||
|
@ -307,7 +307,7 @@ pub const DUMMY_NODE_ID: NodeId = -1;
|
||||
/// detects Copy, Send and Sync.
|
||||
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
|
||||
pub enum TyParamBound {
|
||||
TraitTyParamBound(TraitRef),
|
||||
TraitTyParamBound(PolyTraitRef),
|
||||
RegionTyParamBound(Lifetime)
|
||||
}
|
||||
|
||||
@ -318,7 +318,7 @@ pub struct TyParam {
|
||||
pub ident: Ident,
|
||||
pub id: NodeId,
|
||||
pub bounds: TyParamBounds,
|
||||
pub unbound: Option<TyParamBound>,
|
||||
pub unbound: Option<TraitRef>,
|
||||
pub default: Option<P<Ty>>,
|
||||
pub span: Span
|
||||
}
|
||||
@ -1097,6 +1097,7 @@ pub enum Ty_ {
|
||||
TyBareFn(P<BareFnTy>),
|
||||
TyTup(Vec<P<Ty>> ),
|
||||
TyPath(Path, Option<TyParamBounds>, NodeId), // for #7264; see above
|
||||
TyPolyTraitRef(P<PolyTraitRef>), // a type like `for<'a> Foo<&'a Bar>`
|
||||
/// A "qualified path", e.g. `<Vec<T> as SomeTrait>::SomeType`
|
||||
TyQPath(P<QPath>),
|
||||
/// No-op; kept solely so that we can pretty-print faithfully
|
||||
@ -1350,7 +1351,6 @@ pub struct Attribute_ {
|
||||
pub is_sugared_doc: bool,
|
||||
}
|
||||
|
||||
|
||||
/// TraitRef's appear in impls.
|
||||
/// resolve maps each TraitRef's ref_id to its defining trait; that's all
|
||||
/// that the ref_id is for. The impl_id maps to the "self type" of this impl.
|
||||
@ -1360,7 +1360,15 @@ pub struct Attribute_ {
|
||||
pub struct TraitRef {
|
||||
pub path: Path,
|
||||
pub ref_id: NodeId,
|
||||
pub lifetimes: Vec<LifetimeDef>,
|
||||
}
|
||||
|
||||
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
|
||||
pub struct PolyTraitRef {
|
||||
/// The `'a` in `<'a> Foo<&'a T>`
|
||||
pub bound_lifetimes: Vec<LifetimeDef>,
|
||||
|
||||
/// The `Foo<&'a T>` in `<'a> Foo<&'a T>`
|
||||
pub trait_ref: TraitRef
|
||||
}
|
||||
|
||||
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
|
||||
@ -1448,8 +1456,8 @@ pub enum Item_ {
|
||||
ItemStruct(P<StructDef>, Generics),
|
||||
/// Represents a Trait Declaration
|
||||
ItemTrait(Generics,
|
||||
Option<TyParamBound>, // (optional) default bound not required for Self.
|
||||
// Currently, only Sized makes sense here.
|
||||
Option<TraitRef>, // (optional) default bound not required for Self.
|
||||
// Currently, only Sized makes sense here.
|
||||
TyParamBounds,
|
||||
Vec<TraitItem>),
|
||||
ItemImpl(Generics,
|
||||
|
@ -770,7 +770,7 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
|
||||
for b in bounds.iter() {
|
||||
match *b {
|
||||
TraitTyParamBound(ref t) => {
|
||||
self.insert(t.ref_id, NodeItem(i));
|
||||
self.insert(t.trait_ref.ref_id, NodeItem(i));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
@ -68,10 +68,11 @@ pub trait AstBuilder {
|
||||
span: Span,
|
||||
id: ast::Ident,
|
||||
bounds: OwnedSlice<ast::TyParamBound>,
|
||||
unbound: Option<ast::TyParamBound>,
|
||||
unbound: Option<ast::TraitRef>,
|
||||
default: Option<P<ast::Ty>>) -> ast::TyParam;
|
||||
|
||||
fn trait_ref(&self, path: ast::Path) -> ast::TraitRef;
|
||||
fn poly_trait_ref(&self, path: ast::Path) -> ast::PolyTraitRef;
|
||||
fn typarambound(&self, path: ast::Path) -> ast::TyParamBound;
|
||||
fn lifetime(&self, span: Span, ident: ast::Name) -> ast::Lifetime;
|
||||
fn lifetime_def(&self,
|
||||
@ -417,7 +418,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
||||
span: Span,
|
||||
id: ast::Ident,
|
||||
bounds: OwnedSlice<ast::TyParamBound>,
|
||||
unbound: Option<ast::TyParamBound>,
|
||||
unbound: Option<ast::TraitRef>,
|
||||
default: Option<P<ast::Ty>>) -> ast::TyParam {
|
||||
ast::TyParam {
|
||||
ident: id,
|
||||
@ -445,12 +446,18 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
||||
ast::TraitRef {
|
||||
path: path,
|
||||
ref_id: ast::DUMMY_NODE_ID,
|
||||
lifetimes: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn poly_trait_ref(&self, path: ast::Path) -> ast::PolyTraitRef {
|
||||
ast::PolyTraitRef {
|
||||
bound_lifetimes: Vec::new(),
|
||||
trait_ref: self.trait_ref(path)
|
||||
}
|
||||
}
|
||||
|
||||
fn typarambound(&self, path: ast::Path) -> ast::TyParamBound {
|
||||
ast::TraitTyParamBound(self.trait_ref(path))
|
||||
ast::TraitTyParamBound(self.poly_trait_ref(path))
|
||||
}
|
||||
|
||||
fn lifetime(&self, span: Span, name: ast::Name) -> ast::Lifetime {
|
||||
|
@ -194,7 +194,7 @@ impl<'a> Ty<'a> {
|
||||
|
||||
|
||||
fn mk_ty_param(cx: &ExtCtxt, span: Span, name: &str,
|
||||
bounds: &[Path], unbound: Option<ast::TyParamBound>,
|
||||
bounds: &[Path], unbound: Option<ast::TraitRef>,
|
||||
self_ident: Ident, self_generics: &Generics) -> ast::TyParam {
|
||||
let bounds =
|
||||
bounds.iter().map(|b| {
|
||||
@ -220,7 +220,7 @@ fn mk_generics(lifetimes: Vec<ast::LifetimeDef>, ty_params: Vec<ast::TyParam>)
|
||||
#[deriving(Clone)]
|
||||
pub struct LifetimeBounds<'a> {
|
||||
pub lifetimes: Vec<(&'a str, Vec<&'a str>)>,
|
||||
pub bounds: Vec<(&'a str, Option<ast::TyParamBound>, Vec<Path<'a>>)>,
|
||||
pub bounds: Vec<(&'a str, Option<ast::TraitRef>, Vec<Path<'a>>)>,
|
||||
}
|
||||
|
||||
impl<'a> LifetimeBounds<'a> {
|
||||
|
@ -38,7 +38,6 @@ static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[
|
||||
("globs", Active),
|
||||
("macro_rules", Active),
|
||||
("struct_variant", Active),
|
||||
("once_fns", Active),
|
||||
("asm", Active),
|
||||
("managed_boxes", Removed),
|
||||
("non_ascii_idents", Active),
|
||||
@ -307,11 +306,10 @@ impl<'a, 'v> Visitor<'v> for Context<'a> {
|
||||
|
||||
fn visit_ty(&mut self, t: &ast::Ty) {
|
||||
match t.node {
|
||||
ast::TyClosure(ref closure) if closure.onceness == ast::Once => {
|
||||
self.gate_feature("once_fns", t.span,
|
||||
"once functions are \
|
||||
experimental and likely to be removed");
|
||||
|
||||
ast::TyClosure(ref closure) => {
|
||||
// this used to be blocked by a feature gate, but it should just
|
||||
// be plain impossible right now
|
||||
assert!(closure.onceness != ast::Once);
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
|
@ -227,6 +227,10 @@ pub trait Folder {
|
||||
noop_fold_trait_ref(p, self)
|
||||
}
|
||||
|
||||
fn fold_poly_trait_ref(&mut self, p: PolyTraitRef) -> PolyTraitRef {
|
||||
noop_fold_poly_trait_ref(p, self)
|
||||
}
|
||||
|
||||
fn fold_struct_def(&mut self, struct_def: P<StructDef>) -> P<StructDef> {
|
||||
noop_fold_struct_def(struct_def, self)
|
||||
}
|
||||
@ -442,7 +446,10 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
|
||||
TyFixedLengthVec(ty, e) => {
|
||||
TyFixedLengthVec(fld.fold_ty(ty), fld.fold_expr(e))
|
||||
}
|
||||
TyTypeof(expr) => TyTypeof(fld.fold_expr(expr))
|
||||
TyTypeof(expr) => TyTypeof(fld.fold_expr(expr)),
|
||||
TyPolyTraitRef(poly_trait_ref) => {
|
||||
TyPolyTraitRef(poly_trait_ref.map(|p| fld.fold_poly_trait_ref(p)))
|
||||
},
|
||||
},
|
||||
span: fld.new_span(span)
|
||||
})
|
||||
@ -711,7 +718,7 @@ pub fn noop_fold_ty_param_bound<T>(tpb: TyParamBound, fld: &mut T)
|
||||
-> TyParamBound
|
||||
where T: Folder {
|
||||
match tpb {
|
||||
TraitTyParamBound(ty) => TraitTyParamBound(fld.fold_trait_ref(ty)),
|
||||
TraitTyParamBound(ty) => TraitTyParamBound(fld.fold_poly_trait_ref(ty)),
|
||||
RegionTyParamBound(lifetime) => RegionTyParamBound(fld.fold_lifetime(lifetime)),
|
||||
}
|
||||
}
|
||||
@ -722,7 +729,7 @@ pub fn noop_fold_ty_param<T: Folder>(tp: TyParam, fld: &mut T) -> TyParam {
|
||||
id: fld.new_id(id),
|
||||
ident: ident,
|
||||
bounds: fld.fold_bounds(bounds),
|
||||
unbound: unbound.map(|x| fld.fold_ty_param_bound(x)),
|
||||
unbound: unbound.map(|x| fld.fold_trait_ref(x)),
|
||||
default: default.map(|x| fld.fold_ty(x)),
|
||||
span: span
|
||||
}
|
||||
@ -842,13 +849,18 @@ pub fn noop_fold_trait_ref<T: Folder>(p: TraitRef, fld: &mut T) -> TraitRef {
|
||||
let id = fld.new_id(p.ref_id);
|
||||
let TraitRef {
|
||||
path,
|
||||
lifetimes,
|
||||
..
|
||||
ref_id: _,
|
||||
} = p;
|
||||
ast::TraitRef {
|
||||
path: fld.fold_path(path),
|
||||
ref_id: id,
|
||||
lifetimes: fld.fold_lifetime_defs(lifetimes),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn noop_fold_poly_trait_ref<T: Folder>(p: PolyTraitRef, fld: &mut T) -> PolyTraitRef {
|
||||
ast::PolyTraitRef {
|
||||
bound_lifetimes: fld.fold_lifetime_defs(p.bound_lifetimes),
|
||||
trait_ref: fld.fold_trait_ref(p.trait_ref)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,6 +42,7 @@ use ast::{Method, MutTy, BiMul, Mutability};
|
||||
use ast::{MethodImplItem, NamedField, UnNeg, NoReturn, UnNot};
|
||||
use ast::{Pat, PatEnum, PatIdent, PatLit, PatRange, PatRegion, PatStruct};
|
||||
use ast::{PatTup, PatBox, PatWild, PatWildMulti, PatWildSingle};
|
||||
use ast::{PolyTraitRef};
|
||||
use ast::{QPath, RequiredMethod};
|
||||
use ast::{RetStyle, Return, BiShl, BiShr, Stmt, StmtDecl};
|
||||
use ast::{StmtExpr, StmtSemi, StmtMac, StructDef, StructField};
|
||||
@ -53,7 +54,7 @@ use ast::{TtDelimited, TtSequence, TtToken};
|
||||
use ast::{TupleVariantKind, Ty, Ty_, TyBot};
|
||||
use ast::{TypeField, TyFixedLengthVec, TyClosure, TyProc, TyBareFn};
|
||||
use ast::{TyTypeof, TyInfer, TypeMethod};
|
||||
use ast::{TyNil, TyParam, TyParamBound, TyParen, TyPath, TyPtr, TyQPath};
|
||||
use ast::{TyNil, TyParam, TyParamBound, TyParen, TyPath, TyPolyTraitRef, TyPtr, TyQPath};
|
||||
use ast::{TyRptr, TyTup, TyU32, TyUniq, TyVec, UnUniq};
|
||||
use ast::{TypeImplItem, TypeTraitItem, Typedef, UnboxedClosureKind};
|
||||
use ast::{UnnamedField, UnsafeBlock};
|
||||
@ -968,30 +969,14 @@ impl<'a> Parser<'a> {
|
||||
/// Is the current token one of the keywords that signals a bare function
|
||||
/// type?
|
||||
pub fn token_is_bare_fn_keyword(&mut self) -> bool {
|
||||
if self.token.is_keyword(keywords::Fn) {
|
||||
return true
|
||||
}
|
||||
|
||||
if self.token.is_keyword(keywords::Unsafe) ||
|
||||
self.token.is_keyword(keywords::Once) {
|
||||
return self.look_ahead(1, |t| t.is_keyword(keywords::Fn))
|
||||
}
|
||||
|
||||
false
|
||||
self.token.is_keyword(keywords::Fn) ||
|
||||
self.token.is_keyword(keywords::Unsafe) ||
|
||||
self.token.is_keyword(keywords::Extern)
|
||||
}
|
||||
|
||||
/// Is the current token one of the keywords that signals a closure type?
|
||||
pub fn token_is_closure_keyword(&mut self) -> bool {
|
||||
self.token.is_keyword(keywords::Unsafe) ||
|
||||
self.token.is_keyword(keywords::Once)
|
||||
}
|
||||
|
||||
/// Is the current token one of the keywords that signals an old-style
|
||||
/// closure type (with explicit sigil)?
|
||||
pub fn token_is_old_style_closure_keyword(&mut self) -> bool {
|
||||
self.token.is_keyword(keywords::Unsafe) ||
|
||||
self.token.is_keyword(keywords::Once) ||
|
||||
self.token.is_keyword(keywords::Fn)
|
||||
self.token.is_keyword(keywords::Unsafe)
|
||||
}
|
||||
|
||||
pub fn get_lifetime(&mut self) -> ast::Ident {
|
||||
@ -1001,8 +986,57 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_for_in_type(&mut self) -> Ty_ {
|
||||
/*
|
||||
Parses whatever can come after a `for` keyword in a type.
|
||||
The `for` has already been consumed.
|
||||
|
||||
Deprecated:
|
||||
|
||||
- for <'lt> |S| -> T
|
||||
- for <'lt> proc(S) -> T
|
||||
|
||||
Eventually:
|
||||
|
||||
- for <'lt> [unsafe] [extern "ABI"] fn (S) -> T
|
||||
- for <'lt> path::foo(a, b)
|
||||
|
||||
*/
|
||||
|
||||
// parse <'lt>
|
||||
let lifetime_defs = self.parse_late_bound_lifetime_defs();
|
||||
|
||||
// examine next token to decide to do
|
||||
if self.eat_keyword(keywords::Proc) {
|
||||
self.parse_proc_type(lifetime_defs)
|
||||
} else if self.token_is_bare_fn_keyword() || self.token_is_closure_keyword() {
|
||||
self.parse_ty_bare_fn_or_ty_closure(lifetime_defs)
|
||||
} else if self.token == token::ModSep ||
|
||||
self.token.is_ident() ||
|
||||
self.token.is_path() {
|
||||
let trait_ref = self.parse_trait_ref();
|
||||
TyPolyTraitRef(P(PolyTraitRef { bound_lifetimes: lifetime_defs,
|
||||
trait_ref: trait_ref }))
|
||||
} else {
|
||||
self.parse_ty_closure(lifetime_defs)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_ty_path(&mut self, plus_allowed: bool) -> Ty_ {
|
||||
let mode = if plus_allowed {
|
||||
LifetimeAndTypesAndBounds
|
||||
} else {
|
||||
LifetimeAndTypesWithoutColons
|
||||
};
|
||||
let PathAndBounds {
|
||||
path,
|
||||
bounds
|
||||
} = self.parse_path(mode);
|
||||
TyPath(path, bounds, ast::DUMMY_NODE_ID)
|
||||
}
|
||||
|
||||
/// parse a TyBareFn type:
|
||||
pub fn parse_ty_bare_fn(&mut self) -> Ty_ {
|
||||
pub fn parse_ty_bare_fn(&mut self, lifetime_defs: Vec<ast::LifetimeDef>) -> Ty_ {
|
||||
/*
|
||||
|
||||
[unsafe] [extern "ABI"] fn <'lt> (S) -> T
|
||||
@ -1023,18 +1057,26 @@ impl<'a> Parser<'a> {
|
||||
};
|
||||
|
||||
self.expect_keyword(keywords::Fn);
|
||||
let (decl, lifetimes) = self.parse_ty_fn_decl(true);
|
||||
let lifetime_defs = self.parse_legacy_lifetime_defs(lifetime_defs);
|
||||
let (inputs, variadic) = self.parse_fn_args(false, true);
|
||||
let (ret_style, ret_ty) = self.parse_ret_ty();
|
||||
let decl = P(FnDecl {
|
||||
inputs: inputs,
|
||||
output: ret_ty,
|
||||
cf: ret_style,
|
||||
variadic: variadic
|
||||
});
|
||||
TyBareFn(P(BareFnTy {
|
||||
abi: abi,
|
||||
fn_style: fn_style,
|
||||
lifetimes: lifetimes,
|
||||
lifetimes: lifetime_defs,
|
||||
decl: decl
|
||||
}))
|
||||
}
|
||||
|
||||
/// Parses a procedure type (`proc`). The initial `proc` keyword must
|
||||
/// already have been parsed.
|
||||
pub fn parse_proc_type(&mut self) -> Ty_ {
|
||||
pub fn parse_proc_type(&mut self, lifetime_defs: Vec<ast::LifetimeDef>) -> Ty_ {
|
||||
/*
|
||||
|
||||
proc <'lt> (S) [:Bounds] -> T
|
||||
@ -1043,19 +1085,12 @@ impl<'a> Parser<'a> {
|
||||
| | | | Return type
|
||||
| | | Bounds
|
||||
| | Argument types
|
||||
| Lifetimes
|
||||
| Legacy lifetimes
|
||||
the `proc` keyword
|
||||
|
||||
*/
|
||||
|
||||
let lifetime_defs = if self.eat(&token::Lt) {
|
||||
let lifetime_defs = self.parse_lifetime_defs();
|
||||
self.expect_gt();
|
||||
lifetime_defs
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
|
||||
let lifetime_defs = self.parse_legacy_lifetime_defs(lifetime_defs);
|
||||
let (inputs, variadic) = self.parse_fn_args(false, false);
|
||||
let bounds = self.parse_colon_then_ty_param_bounds();
|
||||
let (ret_style, ret_ty) = self.parse_ret_ty();
|
||||
@ -1100,33 +1135,49 @@ impl<'a> Parser<'a> {
|
||||
return None
|
||||
}
|
||||
|
||||
pub fn parse_ty_bare_fn_or_ty_closure(&mut self, lifetime_defs: Vec<LifetimeDef>) -> Ty_ {
|
||||
// Both bare fns and closures can begin with stuff like unsafe
|
||||
// and extern. So we just scan ahead a few tokens to see if we see
|
||||
// a `fn`.
|
||||
//
|
||||
// Closure: [unsafe] <'lt> |S| [:Bounds] -> T
|
||||
// Fn: [unsafe] [extern "ABI"] fn <'lt> (S) -> T
|
||||
|
||||
if self.token.is_keyword(keywords::Fn) {
|
||||
self.parse_ty_bare_fn(lifetime_defs)
|
||||
} else if self.token.is_keyword(keywords::Extern) {
|
||||
self.parse_ty_bare_fn(lifetime_defs)
|
||||
} else if self.token.is_keyword(keywords::Unsafe) {
|
||||
if self.look_ahead(1, |t| t.is_keyword(keywords::Fn) ||
|
||||
t.is_keyword(keywords::Extern)) {
|
||||
self.parse_ty_bare_fn(lifetime_defs)
|
||||
} else {
|
||||
self.parse_ty_closure(lifetime_defs)
|
||||
}
|
||||
} else {
|
||||
self.parse_ty_closure(lifetime_defs)
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse a TyClosure type
|
||||
pub fn parse_ty_closure(&mut self) -> Ty_ {
|
||||
pub fn parse_ty_closure(&mut self, lifetime_defs: Vec<ast::LifetimeDef>) -> Ty_ {
|
||||
/*
|
||||
|
||||
[unsafe] [once] <'lt> |S| [:Bounds] -> T
|
||||
^~~~~~~^ ^~~~~^ ^~~~^ ^ ^~~~~~~~^ ^
|
||||
| | | | | |
|
||||
| | | | | Return type
|
||||
| | | | Closure bounds
|
||||
| | | Argument types
|
||||
| | Lifetime defs
|
||||
| Once-ness (a.k.a., affine)
|
||||
[unsafe] <'lt> |S| [:Bounds] -> T
|
||||
^~~~~~~^ ^~~~^ ^ ^~~~~~~~^ ^
|
||||
| | | | |
|
||||
| | | | Return type
|
||||
| | | Closure bounds
|
||||
| | Argument types
|
||||
| Deprecated lifetime defs
|
||||
|
|
||||
Function Style
|
||||
|
||||
*/
|
||||
|
||||
let fn_style = self.parse_unsafety();
|
||||
let onceness = if self.eat_keyword(keywords::Once) {Once} else {Many};
|
||||
|
||||
let lifetime_defs = if self.eat(&token::Lt) {
|
||||
let lifetime_defs = self.parse_lifetime_defs();
|
||||
self.expect_gt();
|
||||
|
||||
lifetime_defs
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
let lifetime_defs = self.parse_legacy_lifetime_defs(lifetime_defs);
|
||||
|
||||
let inputs = if self.eat(&token::OrOr) {
|
||||
Vec::new()
|
||||
@ -1152,7 +1203,7 @@ impl<'a> Parser<'a> {
|
||||
|
||||
TyClosure(P(ClosureTy {
|
||||
fn_style: fn_style,
|
||||
onceness: onceness,
|
||||
onceness: Many,
|
||||
bounds: bounds,
|
||||
decl: decl,
|
||||
lifetimes: lifetime_defs,
|
||||
@ -1167,36 +1218,23 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse a function type (following the 'fn')
|
||||
pub fn parse_ty_fn_decl(&mut self, allow_variadic: bool)
|
||||
-> (P<FnDecl>, Vec<ast::LifetimeDef>) {
|
||||
/*
|
||||
|
||||
(fn) <'lt> (S) -> T
|
||||
^~~~^ ^~^ ^
|
||||
| | |
|
||||
| | Return type
|
||||
| Argument types
|
||||
Lifetime_defs
|
||||
|
||||
*/
|
||||
let lifetime_defs = if self.eat(&token::Lt) {
|
||||
let lifetime_defs = self.parse_lifetime_defs();
|
||||
self.expect_gt();
|
||||
lifetime_defs
|
||||
/// Parses `[ 'for' '<' lifetime_defs '>' ]'
|
||||
fn parse_legacy_lifetime_defs(&mut self,
|
||||
lifetime_defs: Vec<ast::LifetimeDef>)
|
||||
-> Vec<ast::LifetimeDef>
|
||||
{
|
||||
if self.eat(&token::Lt) {
|
||||
if lifetime_defs.is_empty() {
|
||||
self.warn("deprecated syntax, use `for` keyword now");
|
||||
let lifetime_defs = self.parse_lifetime_defs();
|
||||
self.expect_gt();
|
||||
lifetime_defs
|
||||
} else {
|
||||
self.fatal("cannot use new `for` keyword and older syntax together");
|
||||
}
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
|
||||
let (inputs, variadic) = self.parse_fn_args(false, allow_variadic);
|
||||
let (ret_style, ret_ty) = self.parse_ret_ty();
|
||||
let decl = P(FnDecl {
|
||||
inputs: inputs,
|
||||
output: ret_ty,
|
||||
cf: ret_style,
|
||||
variadic: variadic
|
||||
});
|
||||
(decl, lifetime_defs)
|
||||
lifetime_defs
|
||||
}
|
||||
}
|
||||
|
||||
/// Parses `type Foo;` in a trait declaration only. The `type` keyword has
|
||||
@ -1433,25 +1471,24 @@ impl<'a> Parser<'a> {
|
||||
self.expect(&token::CloseDelim(token::Bracket));
|
||||
t
|
||||
} else if self.token == token::BinOp(token::And) ||
|
||||
self.token == token::AndAnd {
|
||||
self.token == token::AndAnd {
|
||||
// BORROWED POINTER
|
||||
self.expect_and();
|
||||
self.parse_borrowed_pointee()
|
||||
} else if self.token.is_keyword(keywords::Extern) ||
|
||||
self.token.is_keyword(keywords::Unsafe) ||
|
||||
self.token_is_bare_fn_keyword() {
|
||||
// BARE FUNCTION
|
||||
self.parse_ty_bare_fn()
|
||||
} else if self.token_is_closure_keyword() ||
|
||||
self.token == token::BinOp(token::Or) ||
|
||||
self.token == token::OrOr ||
|
||||
(self.token == token::Lt &&
|
||||
self.look_ahead(1, |t| {
|
||||
*t == token::Gt || t.is_lifetime()
|
||||
})) {
|
||||
} else if self.token.is_keyword(keywords::For) {
|
||||
self.parse_for_in_type()
|
||||
} else if self.token_is_bare_fn_keyword() ||
|
||||
self.token_is_closure_keyword() {
|
||||
// BARE FUNCTION OR CLOSURE
|
||||
self.parse_ty_bare_fn_or_ty_closure(Vec::new())
|
||||
} else if self.token == token::BinOp(token::Or) ||
|
||||
self.token == token::OrOr ||
|
||||
(self.token == token::Lt &&
|
||||
self.look_ahead(1, |t| {
|
||||
*t == token::Gt || t.is_lifetime()
|
||||
})) {
|
||||
// CLOSURE
|
||||
|
||||
self.parse_ty_closure()
|
||||
self.parse_ty_closure(Vec::new())
|
||||
} else if self.eat_keyword(keywords::Typeof) {
|
||||
// TYPEOF
|
||||
// In order to not be ambiguous, the type must be surrounded by parens.
|
||||
@ -1460,7 +1497,7 @@ impl<'a> Parser<'a> {
|
||||
self.expect(&token::CloseDelim(token::Paren));
|
||||
TyTypeof(e)
|
||||
} else if self.eat_keyword(keywords::Proc) {
|
||||
self.parse_proc_type()
|
||||
self.parse_proc_type(Vec::new())
|
||||
} else if self.token == token::Lt {
|
||||
// QUALIFIED PATH
|
||||
self.bump();
|
||||
@ -1479,16 +1516,7 @@ impl<'a> Parser<'a> {
|
||||
self.token.is_ident() ||
|
||||
self.token.is_path() {
|
||||
// NAMED TYPE
|
||||
let mode = if plus_allowed {
|
||||
LifetimeAndTypesAndBounds
|
||||
} else {
|
||||
LifetimeAndTypesWithoutColons
|
||||
};
|
||||
let PathAndBounds {
|
||||
path,
|
||||
bounds
|
||||
} = self.parse_path(mode);
|
||||
TyPath(path, bounds, ast::DUMMY_NODE_ID)
|
||||
self.parse_ty_path(plus_allowed)
|
||||
} else if self.eat(&token::Underscore) {
|
||||
// TYPE TO BE INFERRED
|
||||
TyInfer
|
||||
@ -3848,29 +3876,17 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
// matches bounds = ( boundseq )?
|
||||
// where boundseq = ( bound + boundseq ) | bound
|
||||
// and bound = 'region | ty
|
||||
// where boundseq = ( polybound + boundseq ) | polybound
|
||||
// and polybound = ( 'for' '<' 'region '>' )? bound
|
||||
// and bound = 'region | trait_ref
|
||||
// NB: The None/Some distinction is important for issue #7264.
|
||||
fn parse_ty_param_bounds(&mut self)
|
||||
-> OwnedSlice<TyParamBound>
|
||||
{
|
||||
let mut result = vec!();
|
||||
loop {
|
||||
let lifetime_defs = if self.eat(&token::Lt) {
|
||||
let lifetime_defs = self.parse_lifetime_defs();
|
||||
self.expect_gt();
|
||||
lifetime_defs
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
match self.token {
|
||||
token::Lifetime(lifetime) => {
|
||||
if lifetime_defs.len() > 0 {
|
||||
let span = self.last_span;
|
||||
self.span_err(span, "lifetime declarations are not \
|
||||
allowed here")
|
||||
}
|
||||
|
||||
result.push(RegionTyParamBound(ast::Lifetime {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
span: self.span,
|
||||
@ -3879,13 +3895,8 @@ impl<'a> Parser<'a> {
|
||||
self.bump();
|
||||
}
|
||||
token::ModSep | token::Ident(..) => {
|
||||
let path =
|
||||
self.parse_path(LifetimeAndTypesWithoutColons).path;
|
||||
result.push(TraitTyParamBound(ast::TraitRef {
|
||||
path: path,
|
||||
ref_id: ast::DUMMY_NODE_ID,
|
||||
lifetimes: lifetime_defs,
|
||||
}))
|
||||
let poly_trait_ref = self.parse_poly_trait_ref();
|
||||
result.push(TraitTyParamBound(poly_trait_ref))
|
||||
}
|
||||
_ => break,
|
||||
}
|
||||
@ -3898,7 +3909,7 @@ impl<'a> Parser<'a> {
|
||||
return OwnedSlice::from_vec(result);
|
||||
}
|
||||
|
||||
fn trait_ref_from_ident(ident: Ident, span: Span) -> ast::TraitRef {
|
||||
fn trait_ref_from_ident(ident: Ident, span: Span) -> TraitRef {
|
||||
let segment = ast::PathSegment {
|
||||
identifier: ident,
|
||||
parameters: ast::PathParameters::none()
|
||||
@ -3911,7 +3922,6 @@ impl<'a> Parser<'a> {
|
||||
ast::TraitRef {
|
||||
path: path,
|
||||
ref_id: ast::DUMMY_NODE_ID,
|
||||
lifetimes: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -3927,7 +3937,7 @@ impl<'a> Parser<'a> {
|
||||
let mut unbound = None;
|
||||
if self.eat(&token::Question) {
|
||||
let tref = Parser::trait_ref_from_ident(ident, span);
|
||||
unbound = Some(TraitTyParamBound(tref));
|
||||
unbound = Some(tref);
|
||||
span = self.span;
|
||||
ident = self.parse_ident();
|
||||
}
|
||||
@ -4538,7 +4548,6 @@ impl<'a> Parser<'a> {
|
||||
Some(TraitRef {
|
||||
path: (*path).clone(),
|
||||
ref_id: node_id,
|
||||
lifetimes: Vec::new(),
|
||||
})
|
||||
}
|
||||
TyPath(_, Some(_), _) => {
|
||||
@ -4568,6 +4577,35 @@ impl<'a> Parser<'a> {
|
||||
Some(attrs))
|
||||
}
|
||||
|
||||
/// Parse a::B<String,int>
|
||||
fn parse_trait_ref(&mut self) -> TraitRef {
|
||||
ast::TraitRef {
|
||||
path: self.parse_path(LifetimeAndTypesWithoutColons).path,
|
||||
ref_id: ast::DUMMY_NODE_ID,
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_late_bound_lifetime_defs(&mut self) -> Vec<ast::LifetimeDef> {
|
||||
if self.eat_keyword(keywords::For) {
|
||||
self.expect(&token::Lt);
|
||||
let lifetime_defs = self.parse_lifetime_defs();
|
||||
self.expect_gt();
|
||||
lifetime_defs
|
||||
} else {
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse for<'l> a::B<String,int>
|
||||
fn parse_poly_trait_ref(&mut self) -> PolyTraitRef {
|
||||
let lifetime_defs = self.parse_late_bound_lifetime_defs();
|
||||
|
||||
ast::PolyTraitRef {
|
||||
bound_lifetimes: lifetime_defs,
|
||||
trait_ref: self.parse_trait_ref()
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse struct Foo { ... }
|
||||
fn parse_item_struct(&mut self) -> ItemInfo {
|
||||
let class_name = self.parse_ident();
|
||||
@ -4681,7 +4719,7 @@ impl<'a> Parser<'a> {
|
||||
else { Inherited }
|
||||
}
|
||||
|
||||
fn parse_for_sized(&mut self) -> Option<ast::TyParamBound> {
|
||||
fn parse_for_sized(&mut self) -> Option<ast::TraitRef> {
|
||||
if self.eat_keyword(keywords::For) {
|
||||
let span = self.span;
|
||||
let ident = self.parse_ident();
|
||||
@ -4691,7 +4729,7 @@ impl<'a> Parser<'a> {
|
||||
return None;
|
||||
}
|
||||
let tref = Parser::trait_ref_from_ident(ident, span);
|
||||
Some(TraitTyParamBound(tref))
|
||||
Some(tref)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -503,42 +503,41 @@ declare_special_idents_and_keywords! {
|
||||
(27, Mod, "mod");
|
||||
(28, Move, "move");
|
||||
(29, Mut, "mut");
|
||||
(30, Once, "once");
|
||||
(31, Pub, "pub");
|
||||
(32, Ref, "ref");
|
||||
(33, Return, "return");
|
||||
(30, Pub, "pub");
|
||||
(31, Ref, "ref");
|
||||
(32, Return, "return");
|
||||
// Static and Self are also special idents (prefill de-dupes)
|
||||
(super::STATIC_KEYWORD_NAME_NUM, Static, "static");
|
||||
(super::SELF_KEYWORD_NAME_NUM, Self, "self");
|
||||
(34, Struct, "struct");
|
||||
(33, Struct, "struct");
|
||||
(super::SUPER_KEYWORD_NAME_NUM, Super, "super");
|
||||
(35, True, "true");
|
||||
(36, Trait, "trait");
|
||||
(37, Type, "type");
|
||||
(38, Unsafe, "unsafe");
|
||||
(39, Use, "use");
|
||||
(40, Virtual, "virtual");
|
||||
(41, While, "while");
|
||||
(42, Continue, "continue");
|
||||
(43, Proc, "proc");
|
||||
(44, Box, "box");
|
||||
(45, Const, "const");
|
||||
(46, Where, "where");
|
||||
(34, True, "true");
|
||||
(35, Trait, "trait");
|
||||
(36, Type, "type");
|
||||
(37, Unsafe, "unsafe");
|
||||
(38, Use, "use");
|
||||
(39, Virtual, "virtual");
|
||||
(40, While, "while");
|
||||
(41, Continue, "continue");
|
||||
(42, Proc, "proc");
|
||||
(43, Box, "box");
|
||||
(44, Const, "const");
|
||||
(45, Where, "where");
|
||||
|
||||
'reserved:
|
||||
(47, Alignof, "alignof");
|
||||
(48, Be, "be");
|
||||
(49, Offsetof, "offsetof");
|
||||
(50, Priv, "priv");
|
||||
(51, Pure, "pure");
|
||||
(52, Sizeof, "sizeof");
|
||||
(53, Typeof, "typeof");
|
||||
(54, Unsized, "unsized");
|
||||
(55, Yield, "yield");
|
||||
(56, Do, "do");
|
||||
(57, Abstract, "abstract");
|
||||
(58, Final, "final");
|
||||
(59, Override, "override");
|
||||
(46, Alignof, "alignof");
|
||||
(47, Be, "be");
|
||||
(48, Offsetof, "offsetof");
|
||||
(49, Priv, "priv");
|
||||
(50, Pure, "pure");
|
||||
(51, Sizeof, "sizeof");
|
||||
(52, Typeof, "typeof");
|
||||
(53, Unsized, "unsized");
|
||||
(54, Yield, "yield");
|
||||
(55, Do, "do");
|
||||
(56, Abstract, "abstract");
|
||||
(57, Final, "final");
|
||||
(58, Override, "override");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -743,6 +743,9 @@ impl<'a> State<'a> {
|
||||
ast::TyPath(ref path, ref bounds, _) => {
|
||||
try!(self.print_bounded_path(path, bounds));
|
||||
}
|
||||
ast::TyPolyTraitRef(ref poly_trait_ref) => {
|
||||
try!(self.print_poly_trait_ref(&**poly_trait_ref));
|
||||
}
|
||||
ast::TyQPath(ref qpath) => {
|
||||
try!(word(&mut self.s, "<"));
|
||||
try!(self.print_type(&*qpath.for_type));
|
||||
@ -960,7 +963,7 @@ impl<'a> State<'a> {
|
||||
try!(self.print_ident(item.ident));
|
||||
try!(self.print_generics(generics));
|
||||
match unbound {
|
||||
&Some(TraitTyParamBound(ref tref)) => {
|
||||
&Some(ref tref) => {
|
||||
try!(space(&mut self.s));
|
||||
try!(self.word_space("for"));
|
||||
try!(self.print_trait_ref(tref));
|
||||
@ -995,19 +998,21 @@ impl<'a> State<'a> {
|
||||
}
|
||||
|
||||
fn print_trait_ref(&mut self, t: &ast::TraitRef) -> IoResult<()> {
|
||||
if t.lifetimes.len() > 0 {
|
||||
try!(self.print_generics(&ast::Generics {
|
||||
lifetimes: t.lifetimes.clone(),
|
||||
ty_params: OwnedSlice::empty(),
|
||||
where_clause: ast::WhereClause {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
predicates: Vec::new(),
|
||||
},
|
||||
}));
|
||||
}
|
||||
self.print_path(&t.path, false)
|
||||
}
|
||||
|
||||
fn print_poly_trait_ref(&mut self, t: &ast::PolyTraitRef) -> IoResult<()> {
|
||||
if !t.bound_lifetimes.is_empty() {
|
||||
try!(word(&mut self.s, "for<"));
|
||||
for lifetime_def in t.bound_lifetimes.iter() {
|
||||
try!(self.print_lifetime_def(lifetime_def));
|
||||
}
|
||||
try!(word(&mut self.s, ">"));
|
||||
}
|
||||
|
||||
self.print_trait_ref(&t.trait_ref)
|
||||
}
|
||||
|
||||
pub fn print_enum_def(&mut self, enum_definition: &ast::EnumDef,
|
||||
generics: &ast::Generics, ident: ast::Ident,
|
||||
span: codemap::Span,
|
||||
@ -2383,7 +2388,7 @@ impl<'a> State<'a> {
|
||||
|
||||
try!(match *bound {
|
||||
TraitTyParamBound(ref tref) => {
|
||||
self.print_trait_ref(tref)
|
||||
self.print_poly_trait_ref(tref)
|
||||
}
|
||||
RegionTyParamBound(ref lt) => {
|
||||
self.print_lifetime(lt)
|
||||
@ -2450,7 +2455,7 @@ impl<'a> State<'a> {
|
||||
|
||||
pub fn print_ty_param(&mut self, param: &ast::TyParam) -> IoResult<()> {
|
||||
match param.unbound {
|
||||
Some(TraitTyParamBound(ref tref)) => {
|
||||
Some(ref tref) => {
|
||||
try!(self.print_trait_ref(tref));
|
||||
try!(self.word_space("?"));
|
||||
}
|
||||
@ -2658,12 +2663,10 @@ impl<'a> State<'a> {
|
||||
} else if opt_sigil == Some('&') {
|
||||
try!(self.print_fn_style(fn_style));
|
||||
try!(self.print_extern_opt_abi(opt_abi));
|
||||
try!(self.print_onceness(onceness));
|
||||
} else {
|
||||
assert!(opt_sigil.is_none());
|
||||
try!(self.print_fn_style(fn_style));
|
||||
try!(self.print_opt_abi_and_extern_if_nondefault(opt_abi));
|
||||
try!(self.print_onceness(onceness));
|
||||
try!(word(&mut self.s, "fn"));
|
||||
}
|
||||
|
||||
@ -2982,13 +2985,6 @@ impl<'a> State<'a> {
|
||||
ast::UnsafeFn => self.word_nbsp("unsafe"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn print_onceness(&mut self, o: ast::Onceness) -> IoResult<()> {
|
||||
match o {
|
||||
ast::Once => self.word_nbsp("once"),
|
||||
ast::Many => Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -75,6 +75,10 @@ pub trait Visitor<'v> {
|
||||
}
|
||||
fn visit_ty_method(&mut self, t: &'v TypeMethod) { walk_ty_method(self, t) }
|
||||
fn visit_trait_item(&mut self, t: &'v TraitItem) { walk_trait_item(self, t) }
|
||||
fn visit_trait_ref(&mut self, t: &'v TraitRef) { walk_trait_ref(self, t) }
|
||||
fn visit_poly_trait_ref(&mut self, t: &'v PolyTraitRef) {
|
||||
walk_poly_trait_ref(self, t)
|
||||
}
|
||||
fn visit_struct_def(&mut self, s: &'v StructDef, _: Ident, _: &'v Generics, _: NodeId) {
|
||||
walk_struct_def(self, s)
|
||||
}
|
||||
@ -202,9 +206,20 @@ pub fn walk_explicit_self<'v, V: Visitor<'v>>(visitor: &mut V,
|
||||
|
||||
/// Like with walk_method_helper this doesn't correspond to a method
|
||||
/// in Visitor, and so it gets a _helper suffix.
|
||||
pub fn walk_trait_ref_helper<'v,V>(visitor: &mut V, trait_ref: &'v TraitRef)
|
||||
where V: Visitor<'v> {
|
||||
walk_lifetime_decls(visitor, &trait_ref.lifetimes);
|
||||
pub fn walk_poly_trait_ref<'v, V>(visitor: &mut V,
|
||||
trait_ref: &'v PolyTraitRef)
|
||||
where V: Visitor<'v>
|
||||
{
|
||||
walk_lifetime_decls(visitor, &trait_ref.bound_lifetimes);
|
||||
visitor.visit_trait_ref(&trait_ref.trait_ref);
|
||||
}
|
||||
|
||||
/// Like with walk_method_helper this doesn't correspond to a method
|
||||
/// in Visitor, and so it gets a _helper suffix.
|
||||
pub fn walk_trait_ref<'v,V>(visitor: &mut V,
|
||||
trait_ref: &'v TraitRef)
|
||||
where V: Visitor<'v>
|
||||
{
|
||||
visitor.visit_path(&trait_ref.path, trait_ref.ref_id)
|
||||
}
|
||||
|
||||
@ -248,8 +263,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
|
||||
ref impl_items) => {
|
||||
visitor.visit_generics(type_parameters);
|
||||
match *trait_reference {
|
||||
Some(ref trait_reference) => walk_trait_ref_helper(visitor,
|
||||
trait_reference),
|
||||
Some(ref trait_reference) => visitor.visit_trait_ref(trait_reference),
|
||||
None => ()
|
||||
}
|
||||
visitor.visit_ty(&**typ);
|
||||
@ -383,6 +397,9 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
|
||||
visitor.visit_ty(&**ty);
|
||||
visitor.visit_expr(&**expression)
|
||||
}
|
||||
TyPolyTraitRef(ref poly_trait_ref) => {
|
||||
visitor.visit_poly_trait_ref(&**poly_trait_ref)
|
||||
}
|
||||
TyTypeof(ref expression) => {
|
||||
visitor.visit_expr(&**expression)
|
||||
}
|
||||
@ -497,7 +514,7 @@ pub fn walk_ty_param_bounds<'v, V: Visitor<'v>>(visitor: &mut V,
|
||||
for bound in bounds.iter() {
|
||||
match *bound {
|
||||
TraitTyParamBound(ref typ) => {
|
||||
walk_trait_ref_helper(visitor, typ)
|
||||
visitor.visit_poly_trait_ref(typ)
|
||||
}
|
||||
RegionTyParamBound(ref lifetime) => {
|
||||
visitor.visit_lifetime_ref(lifetime);
|
||||
|
@ -9,7 +9,7 @@
|
||||
// except according to those terms.
|
||||
|
||||
fn test<'x>(x: &'x int) {
|
||||
drop::< <'z>|&'z int| -> &'z int >(|z| {
|
||||
drop::< for<'z>|&'z int| -> &'z int >(|z| {
|
||||
x
|
||||
//~^ ERROR cannot infer an appropriate lifetime
|
||||
});
|
||||
|
@ -1,28 +0,0 @@
|
||||
// Copyright 2013 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.
|
||||
|
||||
// Testing guarantees provided by once functions.
|
||||
// This program would segfault if it were legal.
|
||||
|
||||
#![feature(once_fns)]
|
||||
use std::sync::Arc;
|
||||
|
||||
fn foo(blk: once ||) {
|
||||
blk();
|
||||
blk(); //~ ERROR use of moved value
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x = Arc::new(true);
|
||||
foo(|| {
|
||||
assert!(*x);
|
||||
drop(x);
|
||||
})
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
// Copyright 2013 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.
|
||||
|
||||
// Testing guarantees provided by once functions.
|
||||
// This program would segfault if it were legal.
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
fn foo(blk: ||) {
|
||||
blk();
|
||||
blk();
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x = Arc::new(true);
|
||||
foo(|| {
|
||||
assert!(*x);
|
||||
drop(x); //~ ERROR cannot move out of captured outer variable
|
||||
})
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
// Copyright 2012-2013 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(once_fns)]
|
||||
fn main() {
|
||||
let f: once || = ||();
|
||||
let g: || = f; //~ ERROR mismatched types
|
||||
let h: || = ||();
|
||||
let i: once || = h; // ok
|
||||
}
|
@ -22,11 +22,11 @@
|
||||
struct S;
|
||||
|
||||
// Given 'cx, return 'cx
|
||||
type F = fn<'cx>(&'cx S) -> &'cx S;
|
||||
type F = for<'cx> fn(&'cx S) -> &'cx S;
|
||||
fn want_F(f: F) { }
|
||||
|
||||
// Given anything, return 'static
|
||||
type G = fn<'cx>(&'cx S) -> &'static S;
|
||||
type G = for<'cx> fn(&'cx S) -> &'static S;
|
||||
fn want_G(f: G) { }
|
||||
|
||||
// Should meet both.
|
||||
|
@ -17,29 +17,29 @@ fn test_fn<'x,'y,'z,T>(_x: &'x T, _y: &'y T, _z: &'z T) {
|
||||
// subtype::<T1>(of::<T2>()) will typecheck
|
||||
// iff T1 <: T2.
|
||||
|
||||
subtype::< <'a>|&'a T|>(
|
||||
of::< <'a>|&'a T|>());
|
||||
subtype::< for<'a>|&'a T|>(
|
||||
of::< for<'a>|&'a T|>());
|
||||
|
||||
subtype::< <'a>|&'a T|>(
|
||||
of::< <'b>|&'b T|>());
|
||||
subtype::< for<'a>|&'a T|>(
|
||||
of::< for<'b>|&'b T|>());
|
||||
|
||||
subtype::< <'b>|&'b T|>(
|
||||
subtype::< for<'b>|&'b T|>(
|
||||
of::<|&'x T|>());
|
||||
|
||||
subtype::<|&'x T|>(
|
||||
of::< <'b>|&'b T|>()); //~ ERROR mismatched types
|
||||
of::< for<'b>|&'b T|>()); //~ ERROR mismatched types
|
||||
|
||||
subtype::< <'a,'b>|&'a T, &'b T|>(
|
||||
of::< <'a>|&'a T, &'a T|>());
|
||||
subtype::< for<'a,'b>|&'a T, &'b T|>(
|
||||
of::< for<'a>|&'a T, &'a T|>());
|
||||
|
||||
subtype::< <'a>|&'a T, &'a T|>(
|
||||
of::< <'a,'b>|&'a T, &'b T|>()); //~ ERROR mismatched types
|
||||
subtype::< for<'a>|&'a T, &'a T|>(
|
||||
of::< for<'a,'b>|&'a T, &'b T|>()); //~ ERROR mismatched types
|
||||
|
||||
subtype::< <'a,'b>|&'a T, &'b T|>(
|
||||
subtype::< for<'a,'b>|&'a T, &'b T|>(
|
||||
of::<|&'x T, &'y T|>());
|
||||
|
||||
subtype::<|&'x T, &'y T|>(
|
||||
of::< <'a,'b>|&'a T, &'b T|>()); //~ ERROR mismatched types
|
||||
of::< for<'a,'b>|&'a T, &'b T|>()); //~ ERROR mismatched types
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -9,7 +9,6 @@
|
||||
// except according to those terms.
|
||||
|
||||
struct Foo<'a, 'a> { //~ ERROR lifetime name `'a` declared twice
|
||||
//~^ ERROR lifetime name `'a` declared twice
|
||||
x: &'a int
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,6 @@
|
||||
// except according to those terms.
|
||||
|
||||
struct Foo<'static> { //~ ERROR illegal lifetime parameter name: `'static`
|
||||
//~^ ERROR illegal lifetime parameter name: `'static`
|
||||
x: &'static int
|
||||
}
|
||||
|
||||
|
@ -43,16 +43,16 @@ fn bar<'a>(x: &'a int) {
|
||||
|
||||
// &'a CAN be declared on functions and used then:
|
||||
fn g<'a>(a: &'a int) { } // OK
|
||||
fn h(a: <'a>|&'a int|) { } // OK
|
||||
fn h(a: for<'a>|&'a int|) { } // OK
|
||||
}
|
||||
|
||||
// Test nesting of lifetimes in fn type declarations
|
||||
fn fn_types(a: &'a int, //~ ERROR undeclared lifetime
|
||||
b: <'a>|a: &'a int,
|
||||
b: &'b int, //~ ERROR undeclared lifetime
|
||||
c: <'b>|a: &'a int,
|
||||
b: &'b int|,
|
||||
d: &'b int|, //~ ERROR undeclared lifetime
|
||||
b: for<'a>|a: &'a int,
|
||||
b: &'b int, //~ ERROR undeclared lifetime
|
||||
c: for<'b>|a: &'a int,
|
||||
b: &'b int|,
|
||||
d: &'b int|, //~ ERROR undeclared lifetime
|
||||
c: &'a int) //~ ERROR undeclared lifetime
|
||||
{
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
fn ignore(_f: <'z>|&'z int| -> &'z int) {}
|
||||
fn ignore(_f: for<'z>|&'z int| -> &'z int) {}
|
||||
|
||||
fn nested() {
|
||||
let y = 3;
|
||||
|
@ -14,13 +14,13 @@ fn nested<'x>(x: &'x int) {
|
||||
let y = 3;
|
||||
let mut ay = &y; //~ ERROR cannot infer
|
||||
|
||||
ignore::< <'z>|&'z int|>(|z| {
|
||||
ignore::< for<'z>|&'z int|>(|z| {
|
||||
ay = x;
|
||||
ay = &y;
|
||||
ay = z;
|
||||
});
|
||||
|
||||
ignore::< <'z>|&'z int| -> &'z int>(|z| {
|
||||
ignore::< for<'z>|&'z int| -> &'z int>(|z| {
|
||||
if false { return x; } //~ ERROR cannot infer an appropriate lifetime for automatic
|
||||
if false { return ay; }
|
||||
return z;
|
||||
|
@ -12,7 +12,7 @@
|
||||
// some point regions-ret-borrowed reported an error but this file did
|
||||
// not, due to special hardcoding around the anonymous region.
|
||||
|
||||
fn with<R>(f: <'a>|x: &'a int| -> R) -> R {
|
||||
fn with<R>(f: for<'a>|x: &'a int| -> R) -> R {
|
||||
f(&3)
|
||||
}
|
||||
|
||||
|
48
src/test/run-pass/hrtb-parse.rs
Normal file
48
src/test/run-pass/hrtb-parse.rs
Normal file
@ -0,0 +1,48 @@
|
||||
// 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.
|
||||
|
||||
// Test that we can parse all the various places that a `for` keyword
|
||||
// can appear representing universal quantification.
|
||||
|
||||
#![allow(unused_variables)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
trait Get<A,R> {
|
||||
fn get(&self, arg: A) -> R;
|
||||
}
|
||||
|
||||
// Parse HRTB with explicit `for` in a where-clause:
|
||||
|
||||
fn foo00<T>(t: T)
|
||||
where T : for<'a> Get<&'a int, &'a int>
|
||||
{
|
||||
}
|
||||
|
||||
fn foo01<T: for<'a> Get<&'a int, &'a int>>(t: T)
|
||||
{
|
||||
}
|
||||
|
||||
// Parse HRTB with explicit `for` in various sorts of types:
|
||||
|
||||
fn foo10(t: Box<for<'a> Get<int, int>>) { }
|
||||
fn foo11(t: Box<for<'a> Get(int) -> int>) { }
|
||||
|
||||
fn foo20(t: for<'a> fn(int) -> int) { }
|
||||
fn foo21(t: for<'a> unsafe fn(int) -> int) { }
|
||||
fn foo22(t: for<'a> extern "C" fn(int) -> int) { }
|
||||
fn foo23(t: for<'a> unsafe extern "C" fn(int) -> int) { }
|
||||
|
||||
fn foo30(t: for<'a> |int| -> int) { }
|
||||
fn foo31(t: for<'a> unsafe |int| -> int) { }
|
||||
|
||||
//fn foo40(t: for<'a> proc(int) -> int) { }
|
||||
|
||||
fn main() {
|
||||
}
|
@ -29,7 +29,7 @@ static FOO: int = 0xDEADBEE;
|
||||
|
||||
pub fn main() {
|
||||
unsafe {
|
||||
let f: extern "C" fn<'a>(&'a int) -> &'a int = mem::transmute(foo);
|
||||
let f: for<'a> extern "C" fn(&'a int) -> &'a int = mem::transmute(foo);
|
||||
assert_eq!(*f(&FOO), FOO);
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,6 @@
|
||||
// Testing guarantees provided by once functions.
|
||||
|
||||
|
||||
#![feature(once_fns)]
|
||||
use std::sync::Arc;
|
||||
|
||||
fn foo(blk: proc()) {
|
||||
|
@ -1,27 +0,0 @@
|
||||
// Copyright 2013-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.
|
||||
|
||||
// Testing guarantees provided by once functions.
|
||||
|
||||
|
||||
#![feature(once_fns)]
|
||||
use std::sync::Arc;
|
||||
|
||||
fn foo(blk: once ||) {
|
||||
blk();
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let x = Arc::new(true);
|
||||
foo(|| {
|
||||
assert!(*x);
|
||||
drop(x);
|
||||
})
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user