E0055,
E0056,
E0057,
- E0058,
E0059,
E0060,
E0061,
for input in decl.inputs.iter() {
check_ty(cx, &*input.ty);
}
- check_ty(cx, &*decl.output)
+ if let ast::Return(ref ret_ty) = decl.output {
+ check_ty(cx, &**ret_ty);
+ }
}
match it.node {
let t = ty::expr_ty(cx.tcx, expr);
let mut warned = false;
match ty::get(t).sty {
+ ty::ty_tup(ref tys) if tys.is_empty() => return,
ty::ty_bool => return,
ty::ty_struct(did, _) |
ty::ty_enum(did, _) => {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use middle::const_eval::{compare_const_vals, const_bool, const_float, const_nil, const_val};
+use middle::const_eval::{compare_const_vals, const_bool, const_float, const_val};
use middle::const_eval::{const_expr_to_pat, eval_const_expr, lookup_const_by_id};
use middle::def::*;
use middle::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, Init};
fn const_val_to_expr(value: &const_val) -> P<Expr> {
let node = match value {
&const_bool(b) => LitBool(b),
- &const_nil => LitNil,
_ => unreachable!()
};
P(Expr {
let pats_len = pats.len();
let mut pats = pats.into_iter().map(|p| P((*p).clone()));
let pat = match ty::get(left_ty).sty {
- ty::ty_tup(ref tys) if !tys.is_empty() => PatTup(pats.collect()),
+ ty::ty_tup(_) => PatTup(pats.collect()),
ty::ty_enum(cid, _) | ty::ty_struct(cid, _) => {
let (vid, is_structure) = match ctor {
ty::ty_bool =>
[true, false].iter().map(|b| ConstantValue(const_bool(*b))).collect(),
- ty::ty_tup(ref tys) if tys.is_empty() =>
- vec!(ConstantValue(const_nil)),
-
ty::ty_rptr(_, ty::mt { ty, .. }) => match ty::get(ty).sty {
ty::ty_vec(_, None) =>
range_inclusive(0, max_slice_length).map(|length| Slice(length)).collect(),
const_uint(u64),
const_str(InternedString),
const_binary(Rc<Vec<u8> >),
- const_bool(bool),
- const_nil
+ const_bool(bool)
}
pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr) -> P<Pat> {
LitFloatUnsuffixed(ref n) => {
const_float(from_str::<f64>(n.get()).unwrap() as f64)
}
- LitNil => const_nil,
LitBool(b) => const_bool(b)
}
}
(&const_str(ref a), &const_str(ref b)) => compare_vals(a, b),
(&const_bool(a), &const_bool(b)) => compare_vals(a, b),
(&const_binary(ref a), &const_binary(ref b)) => compare_vals(a, b),
- (&const_nil, &const_nil) => compare_vals((), ()),
_ => None
}
}
_ => {}
}
- this.resolve_type(&*ty_m.decl.output);
+ if let ast::Return(ref ret_ty) = ty_m.decl.output {
+ this.resolve_type(&**ret_ty);
+ }
});
}
ast::ProvidedMethod(ref m) => {
debug!("(resolving function) recorded argument");
}
- this.resolve_type(&*declaration.output);
+ if let ast::Return(ref ret_ty) = declaration.output {
+ this.resolve_type(&**ret_ty);
+ }
}
}
for arg in method.pe_fn_decl().inputs.iter() {
self.visit_ty(&*arg.ty);
}
- self.visit_ty(&*method.pe_fn_decl().output);
+
+ if let ast::Return(ref ret_ty) = method.pe_fn_decl().output {
+ self.visit_ty(&**ret_ty);
+ }
+
// walk the fn body
self.nest(method.id, |v| v.visit_block(&*method.pe_body()));
for arg in decl.inputs.iter() {
self.visit_ty(&*arg.ty);
}
- self.visit_ty(&*decl.output);
+
+ if let ast::Return(ref ret_ty) = decl.output {
+ self.visit_ty(&**ret_ty);
+ }
// walk the body
self.nest(item.id, |v| v.visit_block(&*body));
for arg in method_type.decl.inputs.iter() {
self.visit_ty(&*arg.ty);
}
- self.visit_ty(&*method_type.decl.output);
+
+ if let ast::Return(ref ret_ty) = method_type.decl.output {
+ self.visit_ty(&**ret_ty);
+ }
self.process_generic_params(&method_type.generics,
method_type.span,
for arg in decl.inputs.iter() {
self.visit_ty(&*arg.ty);
}
- self.visit_ty(&*decl.output);
+
+ if let ast::Return(ref ret_ty) = decl.output {
+ self.visit_ty(&**ret_ty);
+ }
// walk the body
self.nest(ex.id, |v| v.visit_block(&**body));
}
}
ast::LitBool(b) => C_bool(cx, b),
- ast::LitNil => C_nil(cx),
ast::LitStr(ref s, _) => C_str_slice(cx, (*s).clone()),
ast::LitBinary(ref data) => C_binary_slice(cx, data.as_slice()),
}
macro_rules! ifn (
($name:expr fn() -> $ret:expr) => (
if *key == $name {
- let f = base::decl_cdecl_fn(ccx, $name, Type::func([], &$ret), ty::mk_nil(ccx.tcx()));
+ let f = base::decl_cdecl_fn(
+ ccx, $name, Type::func([], &$ret),
+ ty::mk_nil(ccx.tcx()));
ccx.intrinsics().borrow_mut().insert($name, f.clone());
return Some(f);
}
let mut signature = Vec::with_capacity(fn_decl.inputs.len() + 1);
// Return type -- llvm::DIBuilder wants this at index 0
- match fn_decl.output.node {
- ast::TyNil => {
- signature.push(ptr::null_mut());
- }
+ match fn_decl.output {
+ ast::Return(ref ret_ty) if ret_ty.node == ast::TyTup(vec![]) =>
+ signature.push(ptr::null_mut()),
_ => {
assert_type_for_node_id(cx, fn_ast_id, error_reporting_span);
debug!("basic_type_metadata: {}", ty::get(t));
let (name, encoding) = match ty::get(t).sty {
+ ty::ty_tup(ref elements) if elements.is_empty() =>
+ ("()".to_string(), DW_ATE_unsigned),
ty::ty_bool => ("bool".to_string(), DW_ATE_boolean),
ty::ty_char => ("char".to_string(), DW_ATE_unsigned_char),
ty::ty_int(int_ty) => match int_ty {
ty::ty_float(_) => {
MetadataCreationResult::new(basic_type_metadata(cx, t), false)
}
+ ty::ty_tup(ref elements) if elements.is_empty() => {
+ MetadataCreationResult::new(basic_type_metadata(cx, t), false)
+ }
ty::ty_enum(def_id, _) => {
prepare_enum_metadata(cx, t, def_id, unique_type_id, usage_site_span).finalize(cx)
}
fn push_debuginfo_type_name(cx: &CrateContext,
t: ty::t,
qualified: bool,
- output:&mut String) {
+ output: &mut String) {
match ty::get(t).sty {
ty::ty_bool => output.push_str("bool"),
ty::ty_char => output.push_str("char"),
push_debuginfo_type_name(cx, component_type, true, output);
output.push_str(", ");
}
- output.pop();
- output.pop();
+ if !component_types.is_empty() {
+ output.pop();
+ output.pop();
+ }
output.push(')');
},
ty::ty_uniq(inner_type) => {
ty_bool | ty_char | ty_int(_) | ty_float(_) | ty_uint(_) |
ty_infer(IntVar(_)) | ty_infer(FloatVar(_)) |
ty_bare_fn(..) | ty_ptr(_) => true,
+ ty_tup(ref tys) if tys.is_empty() => true,
_ => false
}
}
ty_uint(_) | ty_float(_) | ty_str => {
::util::ppaux::ty_to_string(cx, t)
}
+ ty_tup(ref tys) if tys.is_empty() => ::util::ppaux::ty_to_string(cx, t),
ty_enum(id, _) => format!("enum {}", item_path_str(cx, id)),
ty_uniq(_) => "box".to_string(),
// Returns the repeat count for a repeating vector expression.
pub fn eval_repeat_count(tcx: &ctxt, count_expr: &ast::Expr) -> uint {
match const_eval::eval_const_expr_partial(tcx, count_expr) {
- Ok(ref const_val) => match *const_val {
- const_eval::const_int(count) => if count < 0 {
- tcx.sess.span_err(count_expr.span,
- "expected positive integer for \
- repeat count, found negative integer");
- 0
- } else {
- count as uint
- },
- const_eval::const_uint(count) => count as uint,
- const_eval::const_float(count) => {
- tcx.sess.span_err(count_expr.span,
- "expected positive integer for \
- repeat count, found float");
- count as uint
- }
- const_eval::const_str(_) => {
- tcx.sess.span_err(count_expr.span,
- "expected positive integer for \
- repeat count, found string");
- 0
- }
- const_eval::const_bool(_) => {
- tcx.sess.span_err(count_expr.span,
- "expected positive integer for \
- repeat count, found boolean");
- 0
- }
- const_eval::const_binary(_) => {
- tcx.sess.span_err(count_expr.span,
- "expected positive integer for \
- repeat count, found binary array");
- 0
- }
- const_eval::const_nil => {
- tcx.sess.span_err(count_expr.span,
- "expected positive integer for \
- repeat count, found ()");
- 0
- }
- },
- Err(..) => {
- tcx.sess.span_err(count_expr.span,
- "expected constant integer for repeat count, \
- found variable");
- 0
- }
+ Ok(val) => {
+ let found = match val {
+ const_eval::const_uint(count) => return count as uint,
+ const_eval::const_int(count) if count >= 0 => return count as uint,
+ const_eval::const_int(_) =>
+ "negative integer",
+ const_eval::const_float(_) =>
+ "float",
+ const_eval::const_str(_) =>
+ "string",
+ const_eval::const_bool(_) =>
+ "boolean",
+ const_eval::const_binary(_) =>
+ "binary array"
+ };
+ tcx.sess.span_err(count_expr.span, format!(
+ "expected positive integer for repeat count, found {}",
+ found).as_slice());
+ }
+ Err(_) => {
+ let found = match count_expr.node {
+ ast::ExprPath(ast::Path {
+ global: false,
+ ref segments,
+ ..
+ }) if segments.len() == 1 =>
+ "variable",
+ _ =>
+ "non-constant expression"
+ };
+ tcx.sess.span_err(count_expr.span, format!(
+ "expected constant integer for repeat count, found {}",
+ found).as_slice());
+ }
}
+ 0
}
// Iterate over a type parameter's bounded traits and any supertraits
let inputs = data.inputs.iter()
.map(|a_t| ast_ty_to_ty(this, &binding_rscope, &**a_t))
.collect();
- let input_ty = ty::mk_tup_or_nil(this.tcx(), inputs);
+ let input_ty = ty::mk_tup(this.tcx(), inputs);
let output = match data.output {
Some(ref output_ty) => ast_ty_to_ty(this, &binding_rscope, &**output_ty),
}
}
-#[deriving(Show)]
-enum PointerTy {
- RPtr(ty::Region),
- Uniq
-}
-
// Handle `~`, `Box`, and `&` being able to mean strs and vecs.
// If a_seq_ty is a str or a vec, make it a str/vec.
// Also handle first-class trait types.
rscope: &RS,
a_seq_mutbl: ast::Mutability,
a_seq_ty: &ast::Ty,
- ptr_ty: PointerTy,
+ region: ty::Region,
constr: |ty::t| -> ty::t)
-> ty::t
{
let tcx = this.tcx();
- debug!("mk_pointer(ptr_ty={}, a_seq_ty={})",
- ptr_ty,
+ debug!("mk_pointer(region={}, a_seq_ty={})",
+ region,
a_seq_ty.repr(tcx));
match a_seq_ty.node {
match tcx.def_map.borrow().get(&id) {
Some(&def::DefPrimTy(ast::TyStr)) => {
check_path_args(tcx, path, NO_TPS | NO_REGIONS);
- match ptr_ty {
- Uniq => {
- return constr(ty::mk_str(tcx));
- }
- RPtr(r) => {
- return ty::mk_str_slice(tcx, r, a_seq_mutbl);
- }
- }
+ return ty::mk_str_slice(tcx, region, a_seq_mutbl);
}
Some(&def::DefTrait(trait_def_id)) => {
let result = ast_path_to_trait_ref(this,
let tr = ty::mk_trait(tcx,
result,
existential_bounds);
- return match ptr_ty {
- Uniq => {
- return ty::mk_uniq(tcx, tr);
- }
- RPtr(r) => {
- return ty::mk_rptr(tcx, r, ty::mt{mutbl: a_seq_mutbl, ty: tr});
- }
- };
+ return ty::mk_rptr(tcx, region, ty::mt{mutbl: a_seq_mutbl, ty: tr});
}
_ => {}
}
let typ = ast_ty_to_builtin_ty(this, rscope, ast_ty).unwrap_or_else(|| {
match ast_ty.node {
- ast::TyNil => ty::mk_nil(this.tcx()),
- ast::TyBot => unreachable!(),
- ast::TyUniq(ref ty) => {
- mk_pointer(this, rscope, ast::MutImmutable, &**ty, Uniq,
- |ty| ty::mk_uniq(tcx, ty))
- }
ast::TyVec(ref ty) => {
ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty), None)
}
ast::TyRptr(ref region, ref mt) => {
let r = opt_ast_region_to_region(this, rscope, ast_ty.span, region);
debug!("ty_rptr r={}", r.repr(this.tcx()));
- mk_pointer(this, rscope, mt.mutbl, &*mt.ty, RPtr(r),
+ mk_pointer(this, rscope, mt.mutbl, &*mt.ty, r,
|ty| ty::mk_rptr(tcx, r, ty::mt {ty: ty, mutbl: mt.mutbl}))
}
ast::TyTup(ref fields) => {
.filter(|&(_, l)| l != 0)
.collect();
- let output_ty = match decl.output.node {
- ast::TyBot => ty::FnDiverging,
- ast::TyInfer => ty::FnConverging(this.ty_infer(decl.output.span)),
- _ => ty::FnConverging(match implied_output_region {
- Some(implied_output_region) => {
- let rb = SpecificRscope::new(implied_output_region);
- ast_ty_to_ty(this, &rb, &*decl.output)
- }
- None => {
- // All regions must be explicitly specified in the output
- // if the lifetime elision rules do not apply. This saves
- // the user from potentially-confusing errors.
- let rb = UnelidableRscope::new(param_lifetimes);
- ast_ty_to_ty(this, &rb, &*decl.output)
- }
- })
+ let output_ty = match decl.output {
+ ast::Return(ref output) if output.node == ast::TyInfer =>
+ ty::FnConverging(this.ty_infer(output.span)),
+ ast::Return(ref output) =>
+ ty::FnConverging(match implied_output_region {
+ Some(implied_output_region) => {
+ let rb = SpecificRscope::new(implied_output_region);
+ ast_ty_to_ty(this, &rb, &**output)
+ }
+ None => {
+ // All regions must be explicitly specified in the output
+ // if the lifetime elision rules do not apply. This saves
+ // the user from potentially-confusing errors.
+ let rb = UnelidableRscope::new(param_lifetimes);
+ ast_ty_to_ty(this, &rb, &**output)
+ }
+ }),
+ ast::NoReturn(_) => ty::FnDiverging
};
(ty::BareFnTy {
let expected_ret_ty = expected_sig.map(|e| e.output);
- let output_ty = match decl.output.node {
- ast::TyBot => ty::FnDiverging,
- ast::TyInfer if expected_ret_ty.is_some() => expected_ret_ty.unwrap(),
- ast::TyInfer => ty::FnConverging(this.ty_infer(decl.output.span)),
- _ => ty::FnConverging(ast_ty_to_ty(this, &rb, &*decl.output))
+ let output_ty = match decl.output {
+ ast::Return(ref output) if output.node == ast::TyInfer && expected_ret_ty.is_some() =>
+ expected_ret_ty.unwrap(),
+ ast::Return(ref output) if output.node == ast::TyInfer =>
+ ty::FnConverging(this.ty_infer(output.span)),
+ ast::Return(ref output) =>
+ ty::FnConverging(ast_ty_to_ty(this, &rb, &**output)),
+ ast::NoReturn(_) => ty::FnDiverging
};
ty::ClosureTy {
.collect();
if let ty::FnConverging(ret_ty) = ret_ty {
- fcx.require_type_is_sized(ret_ty, decl.output.span, traits::ReturnType);
+ fcx.require_type_is_sized(ret_ty, decl.output.span(), traits::ReturnType);
fn_sig_tys.push(ret_ty);
}
opt_ty.unwrap_or_else(
|| ty::mk_float_var(tcx, fcx.infcx().next_float_var_id()))
}
- ast::LitNil => ty::mk_nil(tcx),
ast::LitBool(_) => ty::mk_bool()
}
}
data.inputs.iter().map(|ty| fcx.to_ty(&**ty)).collect();
let tuple_ty =
- ty::mk_tup_or_nil(fcx.tcx(), input_tys);
+ ty::mk_tup(fcx.tcx(), input_tys);
if type_count >= 1 {
substs.types.push(space, tuple_ty);
.map(|a| ty_of_arg(ccx, &rb, a, None))
.collect();
- let output = match decl.output.node {
- ast::TyBot => ty::FnDiverging,
- _ => ty::FnConverging(ast_ty_to_ty(ccx, &rb, &*decl.output))
+ let output = match decl.output {
+ ast::Return(ref ty) =>
+ ty::FnConverging(ast_ty_to_ty(ccx, &rb, &**ty)),
+ ast::NoReturn(_) =>
+ ty::FnDiverging
};
let t_fn = ty::mk_bare_fn(
.map(|(a, b)| this.tys(*a, *b))
.collect::<Result<_, _>>()
.map(|ts| ty::mk_tup(tcx, ts))
- } else {
+ } else if as_.len() != 0 && bs.len() != 0 {
Err(ty::terr_tuple_size(
expected_found(this, as_.len(), bs.len())))
+ } else {
+ Err(ty::terr_sorts(expected_found(this, a, b)))
}
}
&anon_nums, ®ion_names);
inputs = self.rebuild_args_ty(inputs.as_slice(), lifetime,
&anon_nums, ®ion_names);
- output = self.rebuild_arg_ty_or_output(&*output, lifetime,
- &anon_nums, ®ion_names);
+ output = self.rebuild_output(&output, lifetime, &anon_nums, ®ion_names);
ty_params = self.rebuild_ty_params(ty_params, lifetime,
®ion_names);
}
let new_fn_decl = ast::FnDecl {
inputs: inputs,
output: output,
- cf: self.fn_decl.cf,
variadic: self.fn_decl.variadic
};
(new_fn_decl, expl_self_opt, generics)
new_inputs
}
+ fn rebuild_output(&self, ty: &ast::FunctionRetTy,
+ lifetime: ast::Lifetime,
+ anon_nums: &HashSet<uint>,
+ region_names: &HashSet<ast::Name>) -> ast::FunctionRetTy {
+ match *ty {
+ ast::Return(ref ret_ty) => ast::Return(
+ self.rebuild_arg_ty_or_output(&**ret_ty, lifetime, anon_nums, region_names)
+ ),
+ ast::NoReturn(span) => ast::NoReturn(span)
+ }
+ }
+
fn rebuild_arg_ty_or_output(&self,
ty: &ast::Ty,
lifetime: ast::Lifetime,
ty_queue.push(&*mut_ty.ty);
}
ast::TyVec(ref ty) |
- ast::TyUniq(ref ty) |
ast::TyFixedLengthVec(ref ty, _) => {
ty_queue.push(&**ty);
}
})
}
ast::TyVec(ty) => ast::TyVec(build_to(ty, to)),
- ast::TyUniq(ty) => ast::TyUniq(build_to(ty, to)),
ast::TyFixedLengthVec(ty, e) => {
ast::TyFixedLengthVec(build_to(ty, to), e)
}
inputs: Arguments {
values: inputs.iter().map(|x| x.clean(cx)).collect(),
},
- output: (self.pe_fn_decl().output.clean(cx)),
- cf: self.pe_fn_decl().cf.clean(cx),
+ output: self.pe_fn_decl().output.clean(cx),
attrs: Vec::new()
};
Item {
inputs: Arguments {
values: inputs.iter().map(|x| x.clean(cx)).collect(),
},
- output: (self.decl.output.clean(cx)),
- cf: self.decl.cf.clean(cx),
+ output: self.decl.output.clean(cx),
attrs: Vec::new()
};
Item {
#[deriving(Clone, Encodable, Decodable, PartialEq)]
pub struct FnDecl {
pub inputs: Arguments,
- pub output: Type,
- pub cf: RetStyle,
+ pub output: FunctionRetTy,
pub attrs: Vec<Attribute>,
}
values: self.inputs.clean(cx),
},
output: self.output.clean(cx),
- cf: self.cf.clean(cx),
attrs: Vec::new()
}
}
let _ = names.next();
}
FnDecl {
- output: sig.output.clean(cx),
- cf: Return,
+ output: Return(sig.output.clean(cx)),
attrs: Vec::new(),
inputs: Arguments {
values: sig.inputs.iter().map(|t| {
}
#[deriving(Clone, Encodable, Decodable, PartialEq)]
-pub enum RetStyle {
- NoReturn,
- Return
+pub enum FunctionRetTy {
+ Return(Type),
+ NoReturn
}
-impl Clean<RetStyle> for ast::RetStyle {
- fn clean(&self, _: &DocContext) -> RetStyle {
+impl Clean<FunctionRetTy> for ast::FunctionRetTy {
+ fn clean(&self, cx: &DocContext) -> FunctionRetTy {
match *self {
- ast::Return => Return,
- ast::NoReturn => NoReturn
+ ast::Return(ref typ) => Return(typ.clean(cx)),
+ ast::NoReturn(_) => NoReturn
}
}
}
F32, F64,
Char,
Bool,
- Unit,
Str,
Slice,
PrimitiveTuple,
"u32" => Some(U32),
"u64" => Some(U64),
"bool" => Some(Bool),
- "unit" => Some(Unit),
"char" => Some(Char),
"str" => Some(Str),
"f32" => Some(F32),
Str => "str",
Bool => "bool",
Char => "char",
- Unit => "()",
Slice => "slice",
PrimitiveTuple => "tuple",
}
}
pub fn to_url_str(&self) -> &'static str {
- match *self {
- Unit => "unit",
- other => other.to_string(),
- }
+ self.to_string()
}
/// Creates a rustdoc-specific node id for primitive types.
fn clean(&self, cx: &DocContext) -> Type {
use syntax::ast::*;
match self.node {
- TyNil => Primitive(Unit),
TyPtr(ref m) => RawPointer(m.mutbl.clean(cx), box m.ty.clean(cx)),
TyRptr(ref l, ref m) =>
BorrowedRef {lifetime: l.clean(cx), mutability: m.mutbl.clean(cx),
type_: box m.ty.clean(cx)},
- TyUniq(ref ty) => Unique(box ty.clean(cx)),
TyVec(ref ty) => Vector(box ty.clean(cx)),
TyFixedLengthVec(ref ty, ref e) => FixedVector(box ty.clean(cx),
e.span.to_src(cx)),
TyProc(ref c) => Proc(box c.clean(cx)),
TyBareFn(ref barefn) => BareFunction(box barefn.clean(cx)),
TyParen(ref ty) => ty.clean(cx),
- TyBot => Bottom,
ref x => panic!("Unimplemented type {}", x),
}
}
impl Clean<Type> for ty::t {
fn clean(&self, cx: &DocContext) -> Type {
match ty::get(*self).sty {
- ty::ty_nil => Primitive(Unit),
ty::ty_bool => Primitive(Bool),
ty::ty_char => Primitive(Char),
ty::ty_int(ast::TyI) => Primitive(Int),
}
}
- ty::ty_unboxed_closure(..) => Primitive(Unit), // FIXME(pcwalton)
+ ty::ty_unboxed_closure(..) => Tuple(vec![]), // FIXME(pcwalton)
ty::ty_infer(..) => panic!("ty_infer"),
ty::ty_open(..) => panic!("ty_open"),
ast::LitFloat(ref f, _t) => f.get().to_string(),
ast::LitFloatUnsuffixed(ref f) => f.get().to_string(),
ast::LitBool(b) => b.to_string(),
- ast::LitNil => "".to_string(),
}
}
format!("<{:#}>", decl.lifetimes)
},
args = decl.decl.inputs,
- arrow = match decl.decl.output {
- clean::Primitive(clean::Unit) => "".to_string(),
- _ => format!(" -> {}", decl.decl.output),
- },
+ arrow = decl.decl.output,
bounds = {
let mut ret = String::new();
for bound in decl.bounds.iter() {
": {}",
m.collect::<Vec<String>>().connect(" + "))
},
- arrow = match decl.decl.output {
- clean::Primitive(clean::Unit) => "".to_string(),
- _ => format!(" -> {}", decl.decl.output)
- })
+ arrow = decl.decl.output)
}
clean::BareFunction(ref decl) => {
write!(f, "{}{}fn{}{}",
}
}
+impl fmt::Show for clean::FunctionRetTy {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match *self {
+ clean::Return(clean::Tuple(ref tys)) if tys.is_empty() => Ok(()),
+ clean::Return(ref ty) => write!(f, " -> {}", ty),
+ clean::NoReturn => write!(f, " -> !")
+ }
+ }
+}
+
impl fmt::Show for clean::FnDecl {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "({args}){arrow}",
- args = self.inputs,
- arrow = match self.output {
- clean::Primitive(clean::Unit) => "".to_string(),
- _ => format!(" -> {}", self.output),
- })
+ write!(f, "({args}){arrow}", args = self.inputs, arrow = self.output)
}
}
}
args.push_str(format!("{}", input.type_).as_slice());
}
- write!(f, "({args}){arrow}",
- args = args,
- arrow = match d.output {
- clean::Primitive(clean::Unit) => "".to_string(),
- _ => format!(" -> {}", d.output),
- })
+ write!(f, "({args}){arrow}", args = args, arrow = d.output)
}
}
LitInt(u64, LitIntType),
LitFloat(InternedString, FloatTy),
LitFloatUnsuffixed(InternedString),
- LitNil,
LitBool(bool),
}
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
/// The different kinds of types recognized by the compiler
pub enum Ty_ {
- /// The unit type (`()`)
- TyNil,
- /// The bottom type (`!`)
- TyBot,
- TyUniq(P<Ty>),
- /// An array (`[T]`)
TyVec(P<Ty>),
/// A fixed length array (`[T, ..n]`)
TyFixedLengthVec(P<Ty>, P<Expr>),
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
pub struct FnDecl {
pub inputs: Vec<Arg>,
- pub output: P<Ty>,
- pub cf: RetStyle,
+ pub output: FunctionRetTy,
pub variadic: bool
}
}
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
-pub enum RetStyle {
+pub enum FunctionRetTy {
/// Functions with return type ! that always
/// raise an error or exit (i.e. never return to the caller)
- NoReturn,
+ NoReturn(Span),
/// Everything else
- Return,
+ Return(P<Ty>),
+}
+
+impl FunctionRetTy {
+ pub fn span(&self) -> Span {
+ match *self {
+ NoReturn(span) => span,
+ Return(ref ty) => ty.span
+ }
+ }
}
/// Represents the kind of 'self' associated with a method
pub fn raw_expr(sp: Span) -> P<ast::Expr> {
P(ast::Expr {
id: ast::DUMMY_NODE_ID,
- node: ast::ExprLit(P(codemap::respan(sp, ast::LitNil))),
+ node: ast::ExprLit(P(codemap::respan(sp, ast::LitBool(false)))),
span: sp,
})
}
fn ty_ptr(&self, span: Span,
ty: P<ast::Ty>,
mutbl: ast::Mutability) -> P<ast::Ty>;
- fn ty_uniq(&self, span: Span, ty: P<ast::Ty>) -> P<ast::Ty>;
fn ty_option(&self, ty: P<ast::Ty>) -> P<ast::Ty>;
fn ty_infer(&self, sp: Span) -> P<ast::Ty>;
- fn ty_nil(&self) -> P<ast::Ty>;
fn ty_vars(&self, ty_params: &OwnedSlice<ast::TyParam>) -> Vec<P<ast::Ty>> ;
fn ty_vars_global(&self, ty_params: &OwnedSlice<ast::TyParam>) -> Vec<P<ast::Ty>> ;
self.ty(span,
ast::TyPtr(self.ty_mt(ty, mutbl)))
}
- fn ty_uniq(&self, span: Span, ty: P<ast::Ty>) -> P<ast::Ty> {
- self.ty(span, ast::TyUniq(ty))
- }
fn ty_option(&self, ty: P<ast::Ty>) -> P<ast::Ty> {
self.ty_path(
self.ty(span, ast::TyInfer)
}
- fn ty_nil(&self) -> P<ast::Ty> {
- P(ast::Ty {
- id: ast::DUMMY_NODE_ID,
- node: ast::TyNil,
- span: DUMMY_SP,
- })
- }
-
fn typaram(&self,
span: Span,
id: ast::Ident,
self.pat(span, pat)
}
fn pat_tuple(&self, span: Span, pats: Vec<P<ast::Pat>>) -> P<ast::Pat> {
- let pat = ast::PatTup(pats);
- self.pat(span, pat)
+ self.pat(span, ast::PatTup(pats))
}
fn pat_some(&self, span: Span, pat: P<ast::Pat>) -> P<ast::Pat> {
}
// FIXME unused self
- fn fn_decl(&self, inputs: Vec<ast::Arg> , output: P<ast::Ty>) -> P<ast::FnDecl> {
+ fn fn_decl(&self, inputs: Vec<ast::Arg>, output: P<ast::Ty>) -> P<ast::FnDecl> {
P(ast::FnDecl {
inputs: inputs,
- output: output,
- cf: ast::Return,
+ output: ast::Return(output),
variadic: false
})
}
ast::LitInt(i, ast::UnsuffixedIntLit(ast::Minus)) => {
accumulator.push_str(format!("-{}", i).as_slice());
}
- ast::LitNil => {}
ast::LitBool(b) => {
accumulator.push_str(format!("{}", b).as_slice());
}
//! }
//! ```
-use ast::{MetaItem, Item, Expr, ExprRet, MutMutable, LitNil};
+use ast::{MetaItem, Item, Expr, ExprRet, MutMutable};
use codemap::Span;
use ext::base::ExtCtxt;
use ext::build::AstBuilder;
if stmts.is_empty() {
let ret_ok = cx.expr(trait_span,
ExprRet(Some(cx.expr_ok(trait_span,
- cx.expr_lit(trait_span, LitNil)))));
+ cx.expr_tuple(trait_span, vec![])))));
stmts.push(cx.stmt_expr(ret_ok));
}
if stmts.len() == 0 {
let ret_ok = cx.expr(trait_span,
ExprRet(Some(cx.expr_ok(trait_span,
- cx.expr_lit(trait_span, LitNil)))));
+ cx.expr_tuple(trait_span, vec![])))));
stmts.push(cx.stmt_expr(ret_ok));
}
}
// Here is the pat = `(&VariantK, &VariantK, ...)`
- let single_pat = cx.pat(sp, ast::PatTup(subpats));
+ let single_pat = cx.pat_tuple(sp, subpats);
// For the BodyK, we need to delegate to our caller,
// passing it an EnumMatching to indicate which case
cx.ty_path(self.to_path(cx, span, self_ty, self_generics), None)
}
Tuple(ref fields) => {
- let ty = if fields.is_empty() {
- ast::TyNil
- } else {
- ast::TyTup(fields.iter()
- .map(|f| f.to_ty(cx, span, self_ty, self_generics))
- .collect())
- };
-
+ let ty = ast::TyTup(fields.iter()
+ .map(|f| f.to_ty(cx, span, self_ty, self_generics))
+ .collect());
cx.ty(span, ty)
}
}
// `_ => [<elseopt> | ()]`
let else_arm = {
let pat_under = fld.cx.pat_wild(span);
- let else_expr = elseopt.unwrap_or_else(|| fld.cx.expr_lit(span, ast::LitNil));
+ let else_expr = elseopt.unwrap_or_else(|| fld.cx.expr_tuple(span, vec![]));
fld.cx.arm(span, vec![pat_under], else_expr)
};
//
// But the nested match expression is proved to perform not as well
// as series of let's; the first approach does.
- let pat = self.ecx.pat(self.fmtsp, ast::PatTup(pats));
+ let pat = self.ecx.pat_tuple(self.fmtsp, pats);
let arm = self.ecx.arm(self.fmtsp, vec!(pat), body);
let head = self.ecx.expr(self.fmtsp, ast::ExprTup(heads));
self.ecx.expr_match(self.fmtsp, head, vec!(arm))
t.map(|Ty {id, node, span}| Ty {
id: fld.new_id(id),
node: match node {
- TyNil | TyBot | TyInfer => node,
- TyUniq(ty) => TyUniq(fld.fold_ty(ty)),
+ TyInfer => node,
TyVec(ty) => TyVec(fld.fold_ty(ty)),
TyPtr(mt) => TyPtr(fld.fold_mt(mt)),
TyRptr(region, mt) => {
}
pub fn noop_fold_fn_decl<T: Folder>(decl: P<FnDecl>, fld: &mut T) -> P<FnDecl> {
- decl.map(|FnDecl {inputs, output, cf, variadic}| FnDecl {
+ decl.map(|FnDecl {inputs, output, variadic}| FnDecl {
inputs: inputs.move_map(|x| fld.fold_arg(x)),
- output: fld.fold_ty(output),
- cf: cf,
+ output: match output {
+ Return(ty) => Return(fld.fold_ty(ty)),
+ NoReturn(span) => NoReturn(span)
+ },
variadic: variadic
})
}
attrs: attrs.move_map(|x| folder.fold_attribute(x)),
node: match node {
ForeignItemFn(fdec, generics) => {
- ForeignItemFn(fdec.map(|FnDecl {inputs, output, cf, variadic}| FnDecl {
+ ForeignItemFn(fdec.map(|FnDecl {inputs, output, variadic}| FnDecl {
inputs: inputs.move_map(|a| folder.fold_arg(a)),
- output: folder.fold_ty(output),
- cf: cf,
+ output: match output {
+ Return(ty) => Return(folder.fold_ty(ty)),
+ NoReturn(span) => NoReturn(span)
+ },
variadic: variadic
}), folder.fold_generics(generics))
}
html_root_url = "http://doc.rust-lang.org/nightly/")]
#![allow(unknown_features)]
-#![feature(macro_rules, globs, default_type_params, phase, slicing_syntax)]
+#![feature(if_let, macro_rules, globs, default_type_params, phase, slicing_syntax)]
#![feature(quote, struct_variant, unsafe_destructor, import_shadowing)]
extern crate arena;
}),
id: ast::DUMMY_NODE_ID
}),
- output: P(ast::Ty{id: ast::DUMMY_NODE_ID,
- node: ast::TyNil,
- span:sp(15,15)}), // not sure
- cf: ast::Return,
+ output: ast::Return(P(ast::Ty{id: ast::DUMMY_NODE_ID,
+ node: ast::TyTup(vec![]),
+ span:sp(15,15)})), // not sure
variadic: false
}),
ast::NormalFn,
removed.
*/
-use ast::{Expr, ExprLit, LitNil};
-use codemap::{Span, respan};
+use ast::{Expr, ExprTup};
+use codemap::Span;
use parse::parser;
use parse::token;
use ptr::P;
/// a placeholder expression
fn obsolete_expr(&mut self, sp: Span, kind: ObsoleteSyntax) -> P<Expr> {
self.obsolete(sp, kind);
- self.mk_expr(sp.lo, sp.hi, ExprLit(P(respan(sp, LitNil))))
+ self.mk_expr(sp.lo, sp.hi, ExprTup(vec![]))
}
fn report(&mut self,
use ast::{Once, Many};
use ast::{FnUnboxedClosureKind, FnMutUnboxedClosureKind};
use ast::{FnOnceUnboxedClosureKind};
-use ast::{ForeignItem, ForeignItemStatic, ForeignItemFn, ForeignMod};
+use ast::{ForeignItem, ForeignItemStatic, ForeignItemFn, ForeignMod, FunctionRetTy};
use ast::{Ident, NormalFn, Inherited, ImplItem, Item, Item_, ItemStatic};
use ast::{ItemEnum, ItemFn, ItemForeignMod, ItemImpl, ItemConst};
use ast::{ItemMac, ItemMod, ItemStruct, ItemTrait, ItemTy};
use ast::{LifetimeDef, Lit, Lit_};
use ast::{LitBool, LitChar, LitByte, LitBinary};
-use ast::{LitNil, LitStr, LitInt, Local, LocalLet};
+use ast::{LitStr, LitInt, Local, LocalLet};
use ast::{MutImmutable, MutMutable, Mac_, MacInvocTT, MatchNormal};
use ast::{Method, MutTy, BiMul, Mutability};
use ast::{MethodImplItem, NamedField, UnNeg, NoReturn, UnNot};
use ast::{PatTup, PatBox, PatWild, PatWildMulti, PatWildSingle};
use ast::{PolyTraitRef};
use ast::{QPath, RequiredMethod};
-use ast::{RetStyle, Return, BiShl, BiShr, Stmt, StmtDecl};
+use ast::{Return, BiShl, BiShr, Stmt, StmtDecl};
use ast::{StmtExpr, StmtSemi, StmtMac, StructDef, StructField};
use ast::{StructVariantKind, BiSub};
use ast::StrStyle;
use ast::{SelfExplicit, SelfRegion, SelfStatic, SelfValue};
use ast::{Delimited, SequenceRepetition, TokenTree, TraitItem, TraitRef};
use ast::{TtDelimited, TtSequence, TtToken};
-use ast::{TupleVariantKind, Ty, Ty_, TyBot};
+use ast::{TupleVariantKind, Ty, Ty_};
use ast::{TypeField, TyFixedLengthVec, TyClosure, TyProc, TyBareFn};
use ast::{TyTypeof, TyInfer, TypeMethod};
-use ast::{TyNil, TyParam, TyParamBound, TyParen, TyPath, TyPolyTraitRef, TyPtr, TyQPath};
-use ast::{TyRptr, TyTup, TyU32, TyUniq, TyVec, UnUniq};
+use ast::{TyParam, TyParamBound, TyParen, TyPath, TyPolyTraitRef, TyPtr, TyQPath};
+use ast::{TyRptr, TyTup, TyU32, TyVec, UnUniq};
use ast::{TypeImplItem, TypeTraitItem, Typedef, UnboxedClosureKind};
use ast::{UnnamedField, UnsafeBlock};
use ast::{UnsafeFn, ViewItem, ViewItem_, ViewItemExternCrate, ViewItemUse};
self.expect_keyword(keywords::Fn);
let lifetime_defs = self.parse_legacy_lifetime_defs(lifetime_defs);
let (inputs, variadic) = self.parse_fn_args(false, true);
- let (ret_style, ret_ty) = self.parse_ret_ty();
+ let ret_ty = self.parse_ret_ty();
let decl = P(FnDecl {
inputs: inputs,
output: ret_ty,
- cf: ret_style,
variadic: variadic
});
TyBareFn(P(BareFnTy {
let lifetime_defs = self.parse_legacy_lifetime_defs(lifetime_defs);
let (inputs, variadic) = self.parse_fn_args(false, false);
let bounds = self.parse_colon_then_ty_param_bounds();
- let (ret_style, ret_ty) = self.parse_ret_ty();
+ let ret_ty = self.parse_ret_ty();
let decl = P(FnDecl {
inputs: inputs,
output: ret_ty,
- cf: ret_style,
variadic: variadic
});
TyProc(P(ClosureTy {
let bounds = self.parse_colon_then_ty_param_bounds();
- let (return_style, output) = self.parse_ret_ty();
+ let output = self.parse_ret_ty();
let decl = P(FnDecl {
inputs: inputs,
output: output,
- cf: return_style,
variadic: false
});
}
/// Parse optional return type [ -> TY ] in function decl
- pub fn parse_ret_ty(&mut self) -> (RetStyle, P<Ty>) {
- return if self.eat(&token::RArrow) {
- let lo = self.span.lo;
+ pub fn parse_ret_ty(&mut self) -> FunctionRetTy {
+ if self.eat(&token::RArrow) {
if self.eat(&token::Not) {
- (
- NoReturn,
- P(Ty {
- id: ast::DUMMY_NODE_ID,
- node: TyBot,
- span: mk_sp(lo, self.last_span.hi)
- })
- )
+ NoReturn(self.span)
} else {
- (Return, self.parse_ty(true))
+ Return(self.parse_ty(true))
}
} else {
let pos = self.span.lo;
- (
- Return,
- P(Ty {
- id: ast::DUMMY_NODE_ID,
- node: TyNil,
- span: mk_sp(pos, pos),
- })
- )
+ Return(P(Ty {
+ id: ast::DUMMY_NODE_ID,
+ node: TyTup(vec![]),
+ span: mk_sp(pos, pos),
+ }))
}
}
let t = if self.token == token::OpenDelim(token::Paren) {
self.bump();
- if self.token == token::CloseDelim(token::Paren) {
- self.bump();
- TyNil
- } else {
- // (t) is a parenthesized ty
- // (t,) is the type of a tuple with only one field,
- // of type t
- let mut ts = vec!(self.parse_ty(true));
- let mut one_tuple = false;
- while self.token == token::Comma {
- self.bump();
- if self.token != token::CloseDelim(token::Paren) {
- ts.push(self.parse_ty(true));
- }
- else {
- one_tuple = true;
- }
- }
- if ts.len() == 1 && !one_tuple {
- self.expect(&token::CloseDelim(token::Paren));
- TyParen(ts.into_iter().nth(0).unwrap())
+ // (t) is a parenthesized ty
+ // (t,) is the type of a tuple with only one field,
+ // of type t
+ let mut ts = vec![];
+ let mut last_comma = false;
+ while self.token != token::CloseDelim(token::Paren) {
+ ts.push(self.parse_ty(true));
+ if self.token == token::Comma {
+ last_comma = true;
+ self.bump();
} else {
- let t = TyTup(ts);
- self.expect(&token::CloseDelim(token::Paren));
- t
+ last_comma = false;
+ break;
}
}
+
+ self.expect(&token::CloseDelim(token::Paren));
+ if ts.len() == 1 && !last_comma {
+ TyParen(ts.into_iter().nth(0).unwrap())
+ } else {
+ TyTup(ts)
+ }
} else if self.token == token::Tilde {
// OWNED POINTER
self.bump();
token::OpenDelim(token::Bracket) => self.obsolete(last_span, ObsoleteOwnedVector),
_ => self.obsolete(last_span, ObsoleteOwnedType)
}
- TyUniq(self.parse_ty(false))
+ TyTup(vec![self.parse_ty(false)])
} else if self.token == token::BinOp(token::Star) {
// STAR POINTER (bare pointer?)
self.bump();
LitBinary(parse::binary_lit(i.as_str())),
token::LitBinaryRaw(i, _) =>
LitBinary(Rc::new(i.as_str().as_bytes().iter().map(|&x| x).collect())),
- token::OpenDelim(token::Paren) => {
- self.expect(&token::CloseDelim(token::Paren));
- LitNil
- },
_ => { self.unexpected_last(tok); }
}
}
match self.token {
token::OpenDelim(token::Paren) => {
self.bump();
+
// (e) is parenthesized e
// (e,) is a tuple with only one field, e
+ let mut es = vec![];
let mut trailing_comma = false;
- if self.token == token::CloseDelim(token::Paren) {
- hi = self.span.hi;
- self.bump();
- let lit = P(spanned(lo, hi, LitNil));
- return self.mk_expr(lo, hi, ExprLit(lit));
- }
- let mut es = vec!(self.parse_expr());
- self.commit_expr(&**es.last().unwrap(), &[],
- &[token::Comma, token::CloseDelim(token::Paren)]);
- while self.token == token::Comma {
- self.bump();
- if self.token != token::CloseDelim(token::Paren) {
- es.push(self.parse_expr());
- self.commit_expr(&**es.last().unwrap(), &[],
- &[token::Comma, token::CloseDelim(token::Paren)]);
- } else {
+ while self.token != token::CloseDelim(token::Paren) {
+ es.push(self.parse_expr());
+ self.commit_expr(&**es.last().unwrap(), &[],
+ &[token::Comma, token::CloseDelim(token::Paren)]);
+ if self.token == token::Comma {
trailing_comma = true;
+
+ self.bump();
+ } else {
+ trailing_comma = false;
+ break;
}
}
- hi = self.span.hi;
- self.commit_expr_expecting(&**es.last().unwrap(), token::CloseDelim(token::Paren));
+ self.bump();
+ hi = self.span.hi;
return if es.len() == 1 && !trailing_comma {
- self.mk_expr(lo, hi, ExprParen(es.into_iter().nth(0).unwrap()))
+ self.mk_expr(lo, hi, ExprParen(es.into_iter().nth(0).unwrap()))
} else {
self.mk_expr(lo, hi, ExprTup(es))
}
// parse (pat,pat,pat,...) as tuple
self.bump();
if self.token == token::CloseDelim(token::Paren) {
- hi = self.span.hi;
self.bump();
- let lit = P(codemap::Spanned {
- node: LitNil,
- span: mk_sp(lo, hi)});
- let expr = self.mk_expr(lo, hi, ExprLit(lit));
- pat = PatLit(expr);
+ pat = PatTup(vec![]);
} else {
let mut fields = vec!(self.parse_pat());
if self.look_ahead(1, |t| *t != token::CloseDelim(token::Paren)) {
pub fn parse_fn_decl(&mut self, allow_variadic: bool) -> P<FnDecl> {
let (args, variadic) = self.parse_fn_args(true, allow_variadic);
- let (ret_style, ret_ty) = self.parse_ret_ty();
+ let ret_ty = self.parse_ret_ty();
P(FnDecl {
inputs: args,
output: ret_ty,
- cf: ret_style,
variadic: variadic
})
}
let hi = self.span.hi;
- let (ret_style, ret_ty) = self.parse_ret_ty();
+ let ret_ty = self.parse_ret_ty();
let fn_decl = P(FnDecl {
inputs: fn_inputs,
output: ret_ty,
- cf: ret_style,
variadic: false
});
(optional_unboxed_closure_kind, args)
}
};
- let (style, output) = if self.token == token::RArrow {
+ let output = if self.token == token::RArrow {
self.parse_ret_ty()
} else {
- (Return, P(Ty {
+ Return(P(Ty {
id: ast::DUMMY_NODE_ID,
node: TyInfer,
span: self.span,
(P(FnDecl {
inputs: inputs_captures,
output: output,
- cf: style,
variadic: false
}), optional_unboxed_closure_kind)
}
seq_sep_trailing_allowed(token::Comma),
|p| p.parse_fn_block_arg());
- let (style, output) = if self.token == token::RArrow {
+ let output = if self.token == token::RArrow {
self.parse_ret_ty()
} else {
- (Return, P(Ty {
+ Return(P(Ty {
id: ast::DUMMY_NODE_ID,
node: TyInfer,
span: self.span,
P(FnDecl {
inputs: inputs,
output: output,
- cf: style,
variadic: false
})
}
try!(self.maybe_print_comment(ty.span.lo));
try!(self.ibox(0u));
match ty.node {
- ast::TyNil => try!(word(&mut self.s, "()")),
- ast::TyBot => try!(word(&mut self.s, "!")),
- ast::TyUniq(ref ty) => {
- try!(word(&mut self.s, "~"));
- try!(self.print_type(&**ty));
- }
ast::TyVec(ref ty) => {
try!(word(&mut self.s, "["));
try!(self.print_type(&**ty));
}
try!(self.pclose());
- try!(self.maybe_print_comment(decl.output.span.lo));
- match decl.output.node {
- ast::TyNil => Ok(()),
- _ => {
- try!(self.space_if_not_bol());
- try!(self.word_space("->"));
- self.print_type(&*decl.output)
- }
- }
+ self.print_fn_output(decl)
}
pub fn print_fn_block_args(
try!(self.print_fn_args(decl, None));
try!(word(&mut self.s, "|"));
- match decl.output.node {
- ast::TyInfer => {}
- _ => {
- try!(self.space_if_not_bol());
- try!(self.word_space("->"));
- try!(self.print_type(&*decl.output));
+ if let ast::Return(ref ty) = decl.output {
+ if ty.node == ast::TyInfer {
+ return self.maybe_print_comment(ty.span.lo);
}
}
- self.maybe_print_comment(decl.output.span.lo)
+ try!(self.space_if_not_bol());
+ try!(self.word_space("->"));
+ match decl.output {
+ ast::Return(ref ty) => {
+ try!(self.print_type(&**ty));
+ self.maybe_print_comment(ty.span.lo)
+ }
+ ast::NoReturn(span) => {
+ try!(self.word_nbsp("!"));
+ self.maybe_print_comment(span.lo)
+ }
+ }
}
pub fn print_capture_clause(&mut self, capture_clause: ast::CaptureClause)
try!(self.print_fn_args(decl, None));
try!(word(&mut self.s, ")"));
- match decl.output.node {
- ast::TyInfer => {}
- _ => {
- try!(self.space_if_not_bol());
- try!(self.word_space("->"));
- try!(self.print_type(&*decl.output));
+ if let ast::Return(ref ty) = decl.output {
+ if ty.node == ast::TyInfer {
+ return self.maybe_print_comment(ty.span.lo);
}
}
- self.maybe_print_comment(decl.output.span.lo)
+ try!(self.space_if_not_bol());
+ try!(self.word_space("->"));
+ match decl.output {
+ ast::Return(ref ty) => {
+ try!(self.print_type(&**ty));
+ self.maybe_print_comment(ty.span.lo)
+ }
+ ast::NoReturn(span) => {
+ try!(self.word_nbsp("!"));
+ self.maybe_print_comment(span.lo)
+ }
+ }
}
pub fn print_bounds(&mut self,
}
pub fn print_fn_output(&mut self, decl: &ast::FnDecl) -> IoResult<()> {
- match decl.output.node {
- ast::TyNil => Ok(()),
- _ => {
- try!(self.space_if_not_bol());
- try!(self.ibox(indent_unit));
- try!(self.word_space("->"));
- if decl.cf == ast::NoReturn {
- try!(self.word_nbsp("!"));
- } else {
- try!(self.print_type(&*decl.output));
+ if let ast::Return(ref ty) = decl.output {
+ match ty.node {
+ ast::TyTup(ref tys) if tys.is_empty() => {
+ return self.maybe_print_comment(ty.span.lo);
}
- self.end()
+ _ => ()
}
}
+
+ try!(self.space_if_not_bol());
+ try!(self.ibox(indent_unit));
+ try!(self.word_space("->"));
+ match decl.output {
+ ast::NoReturn(_) =>
+ try!(self.word_nbsp("!")),
+ ast::Return(ref ty) =>
+ try!(self.print_type(&**ty))
+ }
+ try!(self.end());
+
+ match decl.output {
+ ast::Return(ref output) => self.maybe_print_comment(output.span.lo),
+ _ => Ok(())
+ }
}
pub fn print_ty_fn(&mut self,
try!(self.print_bounds(":", bounds));
- try!(self.maybe_print_comment(decl.output.span.lo));
-
try!(self.print_fn_output(decl));
match generics {
ast_util::float_ty_to_string(t).as_slice()).as_slice())
}
ast::LitFloatUnsuffixed(ref f) => word(&mut self.s, f.get()),
- ast::LitNil => word(&mut self.s, "()"),
ast::LitBool(val) => {
if val { word(&mut self.s, "true") } else { word(&mut self.s, "false") }
}
let decl = ast::FnDecl {
inputs: Vec::new(),
- output: P(ast::Ty {id: 0,
- node: ast::TyNil,
- span: codemap::DUMMY_SP}),
- cf: ast::Return,
+ output: ast::Return(P(ast::Ty {id: 0,
+ node: ast::TyTup(vec![]),
+ span: codemap::DUMMY_SP})),
variadic: false
};
let generics = ast_util::empty_generics();
fn has_test_signature(i: &ast::Item) -> HasTestSignature {
match &i.node {
&ast::ItemFn(ref decl, _, _, ref generics, _) => {
- let no_output = match decl.output.node {
- ast::TyNil => true,
- _ => false,
+ let no_output = match decl.output {
+ ast::Return(ref ret_ty) => match ret_ty.node {
+ ast::TyTup(ref tys) if tys.is_empty() => true,
+ _ => false,
+ },
+ ast::NoReturn(_) => false
};
if decl.inputs.is_empty()
&& no_output
match i.node {
ast::ItemFn(ref decl, _, _, ref generics, _) => {
let input_cnt = decl.inputs.len();
- let no_output = match decl.output.node {
- ast::TyNil => true,
- _ => false
+ let no_output = match decl.output {
+ ast::Return(ref ret_ty) => match ret_ty.node {
+ ast::TyTup(ref tys) if tys.is_empty() => true,
+ _ => false,
+ },
+ ast::NoReturn(_) => false
};
let tparm_cnt = generics.ty_params.len();
// NB: inadequate check, but we're running
pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
match typ.node {
- TyUniq(ref ty) | TyVec(ref ty) | TyParen(ref ty) => {
+ TyVec(ref ty) | TyParen(ref ty) => {
visitor.visit_ty(&**ty)
}
TyPtr(ref mutable_type) => {
for argument in function_declaration.decl.inputs.iter() {
visitor.visit_ty(&*argument.ty)
}
- visitor.visit_ty(&*function_declaration.decl.output);
+ walk_fn_ret_ty(visitor, &function_declaration.decl.output);
walk_ty_param_bounds(visitor, &function_declaration.bounds);
walk_lifetime_decls(visitor, &function_declaration.lifetimes);
}
for argument in function_declaration.decl.inputs.iter() {
visitor.visit_ty(&*argument.ty)
}
- visitor.visit_ty(&*function_declaration.decl.output);
+ walk_fn_ret_ty(visitor, &function_declaration.decl.output);
walk_ty_param_bounds(visitor, &function_declaration.bounds);
walk_lifetime_decls(visitor, &function_declaration.lifetimes);
}
for argument in function_declaration.decl.inputs.iter() {
visitor.visit_ty(&*argument.ty)
}
- visitor.visit_ty(&*function_declaration.decl.output);
+ walk_fn_ret_ty(visitor, &function_declaration.decl.output);
walk_lifetime_decls(visitor, &function_declaration.lifetimes);
}
TyPath(ref path, ref opt_bounds, id) => {
TyTypeof(ref expression) => {
visitor.visit_expr(&**expression)
}
- TyNil | TyBot | TyInfer => {}
+ TyInfer => {}
}
}
}
}
+pub fn walk_fn_ret_ty<'v, V: Visitor<'v>>(visitor: &mut V, ret_ty: &'v FunctionRetTy) {
+ if let Return(ref output_ty) = *ret_ty {
+ visitor.visit_ty(&**output_ty)
+ }
+}
+
pub fn walk_fn_decl<'v, V: Visitor<'v>>(visitor: &mut V, function_declaration: &'v FnDecl) {
for argument in function_declaration.inputs.iter() {
visitor.visit_pat(&*argument.pat);
visitor.visit_ty(&*argument.ty)
}
- visitor.visit_ty(&*function_declaration.output)
+ walk_fn_ret_ty(visitor, &function_declaration.output)
}
// Note: there is no visit_method() method in the visitor, instead override
visitor.visit_ty(&*argument_type.ty)
}
visitor.visit_generics(&method_type.generics);
- visitor.visit_ty(&*method_type.decl.output);
+ walk_fn_ret_ty(visitor, &method_type.decl.output);
for attr in method_type.attrs.iter() {
visitor.visit_attribute(attr);
}