diff --git a/Makefile.in b/Makefile.in index 179ae1138d80b..9e87ce1d9e69a 100644 --- a/Makefile.in +++ b/Makefile.in @@ -277,7 +277,9 @@ endif # CTAGS building ifneq ($(strip $(findstring TAGS.emacs,$(MAKECMDGOALS)) \ - $(findstring TAGS.vi,$(MAKECMDGOALS))),) + $(findstring TAGS.vi,$(MAKECMDGOALS)) \ + $(findstring TAGS.rustc.emacs,$(MAKECMDGOALS)) \ + $(findstring TAGS.rustc.vi,$(MAKECMDGOALS))),) CFG_INFO := $(info cfg: including ctags rules) include $(CFG_SRC_DIR)mk/ctags.mk endif diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index 71ca5ccdc8dfb..8fb71295a88a6 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -23,6 +23,7 @@ use super::{Chain, Cycle, Cloned, Enumerate, Filter, FilterMap, FlatMap, Fuse, use super::ChainState; use super::{DoubleEndedIterator, ExactSizeIterator, Extend, FromIterator, IntoIterator}; +use super::ZipImpl; fn _assert_is_object_safe(_: &Iterator) {} @@ -383,7 +384,7 @@ pub trait Iterator { fn zip(self, other: U) -> Zip where Self: Sized, U: IntoIterator { - Zip{a: self, b: other.into_iter()} + Zip::new(self, other.into_iter()) } /// Takes a closure and creates an iterator which calls that closure on each diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index ae1e311682617..b866655bbd53d 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -301,7 +301,9 @@ use clone::Clone; use cmp; +use default::Default; use fmt; +use iter_private::TrustedRandomAccess; use ops::FnMut; use option::Option::{self, Some, None}; use usize; @@ -622,7 +624,8 @@ impl DoubleEndedIterator for Chain where #[stable(feature = "rust1", since = "1.0.0")] pub struct Zip { a: A, - b: B + b: B, + spec: <(A, B) as ZipImplData>::Data, } #[stable(feature = "rust1", since = "1.0.0")] @@ -631,29 +634,13 @@ impl Iterator for Zip where A: Iterator, B: Iterator type Item = (A::Item, B::Item); #[inline] - fn next(&mut self) -> Option<(A::Item, B::Item)> { - self.a.next().and_then(|x| { - self.b.next().and_then(|y| { - Some((x, y)) - }) - }) + fn next(&mut self) -> Option { + ZipImpl::next(self) } #[inline] fn size_hint(&self) -> (usize, Option) { - let (a_lower, a_upper) = self.a.size_hint(); - let (b_lower, b_upper) = self.b.size_hint(); - - let lower = cmp::min(a_lower, b_lower); - - let upper = match (a_upper, b_upper) { - (Some(x), Some(y)) => Some(cmp::min(x,y)), - (Some(x), None) => Some(x), - (None, Some(y)) => Some(y), - (None, None) => None - }; - - (lower, upper) + ZipImpl::size_hint(self) } } @@ -664,6 +651,61 @@ impl DoubleEndedIterator for Zip where { #[inline] fn next_back(&mut self) -> Option<(A::Item, B::Item)> { + ZipImpl::next_back(self) + } +} + +// Zip specialization trait +#[doc(hidden)] +trait ZipImpl { + type Item; + fn new(a: A, b: B) -> Self; + fn next(&mut self) -> Option; + fn size_hint(&self) -> (usize, Option); + fn next_back(&mut self) -> Option + where A: DoubleEndedIterator + ExactSizeIterator, + B: DoubleEndedIterator + ExactSizeIterator; +} + +// Zip specialization data members +#[doc(hidden)] +trait ZipImplData { + type Data: 'static + Clone + Default + fmt::Debug; +} + +#[doc(hidden)] +impl ZipImplData for T { + default type Data = (); +} + +// General Zip impl +#[doc(hidden)] +impl ZipImpl for Zip + where A: Iterator, B: Iterator +{ + type Item = (A::Item, B::Item); + default fn new(a: A, b: B) -> Self { + Zip { + a: a, + b: b, + spec: Default::default(), // unused + } + } + + #[inline] + default fn next(&mut self) -> Option<(A::Item, B::Item)> { + self.a.next().and_then(|x| { + self.b.next().and_then(|y| { + Some((x, y)) + }) + }) + } + + #[inline] + default fn next_back(&mut self) -> Option<(A::Item, B::Item)> + where A: DoubleEndedIterator + ExactSizeIterator, + B: DoubleEndedIterator + ExactSizeIterator + { let a_sz = self.a.len(); let b_sz = self.b.len(); if a_sz != b_sz { @@ -680,12 +722,106 @@ impl DoubleEndedIterator for Zip where _ => unreachable!(), } } + + #[inline] + default fn size_hint(&self) -> (usize, Option) { + let (a_lower, a_upper) = self.a.size_hint(); + let (b_lower, b_upper) = self.b.size_hint(); + + let lower = cmp::min(a_lower, b_lower); + + let upper = match (a_upper, b_upper) { + (Some(x), Some(y)) => Some(cmp::min(x,y)), + (Some(x), None) => Some(x), + (None, Some(y)) => Some(y), + (None, None) => None + }; + + (lower, upper) + } +} + +#[doc(hidden)] +#[derive(Default, Debug, Clone)] +struct ZipImplFields { + index: usize, + len: usize, +} + +#[doc(hidden)] +impl ZipImplData for (A, B) + where A: TrustedRandomAccess, B: TrustedRandomAccess +{ + type Data = ZipImplFields; +} + +#[doc(hidden)] +impl ZipImpl for Zip + where A: TrustedRandomAccess, B: TrustedRandomAccess +{ + fn new(a: A, b: B) -> Self { + let len = cmp::min(a.len(), b.len()); + Zip { + a: a, + b: b, + spec: ZipImplFields { + index: 0, + len: len, + } + } + } + + #[inline] + fn next(&mut self) -> Option<(A::Item, B::Item)> { + if self.spec.index < self.spec.len { + let i = self.spec.index; + self.spec.index += 1; + unsafe { + Some((self.a.get_unchecked(i), self.b.get_unchecked(i))) + } + } else { + None + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let len = self.spec.len - self.spec.index; + (len, Some(len)) + } + + #[inline] + fn next_back(&mut self) -> Option<(A::Item, B::Item)> + where A: DoubleEndedIterator + ExactSizeIterator, + B: DoubleEndedIterator + ExactSizeIterator + { + if self.spec.index < self.spec.len { + self.spec.len -= 1; + let i = self.spec.len; + unsafe { + Some((self.a.get_unchecked(i), self.b.get_unchecked(i))) + } + } else { + None + } + } } #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for Zip where A: ExactSizeIterator, B: ExactSizeIterator {} +#[doc(hidden)] +unsafe impl TrustedRandomAccess for Zip + where A: TrustedRandomAccess, + B: TrustedRandomAccess, +{ + unsafe fn get_unchecked(&mut self, i: usize) -> (A::Item, B::Item) { + (self.a.get_unchecked(i), self.b.get_unchecked(i)) + } + +} + /// An iterator that maps the values of `iter` with `f`. /// /// This `struct` is created by the [`map()`] method on [`Iterator`]. See its @@ -982,6 +1118,15 @@ impl DoubleEndedIterator for Enumerate where #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for Enumerate where I: ExactSizeIterator {} +#[doc(hidden)] +unsafe impl TrustedRandomAccess for Enumerate + where I: TrustedRandomAccess +{ + unsafe fn get_unchecked(&mut self, i: usize) -> (usize, I::Item) { + (self.count + i, self.iter.get_unchecked(i)) + } +} + /// An iterator with a `peek()` that returns an optional reference to the next /// element. /// diff --git a/src/libcore/iter_private.rs b/src/libcore/iter_private.rs new file mode 100644 index 0000000000000..effe43cc67cea --- /dev/null +++ b/src/libcore/iter_private.rs @@ -0,0 +1,27 @@ +// Copyright 2016 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + +use iter::ExactSizeIterator; + +/// An iterator whose items are random accessible efficiently +/// +/// # Safety +/// +/// The iterator's .len() and size_hint() must be exact. +/// +/// .get_unchecked() must return distinct mutable references for distinct +/// indices (if applicable), and must return a valid reference if index is in +/// 0..self.len(). +#[doc(hidden)] +pub unsafe trait TrustedRandomAccess : ExactSizeIterator { + unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item; +} + diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index f2a297b763028..db73f4759a5ff 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -156,4 +156,5 @@ pub mod hash; pub mod fmt; // note: does not need to be public +mod iter_private; mod tuple; diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index b6ae6fde1e35d..727c26ba9abd1 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -50,6 +50,7 @@ use result::Result::{Ok, Err}; use ptr; use mem; use marker::{Copy, Send, Sync, self}; +use iter_private::TrustedRandomAccess; #[repr(C)] struct Repr { @@ -1942,3 +1943,17 @@ macro_rules! impl_marker_for { impl_marker_for!(BytewiseEquality, u8 i8 u16 i16 u32 i32 u64 i64 usize isize char bool); + +#[doc(hidden)] +unsafe impl<'a, T> TrustedRandomAccess for Iter<'a, T> { + unsafe fn get_unchecked(&mut self, i: usize) -> &'a T { + &*self.ptr.offset(i as isize) + } +} + +#[doc(hidden)] +unsafe impl<'a, T> TrustedRandomAccess for IterMut<'a, T> { + unsafe fn get_unchecked(&mut self, i: usize) -> &'a mut T { + &mut *self.ptr.offset(i as isize) + } +} diff --git a/src/libcoretest/iter.rs b/src/libcoretest/iter.rs index 54fca291e5ec2..a2848faa105e9 100644 --- a/src/libcoretest/iter.rs +++ b/src/libcoretest/iter.rs @@ -13,6 +13,7 @@ use core::{i8, i16, isize}; use core::usize; use test::Bencher; +use test::black_box; #[test] fn test_lt() { @@ -1030,3 +1031,33 @@ fn bench_max(b: &mut Bencher) { it.map(scatter).max() }) } + +pub fn copy_zip(xs: &[u8], ys: &mut [u8]) { + for (a, b) in ys.iter_mut().zip(xs) { + *a = *b; + } +} + +pub fn add_zip(xs: &[f32], ys: &mut [f32]) { + for (a, b) in ys.iter_mut().zip(xs) { + *a += *b; + } +} + +#[bench] +fn bench_zip_copy(b: &mut Bencher) { + let source = vec![0u8; 16 * 1024]; + let mut dst = black_box(vec![0u8; 16 * 1024]); + b.iter(|| { + copy_zip(&source, &mut dst) + }) +} + +#[bench] +fn bench_zip_add(b: &mut Bencher) { + let source = vec![1.; 16 * 1024]; + let mut dst = vec![0.; 16 * 1024]; + b.iter(|| { + add_zip(&source, &mut dst) + }); +} diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 377863b016d85..d469191dc273b 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -576,7 +576,9 @@ impl<'a, 'v> Visitor<'v> for Resolver<'a> { self.visit_generics(&sig.generics); MethodRibKind(!sig.decl.has_self()) } - FnKind::Closure => ClosureRibKind(node_id), + FnKind::Closure => { + ClosureRibKind(node_id) + } }; self.resolve_function(rib_kind, declaration, block); } @@ -1617,6 +1619,8 @@ impl<'a> Resolver<'a> { this.visit_generics(generics); walk_list!(this, visit_ty_param_bound, bounds); + let mut types = Vec::new(); + let mut methods = Vec::new(); for trait_item in trait_items { match trait_item.node { TraitItemKind::Const(_, ref default) => { @@ -1631,6 +1635,12 @@ impl<'a> Resolver<'a> { visit::walk_trait_item(this, trait_item) } } + TraitItemKind::Type(..) => { + this.with_type_parameter_rib(NoTypeParameters, |this| { + visit::walk_trait_item(this, trait_item) + }); + types.push(format!("{}", trait_item.ident)); + } TraitItemKind::Method(ref sig, _) => { let type_parameters = HasTypeParameters(&sig.generics, @@ -1639,14 +1649,38 @@ impl<'a> Resolver<'a> { this.with_type_parameter_rib(type_parameters, |this| { visit::walk_trait_item(this, trait_item) }); - } - TraitItemKind::Type(..) => { - this.with_type_parameter_rib(NoTypeParameters, |this| { - visit::walk_trait_item(this, trait_item) - }); + methods.push(sig.clone()); } }; } + if types.len() > 0 { + for method in methods { + for arg in method.decl.inputs.iter() { + if let Some(paths) = arg.ty.get_path() { + for path in paths { + if path.segments.len() == 2 && + &format!("{}", + path.segments[0].identifier) == "Self" { + let name = format!("{}", + path.segments[1].identifier); + let mut found = false; + for ty in types.iter() { + if ty == &name { + found = true; + break; + } + } + if found == false { + let error_variant = + ResolutionError::UndeclaredAssociatedType; + resolve_error(this, arg.ty.span, error_variant); + } + } + } + } + } + } + } }); }); } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index f7cc45a93b297..493d3d6abc9f9 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1656,12 +1656,8 @@ fn plain_summary_line(s: Option<&str>) -> String { } fn document(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item) -> fmt::Result { - for stability in short_stability(item, cx, true) { - write!(w, "
{}
", stability)?; - } - if let Some(s) = item.doc_value() { - write!(w, "
{}
", Markdown(s))?; - } + document_stability(w, cx, item)?; + document_full(w, item)?; Ok(()) } @@ -1678,6 +1674,20 @@ fn document_short(w: &mut fmt::Formatter, item: &clean::Item, link: AssocItemLin Ok(()) } +fn document_full(w: &mut fmt::Formatter, item: &clean::Item) -> fmt::Result { + if let Some(s) = item.doc_value() { + write!(w, "
{}
", Markdown(s))?; + } + Ok(()) +} + +fn document_stability(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item) -> fmt::Result { + for stability in short_stability(item, cx, true) { + write!(w, "
{}
", stability)?; + } + Ok(()) +} + fn item_module(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item, items: &[clean::Item]) -> fmt::Result { document(w, cx, item)?; @@ -2638,20 +2648,23 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi if !is_static || render_static { if !is_default_item { - - if item.doc_value().is_some() { - document(w, cx, item)?; - } else { - // In case the item isn't documented, - // provide short documentation from the trait - if let Some(t) = trait_ { - if let Some(it) = t.items.iter() - .find(|i| i.name == item.name) { - document_short(w, it, link)?; - } + if let Some(t) = trait_ { + let it = t.items.iter().find(|i| i.name == item.name).unwrap(); + // We need the stability of the item from the trait because + // impls can't have a stability. + document_stability(w, cx, it)?; + if item.doc_value().is_some() { + document_full(w, item)?; + } else { + // In case the item isn't documented, + // provide short documentation from the trait. + document_short(w, it, link)?; } + } else { + document(w, cx, item)?; } } else { + document_stability(w, cx, item)?; document_short(w, item, link)?; } } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 8537fcc221c95..c3138ea6b5a3b 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1578,6 +1578,32 @@ impl fmt::Debug for Ty { } } +impl Ty { + pub fn get_path(&self) -> Option> { + match self.node { + TyKind::Vec(ref p) | TyKind::FixedLengthVec(ref p, _) => p.get_path(), + TyKind::Ptr(ref p) | TyKind::Rptr(_, ref p) => p.ty.get_path(), + TyKind::Tup(ref v) => { + let mut res = Vec::new(); + for path in v { + if let Some(p) = path.get_path() { + for path in p { + res.push(path); + } + } + } + if res.len() > 0 { + Some(res) + } else { + None + } + } + TyKind::Path(_, ref p) => Some(vec!(p.clone())), + _ => None, + } + } +} + #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct BareFnTy { pub unsafety: Unsafety, diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 0c90e102f3425..e2c1b3fc45ba8 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1031,7 +1031,7 @@ impl<'a> State<'a> { try!(word(&mut self.s, "_")); } ast::TyKind::ImplicitSelf => { - unreachable!(); + try!(word(&mut self.s, "Self")); } ast::TyKind::Mac(ref m) => { try!(self.print_mac(m, token::Paren)); diff --git a/src/test/codegen/zip.rs b/src/test/codegen/zip.rs new file mode 100644 index 0000000000000..6c956364bf80f --- /dev/null +++ b/src/test/codegen/zip.rs @@ -0,0 +1,22 @@ +// Copyright 2016 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -C no-prepopulate-passes -O + +#![crate_type = "lib"] + +// CHECK-LABEL: @zip_copy +#[no_mangle] +pub fn zip_copy(xs: &[u8], ys: &mut [u8]) { +// CHECK: memcpy + for (x, y) in xs.iter().zip(ys) { + *y = *x; + } +} diff --git a/src/test/compile-fail/E0406.rs b/src/test/compile-fail/E0406.rs new file mode 100644 index 0000000000000..66f82f2c1a821 --- /dev/null +++ b/src/test/compile-fail/E0406.rs @@ -0,0 +1,23 @@ +// Copyright 2016 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +trait Foo { + type Bar; + type Bar2; + + fn return_bool(&self, &Self::Bar, &Self::Baz) -> bool; + //~^ ERROR E0406 + //~| ERROR E0220 + fn return_bool2(&self, &(u32, Self::Babar)) -> bool; + //~^ ERROR E0406 + //~| ERROR E0220 +} + +fn main() {} diff --git a/src/test/rustdoc/deprecated-impls.rs b/src/test/rustdoc/deprecated-impls.rs new file mode 100644 index 0000000000000..bcf0645766b30 --- /dev/null +++ b/src/test/rustdoc/deprecated-impls.rs @@ -0,0 +1,128 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_name = "foo"] + +// @has foo/struct.Foo0.html +pub struct Foo0; + +impl Foo0 { + // @has - '//*[@class="stab deprecated"]' 'Deprecated since 1.0.1: fn_with_doc' + // @has - 'fn_with_doc short' + // @has - 'fn_with_doc full' + /// fn_with_doc short + /// + /// fn_with_doc full + #[deprecated(since = "1.0.1", note = "fn_with_doc")] + pub fn fn_with_doc() {} + + // @has - '//*[@class="stab deprecated"]' 'Deprecated since 1.0.2: fn_without_doc' + #[deprecated(since = "1.0.2", note = "fn_without_doc")] + pub fn fn_without_doc() {} +} + +pub trait Bar { + /// fn_empty_with_doc short + /// + /// fn_empty_with_doc full + #[deprecated(since = "1.0.3", note = "fn_empty_with_doc")] + fn fn_empty_with_doc(); + + #[deprecated(since = "1.0.4", note = "fn_empty_without_doc")] + fn fn_empty_without_doc(); + + /// fn_def_with_doc short + /// + /// fn_def_with_doc full + #[deprecated(since = "1.0.5", note = "fn_def_with_doc")] + fn fn_def_with_doc() {} + + #[deprecated(since = "1.0.6", note = "fn_def_without_doc")] + fn fn_def_without_doc() {} + + /// fn_def_def_with_doc short + /// + /// fn_def_def_with_doc full + #[deprecated(since = "1.0.7", note = "fn_def_def_with_doc")] + fn fn_def_def_with_doc() {} + + #[deprecated(since = "1.0.8", note = "fn_def_def_without_doc")] + fn fn_def_def_without_doc() {} +} + +// @has foo/struct.Foo1.html +pub struct Foo1; + +impl Bar for Foo1 { + // @has - '//*[@class="stab deprecated"]' 'Deprecated since 1.0.3: fn_empty_with_doc' + // @has - 'fn_empty_with_doc_impl short' + // @has - 'fn_empty_with_doc_impl full' + /// fn_empty_with_doc_impl short + /// + /// fn_empty_with_doc_impl full + fn fn_empty_with_doc() {} + + // @has - '//*[@class="stab deprecated"]' 'Deprecated since 1.0.4: fn_empty_without_doc' + fn fn_empty_without_doc() {} + + // @has - '//*[@class="stab deprecated"]' 'Deprecated since 1.0.5: fn_def_with_doc' + // @has - 'fn_def_with_doc_impl short' + // @has - 'fn_def_with_doc_impl full' + /// fn_def_with_doc_impl short + /// + /// fn_def_with_doc_impl full + fn fn_def_with_doc() {} + + // @has - '//*[@class="stab deprecated"]' 'Deprecated since 1.0.6: fn_def_without_doc' + fn fn_def_without_doc() {} + + // @has - '//*[@class="stab deprecated"]' 'Deprecated since 1.0.7: fn_def_def_with_doc' + // @has - 'fn_def_def_with_doc short' + // @!has - 'fn_def_def_with_doc full' + + // @has - '//*[@class="stab deprecated"]' 'Deprecated since 1.0.8: fn_def_def_without_doc' +} + +// @has foo/struct.Foo2.html +pub struct Foo2; + +impl Bar for Foo2 { + // @has - '//*[@class="stab deprecated"]' 'Deprecated since 1.0.3: fn_empty_with_doc' + // @has - 'fn_empty_with_doc short' + // @!has - 'fn_empty_with_doc full' + fn fn_empty_with_doc() {} + + // @has - '//*[@class="stab deprecated"]' 'Deprecated since 1.0.4: fn_empty_without_doc' + // @has - 'fn_empty_without_doc_impl short' + // @has - 'fn_empty_without_doc_impl full' + /// fn_empty_without_doc_impl short + /// + /// fn_empty_without_doc_impl full + fn fn_empty_without_doc() {} + + // @has - '//*[@class="stab deprecated"]' 'Deprecated since 1.0.5: fn_def_with_doc' + // @has - 'fn_def_with_doc short' + // @!has - 'fn_def_with full' + fn fn_def_with_doc() {} + + // @has - '//*[@class="stab deprecated"]' 'Deprecated since 1.0.6: fn_def_without_doc' + // @has - 'fn_def_without_doc_impl short' + // @has - 'fn_def_without_doc_impl full' + /// fn_def_without_doc_impl short + /// + /// fn_def_without_doc_impl full + fn fn_def_without_doc() {} + + // @has - '//*[@class="stab deprecated"]' 'Deprecated since 1.0.7: fn_def_def_with_doc' + // @has - 'fn_def_def_with_doc short' + // @!has - 'fn_def_def_with_doc full' + + // @has - '//*[@class="stab deprecated"]' 'Deprecated since 1.0.8: fn_def_def_without_doc' +}