diff --git a/src/items.rs b/src/items.rs index d1502d173dab..bbe51c73c400 100644 --- a/src/items.rs +++ b/src/items.rs @@ -80,11 +80,7 @@ impl Rewrite for ast::Local { impl<'a> FmtVisitor<'a> { pub fn format_foreign_mod(&mut self, fm: &ast::ForeignMod, span: Span) { - self.buffer.push_str("extern "); - - if fm.abi != abi::Abi::C { - self.buffer.push_str(&format!("{} ", fm.abi)); - } + self.buffer.push_str(&::utils::format_abi(fm.abi)); let snippet = self.snippet(span); let brace_pos = snippet.find_uncommented("{").unwrap() as u32; @@ -856,17 +852,14 @@ fn rewrite_fn_base(context: &RewriteContext, let mut result = String::with_capacity(1024); // Vis unsafety abi. result.push_str(format_visibility(vis)); + result.push_str(::utils::format_unsafety(unsafety)); - if let ast::Unsafety::Unsafe = unsafety { - result.push_str("unsafe "); - } if let ast::Constness::Const = constness { result.push_str("const "); } + if abi != abi::Rust { - result.push_str("extern "); - result.push_str(&abi.to_string()); - result.push(' '); + result.push_str(&::utils::format_abi(abi)); } // fn foo diff --git a/src/types.rs b/src/types.rs index 6d8ee483b14c..807f0f17a43b 100644 --- a/src/types.rs +++ b/src/types.rs @@ -8,9 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use syntax::ast::{self, Mutability}; +use syntax::ast::{self, Mutability, FunctionRetTy}; use syntax::print::pprust; use syntax::codemap::{self, Span, BytePos}; +use syntax::abi; use Indent; use lists::{format_item_list, itemize_list, format_fn_args}; @@ -214,43 +215,12 @@ fn rewrite_segment(expr_context: bool, format!("{}<{}>", separator, list_str) } ast::PathParameters::ParenthesizedParameters(ref data) => { - // 2 for () - let budget = try_opt!(width.checked_sub(2)); - // 1 for ( - let offset = offset + 1; - let list_lo = span_after(data.span, "(", context.codemap); - let items = itemize_list(context.codemap, - data.inputs.iter(), - ")", - |ty| ty.span.lo, - |ty| ty.span.hi, - |ty| ty.rewrite(context, budget, offset), - list_lo, - span_hi); - println!("got here"); - - let list_str = try_opt!(format_fn_args(items, budget, offset, context.config)); - - println!("got here 2"); - let output = match data.output { - Some(ref ty) => { - let budget = try_opt!(width.checked_sub(4)); - let type_str = try_opt!(ty.rewrite(context, budget, offset + 4)); - format!(" -> {}", type_str) - } - None => String::new(), - }; - - println!("got here 3"); - - let infix = if output.len() + list_str.len() > width { - format!("\n{}", (offset - 1).to_string(context.config)) - } else { - String::new() - }; - println!("({}){}{}", &list_str, &infix, &output); - - format!("({}){}{}", list_str, infix, output) + try_opt!(format_function_type(data.inputs.iter().map(|x| &**x), + data.output.as_ref().map(|x| &**x), + data.span, + context, + width, + offset)) } _ => String::new(), }; @@ -258,6 +228,49 @@ fn rewrite_segment(expr_context: bool, Some(format!("{}{}", segment.identifier, params)) } +fn format_function_type<'a, I>(inputs: I, + output: Option<&ast::Ty>, + span: Span, + context: &RewriteContext, + width: usize, + offset: Indent) + -> Option + where I: Iterator +{ + // 2 for () + let budget = try_opt!(width.checked_sub(2)); + // 1 for ( + let offset = offset + 1; + let list_lo = span_after(span, "(", context.codemap); + let items = itemize_list(context.codemap, + inputs, + ")", + |ty| ty.span.lo, + |ty| ty.span.hi, + |ty| ty.rewrite(context, budget, offset), + list_lo, + span.hi); + + let list_str = try_opt!(format_fn_args(items, budget, offset, context.config)); + + let output = match output { + Some(ref ty) => { + let budget = try_opt!(width.checked_sub(4)); + let type_str = try_opt!(ty.rewrite(context, budget, offset + 4)); + format!(" -> {}", type_str) + } + None => String::new(), + }; + + let infix = if output.len() + list_str.len() > width { + format!("\n{}", (offset - 1).to_string(context.config)) + } else { + String::new() + }; + + Some(format!("({}){}{}", list_str, infix, output)) +} + impl Rewrite for ast::WherePredicate { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { // TODO: dead spans? @@ -501,14 +514,47 @@ impl Rewrite for ast::Ty { None } } - ast::TyBareFn(ref bare_fn) => bare_fn.rewrite(context, width, offset), + ast::TyBareFn(ref bare_fn) => { + rewrite_bare_fn(bare_fn, self.span, context, width, offset) + } ast::TyMac(..) | ast::TyTypeof(..) => unreachable!(), } } } -impl Rewrite for ast::BareFnTy { - fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { - None +fn rewrite_bare_fn(bare_fn: &ast::BareFnTy, + span: Span, + context: &RewriteContext, + width: usize, + offset: Indent) + -> Option { + let mut result = String::with_capacity(128); + + result.push_str(&::utils::format_unsafety(bare_fn.unsafety)); + + if bare_fn.abi != abi::Rust { + result.push_str(&::utils::format_abi(bare_fn.abi)); } + + result.push_str("fn"); + + let output = match bare_fn.decl.output { + FunctionRetTy::Return(ref ty) => Some(&**ty), + FunctionRetTy::NoReturn(..) => None, + FunctionRetTy::DefaultReturn(..) => unreachable!(), + }; + + let budget = try_opt!(width.checked_sub(result.len())); + let indent = offset + result.len(); + + let rewrite = try_opt!(format_function_type(bare_fn.decl.inputs.iter().map(|x| &*(x.ty)), + output, + span, + context, + budget, + indent)); + + result.push_str(&rewrite); + + Some(result) } diff --git a/src/utils.rs b/src/utils.rs index 37dfb7569725..6170b0c5ee0f 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -12,6 +12,7 @@ use std::cmp::Ordering; use syntax::ast::{self, Visibility, Attribute, MetaItem, MetaItem_}; use syntax::codemap::{CodeMap, Span, BytePos}; +use syntax::abi; use Indent; use comment::FindUncommented; @@ -45,6 +46,14 @@ pub fn format_visibility(vis: Visibility) -> &'static str { } } +#[inline] +pub fn format_unsafety(unsafety: ast::Unsafety) -> &'static str { + match unsafety { + ast::Unsafety::Unsafe => "unsafe ", + ast::Unsafety::Normal => "", + } +} + #[inline] pub fn format_mutability(mutability: ast::Mutability) -> &'static str { match mutability { @@ -53,6 +62,12 @@ pub fn format_mutability(mutability: ast::Mutability) -> &'static str { } } +#[inline] +// FIXME(#451): include "C"? +pub fn format_abi(abi: abi::Abi) -> String { + format!("extern {} ", abi) +} + // The width of the first line in s. #[inline] pub fn first_line_width(s: &str) -> usize { diff --git a/tests/source/fn-simple.rs b/tests/source/fn-simple.rs index 4c216ec26b87..93c432244170 100644 --- a/tests/source/fn-simple.rs +++ b/tests/source/fn-simple.rs @@ -32,3 +32,12 @@ fn zzzzzzzzzzzzzzzzzzzz (selff: Type, mut handle: node::Handle>, Type, NodeType>) -> SearchStack<'a, K, V, Type, NodeType>{ } + +unsafe fn generic_call(cx: *mut JSContext, argc: libc::c_uint, vp: *mut JSVal, + is_lenient: bool, + call: unsafe extern fn(*const JSJitInfo, *mut JSContext, + HandleObject, *mut libc::c_void, u32, + *mut JSVal) + -> u8) { + let f: fn ( _ , _ ) -> _ = panic!() ; +} diff --git a/tests/target/extern.rs b/tests/target/extern.rs index 35475660bae7..ca8c43d8b2c6 100644 --- a/tests/target/extern.rs +++ b/tests/target/extern.rs @@ -1,5 +1,5 @@ -extern { +extern "C" { fn c_func(x: *mut *mut libc::c_void); fn c_func(x: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX, @@ -11,7 +11,7 @@ extern { pub fn bar(); } -extern { +extern "C" { fn DMR_GetDevice(pHDev: *mut HDEV, searchMode: DeviceSearchMode, pSearchString: *const c_char, @@ -28,7 +28,7 @@ extern "Rust" { pub static mut var: SomeType; } -extern { +extern "C" { fn syscall(number: libc::c_long, // comment 1 // comm 2 ... /* sup? */) @@ -37,7 +37,7 @@ extern { fn foo(x: *const c_char, ...) -> libc::c_long; } -extern { +extern "C" { pub fn freopen(filename: *const c_char, mode: *const c_char, mode2: *const c_char, diff --git a/tests/target/fn-simple.rs b/tests/target/fn-simple.rs index 6acb1a3e582f..e5de6b0f00d1 100644 --- a/tests/target/fn-simple.rs +++ b/tests/target/fn-simple.rs @@ -50,3 +50,17 @@ fn zzzzzzzzzzzzzzzzzzzz(selff: Type, NodeType>) -> SearchStack<'a, K, V, Type, NodeType> { } + +unsafe fn generic_call(cx: *mut JSContext, + argc: libc::c_uint, + vp: *mut JSVal, + is_lenient: bool, + call: unsafe extern "C" fn(*const JSJitInfo, + *mut JSContext, + HandleObject, + *mut libc::c_void, + u32, + *mut JSVal) + -> u8) { + let f: fn(_, _) -> _ = panic!(); +}