rollup merge of #19298: nikomatsakis/unboxed-closure-parse-the-plus
Implements RFC 438. Fixes #19092. This is a [breaking-change]: change types like `&Foo+Send` or `&'a mut Foo+'a` to `&(Foo+Send)` and `&'a mut (Foo+'a)`, respectively. r? @brson
This commit is contained in:
commit
f4a775639c
63 changed files with 479 additions and 373 deletions
|
@ -85,7 +85,7 @@ pub struct Formatter<'a> {
|
||||||
width: Option<uint>,
|
width: Option<uint>,
|
||||||
precision: Option<uint>,
|
precision: Option<uint>,
|
||||||
|
|
||||||
buf: &'a mut FormatWriter+'a,
|
buf: &'a mut (FormatWriter+'a),
|
||||||
curarg: slice::Items<'a, Argument<'a>>,
|
curarg: slice::Items<'a, Argument<'a>>,
|
||||||
args: &'a [Argument<'a>],
|
args: &'a [Argument<'a>],
|
||||||
}
|
}
|
||||||
|
@ -565,7 +565,7 @@ impl<'a, Sized? T: Show> Show for &'a T {
|
||||||
impl<'a, Sized? T: Show> Show for &'a mut T {
|
impl<'a, Sized? T: Show> Show for &'a mut T {
|
||||||
fn fmt(&self, f: &mut Formatter) -> Result { (**self).fmt(f) }
|
fn fmt(&self, f: &mut Formatter) -> Result { (**self).fmt(f) }
|
||||||
}
|
}
|
||||||
impl<'a> Show for &'a Show+'a {
|
impl<'a> Show for &'a (Show+'a) {
|
||||||
fn fmt(&self, f: &mut Formatter) -> Result { (*self).fmt(f) }
|
fn fmt(&self, f: &mut Formatter) -> Result { (*self).fmt(f) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -724,7 +724,7 @@ macro_rules! tuple (
|
||||||
|
|
||||||
tuple! { T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, }
|
tuple! { T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, }
|
||||||
|
|
||||||
impl<'a> Show for &'a any::Any+'a {
|
impl<'a> Show for &'a (any::Any+'a) {
|
||||||
fn fmt(&self, f: &mut Formatter) -> Result { f.pad("&Any") }
|
fn fmt(&self, f: &mut Formatter) -> Result { f.pad("&Any") }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -146,5 +146,6 @@ register_diagnostics!(
|
||||||
E0167,
|
E0167,
|
||||||
E0168,
|
E0168,
|
||||||
E0169,
|
E0169,
|
||||||
E0170
|
E0170,
|
||||||
|
E0171
|
||||||
)
|
)
|
||||||
|
|
|
@ -421,7 +421,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
||||||
impl<'a, 'tcx, 'v> Visitor<'v> for ImproperCTypesVisitor<'a, 'tcx> {
|
impl<'a, 'tcx, 'v> Visitor<'v> for ImproperCTypesVisitor<'a, 'tcx> {
|
||||||
fn visit_ty(&mut self, ty: &ast::Ty) {
|
fn visit_ty(&mut self, ty: &ast::Ty) {
|
||||||
match ty.node {
|
match ty.node {
|
||||||
ast::TyPath(_, _, id) => self.check_def(ty.span, ty.id, id),
|
ast::TyPath(_, id) => self.check_def(ty.span, ty.id, id),
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
visit::walk_ty(self, ty);
|
visit::walk_ty(self, ty);
|
||||||
|
|
|
@ -1230,10 +1230,9 @@ fn encode_info_for_item(ecx: &EncodeContext,
|
||||||
encode_name(rbml_w, item.ident.name);
|
encode_name(rbml_w, item.ident.name);
|
||||||
encode_attributes(rbml_w, item.attrs.as_slice());
|
encode_attributes(rbml_w, item.attrs.as_slice());
|
||||||
match ty.node {
|
match ty.node {
|
||||||
ast::TyPath(ref path, ref bounds, _) if path.segments
|
ast::TyPath(ref path, _) if path.segments
|
||||||
.len() == 1 => {
|
.len() == 1 => {
|
||||||
let ident = path.segments.last().unwrap().identifier;
|
let ident = path.segments.last().unwrap().identifier;
|
||||||
assert!(bounds.is_none());
|
|
||||||
encode_impl_type_basename(rbml_w, ident);
|
encode_impl_type_basename(rbml_w, ident);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|
|
@ -295,7 +295,7 @@ impl OverloadedCallType {
|
||||||
pub struct ExprUseVisitor<'d,'t,'tcx,TYPER:'t> {
|
pub struct ExprUseVisitor<'d,'t,'tcx,TYPER:'t> {
|
||||||
typer: &'t TYPER,
|
typer: &'t TYPER,
|
||||||
mc: mc::MemCategorizationContext<'t,TYPER>,
|
mc: mc::MemCategorizationContext<'t,TYPER>,
|
||||||
delegate: &'d mut Delegate<'tcx>+'d,
|
delegate: &'d mut (Delegate<'tcx>+'d),
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the TYPER results in an error, it's because the type check
|
// If the TYPER results in an error, it's because the type check
|
||||||
|
|
|
@ -243,7 +243,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
|
||||||
// * Private trait impls for private types can be completely ignored
|
// * Private trait impls for private types can be completely ignored
|
||||||
ast::ItemImpl(_, _, ref ty, ref impl_items) => {
|
ast::ItemImpl(_, _, ref ty, ref impl_items) => {
|
||||||
let public_ty = match ty.node {
|
let public_ty = match ty.node {
|
||||||
ast::TyPath(_, _, id) => {
|
ast::TyPath(_, id) => {
|
||||||
match self.tcx.def_map.borrow()[id].clone() {
|
match self.tcx.def_map.borrow()[id].clone() {
|
||||||
def::DefPrimTy(..) => true,
|
def::DefPrimTy(..) => true,
|
||||||
def => {
|
def => {
|
||||||
|
@ -311,7 +311,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
|
||||||
|
|
||||||
ast::ItemTy(ref ty, _) if public_first => {
|
ast::ItemTy(ref ty, _) if public_first => {
|
||||||
match ty.node {
|
match ty.node {
|
||||||
ast::TyPath(_, _, id) => {
|
ast::TyPath(_, id) => {
|
||||||
match self.tcx.def_map.borrow()[id].clone() {
|
match self.tcx.def_map.borrow()[id].clone() {
|
||||||
def::DefPrimTy(..) | def::DefTyParam(..) => {},
|
def::DefPrimTy(..) | def::DefTyParam(..) => {},
|
||||||
def => {
|
def => {
|
||||||
|
@ -616,7 +616,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
|
||||||
// was private.
|
// was private.
|
||||||
ast::ItemImpl(_, _, ref ty, _) => {
|
ast::ItemImpl(_, _, ref ty, _) => {
|
||||||
let id = match ty.node {
|
let id = match ty.node {
|
||||||
ast::TyPath(_, _, id) => id,
|
ast::TyPath(_, id) => id,
|
||||||
_ => return Some((err_span, err_msg, None)),
|
_ => return Some((err_span, err_msg, None)),
|
||||||
};
|
};
|
||||||
let def = self.tcx.def_map.borrow()[id].clone();
|
let def = self.tcx.def_map.borrow()[id].clone();
|
||||||
|
@ -1292,7 +1292,7 @@ impl<'a, 'tcx> VisiblePrivateTypesVisitor<'a, 'tcx> {
|
||||||
impl<'a, 'b, 'tcx, 'v> Visitor<'v> for CheckTypeForPrivatenessVisitor<'a, 'b, 'tcx> {
|
impl<'a, 'b, 'tcx, 'v> Visitor<'v> for CheckTypeForPrivatenessVisitor<'a, 'b, 'tcx> {
|
||||||
fn visit_ty(&mut self, ty: &ast::Ty) {
|
fn visit_ty(&mut self, ty: &ast::Ty) {
|
||||||
match ty.node {
|
match ty.node {
|
||||||
ast::TyPath(_, _, path_id) => {
|
ast::TyPath(_, path_id) => {
|
||||||
if self.inner.path_is_private_type(path_id) {
|
if self.inner.path_is_private_type(path_id) {
|
||||||
self.contains_private = true;
|
self.contains_private = true;
|
||||||
// found what we're looking for so let's stop
|
// found what we're looking for so let's stop
|
||||||
|
@ -1493,7 +1493,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
|
||||||
|
|
||||||
fn visit_ty(&mut self, t: &ast::Ty) {
|
fn visit_ty(&mut self, t: &ast::Ty) {
|
||||||
match t.node {
|
match t.node {
|
||||||
ast::TyPath(ref p, _, path_id) => {
|
ast::TyPath(ref p, path_id) => {
|
||||||
if !self.tcx.sess.features.borrow().visible_private_types &&
|
if !self.tcx.sess.features.borrow().visible_private_types &&
|
||||||
self.path_is_private_type(path_id) {
|
self.path_is_private_type(path_id) {
|
||||||
self.tcx.sess.span_err(p.span,
|
self.tcx.sess.span_err(p.span,
|
||||||
|
|
|
@ -63,7 +63,7 @@ use syntax::ast::{PolyTraitRef, PrimTy, Public, SelfExplicit, SelfStatic};
|
||||||
use syntax::ast::{RegionTyParamBound, StmtDecl, StructField};
|
use syntax::ast::{RegionTyParamBound, StmtDecl, StructField};
|
||||||
use syntax::ast::{StructVariantKind, TraitRef, TraitTyParamBound};
|
use syntax::ast::{StructVariantKind, TraitRef, TraitTyParamBound};
|
||||||
use syntax::ast::{TupleVariantKind, Ty, TyBool, TyChar, TyClosure, TyF32};
|
use syntax::ast::{TupleVariantKind, Ty, TyBool, TyChar, TyClosure, TyF32};
|
||||||
use syntax::ast::{TyF64, TyFloat, TyI, TyI8, TyI16, TyI32, TyI64, TyInt};
|
use syntax::ast::{TyF64, TyFloat, TyI, TyI8, TyI16, TyI32, TyI64, TyInt, TyObjectSum};
|
||||||
use syntax::ast::{TyParam, TyParamBound, TyPath, TyPtr, TyPolyTraitRef, 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::{TyRptr, TyStr, TyU, TyU8, TyU16, TyU32, TyU64, TyUint};
|
||||||
use syntax::ast::{TypeImplItem, UnnamedField};
|
use syntax::ast::{TypeImplItem, UnnamedField};
|
||||||
|
@ -1392,13 +1392,37 @@ impl<'a> Resolver<'a> {
|
||||||
// methods within to a new module, if the type was defined
|
// methods within to a new module, if the type was defined
|
||||||
// within this module.
|
// within this module.
|
||||||
|
|
||||||
// Create the module and add all methods.
|
let mod_name = match ty.node {
|
||||||
match ty.node {
|
TyPath(ref path, _) if path.segments.len() == 1 => {
|
||||||
TyPath(ref path, _, _) if path.segments.len() == 1 => {
|
|
||||||
// FIXME(18446) we should distinguish between the name of
|
// FIXME(18446) we should distinguish between the name of
|
||||||
// a trait and the name of an impl of that trait.
|
// a trait and the name of an impl of that trait.
|
||||||
let mod_name = path.segments.last().unwrap().identifier.name;
|
Some(path.segments.last().unwrap().identifier.name)
|
||||||
|
}
|
||||||
|
TyObjectSum(ref lhs_ty, _) => {
|
||||||
|
match lhs_ty.node {
|
||||||
|
TyPath(ref path, _) if path.segments.len() == 1 => {
|
||||||
|
Some(path.segments.last().unwrap().identifier.name)
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
match mod_name {
|
||||||
|
None => {
|
||||||
|
self.resolve_error(ty.span,
|
||||||
|
"inherent implementations may \
|
||||||
|
only be implemented in the same \
|
||||||
|
module as the type they are \
|
||||||
|
implemented for")
|
||||||
|
}
|
||||||
|
Some(mod_name) => {
|
||||||
|
// Create the module and add all methods.
|
||||||
let parent_opt = parent.module().children.borrow()
|
let parent_opt = parent.module().children.borrow()
|
||||||
.get(&mod_name).cloned();
|
.get(&mod_name).cloned();
|
||||||
let new_parent = match parent_opt {
|
let new_parent = match parent_opt {
|
||||||
|
@ -1507,13 +1531,6 @@ impl<'a> Resolver<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
|
||||||
self.resolve_error(ty.span,
|
|
||||||
"inherent implementations may \
|
|
||||||
only be implemented in the same \
|
|
||||||
module as the type they are \
|
|
||||||
implemented for")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
parent
|
parent
|
||||||
|
@ -4721,7 +4738,7 @@ impl<'a> Resolver<'a> {
|
||||||
// type, the result will be that the type name resolves to a module but not
|
// type, the result will be that the type name resolves to a module but not
|
||||||
// a type (shadowing any imported modules or types with this name), leading
|
// a type (shadowing any imported modules or types with this name), leading
|
||||||
// to weird user-visible bugs. So we ward this off here. See #15060.
|
// to weird user-visible bugs. So we ward this off here. See #15060.
|
||||||
TyPath(ref path, _, path_id) => {
|
TyPath(ref path, path_id) => {
|
||||||
match self.def_map.borrow().get(&path_id) {
|
match self.def_map.borrow().get(&path_id) {
|
||||||
// FIXME: should we catch other options and give more precise errors?
|
// FIXME: should we catch other options and give more precise errors?
|
||||||
Some(&DefMod(_)) => {
|
Some(&DefMod(_)) => {
|
||||||
|
@ -4887,7 +4904,7 @@ impl<'a> Resolver<'a> {
|
||||||
// Like path expressions, the interpretation of path types depends
|
// Like path expressions, the interpretation of path types depends
|
||||||
// on whether the path has multiple elements in it or not.
|
// on whether the path has multiple elements in it or not.
|
||||||
|
|
||||||
TyPath(ref path, ref bounds, path_id) => {
|
TyPath(ref path, path_id) => {
|
||||||
// This is a path in the type namespace. Walk through scopes
|
// This is a path in the type namespace. Walk through scopes
|
||||||
// looking for it.
|
// looking for it.
|
||||||
let mut result_def = None;
|
let mut result_def = None;
|
||||||
|
@ -4957,11 +4974,12 @@ impl<'a> Resolver<'a> {
|
||||||
self.resolve_error(ty.span, msg.as_slice());
|
self.resolve_error(ty.span, msg.as_slice());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bounds.as_ref().map(|bound_vec| {
|
TyObjectSum(ref ty, ref bound_vec) => {
|
||||||
|
self.resolve_type(&**ty);
|
||||||
self.resolve_type_parameter_bounds(ty.id, bound_vec,
|
self.resolve_type_parameter_bounds(ty.id, bound_vec,
|
||||||
TraitBoundingTypeParameter);
|
TraitBoundingTypeParameter);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TyQPath(ref qpath) => {
|
TyQPath(ref qpath) => {
|
||||||
|
@ -5598,7 +5616,7 @@ impl<'a> Resolver<'a> {
|
||||||
fn extract_path_and_node_id(t: &Ty, allow: FallbackChecks)
|
fn extract_path_and_node_id(t: &Ty, allow: FallbackChecks)
|
||||||
-> Option<(Path, NodeId, FallbackChecks)> {
|
-> Option<(Path, NodeId, FallbackChecks)> {
|
||||||
match t.node {
|
match t.node {
|
||||||
TyPath(ref path, _, node_id) => Some((path.clone(), node_id, allow)),
|
TyPath(ref path, node_id) => Some((path.clone(), node_id, allow)),
|
||||||
TyPtr(ref mut_ty) => extract_path_and_node_id(&*mut_ty.ty, OnlyTraitAndStatics),
|
TyPtr(ref mut_ty) => extract_path_and_node_id(&*mut_ty.ty, OnlyTraitAndStatics),
|
||||||
TyRptr(_, ref mut_ty) => extract_path_and_node_id(&*mut_ty.ty, allow),
|
TyRptr(_, ref mut_ty) => extract_path_and_node_id(&*mut_ty.ty, allow),
|
||||||
// This doesn't handle the remaining `Ty` variants as they are not
|
// This doesn't handle the remaining `Ty` variants as they are not
|
||||||
|
|
|
@ -162,7 +162,7 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
|
||||||
visit::walk_ty(this, ty);
|
visit::walk_ty(this, ty);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
ast::TyPath(ref path, ref opt_bounds, id) => {
|
ast::TyPath(ref path, id) => {
|
||||||
// if this path references a trait, then this will resolve to
|
// if this path references a trait, then this will resolve to
|
||||||
// a trait ref, which introduces a binding scope.
|
// a trait ref, which introduces a binding scope.
|
||||||
match self.def_map.borrow().get(&id) {
|
match self.def_map.borrow().get(&id) {
|
||||||
|
@ -170,13 +170,6 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
|
||||||
self.with(LateScope(&Vec::new(), self.scope), |this| {
|
self.with(LateScope(&Vec::new(), self.scope), |this| {
|
||||||
this.visit_path(path, id);
|
this.visit_path(path, id);
|
||||||
});
|
});
|
||||||
|
|
||||||
match *opt_bounds {
|
|
||||||
Some(ref bounds) => {
|
|
||||||
visit::walk_ty_param_bounds_helper(self, bounds);
|
|
||||||
}
|
|
||||||
None => { }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
visit::walk_ty(self, ty);
|
visit::walk_ty(self, ty);
|
||||||
|
|
|
@ -43,7 +43,7 @@ use util::ppaux::Repr;
|
||||||
pub struct SelectionContext<'cx, 'tcx:'cx> {
|
pub struct SelectionContext<'cx, 'tcx:'cx> {
|
||||||
infcx: &'cx InferCtxt<'cx, 'tcx>,
|
infcx: &'cx InferCtxt<'cx, 'tcx>,
|
||||||
param_env: &'cx ty::ParameterEnvironment<'tcx>,
|
param_env: &'cx ty::ParameterEnvironment<'tcx>,
|
||||||
typer: &'cx Typer<'tcx>+'cx,
|
typer: &'cx (Typer<'tcx>+'cx),
|
||||||
|
|
||||||
/// Skolemizer used specifically for skolemizing entries on the
|
/// Skolemizer used specifically for skolemizing entries on the
|
||||||
/// obligation stack. This ensures that all entries on the stack
|
/// obligation stack. This ensures that all entries on the stack
|
||||||
|
|
|
@ -59,8 +59,9 @@ use middle::typeck::rscope::{UnelidableRscope, RegionScope, SpecificRscope,
|
||||||
ShiftedRscope, BindingRscope};
|
ShiftedRscope, BindingRscope};
|
||||||
use middle::typeck::rscope;
|
use middle::typeck::rscope;
|
||||||
use middle::typeck::TypeAndSubsts;
|
use middle::typeck::TypeAndSubsts;
|
||||||
|
use util::common::ErrorReported;
|
||||||
use util::nodemap::DefIdMap;
|
use util::nodemap::DefIdMap;
|
||||||
use util::ppaux::{Repr, UserString};
|
use util::ppaux::{mod, Repr, UserString};
|
||||||
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::iter::AdditiveIterator;
|
use std::iter::AdditiveIterator;
|
||||||
|
@ -585,7 +586,7 @@ fn check_path_args(tcx: &ty::ctxt,
|
||||||
pub fn ast_ty_to_prim_ty<'tcx>(tcx: &ty::ctxt<'tcx>, ast_ty: &ast::Ty)
|
pub fn ast_ty_to_prim_ty<'tcx>(tcx: &ty::ctxt<'tcx>, ast_ty: &ast::Ty)
|
||||||
-> Option<Ty<'tcx>> {
|
-> Option<Ty<'tcx>> {
|
||||||
match ast_ty.node {
|
match ast_ty.node {
|
||||||
ast::TyPath(ref path, _, id) => {
|
ast::TyPath(ref path, id) => {
|
||||||
let a_def = match tcx.def_map.borrow().get(&id) {
|
let a_def = match tcx.def_map.borrow().get(&id) {
|
||||||
None => {
|
None => {
|
||||||
tcx.sess.span_bug(ast_ty.span,
|
tcx.sess.span_bug(ast_ty.span,
|
||||||
|
@ -642,7 +643,7 @@ pub fn ast_ty_to_builtin_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||||
}
|
}
|
||||||
|
|
||||||
match ast_ty.node {
|
match ast_ty.node {
|
||||||
ast::TyPath(ref path, _, id) => {
|
ast::TyPath(ref path, id) => {
|
||||||
let a_def = match this.tcx().def_map.borrow().get(&id) {
|
let a_def = match this.tcx().def_map.borrow().get(&id) {
|
||||||
None => {
|
None => {
|
||||||
this.tcx()
|
this.tcx()
|
||||||
|
@ -682,64 +683,92 @@ pub fn ast_ty_to_builtin_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle `~`, `Box`, and `&` being able to mean strs and vecs.
|
fn ast_ty_to_trait_ref<'tcx,AC,RS>(this: &AC,
|
||||||
// If a_seq_ty is a str or a vec, make it a str/vec.
|
|
||||||
// Also handle first-class trait types.
|
|
||||||
fn mk_pointer<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
|
||||||
this: &AC,
|
|
||||||
rscope: &RS,
|
rscope: &RS,
|
||||||
a_seq_mutbl: ast::Mutability,
|
ty: &ast::Ty,
|
||||||
a_seq_ty: &ast::Ty,
|
bounds: &[ast::TyParamBound])
|
||||||
region: ty::Region,
|
-> Result<ty::TraitRef<'tcx>, ErrorReported>
|
||||||
constr: |Ty<'tcx>| -> Ty<'tcx>)
|
where AC : AstConv<'tcx>, RS : RegionScope
|
||||||
-> Ty<'tcx>
|
|
||||||
{
|
{
|
||||||
let tcx = this.tcx();
|
/*!
|
||||||
|
* In a type like `Foo + Send`, we want to wait to collect the
|
||||||
|
* full set of bounds before we make the object type, because we
|
||||||
|
* need them to infer a region bound. (For example, if we tried
|
||||||
|
* made a type from just `Foo`, then it wouldn't be enough to
|
||||||
|
* infer a 'static bound, and hence the user would get an error.)
|
||||||
|
* So this function is used when we're dealing with a sum type to
|
||||||
|
* convert the LHS. It only accepts a type that refers to a trait
|
||||||
|
* name, and reports an error otherwise.
|
||||||
|
*/
|
||||||
|
|
||||||
debug!("mk_pointer(region={}, a_seq_ty={})",
|
match ty.node {
|
||||||
region,
|
ast::TyPath(ref path, id) => {
|
||||||
a_seq_ty.repr(tcx));
|
match this.tcx().def_map.borrow().get(&id) {
|
||||||
|
|
||||||
match a_seq_ty.node {
|
|
||||||
ast::TyVec(ref ty) => {
|
|
||||||
let ty = ast_ty_to_ty(this, rscope, &**ty);
|
|
||||||
return constr(ty::mk_vec(tcx, ty, None));
|
|
||||||
}
|
|
||||||
ast::TyPath(ref path, ref opt_bounds, id) => {
|
|
||||||
// Note that the "bounds must be empty if path is not a trait"
|
|
||||||
// restriction is enforced in the below case for ty_path, which
|
|
||||||
// will run after this as long as the path isn't a trait.
|
|
||||||
match tcx.def_map.borrow().get(&id) {
|
|
||||||
Some(&def::DefPrimTy(ast::TyStr)) => {
|
|
||||||
check_path_args(tcx, path, NO_TPS | NO_REGIONS);
|
|
||||||
return ty::mk_str_slice(tcx, region, a_seq_mutbl);
|
|
||||||
}
|
|
||||||
Some(&def::DefTrait(trait_def_id)) => {
|
Some(&def::DefTrait(trait_def_id)) => {
|
||||||
let result = ast_path_to_trait_ref(this,
|
return Ok(ast_path_to_trait_ref(this,
|
||||||
rscope,
|
rscope,
|
||||||
trait_def_id,
|
trait_def_id,
|
||||||
None,
|
None,
|
||||||
path);
|
path));
|
||||||
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,
|
|
||||||
existential_bounds);
|
|
||||||
return ty::mk_rptr(tcx, region, ty::mt{mutbl: a_seq_mutbl, ty: tr});
|
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {
|
||||||
|
span_err!(this.tcx().sess, ty.span, E0170, "expected a reference to a trait");
|
||||||
|
Err(ErrorReported)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
}
|
||||||
|
_ => {
|
||||||
|
span_err!(this.tcx().sess, ty.span, E0171,
|
||||||
|
"expected a path on the left-hand side of `+`, not `{}`",
|
||||||
|
pprust::ty_to_string(ty));
|
||||||
|
match ty.node {
|
||||||
|
ast::TyRptr(None, ref mut_ty) => {
|
||||||
|
span_note!(this.tcx().sess, ty.span,
|
||||||
|
"perhaps you meant `&{}({} +{})`? (per RFC 248)",
|
||||||
|
ppaux::mutability_to_string(mut_ty.mutbl),
|
||||||
|
pprust::ty_to_string(&*mut_ty.ty),
|
||||||
|
pprust::bounds_to_string(bounds));
|
||||||
}
|
}
|
||||||
|
|
||||||
constr(ast_ty_to_ty(this, rscope, a_seq_ty))
|
ast::TyRptr(Some(ref lt), ref mut_ty) => {
|
||||||
|
span_note!(this.tcx().sess, ty.span,
|
||||||
|
"perhaps you meant `&{} {}({} +{})`? (per RFC 248)",
|
||||||
|
pprust::lifetime_to_string(lt),
|
||||||
|
ppaux::mutability_to_string(mut_ty.mutbl),
|
||||||
|
pprust::ty_to_string(&*mut_ty.ty),
|
||||||
|
pprust::bounds_to_string(bounds));
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => {
|
||||||
|
span_note!(this.tcx().sess, ty.span,
|
||||||
|
"perhaps you forget parentheses? (per RFC 248)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(ErrorReported)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fn trait_ref_to_object_type<'tcx,AC,RS>(this: &AC,
|
||||||
|
rscope: &RS,
|
||||||
|
span: Span,
|
||||||
|
trait_ref: ty::TraitRef<'tcx>,
|
||||||
|
bounds: &[ast::TyParamBound])
|
||||||
|
-> Ty<'tcx>
|
||||||
|
where AC : AstConv<'tcx>, RS : RegionScope
|
||||||
|
{
|
||||||
|
let existential_bounds = conv_existential_bounds(this,
|
||||||
|
rscope,
|
||||||
|
span,
|
||||||
|
&[Rc::new(trait_ref.clone())],
|
||||||
|
bounds);
|
||||||
|
|
||||||
|
let result = ty::mk_trait(this.tcx(), trait_ref, existential_bounds);
|
||||||
|
debug!("trait_ref_to_object_type: result={}",
|
||||||
|
result.repr(this.tcx()));
|
||||||
|
|
||||||
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
fn qpath_to_ty<'tcx,AC,RS>(this: &AC,
|
fn qpath_to_ty<'tcx,AC,RS>(this: &AC,
|
||||||
|
@ -806,6 +835,17 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||||
ast::TyVec(ref ty) => {
|
ast::TyVec(ref ty) => {
|
||||||
ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty), None)
|
ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty), None)
|
||||||
}
|
}
|
||||||
|
ast::TyObjectSum(ref ty, ref bounds) => {
|
||||||
|
match ast_ty_to_trait_ref(this, rscope, &**ty, bounds.as_slice()) {
|
||||||
|
Ok(trait_ref) => {
|
||||||
|
trait_ref_to_object_type(this, rscope, ast_ty.span,
|
||||||
|
trait_ref, bounds.as_slice())
|
||||||
|
}
|
||||||
|
Err(ErrorReported) => {
|
||||||
|
ty::mk_err()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
ast::TyPtr(ref mt) => {
|
ast::TyPtr(ref mt) => {
|
||||||
ty::mk_ptr(tcx, ty::mt {
|
ty::mk_ptr(tcx, ty::mt {
|
||||||
ty: ast_ty_to_ty(this, rscope, &*mt.ty),
|
ty: ast_ty_to_ty(this, rscope, &*mt.ty),
|
||||||
|
@ -815,8 +855,8 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||||
ast::TyRptr(ref region, ref mt) => {
|
ast::TyRptr(ref region, ref mt) => {
|
||||||
let r = opt_ast_region_to_region(this, rscope, ast_ty.span, region);
|
let r = opt_ast_region_to_region(this, rscope, ast_ty.span, region);
|
||||||
debug!("ty_rptr r={}", r.repr(this.tcx()));
|
debug!("ty_rptr r={}", r.repr(this.tcx()));
|
||||||
mk_pointer(this, rscope, mt.mutbl, &*mt.ty, r,
|
let t = ast_ty_to_ty(this, rscope, &*mt.ty);
|
||||||
|ty| ty::mk_rptr(tcx, r, ty::mt {ty: ty, mutbl: mt.mutbl}))
|
ty::mk_rptr(tcx, r, ty::mt {ty: t, mutbl: mt.mutbl})
|
||||||
}
|
}
|
||||||
ast::TyTup(ref fields) => {
|
ast::TyTup(ref fields) => {
|
||||||
let flds = fields.iter()
|
let flds = fields.iter()
|
||||||
|
@ -874,7 +914,7 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||||
ast::TyPolyTraitRef(ref bounds) => {
|
ast::TyPolyTraitRef(ref bounds) => {
|
||||||
conv_ty_poly_trait_ref(this, rscope, ast_ty.span, bounds.as_slice())
|
conv_ty_poly_trait_ref(this, rscope, ast_ty.span, bounds.as_slice())
|
||||||
}
|
}
|
||||||
ast::TyPath(ref path, ref bounds, id) => {
|
ast::TyPath(ref path, id) => {
|
||||||
let a_def = match tcx.def_map.borrow().get(&id) {
|
let a_def = match tcx.def_map.borrow().get(&id) {
|
||||||
None => {
|
None => {
|
||||||
tcx.sess
|
tcx.sess
|
||||||
|
@ -884,35 +924,16 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||||
}
|
}
|
||||||
Some(&d) => d
|
Some(&d) => d
|
||||||
};
|
};
|
||||||
// Kind bounds on path types are only supported for traits.
|
|
||||||
match a_def {
|
|
||||||
// But don't emit the error if the user meant to do a trait anyway.
|
|
||||||
def::DefTrait(..) => { },
|
|
||||||
_ if bounds.is_some() =>
|
|
||||||
tcx.sess.span_err(ast_ty.span,
|
|
||||||
"kind bounds can only be used on trait types"),
|
|
||||||
_ => { },
|
|
||||||
}
|
|
||||||
match a_def {
|
match a_def {
|
||||||
def::DefTrait(trait_def_id) => {
|
def::DefTrait(trait_def_id) => {
|
||||||
|
// N.B. this case overlaps somewhat with
|
||||||
|
// TyObjectSum, see that fn for details
|
||||||
let result = ast_path_to_trait_ref(this,
|
let result = ast_path_to_trait_ref(this,
|
||||||
rscope,
|
rscope,
|
||||||
trait_def_id,
|
trait_def_id,
|
||||||
None,
|
None,
|
||||||
path);
|
path);
|
||||||
let empty_bounds: &[ast::TyParamBound] = &[];
|
trait_ref_to_object_type(this, rscope, path.span, result, &[])
|
||||||
let ast_bounds = match *bounds {
|
|
||||||
Some(ref b) => b.as_slice(),
|
|
||||||
None => empty_bounds
|
|
||||||
};
|
|
||||||
let bounds = conv_existential_bounds(this,
|
|
||||||
rscope,
|
|
||||||
ast_ty.span,
|
|
||||||
&[Rc::new(result.clone())],
|
|
||||||
ast_bounds);
|
|
||||||
let result_ty = ty::mk_trait(tcx, result, bounds);
|
|
||||||
debug!("ast_ty_to_ty: result_ty={}", result_ty.repr(this.tcx()));
|
|
||||||
result_ty
|
|
||||||
}
|
}
|
||||||
def::DefTy(did, _) | def::DefStruct(did) => {
|
def::DefTy(did, _) | def::DefStruct(did) => {
|
||||||
ast_path_to_ty(this, rscope, did, path).ty
|
ast_path_to_ty(this, rscope, did, path).ty
|
||||||
|
|
|
@ -1249,7 +1249,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
ty_queue.push(&*mut_ty.ty);
|
ty_queue.push(&*mut_ty.ty);
|
||||||
}
|
}
|
||||||
ast::TyPath(ref path, ref bounds, id) => {
|
ast::TyPath(ref path, id) => {
|
||||||
let a_def = match self.tcx.def_map.borrow().get(&id) {
|
let a_def = match self.tcx.def_map.borrow().get(&id) {
|
||||||
None => {
|
None => {
|
||||||
self.tcx
|
self.tcx
|
||||||
|
@ -1296,7 +1296,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
|
||||||
let new_path = self.rebuild_path(rebuild_info, lifetime);
|
let new_path = self.rebuild_path(rebuild_info, lifetime);
|
||||||
let to = ast::Ty {
|
let to = ast::Ty {
|
||||||
id: cur_ty.id,
|
id: cur_ty.id,
|
||||||
node: ast::TyPath(new_path, bounds.clone(), id),
|
node: ast::TyPath(new_path, id),
|
||||||
span: cur_ty.span
|
span: cur_ty.span
|
||||||
};
|
};
|
||||||
new_ty = self.rebuild_ty(new_ty, P(to));
|
new_ty = self.rebuild_ty(new_ty, P(to));
|
||||||
|
|
|
@ -139,11 +139,11 @@ impl RegionScope for BindingRscope {
|
||||||
/// A scope which simply shifts the Debruijn index of other scopes
|
/// A scope which simply shifts the Debruijn index of other scopes
|
||||||
/// to account for binding levels.
|
/// to account for binding levels.
|
||||||
pub struct ShiftedRscope<'r> {
|
pub struct ShiftedRscope<'r> {
|
||||||
base_scope: &'r RegionScope+'r
|
base_scope: &'r (RegionScope+'r)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'r> ShiftedRscope<'r> {
|
impl<'r> ShiftedRscope<'r> {
|
||||||
pub fn new(base_scope: &'r RegionScope+'r) -> ShiftedRscope<'r> {
|
pub fn new(base_scope: &'r (RegionScope+'r)) -> ShiftedRscope<'r> {
|
||||||
ShiftedRscope { base_scope: base_scope }
|
ShiftedRscope { base_scope: base_scope }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -651,7 +651,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
|
||||||
typ: &ast::Ty,
|
typ: &ast::Ty,
|
||||||
impl_items: &Vec<ast::ImplItem>) {
|
impl_items: &Vec<ast::ImplItem>) {
|
||||||
match typ.node {
|
match typ.node {
|
||||||
ast::TyPath(ref path, _, id) => {
|
ast::TyPath(ref path, id) => {
|
||||||
match self.lookup_type_ref(id) {
|
match self.lookup_type_ref(id) {
|
||||||
Some(id) => {
|
Some(id) => {
|
||||||
let sub_span = self.span.sub_span_for_type_name(path.span);
|
let sub_span = self.span.sub_span_for_type_name(path.span);
|
||||||
|
@ -1256,7 +1256,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
match t.node {
|
match t.node {
|
||||||
ast::TyPath(ref path, _, id) => {
|
ast::TyPath(ref path, id) => {
|
||||||
match self.lookup_type_ref(id) {
|
match self.lookup_type_ref(id) {
|
||||||
Some(id) => {
|
Some(id) => {
|
||||||
let sub_span = self.span.sub_span_for_type_name(t.span);
|
let sub_span = self.span.sub_span_for_type_name(t.span);
|
||||||
|
|
|
@ -992,7 +992,7 @@ impl Clean<Item> for doctree::Trait {
|
||||||
|
|
||||||
impl Clean<Type> for ast::TraitRef {
|
impl Clean<Type> for ast::TraitRef {
|
||||||
fn clean(&self, cx: &DocContext) -> Type {
|
fn clean(&self, cx: &DocContext) -> Type {
|
||||||
resolve_type(cx, self.path.clean(cx), None, self.ref_id)
|
resolve_type(cx, self.path.clean(cx), self.ref_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1278,8 +1278,19 @@ impl Clean<Type> for ast::Ty {
|
||||||
TyFixedLengthVec(ref ty, ref e) => FixedVector(box ty.clean(cx),
|
TyFixedLengthVec(ref ty, ref e) => FixedVector(box ty.clean(cx),
|
||||||
e.span.to_src(cx)),
|
e.span.to_src(cx)),
|
||||||
TyTup(ref tys) => Tuple(tys.clean(cx)),
|
TyTup(ref tys) => Tuple(tys.clean(cx)),
|
||||||
TyPath(ref p, ref tpbs, id) => {
|
TyPath(ref p, id) => {
|
||||||
resolve_type(cx, p.clean(cx), tpbs.clean(cx), id)
|
resolve_type(cx, p.clean(cx), id)
|
||||||
|
}
|
||||||
|
TyObjectSum(ref lhs, ref bounds) => {
|
||||||
|
let lhs_ty = lhs.clean(cx);
|
||||||
|
match lhs_ty {
|
||||||
|
ResolvedPath { path, typarams: None, did } => {
|
||||||
|
ResolvedPath { path: path, typarams: Some(bounds.clean(cx)), did: did}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
lhs_ty // shouldn't happen
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
TyClosure(ref c) => Closure(box c.clean(cx)),
|
TyClosure(ref c) => Closure(box c.clean(cx)),
|
||||||
TyProc(ref c) => Proc(box c.clean(cx)),
|
TyProc(ref c) => Proc(box c.clean(cx)),
|
||||||
|
@ -2130,8 +2141,8 @@ fn name_from_pat(p: &ast::Pat) -> String {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a Type, resolve it using the def_map
|
/// Given a Type, resolve it using the def_map
|
||||||
fn resolve_type(cx: &DocContext, path: Path,
|
fn resolve_type(cx: &DocContext,
|
||||||
tpbs: Option<Vec<TyParamBound>>,
|
path: Path,
|
||||||
id: ast::NodeId) -> Type {
|
id: ast::NodeId) -> Type {
|
||||||
let tcx = match cx.tcx_opt() {
|
let tcx = match cx.tcx_opt() {
|
||||||
Some(tcx) => tcx,
|
Some(tcx) => tcx,
|
||||||
|
@ -2168,7 +2179,7 @@ fn resolve_type(cx: &DocContext, path: Path,
|
||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
let did = register_def(&*cx, def);
|
let did = register_def(&*cx, def);
|
||||||
ResolvedPath { path: path, typarams: tpbs, did: did }
|
ResolvedPath { path: path, typarams: None, did: did }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn register_def(cx: &DocContext, def: def::Def) -> ast::DefId {
|
fn register_def(cx: &DocContext, def: def::Def) -> ast::DefId {
|
||||||
|
|
|
@ -86,7 +86,7 @@ struct Exception {
|
||||||
cause: Option<Box<Any + Send>>,
|
cause: Option<Box<Any + Send>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Callback = fn(msg: &Any + Send, file: &'static str, line: uint);
|
pub type Callback = fn(msg: &(Any + Send), file: &'static str, line: uint);
|
||||||
|
|
||||||
// Variables used for invoking callbacks when a task starts to unwind.
|
// Variables used for invoking callbacks when a task starts to unwind.
|
||||||
//
|
//
|
||||||
|
|
|
@ -397,7 +397,7 @@ fn fmt_number_or_null(v: f64) -> string::String {
|
||||||
|
|
||||||
/// A structure for implementing serialization to JSON.
|
/// A structure for implementing serialization to JSON.
|
||||||
pub struct Encoder<'a> {
|
pub struct Encoder<'a> {
|
||||||
writer: &'a mut io::Writer+'a,
|
writer: &'a mut (io::Writer+'a),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Encoder<'a> {
|
impl<'a> Encoder<'a> {
|
||||||
|
@ -601,7 +601,7 @@ impl<'a> ::Encoder<io::IoError> for Encoder<'a> {
|
||||||
/// Another encoder for JSON, but prints out human-readable JSON instead of
|
/// Another encoder for JSON, but prints out human-readable JSON instead of
|
||||||
/// compact data
|
/// compact data
|
||||||
pub struct PrettyEncoder<'a> {
|
pub struct PrettyEncoder<'a> {
|
||||||
writer: &'a mut io::Writer+'a,
|
writer: &'a mut (io::Writer+'a),
|
||||||
curr_indent: uint,
|
curr_indent: uint,
|
||||||
indent: uint,
|
indent: uint,
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,7 +84,7 @@ pub struct Handle<'rx, T:'rx> {
|
||||||
next: *mut Handle<'static, ()>,
|
next: *mut Handle<'static, ()>,
|
||||||
prev: *mut Handle<'static, ()>,
|
prev: *mut Handle<'static, ()>,
|
||||||
added: bool,
|
added: bool,
|
||||||
packet: &'rx Packet+'rx,
|
packet: &'rx (Packet+'rx),
|
||||||
|
|
||||||
// due to our fun transmutes, we be sure to place this at the end. (nothing
|
// due to our fun transmutes, we be sure to place this at the end. (nothing
|
||||||
// previous relies on T)
|
// previous relies on T)
|
||||||
|
|
|
@ -40,7 +40,7 @@ impl Writer for Stdio {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_fail(obj: &Any + Send, file: &'static str, line: uint) {
|
pub fn on_fail(obj: &(Any+Send), file: &'static str, line: uint) {
|
||||||
let msg = match obj.downcast_ref::<&'static str>() {
|
let msg = match obj.downcast_ref::<&'static str>() {
|
||||||
Some(s) => *s,
|
Some(s) => *s,
|
||||||
None => match obj.downcast_ref::<String>() {
|
None => match obj.downcast_ref::<String>() {
|
||||||
|
|
|
@ -910,7 +910,7 @@ impl<'a> Reader for Box<Reader+'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Reader for &'a mut Reader+'a {
|
impl<'a> Reader for &'a mut (Reader+'a) {
|
||||||
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> { (*self).read(buf) }
|
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> { (*self).read(buf) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1278,7 +1278,7 @@ impl<'a> Writer for Box<Writer+'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Writer for &'a mut Writer+'a {
|
impl<'a> Writer for &'a mut (Writer+'a) {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn write(&mut self, buf: &[u8]) -> IoResult<()> { (**self).write(buf) }
|
fn write(&mut self, buf: &[u8]) -> IoResult<()> { (**self).write(buf) }
|
||||||
|
|
||||||
|
|
|
@ -288,7 +288,7 @@ mod imp {
|
||||||
|
|
||||||
struct Context<'a> {
|
struct Context<'a> {
|
||||||
idx: int,
|
idx: int,
|
||||||
writer: &'a mut Writer+'a,
|
writer: &'a mut (Writer+'a),
|
||||||
last_error: Option<IoError>,
|
last_error: Option<IoError>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1151,7 +1151,9 @@ pub enum Ty_ {
|
||||||
/// A path (`module::module::...::Type`) or primitive
|
/// A path (`module::module::...::Type`) or primitive
|
||||||
///
|
///
|
||||||
/// Type parameters are stored in the Path itself
|
/// Type parameters are stored in the Path itself
|
||||||
TyPath(Path, Option<TyParamBounds>, NodeId), // for #7264; see above
|
TyPath(Path, NodeId),
|
||||||
|
/// Something like `A+B`. Note that `B` must always be a path.
|
||||||
|
TyObjectSum(P<Ty>, TyParamBounds),
|
||||||
/// A type like `for<'a> Foo<&'a Bar>`
|
/// A type like `for<'a> Foo<&'a Bar>`
|
||||||
TyPolyTraitRef(TyParamBounds),
|
TyPolyTraitRef(TyParamBounds),
|
||||||
/// A "qualified path", e.g. `<Vec<T> as SomeTrait>::SomeType`
|
/// A "qualified path", e.g. `<Vec<T> as SomeTrait>::SomeType`
|
||||||
|
|
|
@ -454,7 +454,7 @@ impl<'a, 'v, O: IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> {
|
||||||
fn visit_ty(&mut self, typ: &Ty) {
|
fn visit_ty(&mut self, typ: &Ty) {
|
||||||
self.operation.visit_id(typ.id);
|
self.operation.visit_id(typ.id);
|
||||||
match typ.node {
|
match typ.node {
|
||||||
TyPath(_, _, id) => self.operation.visit_id(id),
|
TyPath(_, id) => self.operation.visit_id(id),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
visit::walk_ty(self, typ)
|
visit::walk_ty(self, typ)
|
||||||
|
|
|
@ -44,7 +44,8 @@ pub trait AstBuilder {
|
||||||
fn ty_mt(&self, ty: P<ast::Ty>, mutbl: ast::Mutability) -> ast::MutTy;
|
fn ty_mt(&self, ty: P<ast::Ty>, mutbl: ast::Mutability) -> ast::MutTy;
|
||||||
|
|
||||||
fn ty(&self, span: Span, ty: ast::Ty_) -> P<ast::Ty>;
|
fn ty(&self, span: Span, ty: ast::Ty_) -> P<ast::Ty>;
|
||||||
fn ty_path(&self, ast::Path, Option<OwnedSlice<ast::TyParamBound>>) -> P<ast::Ty>;
|
fn ty_path(&self, ast::Path) -> P<ast::Ty>;
|
||||||
|
fn ty_sum(&self, ast::Path, OwnedSlice<ast::TyParamBound>) -> P<ast::Ty>;
|
||||||
fn ty_ident(&self, span: Span, idents: ast::Ident) -> P<ast::Ty>;
|
fn ty_ident(&self, span: Span, idents: ast::Ident) -> P<ast::Ty>;
|
||||||
|
|
||||||
fn ty_rptr(&self, span: Span,
|
fn ty_rptr(&self, span: Span,
|
||||||
|
@ -344,17 +345,21 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ty_path(&self, path: ast::Path, bounds: Option<OwnedSlice<ast::TyParamBound>>)
|
fn ty_path(&self, path: ast::Path) -> P<ast::Ty> {
|
||||||
-> P<ast::Ty> {
|
self.ty(path.span, ast::TyPath(path, ast::DUMMY_NODE_ID))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ty_sum(&self, path: ast::Path, bounds: OwnedSlice<ast::TyParamBound>) -> P<ast::Ty> {
|
||||||
self.ty(path.span,
|
self.ty(path.span,
|
||||||
ast::TyPath(path, bounds, ast::DUMMY_NODE_ID))
|
ast::TyObjectSum(self.ty_path(path),
|
||||||
|
bounds))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Might need to take bounds as an argument in the future, if you ever want
|
// Might need to take bounds as an argument in the future, if you ever want
|
||||||
// to generate a bounded existential trait type.
|
// to generate a bounded existential trait type.
|
||||||
fn ty_ident(&self, span: Span, ident: ast::Ident)
|
fn ty_ident(&self, span: Span, ident: ast::Ident)
|
||||||
-> P<ast::Ty> {
|
-> P<ast::Ty> {
|
||||||
self.ty_path(self.path_ident(span, ident), None)
|
self.ty_path(self.path_ident(span, ident))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ty_rptr(&self,
|
fn ty_rptr(&self,
|
||||||
|
@ -386,7 +391,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
||||||
self.ident_of("Option")
|
self.ident_of("Option")
|
||||||
),
|
),
|
||||||
Vec::new(),
|
Vec::new(),
|
||||||
vec!( ty )), None)
|
vec!( ty )))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ty_field_imm(&self, span: Span, name: Ident, ty: P<ast::Ty>) -> ast::TypeField {
|
fn ty_field_imm(&self, span: Span, name: Ident, ty: P<ast::Ty>) -> ast::TypeField {
|
||||||
|
@ -425,8 +430,10 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ty_vars_global(&self, ty_params: &OwnedSlice<ast::TyParam>) -> Vec<P<ast::Ty>> {
|
fn ty_vars_global(&self, ty_params: &OwnedSlice<ast::TyParam>) -> Vec<P<ast::Ty>> {
|
||||||
ty_params.iter().map(|p| self.ty_path(
|
ty_params
|
||||||
self.path_global(DUMMY_SP, vec!(p.ident)), None)).collect()
|
.iter()
|
||||||
|
.map(|p| self.ty_path(self.path_global(DUMMY_SP, vec!(p.ident))))
|
||||||
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trait_ref(&self, path: ast::Path) -> ast::TraitRef {
|
fn trait_ref(&self, path: ast::Path) -> ast::TraitRef {
|
||||||
|
|
|
@ -444,7 +444,7 @@ impl<'a> TraitDef<'a> {
|
||||||
// Create the type of `self`.
|
// Create the type of `self`.
|
||||||
let self_type = cx.ty_path(
|
let self_type = cx.ty_path(
|
||||||
cx.path_all(self.span, false, vec!( type_ident ), self_lifetimes,
|
cx.path_all(self.span, false, vec!( type_ident ), self_lifetimes,
|
||||||
self_ty_params.into_vec()), None);
|
self_ty_params.into_vec()));
|
||||||
|
|
||||||
let attr = cx.attribute(
|
let attr = cx.attribute(
|
||||||
self.span,
|
self.span,
|
||||||
|
|
|
@ -70,7 +70,7 @@ impl<'a> Path<'a> {
|
||||||
self_ty: Ident,
|
self_ty: Ident,
|
||||||
self_generics: &Generics)
|
self_generics: &Generics)
|
||||||
-> P<ast::Ty> {
|
-> P<ast::Ty> {
|
||||||
cx.ty_path(self.to_path(cx, span, self_ty, self_generics), None)
|
cx.ty_path(self.to_path(cx, span, self_ty, self_generics))
|
||||||
}
|
}
|
||||||
pub fn to_path(&self,
|
pub fn to_path(&self,
|
||||||
cx: &ExtCtxt,
|
cx: &ExtCtxt,
|
||||||
|
@ -152,7 +152,7 @@ impl<'a> Ty<'a> {
|
||||||
}
|
}
|
||||||
Literal(ref p) => { p.to_ty(cx, span, self_ty, self_generics) }
|
Literal(ref p) => { p.to_ty(cx, span, self_ty, self_generics) }
|
||||||
Self => {
|
Self => {
|
||||||
cx.ty_path(self.to_path(cx, span, self_ty, self_generics), None)
|
cx.ty_path(self.to_path(cx, span, self_ty, self_generics))
|
||||||
}
|
}
|
||||||
Tuple(ref fields) => {
|
Tuple(ref fields) => {
|
||||||
let ty = ast::TyTup(fields.iter()
|
let ty = ast::TyTup(fields.iter()
|
||||||
|
|
|
@ -531,7 +531,7 @@ impl<'a, 'b> Context<'a, 'b> {
|
||||||
true, Context::rtpath(self.ecx, "Argument"),
|
true, Context::rtpath(self.ecx, "Argument"),
|
||||||
vec![static_lifetime],
|
vec![static_lifetime],
|
||||||
vec![]
|
vec![]
|
||||||
), None);
|
));
|
||||||
lets.push(Context::item_static_array(self.ecx,
|
lets.push(Context::item_static_array(self.ecx,
|
||||||
static_args_name,
|
static_args_name,
|
||||||
piece_ty,
|
piece_ty,
|
||||||
|
|
|
@ -514,7 +514,7 @@ pub fn parse_nt(p: &mut Parser, name: &str) -> Nonterminal {
|
||||||
"stmt" => token::NtStmt(p.parse_stmt(Vec::new())),
|
"stmt" => token::NtStmt(p.parse_stmt(Vec::new())),
|
||||||
"pat" => token::NtPat(p.parse_pat()),
|
"pat" => token::NtPat(p.parse_pat()),
|
||||||
"expr" => token::NtExpr(p.parse_expr()),
|
"expr" => token::NtExpr(p.parse_expr()),
|
||||||
"ty" => token::NtTy(p.parse_ty(false /* no need to disambiguate*/)),
|
"ty" => token::NtTy(p.parse_ty()),
|
||||||
// this could be handled like a token, since it is one
|
// this could be handled like a token, since it is one
|
||||||
"ident" => match p.token {
|
"ident" => match p.token {
|
||||||
token::Ident(sn,b) => { p.bump(); token::NtIdent(box sn,b) }
|
token::Ident(sn,b) => { p.bump(); token::NtIdent(box sn,b) }
|
||||||
|
@ -525,7 +525,7 @@ pub fn parse_nt(p: &mut Parser, name: &str) -> Nonterminal {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"path" => {
|
"path" => {
|
||||||
token::NtPath(box p.parse_path(LifetimeAndTypesWithoutColons).path)
|
token::NtPath(box p.parse_path(LifetimeAndTypesWithoutColons))
|
||||||
}
|
}
|
||||||
"meta" => token::NtMeta(p.parse_meta_item()),
|
"meta" => token::NtMeta(p.parse_meta_item()),
|
||||||
"tt" => {
|
"tt" => {
|
||||||
|
|
|
@ -433,11 +433,13 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
|
||||||
}
|
}
|
||||||
TyTup(tys) => TyTup(tys.move_map(|ty| fld.fold_ty(ty))),
|
TyTup(tys) => TyTup(tys.move_map(|ty| fld.fold_ty(ty))),
|
||||||
TyParen(ty) => TyParen(fld.fold_ty(ty)),
|
TyParen(ty) => TyParen(fld.fold_ty(ty)),
|
||||||
TyPath(path, bounds, id) => {
|
TyPath(path, id) => {
|
||||||
let id = fld.new_id(id);
|
let id = fld.new_id(id);
|
||||||
TyPath(fld.fold_path(path),
|
TyPath(fld.fold_path(path), id)
|
||||||
fld.fold_opt_bounds(bounds),
|
}
|
||||||
id)
|
TyObjectSum(ty, bounds) => {
|
||||||
|
TyObjectSum(fld.fold_ty(ty),
|
||||||
|
fld.fold_bounds(bounds))
|
||||||
}
|
}
|
||||||
TyQPath(qpath) => {
|
TyQPath(qpath) => {
|
||||||
TyQPath(fld.fold_qpath(qpath))
|
TyQPath(fld.fold_qpath(qpath))
|
||||||
|
|
|
@ -1029,7 +1029,7 @@ mod test {
|
||||||
parameters: ast::PathParameters::none(),
|
parameters: ast::PathParameters::none(),
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
}, None, ast::DUMMY_NODE_ID),
|
}, ast::DUMMY_NODE_ID),
|
||||||
span:sp(10,13)
|
span:sp(10,13)
|
||||||
}),
|
}),
|
||||||
pat: P(ast::Pat {
|
pat: P(ast::Pat {
|
||||||
|
|
|
@ -111,16 +111,6 @@ pub enum PathParsingMode {
|
||||||
/// A path with a lifetime and type parameters with double colons before
|
/// A path with a lifetime and type parameters with double colons before
|
||||||
/// the type parameters; e.g. `foo::bar::<'a>::Baz::<T>`
|
/// the type parameters; e.g. `foo::bar::<'a>::Baz::<T>`
|
||||||
LifetimeAndTypesWithColons,
|
LifetimeAndTypesWithColons,
|
||||||
/// A path with a lifetime and type parameters with bounds before the last
|
|
||||||
/// set of type parameters only; e.g. `foo::bar<'a>::Baz+X+Y<T>` This
|
|
||||||
/// form does not use extra double colons.
|
|
||||||
LifetimeAndTypesAndBounds,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A path paired with optional type bounds.
|
|
||||||
pub struct PathAndBounds {
|
|
||||||
pub path: ast::Path,
|
|
||||||
pub bounds: Option<ast::TyParamBounds>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ItemOrViewItem {
|
enum ItemOrViewItem {
|
||||||
|
@ -1053,17 +1043,9 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_ty_path(&mut self, plus_allowed: bool) -> Ty_ {
|
pub fn parse_ty_path(&mut self) -> Ty_ {
|
||||||
let mode = if plus_allowed {
|
let path = self.parse_path(LifetimeAndTypesWithoutColons);
|
||||||
LifetimeAndTypesAndBounds
|
TyPath(path, ast::DUMMY_NODE_ID)
|
||||||
} else {
|
|
||||||
LifetimeAndTypesWithoutColons
|
|
||||||
};
|
|
||||||
let PathAndBounds {
|
|
||||||
path,
|
|
||||||
bounds
|
|
||||||
} = self.parse_path(mode);
|
|
||||||
TyPath(path, bounds, ast::DUMMY_NODE_ID)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// parse a TyBareFn type:
|
/// parse a TyBareFn type:
|
||||||
|
@ -1286,7 +1268,7 @@ impl<'a> Parser<'a> {
|
||||||
let lo = self.span.lo;
|
let lo = self.span.lo;
|
||||||
let ident = self.parse_ident();
|
let ident = self.parse_ident();
|
||||||
self.expect(&token::Eq);
|
self.expect(&token::Eq);
|
||||||
let typ = self.parse_ty(true);
|
let typ = self.parse_ty_sum();
|
||||||
let hi = self.span.hi;
|
let hi = self.span.hi;
|
||||||
self.expect(&token::Semi);
|
self.expect(&token::Semi);
|
||||||
Typedef {
|
Typedef {
|
||||||
|
@ -1385,7 +1367,7 @@ impl<'a> Parser<'a> {
|
||||||
/// Parse a possibly mutable type
|
/// Parse a possibly mutable type
|
||||||
pub fn parse_mt(&mut self) -> MutTy {
|
pub fn parse_mt(&mut self) -> MutTy {
|
||||||
let mutbl = self.parse_mutability();
|
let mutbl = self.parse_mutability();
|
||||||
let t = self.parse_ty(true);
|
let t = self.parse_ty();
|
||||||
MutTy { ty: t, mutbl: mutbl }
|
MutTy { ty: t, mutbl: mutbl }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1396,7 +1378,7 @@ impl<'a> Parser<'a> {
|
||||||
let mutbl = self.parse_mutability();
|
let mutbl = self.parse_mutability();
|
||||||
let id = self.parse_ident();
|
let id = self.parse_ident();
|
||||||
self.expect(&token::Colon);
|
self.expect(&token::Colon);
|
||||||
let ty = self.parse_ty(true);
|
let ty = self.parse_ty_sum();
|
||||||
let hi = ty.span.hi;
|
let hi = ty.span.hi;
|
||||||
ast::TypeField {
|
ast::TypeField {
|
||||||
ident: id,
|
ident: id,
|
||||||
|
@ -1411,7 +1393,19 @@ impl<'a> Parser<'a> {
|
||||||
if self.eat(&token::Not) {
|
if self.eat(&token::Not) {
|
||||||
NoReturn(self.span)
|
NoReturn(self.span)
|
||||||
} else {
|
} else {
|
||||||
Return(self.parse_ty(true))
|
let t = self.parse_ty();
|
||||||
|
|
||||||
|
// We used to allow `fn foo() -> &T + U`, but don't
|
||||||
|
// anymore. If we see it, report a useful error. This
|
||||||
|
// only makes sense because `parse_ret_ty` is only
|
||||||
|
// used in fn *declarations*, not fn types or where
|
||||||
|
// clauses (i.e., not when parsing something like
|
||||||
|
// `FnMut() -> T + Send`, where the `+` is legal).
|
||||||
|
if self.token == token::BinOp(token::Plus) {
|
||||||
|
self.warn("deprecated syntax: `()` are required, see RFC 248 for details");
|
||||||
|
}
|
||||||
|
|
||||||
|
Return(t)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let pos = self.span.lo;
|
let pos = self.span.lo;
|
||||||
|
@ -1423,11 +1417,36 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parse a type in a context where `T1+T2` is allowed.
|
||||||
|
pub fn parse_ty_sum(&mut self) -> P<Ty> {
|
||||||
|
let lo = self.span.lo;
|
||||||
|
let lhs = self.parse_ty();
|
||||||
|
|
||||||
|
if !self.eat(&token::BinOp(token::Plus)) {
|
||||||
|
return lhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
let bounds = self.parse_ty_param_bounds();
|
||||||
|
|
||||||
|
// In type grammar, `+` is treated like a binary operator,
|
||||||
|
// and hence both L and R side are required.
|
||||||
|
if bounds.len() == 0 {
|
||||||
|
let last_span = self.last_span;
|
||||||
|
self.span_err(last_span,
|
||||||
|
"at least one type parameter bound \
|
||||||
|
must be specified");
|
||||||
|
}
|
||||||
|
|
||||||
|
let sp = mk_sp(lo, self.last_span.hi);
|
||||||
|
let sum = ast::TyObjectSum(lhs, bounds);
|
||||||
|
P(Ty {id: ast::DUMMY_NODE_ID, node: sum, span: sp})
|
||||||
|
}
|
||||||
|
|
||||||
/// Parse a type.
|
/// Parse a type.
|
||||||
///
|
///
|
||||||
/// The second parameter specifies whether the `+` binary operator is
|
/// The second parameter specifies whether the `+` binary operator is
|
||||||
/// allowed in the type grammar.
|
/// allowed in the type grammar.
|
||||||
pub fn parse_ty(&mut self, plus_allowed: bool) -> P<Ty> {
|
pub fn parse_ty(&mut self) -> P<Ty> {
|
||||||
maybe_whole!(no_clone self, NtTy);
|
maybe_whole!(no_clone self, NtTy);
|
||||||
|
|
||||||
let lo = self.span.lo;
|
let lo = self.span.lo;
|
||||||
|
@ -1441,7 +1460,7 @@ impl<'a> Parser<'a> {
|
||||||
let mut ts = vec![];
|
let mut ts = vec![];
|
||||||
let mut last_comma = false;
|
let mut last_comma = false;
|
||||||
while self.token != token::CloseDelim(token::Paren) {
|
while self.token != token::CloseDelim(token::Paren) {
|
||||||
ts.push(self.parse_ty(true));
|
ts.push(self.parse_ty_sum());
|
||||||
if self.token == token::Comma {
|
if self.token == token::Comma {
|
||||||
last_comma = true;
|
last_comma = true;
|
||||||
self.bump();
|
self.bump();
|
||||||
|
@ -1465,7 +1484,7 @@ impl<'a> Parser<'a> {
|
||||||
token::OpenDelim(token::Bracket) => self.obsolete(last_span, ObsoleteOwnedVector),
|
token::OpenDelim(token::Bracket) => self.obsolete(last_span, ObsoleteOwnedVector),
|
||||||
_ => self.obsolete(last_span, ObsoleteOwnedType)
|
_ => self.obsolete(last_span, ObsoleteOwnedType)
|
||||||
}
|
}
|
||||||
TyTup(vec![self.parse_ty(false)])
|
TyTup(vec![self.parse_ty()])
|
||||||
} else if self.token == token::BinOp(token::Star) {
|
} else if self.token == token::BinOp(token::Star) {
|
||||||
// STAR POINTER (bare pointer?)
|
// STAR POINTER (bare pointer?)
|
||||||
self.bump();
|
self.bump();
|
||||||
|
@ -1473,7 +1492,7 @@ impl<'a> Parser<'a> {
|
||||||
} else if self.token == token::OpenDelim(token::Bracket) {
|
} else if self.token == token::OpenDelim(token::Bracket) {
|
||||||
// VECTOR
|
// VECTOR
|
||||||
self.expect(&token::OpenDelim(token::Bracket));
|
self.expect(&token::OpenDelim(token::Bracket));
|
||||||
let t = self.parse_ty(true);
|
let t = self.parse_ty_sum();
|
||||||
|
|
||||||
// Parse the `, ..e` in `[ int, ..e ]`
|
// Parse the `, ..e` in `[ int, ..e ]`
|
||||||
// where `e` is a const expression
|
// where `e` is a const expression
|
||||||
|
@ -1514,7 +1533,7 @@ impl<'a> Parser<'a> {
|
||||||
} else if self.token == token::Lt {
|
} else if self.token == token::Lt {
|
||||||
// QUALIFIED PATH `<TYPE as TRAIT_REF>::item`
|
// QUALIFIED PATH `<TYPE as TRAIT_REF>::item`
|
||||||
self.bump();
|
self.bump();
|
||||||
let self_type = self.parse_ty(true);
|
let self_type = self.parse_ty_sum();
|
||||||
self.expect_keyword(keywords::As);
|
self.expect_keyword(keywords::As);
|
||||||
let trait_ref = self.parse_trait_ref();
|
let trait_ref = self.parse_trait_ref();
|
||||||
self.expect(&token::Gt);
|
self.expect(&token::Gt);
|
||||||
|
@ -1529,7 +1548,7 @@ impl<'a> Parser<'a> {
|
||||||
self.token.is_ident() ||
|
self.token.is_ident() ||
|
||||||
self.token.is_path() {
|
self.token.is_path() {
|
||||||
// NAMED TYPE
|
// NAMED TYPE
|
||||||
self.parse_ty_path(plus_allowed)
|
self.parse_ty_path()
|
||||||
} else if self.eat(&token::Underscore) {
|
} else if self.eat(&token::Underscore) {
|
||||||
// TYPE TO BE INFERRED
|
// TYPE TO BE INFERRED
|
||||||
TyInfer
|
TyInfer
|
||||||
|
@ -1563,7 +1582,7 @@ impl<'a> Parser<'a> {
|
||||||
known as `*const T`");
|
known as `*const T`");
|
||||||
MutImmutable
|
MutImmutable
|
||||||
};
|
};
|
||||||
let t = self.parse_ty(true);
|
let t = self.parse_ty();
|
||||||
MutTy { ty: t, mutbl: mutbl }
|
MutTy { ty: t, mutbl: mutbl }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1603,7 +1622,7 @@ impl<'a> Parser<'a> {
|
||||||
special_idents::invalid)
|
special_idents::invalid)
|
||||||
};
|
};
|
||||||
|
|
||||||
let t = self.parse_ty(true);
|
let t = self.parse_ty_sum();
|
||||||
|
|
||||||
Arg {
|
Arg {
|
||||||
ty: t,
|
ty: t,
|
||||||
|
@ -1621,7 +1640,7 @@ impl<'a> Parser<'a> {
|
||||||
pub fn parse_fn_block_arg(&mut self) -> Arg {
|
pub fn parse_fn_block_arg(&mut self) -> Arg {
|
||||||
let pat = self.parse_pat();
|
let pat = self.parse_pat();
|
||||||
let t = if self.eat(&token::Colon) {
|
let t = if self.eat(&token::Colon) {
|
||||||
self.parse_ty(true)
|
self.parse_ty_sum()
|
||||||
} else {
|
} else {
|
||||||
P(Ty {
|
P(Ty {
|
||||||
id: ast::DUMMY_NODE_ID,
|
id: ast::DUMMY_NODE_ID,
|
||||||
|
@ -1739,7 +1758,7 @@ impl<'a> Parser<'a> {
|
||||||
/// mode. The `mode` parameter determines whether lifetimes, types, and/or
|
/// mode. The `mode` parameter determines whether lifetimes, types, and/or
|
||||||
/// bounds are permitted and whether `::` must precede type parameter
|
/// bounds are permitted and whether `::` must precede type parameter
|
||||||
/// groups.
|
/// groups.
|
||||||
pub fn parse_path(&mut self, mode: PathParsingMode) -> PathAndBounds {
|
pub fn parse_path(&mut self, mode: PathParsingMode) -> ast::Path {
|
||||||
// Check for a whole path...
|
// Check for a whole path...
|
||||||
let found = match self.token {
|
let found = match self.token {
|
||||||
token::Interpolated(token::NtPath(_)) => Some(self.bump_and_get()),
|
token::Interpolated(token::NtPath(_)) => Some(self.bump_and_get()),
|
||||||
|
@ -1747,10 +1766,7 @@ impl<'a> Parser<'a> {
|
||||||
};
|
};
|
||||||
match found {
|
match found {
|
||||||
Some(token::Interpolated(token::NtPath(box path))) => {
|
Some(token::Interpolated(token::NtPath(box path))) => {
|
||||||
return PathAndBounds {
|
return path;
|
||||||
path: path,
|
|
||||||
bounds: None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
@ -1762,8 +1778,7 @@ impl<'a> Parser<'a> {
|
||||||
// identifier followed by an optional lifetime and a set of types.
|
// identifier followed by an optional lifetime and a set of types.
|
||||||
// A bound set is a set of type parameter bounds.
|
// A bound set is a set of type parameter bounds.
|
||||||
let segments = match mode {
|
let segments = match mode {
|
||||||
LifetimeAndTypesWithoutColons |
|
LifetimeAndTypesWithoutColons => {
|
||||||
LifetimeAndTypesAndBounds => {
|
|
||||||
self.parse_path_segments_without_colons()
|
self.parse_path_segments_without_colons()
|
||||||
}
|
}
|
||||||
LifetimeAndTypesWithColons => {
|
LifetimeAndTypesWithColons => {
|
||||||
|
@ -1774,44 +1789,14 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Next, parse a plus and bounded type parameters, if
|
|
||||||
// applicable. We need to remember whether the separate was
|
|
||||||
// present for later, because in some contexts it's a parse
|
|
||||||
// error.
|
|
||||||
let opt_bounds = {
|
|
||||||
if mode == LifetimeAndTypesAndBounds &&
|
|
||||||
self.eat(&token::BinOp(token::Plus))
|
|
||||||
{
|
|
||||||
let bounds = self.parse_ty_param_bounds();
|
|
||||||
|
|
||||||
// For some reason that I do not fully understand, we
|
|
||||||
// do not permit an empty list in the case where it is
|
|
||||||
// introduced by a `+`, but we do for `:` and other
|
|
||||||
// separators. -nmatsakis
|
|
||||||
if bounds.len() == 0 {
|
|
||||||
let last_span = self.last_span;
|
|
||||||
self.span_err(last_span,
|
|
||||||
"at least one type parameter bound \
|
|
||||||
must be specified");
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(bounds)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Assemble the span.
|
// Assemble the span.
|
||||||
let span = mk_sp(lo, self.last_span.hi);
|
let span = mk_sp(lo, self.last_span.hi);
|
||||||
|
|
||||||
// Assemble the result.
|
// Assemble the result.
|
||||||
PathAndBounds {
|
ast::Path {
|
||||||
path: ast::Path {
|
|
||||||
span: span,
|
span: span,
|
||||||
global: is_global,
|
global: is_global,
|
||||||
segments: segments,
|
segments: segments,
|
||||||
},
|
|
||||||
bounds: opt_bounds,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1837,10 +1822,10 @@ impl<'a> Parser<'a> {
|
||||||
let inputs = self.parse_seq_to_end(
|
let inputs = self.parse_seq_to_end(
|
||||||
&token::CloseDelim(token::Paren),
|
&token::CloseDelim(token::Paren),
|
||||||
seq_sep_trailing_allowed(token::Comma),
|
seq_sep_trailing_allowed(token::Comma),
|
||||||
|p| p.parse_ty(true));
|
|p| p.parse_ty_sum());
|
||||||
|
|
||||||
let output_ty = if self.eat(&token::RArrow) {
|
let output_ty = if self.eat(&token::RArrow) {
|
||||||
Some(self.parse_ty(true))
|
Some(self.parse_ty())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
@ -2327,7 +2312,7 @@ impl<'a> Parser<'a> {
|
||||||
!self.token.is_keyword(keywords::True) &&
|
!self.token.is_keyword(keywords::True) &&
|
||||||
!self.token.is_keyword(keywords::False) {
|
!self.token.is_keyword(keywords::False) {
|
||||||
let pth =
|
let pth =
|
||||||
self.parse_path(LifetimeAndTypesWithColons).path;
|
self.parse_path(LifetimeAndTypesWithColons);
|
||||||
|
|
||||||
// `!`, as an operator, is prefix, so we know this isn't that
|
// `!`, as an operator, is prefix, so we know this isn't that
|
||||||
if self.token == token::Not {
|
if self.token == token::Not {
|
||||||
|
@ -2898,7 +2883,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
if as_prec > min_prec && self.eat_keyword(keywords::As) {
|
if as_prec > min_prec && self.eat_keyword(keywords::As) {
|
||||||
let rhs = self.parse_ty(false);
|
let rhs = self.parse_ty();
|
||||||
let _as = self.mk_expr(lhs.span.lo,
|
let _as = self.mk_expr(lhs.span.lo,
|
||||||
rhs.span.hi,
|
rhs.span.hi,
|
||||||
ExprCast(lhs, rhs));
|
ExprCast(lhs, rhs));
|
||||||
|
@ -3362,8 +3347,7 @@ impl<'a> Parser<'a> {
|
||||||
}) {
|
}) {
|
||||||
self.bump();
|
self.bump();
|
||||||
let end = if self.token.is_ident() || self.token.is_path() {
|
let end = if self.token.is_ident() || self.token.is_path() {
|
||||||
let path = self.parse_path(LifetimeAndTypesWithColons)
|
let path = self.parse_path(LifetimeAndTypesWithColons);
|
||||||
.path;
|
|
||||||
let hi = self.span.hi;
|
let hi = self.span.hi;
|
||||||
self.mk_expr(lo, hi, ExprPath(path))
|
self.mk_expr(lo, hi, ExprPath(path))
|
||||||
} else {
|
} else {
|
||||||
|
@ -3433,8 +3417,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// parse an enum pat
|
// parse an enum pat
|
||||||
let enum_path = self.parse_path(LifetimeAndTypesWithColons)
|
let enum_path = self.parse_path(LifetimeAndTypesWithColons);
|
||||||
.path;
|
|
||||||
match self.token {
|
match self.token {
|
||||||
token::OpenDelim(token::Brace) => {
|
token::OpenDelim(token::Brace) => {
|
||||||
self.bump();
|
self.bump();
|
||||||
|
@ -3548,7 +3531,7 @@ impl<'a> Parser<'a> {
|
||||||
span: mk_sp(lo, lo),
|
span: mk_sp(lo, lo),
|
||||||
});
|
});
|
||||||
if self.eat(&token::Colon) {
|
if self.eat(&token::Colon) {
|
||||||
ty = self.parse_ty(true);
|
ty = self.parse_ty_sum();
|
||||||
}
|
}
|
||||||
let init = self.parse_initializer();
|
let init = self.parse_initializer();
|
||||||
P(ast::Local {
|
P(ast::Local {
|
||||||
|
@ -3577,7 +3560,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
let name = self.parse_ident();
|
let name = self.parse_ident();
|
||||||
self.expect(&token::Colon);
|
self.expect(&token::Colon);
|
||||||
let ty = self.parse_ty(true);
|
let ty = self.parse_ty_sum();
|
||||||
spanned(lo, self.last_span.hi, ast::StructField_ {
|
spanned(lo, self.last_span.hi, ast::StructField_ {
|
||||||
kind: NamedField(name, pr),
|
kind: NamedField(name, pr),
|
||||||
id: ast::DUMMY_NODE_ID,
|
id: ast::DUMMY_NODE_ID,
|
||||||
|
@ -3624,7 +3607,7 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
// Potential trouble: if we allow macros with paths instead of
|
// Potential trouble: if we allow macros with paths instead of
|
||||||
// idents, we'd need to look ahead past the whole path here...
|
// idents, we'd need to look ahead past the whole path here...
|
||||||
let pth = self.parse_path(NoTypesAllowed).path;
|
let pth = self.parse_path(NoTypesAllowed);
|
||||||
self.bump();
|
self.bump();
|
||||||
|
|
||||||
let id = match self.token {
|
let id = match self.token {
|
||||||
|
@ -3976,7 +3959,7 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
let default = if self.token == token::Eq {
|
let default = if self.token == token::Eq {
|
||||||
self.bump();
|
self.bump();
|
||||||
Some(self.parse_ty(true))
|
Some(self.parse_ty_sum())
|
||||||
}
|
}
|
||||||
else { None };
|
else { None };
|
||||||
|
|
||||||
|
@ -4032,7 +4015,7 @@ impl<'a> Parser<'a> {
|
||||||
Some(token::Comma),
|
Some(token::Comma),
|
||||||
|p| {
|
|p| {
|
||||||
p.forbid_lifetime();
|
p.forbid_lifetime();
|
||||||
p.parse_ty(true)
|
p.parse_ty_sum()
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
(lifetimes, result.into_vec())
|
(lifetimes, result.into_vec())
|
||||||
|
@ -4265,7 +4248,7 @@ impl<'a> Parser<'a> {
|
||||||
// Determine whether this is the fully explicit form, `self:
|
// Determine whether this is the fully explicit form, `self:
|
||||||
// TYPE`.
|
// TYPE`.
|
||||||
if self.eat(&token::Colon) {
|
if self.eat(&token::Colon) {
|
||||||
SelfExplicit(self.parse_ty(false), self_ident)
|
SelfExplicit(self.parse_ty_sum(), self_ident)
|
||||||
} else {
|
} else {
|
||||||
SelfValue(self_ident)
|
SelfValue(self_ident)
|
||||||
}
|
}
|
||||||
|
@ -4277,7 +4260,7 @@ impl<'a> Parser<'a> {
|
||||||
// Determine whether this is the fully explicit form,
|
// Determine whether this is the fully explicit form,
|
||||||
// `self: TYPE`.
|
// `self: TYPE`.
|
||||||
if self.eat(&token::Colon) {
|
if self.eat(&token::Colon) {
|
||||||
SelfExplicit(self.parse_ty(false), self_ident)
|
SelfExplicit(self.parse_ty_sum(), self_ident)
|
||||||
} else {
|
} else {
|
||||||
SelfValue(self_ident)
|
SelfValue(self_ident)
|
||||||
}
|
}
|
||||||
|
@ -4466,7 +4449,7 @@ impl<'a> Parser<'a> {
|
||||||
&& (self.look_ahead(2, |t| *t == token::OpenDelim(token::Paren))
|
&& (self.look_ahead(2, |t| *t == token::OpenDelim(token::Paren))
|
||||||
|| self.look_ahead(2, |t| *t == token::OpenDelim(token::Brace))) {
|
|| self.look_ahead(2, |t| *t == token::OpenDelim(token::Brace))) {
|
||||||
// method macro.
|
// method macro.
|
||||||
let pth = self.parse_path(NoTypesAllowed).path;
|
let pth = self.parse_path(NoTypesAllowed);
|
||||||
self.expect(&token::Not);
|
self.expect(&token::Not);
|
||||||
|
|
||||||
// eat a matched-delimiter token tree:
|
// eat a matched-delimiter token tree:
|
||||||
|
@ -4564,30 +4547,25 @@ impl<'a> Parser<'a> {
|
||||||
let could_be_trait = self.token != token::OpenDelim(token::Paren);
|
let could_be_trait = self.token != token::OpenDelim(token::Paren);
|
||||||
|
|
||||||
// Parse the trait.
|
// Parse the trait.
|
||||||
let mut ty = self.parse_ty(true);
|
let mut ty = self.parse_ty_sum();
|
||||||
|
|
||||||
// Parse traits, if necessary.
|
// Parse traits, if necessary.
|
||||||
let opt_trait = if could_be_trait && self.eat_keyword(keywords::For) {
|
let opt_trait = if could_be_trait && self.eat_keyword(keywords::For) {
|
||||||
// New-style trait. Reinterpret the type as a trait.
|
// New-style trait. Reinterpret the type as a trait.
|
||||||
let opt_trait_ref = match ty.node {
|
let opt_trait_ref = match ty.node {
|
||||||
TyPath(ref path, None, node_id) => {
|
TyPath(ref path, node_id) => {
|
||||||
Some(TraitRef {
|
Some(TraitRef {
|
||||||
path: (*path).clone(),
|
path: (*path).clone(),
|
||||||
ref_id: node_id,
|
ref_id: node_id,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
TyPath(_, Some(_), _) => {
|
|
||||||
self.span_err(ty.span,
|
|
||||||
"bounded traits are only valid in type position");
|
|
||||||
None
|
|
||||||
}
|
|
||||||
_ => {
|
_ => {
|
||||||
self.span_err(ty.span, "not a trait");
|
self.span_err(ty.span, "not a trait");
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ty = self.parse_ty(true);
|
ty = self.parse_ty_sum();
|
||||||
opt_trait_ref
|
opt_trait_ref
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -4606,7 +4584,7 @@ impl<'a> Parser<'a> {
|
||||||
/// Parse a::B<String,int>
|
/// Parse a::B<String,int>
|
||||||
fn parse_trait_ref(&mut self) -> TraitRef {
|
fn parse_trait_ref(&mut self) -> TraitRef {
|
||||||
ast::TraitRef {
|
ast::TraitRef {
|
||||||
path: self.parse_path(LifetimeAndTypesWithoutColons).path,
|
path: self.parse_path(LifetimeAndTypesWithoutColons),
|
||||||
ref_id: ast::DUMMY_NODE_ID,
|
ref_id: ast::DUMMY_NODE_ID,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4638,7 +4616,7 @@ impl<'a> Parser<'a> {
|
||||||
let mut generics = self.parse_generics();
|
let mut generics = self.parse_generics();
|
||||||
|
|
||||||
if self.eat(&token::Colon) {
|
if self.eat(&token::Colon) {
|
||||||
let ty = self.parse_ty(true);
|
let ty = self.parse_ty_sum();
|
||||||
self.span_err(ty.span, "`virtual` structs have been removed from the language");
|
self.span_err(ty.span, "`virtual` structs have been removed from the language");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4673,7 +4651,7 @@ impl<'a> Parser<'a> {
|
||||||
let struct_field_ = ast::StructField_ {
|
let struct_field_ = ast::StructField_ {
|
||||||
kind: UnnamedField(p.parse_visibility()),
|
kind: UnnamedField(p.parse_visibility()),
|
||||||
id: ast::DUMMY_NODE_ID,
|
id: ast::DUMMY_NODE_ID,
|
||||||
ty: p.parse_ty(true),
|
ty: p.parse_ty_sum(),
|
||||||
attrs: attrs,
|
attrs: attrs,
|
||||||
};
|
};
|
||||||
spanned(lo, p.span.hi, struct_field_)
|
spanned(lo, p.span.hi, struct_field_)
|
||||||
|
@ -4830,7 +4808,7 @@ impl<'a> Parser<'a> {
|
||||||
fn parse_item_const(&mut self, m: Option<Mutability>) -> ItemInfo {
|
fn parse_item_const(&mut self, m: Option<Mutability>) -> ItemInfo {
|
||||||
let id = self.parse_ident();
|
let id = self.parse_ident();
|
||||||
self.expect(&token::Colon);
|
self.expect(&token::Colon);
|
||||||
let ty = self.parse_ty(true);
|
let ty = self.parse_ty_sum();
|
||||||
self.expect(&token::Eq);
|
self.expect(&token::Eq);
|
||||||
let e = self.parse_expr();
|
let e = self.parse_expr();
|
||||||
self.commit_expr_expecting(&*e, token::Semi);
|
self.commit_expr_expecting(&*e, token::Semi);
|
||||||
|
@ -5023,7 +5001,7 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
let ident = self.parse_ident();
|
let ident = self.parse_ident();
|
||||||
self.expect(&token::Colon);
|
self.expect(&token::Colon);
|
||||||
let ty = self.parse_ty(true);
|
let ty = self.parse_ty_sum();
|
||||||
let hi = self.span.hi;
|
let hi = self.span.hi;
|
||||||
self.expect(&token::Semi);
|
self.expect(&token::Semi);
|
||||||
P(ForeignItem {
|
P(ForeignItem {
|
||||||
|
@ -5181,7 +5159,7 @@ impl<'a> Parser<'a> {
|
||||||
let mut tps = self.parse_generics();
|
let mut tps = self.parse_generics();
|
||||||
self.parse_where_clause(&mut tps);
|
self.parse_where_clause(&mut tps);
|
||||||
self.expect(&token::Eq);
|
self.expect(&token::Eq);
|
||||||
let ty = self.parse_ty(true);
|
let ty = self.parse_ty_sum();
|
||||||
self.expect(&token::Semi);
|
self.expect(&token::Semi);
|
||||||
(ident, ItemTy(ty, tps), None)
|
(ident, ItemTy(ty, tps), None)
|
||||||
}
|
}
|
||||||
|
@ -5235,7 +5213,7 @@ impl<'a> Parser<'a> {
|
||||||
&token::OpenDelim(token::Paren),
|
&token::OpenDelim(token::Paren),
|
||||||
&token::CloseDelim(token::Paren),
|
&token::CloseDelim(token::Paren),
|
||||||
seq_sep_trailing_allowed(token::Comma),
|
seq_sep_trailing_allowed(token::Comma),
|
||||||
|p| p.parse_ty(true)
|
|p| p.parse_ty_sum()
|
||||||
);
|
);
|
||||||
for ty in arg_tys.into_iter() {
|
for ty in arg_tys.into_iter() {
|
||||||
args.push(ast::VariantArg {
|
args.push(ast::VariantArg {
|
||||||
|
@ -5593,7 +5571,7 @@ impl<'a> Parser<'a> {
|
||||||
// MACRO INVOCATION ITEM
|
// MACRO INVOCATION ITEM
|
||||||
|
|
||||||
// item macro.
|
// item macro.
|
||||||
let pth = self.parse_path(NoTypesAllowed).path;
|
let pth = self.parse_path(NoTypesAllowed);
|
||||||
self.expect(&token::Not);
|
self.expect(&token::Not);
|
||||||
|
|
||||||
// a 'special' identifier (like what `macro_rules!` uses)
|
// a 'special' identifier (like what `macro_rules!` uses)
|
||||||
|
|
|
@ -61,7 +61,7 @@ pub struct State<'a> {
|
||||||
literals: Option<Vec<comments::Literal> >,
|
literals: Option<Vec<comments::Literal> >,
|
||||||
cur_cmnt_and_lit: CurrentCommentAndLiteral,
|
cur_cmnt_and_lit: CurrentCommentAndLiteral,
|
||||||
boxes: Vec<pp::Breaks>,
|
boxes: Vec<pp::Breaks>,
|
||||||
ann: &'a PpAnn+'a,
|
ann: &'a (PpAnn+'a),
|
||||||
encode_idents_with_hygiene: bool,
|
encode_idents_with_hygiene: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -293,6 +293,10 @@ pub fn ty_to_string(ty: &ast::Ty) -> String {
|
||||||
$to_string(|s| s.print_type(ty))
|
$to_string(|s| s.print_type(ty))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn bounds_to_string(bounds: &[ast::TyParamBound]) -> String {
|
||||||
|
$to_string(|s| s.print_bounds("", bounds))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn pat_to_string(pat: &ast::Pat) -> String {
|
pub fn pat_to_string(pat: &ast::Pat) -> String {
|
||||||
$to_string(|s| s.print_pat(pat))
|
$to_string(|s| s.print_pat(pat))
|
||||||
}
|
}
|
||||||
|
@ -739,11 +743,15 @@ impl<'a> State<'a> {
|
||||||
Some(&generics),
|
Some(&generics),
|
||||||
None));
|
None));
|
||||||
}
|
}
|
||||||
ast::TyPath(ref path, ref bounds, _) => {
|
ast::TyPath(ref path, _) => {
|
||||||
try!(self.print_bounded_path(path, bounds));
|
try!(self.print_path(path, false));
|
||||||
|
}
|
||||||
|
ast::TyObjectSum(ref ty, ref bounds) => {
|
||||||
|
try!(self.print_type(&**ty));
|
||||||
|
try!(self.print_bounds("+", bounds.as_slice()));
|
||||||
}
|
}
|
||||||
ast::TyPolyTraitRef(ref bounds) => {
|
ast::TyPolyTraitRef(ref bounds) => {
|
||||||
try!(self.print_bounds("", bounds));
|
try!(self.print_bounds("", bounds.as_slice()));
|
||||||
}
|
}
|
||||||
ast::TyQPath(ref qpath) => {
|
ast::TyQPath(ref qpath) => {
|
||||||
try!(word(&mut self.s, "<"));
|
try!(word(&mut self.s, "<"));
|
||||||
|
@ -970,7 +978,7 @@ impl<'a> State<'a> {
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
try!(self.print_bounds(":", bounds));
|
try!(self.print_bounds(":", bounds.as_slice()));
|
||||||
try!(self.print_where_clause(generics));
|
try!(self.print_where_clause(generics));
|
||||||
try!(word(&mut self.s, " "));
|
try!(word(&mut self.s, " "));
|
||||||
try!(self.bopen());
|
try!(self.bopen());
|
||||||
|
@ -1908,11 +1916,11 @@ impl<'a> State<'a> {
|
||||||
self.print_expr(coll)
|
self.print_expr(coll)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_path_(&mut self,
|
fn print_path(&mut self,
|
||||||
path: &ast::Path,
|
path: &ast::Path,
|
||||||
colons_before_params: bool,
|
colons_before_params: bool)
|
||||||
opt_bounds: &Option<OwnedSlice<ast::TyParamBound>>)
|
-> IoResult<()>
|
||||||
-> IoResult<()> {
|
{
|
||||||
try!(self.maybe_print_comment(path.span.lo));
|
try!(self.maybe_print_comment(path.span.lo));
|
||||||
if path.global {
|
if path.global {
|
||||||
try!(word(&mut self.s, "::"));
|
try!(word(&mut self.s, "::"));
|
||||||
|
@ -1931,10 +1939,7 @@ impl<'a> State<'a> {
|
||||||
try!(self.print_path_parameters(&segment.parameters, colons_before_params));
|
try!(self.print_path_parameters(&segment.parameters, colons_before_params));
|
||||||
}
|
}
|
||||||
|
|
||||||
match *opt_bounds {
|
Ok(())
|
||||||
None => Ok(()),
|
|
||||||
Some(ref bounds) => self.print_bounds("+", bounds)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_path_parameters(&mut self,
|
fn print_path_parameters(&mut self,
|
||||||
|
@ -1997,17 +2002,6 @@ impl<'a> State<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_path(&mut self, path: &ast::Path,
|
|
||||||
colons_before_params: bool) -> IoResult<()> {
|
|
||||||
self.print_path_(path, colons_before_params, &None)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn print_bounded_path(&mut self, path: &ast::Path,
|
|
||||||
bounds: &Option<OwnedSlice<ast::TyParamBound>>)
|
|
||||||
-> IoResult<()> {
|
|
||||||
self.print_path_(path, false, bounds)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn print_pat(&mut self, pat: &ast::Pat) -> IoResult<()> {
|
pub fn print_pat(&mut self, pat: &ast::Pat) -> IoResult<()> {
|
||||||
try!(self.maybe_print_comment(pat.span.lo));
|
try!(self.maybe_print_comment(pat.span.lo));
|
||||||
try!(self.ann.pre(self, NodePat(pat)));
|
try!(self.ann.pre(self, NodePat(pat)));
|
||||||
|
@ -2329,7 +2323,7 @@ impl<'a> State<'a> {
|
||||||
|
|
||||||
pub fn print_bounds(&mut self,
|
pub fn print_bounds(&mut self,
|
||||||
prefix: &str,
|
prefix: &str,
|
||||||
bounds: &OwnedSlice<ast::TyParamBound>)
|
bounds: &[ast::TyParamBound])
|
||||||
-> IoResult<()> {
|
-> IoResult<()> {
|
||||||
if !bounds.is_empty() {
|
if !bounds.is_empty() {
|
||||||
try!(word(&mut self.s, prefix));
|
try!(word(&mut self.s, prefix));
|
||||||
|
@ -2418,7 +2412,7 @@ impl<'a> State<'a> {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
try!(self.print_ident(param.ident));
|
try!(self.print_ident(param.ident));
|
||||||
try!(self.print_bounds(":", ¶m.bounds));
|
try!(self.print_bounds(":", param.bounds.as_slice()));
|
||||||
match param.default {
|
match param.default {
|
||||||
Some(ref default) => {
|
Some(ref default) => {
|
||||||
try!(space(&mut self.s));
|
try!(space(&mut self.s));
|
||||||
|
@ -2447,7 +2441,7 @@ impl<'a> State<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
try!(self.print_ident(predicate.ident));
|
try!(self.print_ident(predicate.ident));
|
||||||
try!(self.print_bounds(":", &predicate.bounds));
|
try!(self.print_bounds(":", predicate.bounds.as_slice()));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -2664,7 +2658,7 @@ impl<'a> State<'a> {
|
||||||
try!(self.pclose());
|
try!(self.pclose());
|
||||||
}
|
}
|
||||||
|
|
||||||
try!(self.print_bounds(":", bounds));
|
try!(self.print_bounds(":", bounds.as_slice()));
|
||||||
|
|
||||||
try!(self.print_fn_output(decl));
|
try!(self.print_fn_output(decl));
|
||||||
|
|
||||||
|
|
|
@ -482,8 +482,7 @@ fn mk_tests(cx: &TestCtxt) -> P<ast::Item> {
|
||||||
let ecx = &cx.ext_cx;
|
let ecx = &cx.ext_cx;
|
||||||
let struct_type = ecx.ty_path(ecx.path(sp, vec![ecx.ident_of("self"),
|
let struct_type = ecx.ty_path(ecx.path(sp, vec![ecx.ident_of("self"),
|
||||||
ecx.ident_of("test"),
|
ecx.ident_of("test"),
|
||||||
ecx.ident_of("TestDescAndFn")]),
|
ecx.ident_of("TestDescAndFn")]));
|
||||||
None);
|
|
||||||
let static_lt = ecx.lifetime(sp, token::special_idents::static_lifetime.name);
|
let static_lt = ecx.lifetime(sp, token::special_idents::static_lifetime.name);
|
||||||
// &'static [self::test::TestDescAndFn]
|
// &'static [self::test::TestDescAndFn]
|
||||||
let static_type = ecx.ty_rptr(sp,
|
let static_type = ecx.ty_rptr(sp,
|
||||||
|
|
|
@ -404,15 +404,13 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
|
||||||
walk_fn_ret_ty(visitor, &function_declaration.decl.output);
|
walk_fn_ret_ty(visitor, &function_declaration.decl.output);
|
||||||
walk_lifetime_decls_helper(visitor, &function_declaration.lifetimes);
|
walk_lifetime_decls_helper(visitor, &function_declaration.lifetimes);
|
||||||
}
|
}
|
||||||
TyPath(ref path, ref opt_bounds, id) => {
|
TyPath(ref path, id) => {
|
||||||
visitor.visit_path(path, id);
|
visitor.visit_path(path, id);
|
||||||
match *opt_bounds {
|
}
|
||||||
Some(ref bounds) => {
|
TyObjectSum(ref ty, ref bounds) => {
|
||||||
|
visitor.visit_ty(&**ty);
|
||||||
walk_ty_param_bounds_helper(visitor, bounds);
|
walk_ty_param_bounds_helper(visitor, bounds);
|
||||||
}
|
}
|
||||||
None => { }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
TyQPath(ref qpath) => {
|
TyQPath(ref qpath) => {
|
||||||
visitor.visit_ty(&*qpath.self_type);
|
visitor.visit_ty(&*qpath.self_type);
|
||||||
visitor.visit_trait_ref(&*qpath.trait_ref);
|
visitor.visit_trait_ref(&*qpath.trait_ref);
|
||||||
|
|
|
@ -115,7 +115,7 @@ pub fn stdout() -> Option<Box<Terminal<WriterWrapper> + Send>> {
|
||||||
#[cfg(not(windows))]
|
#[cfg(not(windows))]
|
||||||
/// Return a Terminal wrapping stderr, or None if a terminal couldn't be
|
/// Return a Terminal wrapping stderr, or None if a terminal couldn't be
|
||||||
/// opened.
|
/// opened.
|
||||||
pub fn stderr() -> Option<Box<Terminal<WriterWrapper> + Send> + Send> {
|
pub fn stderr() -> Option<Box<Terminal<WriterWrapper> + Send>> {
|
||||||
TerminfoTerminal::new(WriterWrapper {
|
TerminfoTerminal::new(WriterWrapper {
|
||||||
wrapped: box std::io::stderr() as Box<Writer + Send>,
|
wrapped: box std::io::stderr() as Box<Writer + Send>,
|
||||||
})
|
})
|
||||||
|
|
|
@ -25,7 +25,7 @@ impl Index<uint, str> for S {
|
||||||
struct T;
|
struct T;
|
||||||
|
|
||||||
impl Index<uint, Show + 'static> for T {
|
impl Index<uint, Show + 'static> for T {
|
||||||
fn index<'a>(&'a self, idx: &uint) -> &'a Show + 'static {
|
fn index<'a>(&'a self, idx: &uint) -> &'a (Show + 'static) {
|
||||||
static x: uint = 42;
|
static x: uint = 42;
|
||||||
&x
|
&x
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
#![feature(unboxed_closures)]
|
||||||
|
|
||||||
|
// Test that we suggest the correct parentheses
|
||||||
|
|
||||||
|
trait Bar {
|
||||||
|
fn dummy(&self) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Foo<'a> {
|
||||||
|
a: &'a Bar+'a,
|
||||||
|
//~^ ERROR E0171
|
||||||
|
//~^^ NOTE perhaps you meant `&'a (Bar + 'a)`?
|
||||||
|
|
||||||
|
b: &'a mut Bar+'a,
|
||||||
|
//~^ ERROR E0171
|
||||||
|
//~^^ NOTE perhaps you meant `&'a mut (Bar + 'a)`?
|
||||||
|
|
||||||
|
c: Box<Bar+'a>, // OK, no paren needed in this context
|
||||||
|
|
||||||
|
d: fn() -> Bar+'a,
|
||||||
|
//~^ ERROR E0171
|
||||||
|
//~^^ NOTE perhaps you forgot parentheses
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() { }
|
|
@ -24,7 +24,7 @@ impl X for B {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct A<'a> {
|
struct A<'a> {
|
||||||
p: &'a X+'a
|
p: &'a (X+'a)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_a<'a>(p: &'a X) -> A<'a> {
|
fn make_a<'a>(p: &'a X) -> A<'a> {
|
||||||
|
|
|
@ -14,7 +14,7 @@ struct A;
|
||||||
|
|
||||||
impl Foo for A {}
|
impl Foo for A {}
|
||||||
|
|
||||||
struct B<'a>(&'a Foo+'a);
|
struct B<'a>(&'a (Foo+'a));
|
||||||
|
|
||||||
fn foo<'a>(a: &Foo) -> B<'a> {
|
fn foo<'a>(a: &Foo) -> B<'a> {
|
||||||
B(a) //~ ERROR cannot infer an appropriate lifetime
|
B(a) //~ ERROR cannot infer an appropriate lifetime
|
||||||
|
|
|
@ -44,15 +44,15 @@ fn test<'a,T,U:Copy>(_: &'a int) {
|
||||||
|
|
||||||
// borrowed object types are generally ok
|
// borrowed object types are generally ok
|
||||||
assert_copy::<&'a Dummy>();
|
assert_copy::<&'a Dummy>();
|
||||||
assert_copy::<&'a Dummy+Copy>();
|
assert_copy::<&'a (Dummy+Copy)>();
|
||||||
assert_copy::<&'static Dummy+Copy>();
|
assert_copy::<&'static (Dummy+Copy)>();
|
||||||
|
|
||||||
// owned object types are not ok
|
// owned object types are not ok
|
||||||
assert_copy::<Box<Dummy>>(); //~ ERROR `core::kinds::Copy` is not implemented
|
assert_copy::<Box<Dummy>>(); //~ ERROR `core::kinds::Copy` is not implemented
|
||||||
assert_copy::<Box<Dummy+Copy>>(); //~ ERROR `core::kinds::Copy` is not implemented
|
assert_copy::<Box<Dummy+Copy>>(); //~ ERROR `core::kinds::Copy` is not implemented
|
||||||
|
|
||||||
// mutable object types are not ok
|
// mutable object types are not ok
|
||||||
assert_copy::<&'a mut Dummy+Copy>(); //~ ERROR `core::kinds::Copy` is not implemented
|
assert_copy::<&'a mut (Dummy+Copy)>(); //~ ERROR `core::kinds::Copy` is not implemented
|
||||||
|
|
||||||
// closures are like an `&mut` object
|
// closures are like an `&mut` object
|
||||||
assert_copy::<||>(); //~ ERROR `core::kinds::Copy` is not implemented
|
assert_copy::<||>(); //~ ERROR `core::kinds::Copy` is not implemented
|
||||||
|
|
|
@ -19,7 +19,7 @@ trait Message : Send { }
|
||||||
// careful with object types, who knows what they close over...
|
// careful with object types, who knows what they close over...
|
||||||
|
|
||||||
fn object_ref_with_static_bound_not_ok() {
|
fn object_ref_with_static_bound_not_ok() {
|
||||||
assert_send::<&'static Dummy+'static>();
|
assert_send::<&'static (Dummy+'static)>();
|
||||||
//~^ ERROR the trait `core::kinds::Send` is not implemented
|
//~^ ERROR the trait `core::kinds::Send` is not implemented
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ fn closure_with_no_bound_not_ok<'a>() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn object_with_send_bound_ok() {
|
fn object_with_send_bound_ok() {
|
||||||
assert_send::<&'static Dummy+Send>();
|
assert_send::<&'static (Dummy+Send)>();
|
||||||
assert_send::<Box<Dummy+Send>>();
|
assert_send::<Box<Dummy+Send>>();
|
||||||
assert_send::<proc():Send>;
|
assert_send::<proc():Send>;
|
||||||
assert_send::<||:Send>;
|
assert_send::<||:Send>;
|
||||||
|
|
|
@ -21,13 +21,13 @@ fn test51<'a>() {
|
||||||
//~^ ERROR the trait `core::kinds::Send` is not implemented
|
//~^ ERROR the trait `core::kinds::Send` is not implemented
|
||||||
}
|
}
|
||||||
fn test52<'a>() {
|
fn test52<'a>() {
|
||||||
assert_send::<&'a Dummy+Send>();
|
assert_send::<&'a (Dummy+Send)>();
|
||||||
//~^ ERROR does not fulfill the required lifetime
|
//~^ ERROR does not fulfill the required lifetime
|
||||||
}
|
}
|
||||||
|
|
||||||
// ...unless they are properly bounded
|
// ...unless they are properly bounded
|
||||||
fn test60() {
|
fn test60() {
|
||||||
assert_send::<&'static Dummy+Send>();
|
assert_send::<&'static (Dummy+Send)>();
|
||||||
}
|
}
|
||||||
fn test61() {
|
fn test61() {
|
||||||
assert_send::<Box<Dummy+Send>>();
|
assert_send::<Box<Dummy+Send>>();
|
||||||
|
|
|
@ -23,7 +23,7 @@ fn test53() {
|
||||||
|
|
||||||
// ...unless they are properly bounded
|
// ...unless they are properly bounded
|
||||||
fn test60() {
|
fn test60() {
|
||||||
assert_send::<&'static Dummy+Send>();
|
assert_send::<&'static (Dummy+Send)>();
|
||||||
}
|
}
|
||||||
fn test61() {
|
fn test61() {
|
||||||
assert_send::<Box<Dummy+Send>>();
|
assert_send::<Box<Dummy+Send>>();
|
||||||
|
|
|
@ -28,14 +28,14 @@ fn borrowed_receiver_different_lifetimes<'a,'b>(x: &'a Foo) -> &'b () {
|
||||||
|
|
||||||
// Borrowed receiver with two distinct lifetimes, but we know that
|
// Borrowed receiver with two distinct lifetimes, but we know that
|
||||||
// 'b:'a, hence &'a () is permitted.
|
// 'b:'a, hence &'a () is permitted.
|
||||||
fn borrowed_receiver_related_lifetimes<'a,'b>(x: &'a Foo+'b) -> &'a () {
|
fn borrowed_receiver_related_lifetimes<'a,'b>(x: &'a (Foo+'b)) -> &'a () {
|
||||||
x.borrowed()
|
x.borrowed()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Here we have two distinct lifetimes, but we try to return a pointer
|
// Here we have two distinct lifetimes, but we try to return a pointer
|
||||||
// with the longer lifetime when (from the signature) we only know
|
// with the longer lifetime when (from the signature) we only know
|
||||||
// that it lives as long as the shorter lifetime. Therefore, error.
|
// that it lives as long as the shorter lifetime. Therefore, error.
|
||||||
fn borrowed_receiver_related_lifetimes2<'a,'b>(x: &'a Foo+'b) -> &'b () {
|
fn borrowed_receiver_related_lifetimes2<'a,'b>(x: &'a (Foo+'b)) -> &'b () {
|
||||||
x.borrowed() //~ ERROR cannot infer
|
x.borrowed() //~ ERROR cannot infer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,12 +57,12 @@ fn box_with_region_not_ok<'a>() {
|
||||||
// objects with insufficient bounds no ok
|
// objects with insufficient bounds no ok
|
||||||
|
|
||||||
fn object_with_random_bound_not_ok<'a>() {
|
fn object_with_random_bound_not_ok<'a>() {
|
||||||
assert_send::<&'a Dummy+'a>();
|
assert_send::<&'a (Dummy+'a)>();
|
||||||
//~^ ERROR not implemented
|
//~^ ERROR not implemented
|
||||||
}
|
}
|
||||||
|
|
||||||
fn object_with_send_bound_not_ok<'a>() {
|
fn object_with_send_bound_not_ok<'a>() {
|
||||||
assert_send::<&'a Dummy+Send>();
|
assert_send::<&'a (Dummy+Send)>();
|
||||||
//~^ ERROR does not fulfill
|
//~^ ERROR does not fulfill
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
|
|
||||||
trait A<T> {}
|
trait A<T> {}
|
||||||
struct B<'a, T>(&'a A<T>+'a);
|
struct B<'a, T>(&'a (A<T>+'a));
|
||||||
|
|
||||||
trait X {}
|
trait X {}
|
||||||
impl<'a, T> X for B<'a, T> {}
|
impl<'a, T> X for B<'a, T> {}
|
||||||
|
|
|
@ -31,7 +31,7 @@ impl Drop for B {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct A<'r> {
|
struct A<'r> {
|
||||||
p: &'r X+'r
|
p: &'r (X+'r)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_a(p:&X) -> A {
|
fn make_a(p:&X) -> A {
|
||||||
|
|
|
@ -13,7 +13,7 @@ trait Foo {
|
||||||
|
|
||||||
struct Bar;
|
struct Bar;
|
||||||
|
|
||||||
impl Foo + Owned for Bar { //~ ERROR bounded traits are only valid in type position
|
impl Foo + Owned for Bar { //~ ERROR not a trait
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() { }
|
fn main() { }
|
||||||
|
|
|
@ -11,6 +11,6 @@
|
||||||
|
|
||||||
struct Foo;
|
struct Foo;
|
||||||
|
|
||||||
fn foo(_x: Box<Foo + Send>) { } //~ ERROR kind bounds can only be used on trait types
|
fn foo(_x: Box<Foo + Send>) { } //~ ERROR expected a reference to a trait
|
||||||
|
|
||||||
fn main() { }
|
fn main() { }
|
||||||
|
|
|
@ -16,14 +16,14 @@ trait Foo {}
|
||||||
fn a(_x: Box<Foo+Send>) {
|
fn a(_x: Box<Foo+Send>) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn b(_x: &'static Foo+'static) {
|
fn b(_x: &'static (Foo+'static)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn c(x: Box<Foo+Sync>) {
|
fn c(x: Box<Foo+Sync>) {
|
||||||
a(x); //~ ERROR mismatched types
|
a(x); //~ ERROR mismatched types
|
||||||
}
|
}
|
||||||
|
|
||||||
fn d(x: &'static Foo+Sync) {
|
fn d(x: &'static (Foo+Sync)) {
|
||||||
b(x); //~ ERROR cannot infer
|
b(x); //~ ERROR cannot infer
|
||||||
//~^ ERROR mismatched types
|
//~^ ERROR mismatched types
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ use std::fmt;
|
||||||
use std::fmt::FormatWriter;
|
use std::fmt::FormatWriter;
|
||||||
|
|
||||||
struct Foo<'a> {
|
struct Foo<'a> {
|
||||||
writer: &'a mut Writer+'a,
|
writer: &'a mut (Writer+'a),
|
||||||
other: &'a str,
|
other: &'a str,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ impl Index<uint, str> for S {
|
||||||
struct T;
|
struct T;
|
||||||
|
|
||||||
impl Index<uint, Show + 'static> for T {
|
impl Index<uint, Show + 'static> for T {
|
||||||
fn index<'a>(&'a self, idx: &uint) -> &'a Show + 'static {
|
fn index<'a>(&'a self, idx: &uint) -> &'a (Show + 'static) {
|
||||||
static x: uint = 42;
|
static x: uint = 42;
|
||||||
&x
|
&x
|
||||||
}
|
}
|
||||||
|
|
27
src/test/run-pass/hrtb-precedence-of-plus-where-clause.rs
Normal file
27
src/test/run-pass/hrtb-precedence-of-plus-where-clause.rs
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
#![feature(unboxed_closures)]
|
||||||
|
|
||||||
|
// Test that `F : Fn(int) -> int + Send` is interpreted as two
|
||||||
|
// distinct bounds on `F`.
|
||||||
|
|
||||||
|
fn foo<F>(f: F)
|
||||||
|
where F : FnOnce(int) -> int + Send
|
||||||
|
{
|
||||||
|
bar(f);
|
||||||
|
baz(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bar<F:Send>(f: F) { }
|
||||||
|
|
||||||
|
fn baz<F:FnOnce(int) -> int>(f: F) { }
|
||||||
|
|
||||||
|
fn main() {}
|
21
src/test/run-pass/hrtb-precedence-of-plus.rs
Normal file
21
src/test/run-pass/hrtb-precedence-of-plus.rs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
#![feature(unboxed_closures)]
|
||||||
|
|
||||||
|
// Test that `Fn(int) -> int + 'static` parses as `(Fn(int) -> int) +
|
||||||
|
// 'static` and not `Fn(int) -> (int + 'static)`. The latter would
|
||||||
|
// cause a compilation error. Issue #18772.
|
||||||
|
|
||||||
|
fn adder(y: int) -> Box<Fn(int) -> int + 'static> {
|
||||||
|
box move |&: x| y + x
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
pub mod two_tuple {
|
pub mod two_tuple {
|
||||||
pub trait T {}
|
pub trait T {}
|
||||||
pub struct P<'a>(&'a T + 'a, &'a T + 'a);
|
pub struct P<'a>(&'a (T + 'a), &'a (T + 'a));
|
||||||
pub fn f<'a>(car: &'a T, cdr: &'a T) -> P<'a> {
|
pub fn f<'a>(car: &'a T, cdr: &'a T) -> P<'a> {
|
||||||
P(car, cdr)
|
P(car, cdr)
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ pub mod two_tuple {
|
||||||
|
|
||||||
pub mod two_fields {
|
pub mod two_fields {
|
||||||
pub trait T {}
|
pub trait T {}
|
||||||
pub struct P<'a> { car: &'a T + 'a, cdr: &'a T + 'a }
|
pub struct P<'a> { car: &'a (T + 'a), cdr: &'a (T + 'a) }
|
||||||
pub fn f<'a>(car: &'a T, cdr: &'a T) -> P<'a> {
|
pub fn f<'a>(car: &'a T, cdr: &'a T) -> P<'a> {
|
||||||
P{ car: car, cdr: cdr }
|
P{ car: car, cdr: cdr }
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ fn main() {
|
||||||
foog(x, &[box 1i]);
|
foog(x, &[box 1i]);
|
||||||
|
|
||||||
struct T<'a> {
|
struct T<'a> {
|
||||||
t: [&'a Foo+'a, ..2]
|
t: [&'a (Foo+'a), ..2]
|
||||||
}
|
}
|
||||||
let _n = T {
|
let _n = T {
|
||||||
t: [&1i, &2i]
|
t: [&1i, &2i]
|
||||||
|
@ -64,7 +64,7 @@ fn main() {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct F<'b> {
|
struct F<'b> {
|
||||||
t: &'b [&'b Foo+'b]
|
t: &'b [&'b (Foo+'b)]
|
||||||
}
|
}
|
||||||
let _n = F {
|
let _n = F {
|
||||||
t: &[&1i, &2i]
|
t: &[&1i, &2i]
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
use std::io::Reader;
|
use std::io::Reader;
|
||||||
|
|
||||||
enum Wrapper<'a> {
|
enum Wrapper<'a> {
|
||||||
WrapReader(&'a Reader + 'a)
|
WrapReader(&'a (Reader + 'a))
|
||||||
}
|
}
|
||||||
|
|
||||||
trait Wrap<'a> {
|
trait Wrap<'a> {
|
||||||
|
|
|
@ -14,7 +14,7 @@ trait Foo {}
|
||||||
|
|
||||||
struct Bar;
|
struct Bar;
|
||||||
|
|
||||||
impl<'a> std::ops::Fn<(&'a Foo+'a,), ()> for Bar {
|
impl<'a> std::ops::Fn<(&'a (Foo+'a),), ()> for Bar {
|
||||||
extern "rust-call" fn call(&self, _: (&'a Foo,)) {}
|
extern "rust-call" fn call(&self, _: (&'a Foo,)) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,8 +33,8 @@ impl Alloy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> Fn<(&'b mut Response+'b,),()> for SendFile<'a> {
|
impl<'a, 'b> Fn<(&'b mut (Response+'b),),()> for SendFile<'a> {
|
||||||
extern "rust-call" fn call(&self, (_res,): (&'b mut Response+'b,)) {}
|
extern "rust-call" fn call(&self, (_res,): (&'b mut (Response+'b),)) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Rq: Request, Rs: Response> Ingot<Rq, Rs> for HelloWorld {
|
impl<Rq: Request, Rs: Response> Ingot<Rq, Rs> for HelloWorld {
|
||||||
|
|
|
@ -29,7 +29,7 @@ impl Inner for int {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Outer<'a> {
|
struct Outer<'a> {
|
||||||
inner: &'a Inner+'a
|
inner: &'a (Inner+'a)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Outer<'a> {
|
impl<'a> Outer<'a> {
|
||||||
|
@ -51,7 +51,7 @@ pub fn main() {
|
||||||
pub trait MyTrait<T> { }
|
pub trait MyTrait<T> { }
|
||||||
|
|
||||||
pub struct MyContainer<'a, T> {
|
pub struct MyContainer<'a, T> {
|
||||||
foos: Vec<&'a MyTrait<T>+'a> ,
|
foos: Vec<&'a (MyTrait<T>+'a)> ,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T> MyContainer<'a, T> {
|
impl<'a, T> MyContainer<'a, T> {
|
||||||
|
|
|
@ -13,7 +13,7 @@ struct B;
|
||||||
impl A for B {}
|
impl A for B {}
|
||||||
|
|
||||||
struct C<'a> {
|
struct C<'a> {
|
||||||
foo: &'a mut A+'a,
|
foo: &'a mut (A+'a),
|
||||||
}
|
}
|
||||||
|
|
||||||
fn foo(a: &mut A) {
|
fn foo(a: &mut A) {
|
||||||
|
|
|
@ -16,7 +16,7 @@ mod a {
|
||||||
pub trait X {}
|
pub trait X {}
|
||||||
impl X for int {}
|
impl X for int {}
|
||||||
|
|
||||||
pub struct Z<'a>(Enum<&'a X+'a>);
|
pub struct Z<'a>(Enum<&'a (X+'a)>);
|
||||||
fn foo() { let x = 42i; let z = Z(Enum::A(&x as &X)); let _ = z; }
|
fn foo() { let x = 42i; let z = Z(Enum::A(&x as &X)); let _ = z; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ mod b {
|
||||||
trait X {}
|
trait X {}
|
||||||
impl X for int {}
|
impl X for int {}
|
||||||
struct Y<'a>{
|
struct Y<'a>{
|
||||||
x:Option<&'a X+'a>,
|
x:Option<&'a (X+'a)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bar() {
|
fn bar() {
|
||||||
|
@ -36,7 +36,7 @@ mod b {
|
||||||
mod c {
|
mod c {
|
||||||
pub trait X { fn f(&self); }
|
pub trait X { fn f(&self); }
|
||||||
impl X for int { fn f(&self) {} }
|
impl X for int { fn f(&self) {} }
|
||||||
pub struct Z<'a>(Option<&'a X+'a>);
|
pub struct Z<'a>(Option<&'a (X+'a)>);
|
||||||
fn main() { let x = 42i; let z = Z(Some(&x as &X)); let _ = z; }
|
fn main() { let x = 42i; let z = Z(Some(&x as &X)); let _ = z; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ mod foo {
|
||||||
pub trait D<'a, T> {}
|
pub trait D<'a, T> {}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn foo1<T>(_: &A<T> + Send) {}
|
fn foo1<T>(_: &(A<T> + Send)) {}
|
||||||
fn foo2<T>(_: Box<A<T> + Send + Sync>) {}
|
fn foo2<T>(_: Box<A<T> + Send + Sync>) {}
|
||||||
fn foo3<T>(_: Box<B<int, uint> + 'static>) {}
|
fn foo3<T>(_: Box<B<int, uint> + 'static>) {}
|
||||||
fn foo4<'a, T>(_: Box<C<'a, T> + 'static + Send>) {}
|
fn foo4<'a, T>(_: Box<C<'a, T> + 'static + Send>) {}
|
||||||
|
|
|
@ -30,7 +30,7 @@ fn object_invoke1<'d>(x: &'d Trait<'d>) -> (int, int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Struct1<'e> {
|
struct Struct1<'e> {
|
||||||
f: &'e Trait<'e>+'e
|
f: &'e (Trait<'e>+'e)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn field_invoke1<'f, 'g>(x: &'g Struct1<'f>) -> (int,int) {
|
fn field_invoke1<'f, 'g>(x: &'g Struct1<'f>) -> (int,int) {
|
||||||
|
@ -40,7 +40,7 @@ fn field_invoke1<'f, 'g>(x: &'g Struct1<'f>) -> (int,int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Struct2<'h, 'i> {
|
struct Struct2<'h, 'i> {
|
||||||
f: &'h Trait<'i>+'h
|
f: &'h (Trait<'i>+'h)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn object_invoke2<'j, 'k>(x: &'k Trait<'j>) -> int {
|
fn object_invoke2<'j, 'k>(x: &'k Trait<'j>) -> int {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue