diff --git a/Cargo.lock b/Cargo.lock index f135dd0170bc1..a36df24359df7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,3 +1,5 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. [[package]] name = "adler32" version = "1.0.3" diff --git a/src/doc/embedded-book b/src/doc/embedded-book index d663113d1d9fb..bd2778f304989 160000 --- a/src/doc/embedded-book +++ b/src/doc/embedded-book @@ -1 +1 @@ -Subproject commit d663113d1d9fbd35f1145c29f6080a6350b7f419 +Subproject commit bd2778f304989ee52be8201504d6ec621dd60ca9 diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index d3eb8cb3d3b8a..3463cdb126cc6 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -1,9 +1,8 @@ # Unstable features Rustdoc is under active development, and like the Rust compiler, some features are only available -on the nightly releases. Some of these are new and need some more testing before they're able to get -released to the world at large, and some of them are tied to features in the Rust compiler that are -themselves unstable. Several features here require a matching `#![feature(...)]` attribute to +on nightly releases. Some of these features are new and need some more testing before they're able to be +released to the world at large, and some of them are tied to features in the Rust compiler that are unstable. Several features here require a matching `#![feature(...)]` attribute to enable, and thus are more fully documented in the [Unstable Book]. Those sections will link over there as necessary. @@ -428,4 +427,4 @@ $ rustdoc src/lib.rs --test -Z unstable-options --persist-doctests target/rustdo This flag allows you to keep doctest executables around after they're compiled or run. Usually, rustdoc will immediately discard a compiled doctest after it's been tested, but -with this option, you can keep those binaries around for farther testing. \ No newline at end of file +with this option, you can keep those binaries around for farther testing. diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs index 203be541e492f..d4a1d15e4e7e1 100644 --- a/src/libcore/convert.rs +++ b/src/libcore/convert.rs @@ -17,7 +17,10 @@ //! [`TryFrom`][`TryFrom`] rather than [`Into`][`Into`] or [`TryInto`][`TryInto`], //! as [`From`] and [`TryFrom`] provide greater flexibility and offer //! equivalent [`Into`] or [`TryInto`] implementations for free, thanks to a -//! blanket implementation in the standard library. +//! blanket implementation in the standard library. However, there are some cases +//! where this is not possible, such as creating conversions into a type defined +//! outside your library, so implementing [`Into`] instead of [`From`] is +//! sometimes necessary. //! //! # Generic Implementations //! diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 78f1c3c0dffa5..8b728c9414d4a 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -24,7 +24,7 @@ //! often generated by LLVM. Additionally, this library can make explicit //! calls to these functions. Their signatures are the same as found in C. //! These functions are often provided by the system libc, but can also be -//! provided by the [rlibc crate](https://crates.io/crates/rlibc). +//! provided by the [compiler-builtins crate](https://crates.io/crates/compiler_builtins). //! //! * `rust_begin_panic` - This function takes four arguments, a //! `fmt::Arguments`, a `&'static str`, and two `u32`'s. These four arguments diff --git a/src/libcore/ops/function.rs b/src/libcore/ops/function.rs index 3a1d765f7b816..c69f5fd989696 100644 --- a/src/libcore/ops/function.rs +++ b/src/libcore/ops/function.rs @@ -62,7 +62,7 @@ label="expected an `Fn<{Args}>` closure, found `{Self}`", )] #[fundamental] // so that regex can rely that `&str: !FnMut` -#[must_use] +#[must_use = "closures are lazy and do nothing unless called"] pub trait Fn : FnMut { /// Performs the call operation. #[unstable(feature = "fn_traits", issue = "29625")] @@ -141,7 +141,7 @@ pub trait Fn : FnMut { label="expected an `FnMut<{Args}>` closure, found `{Self}`", )] #[fundamental] // so that regex can rely that `&str: !FnMut` -#[must_use] +#[must_use = "closures are lazy and do nothing unless called"] pub trait FnMut : FnOnce { /// Performs the call operation. #[unstable(feature = "fn_traits", issue = "29625")] @@ -220,7 +220,7 @@ pub trait FnMut : FnOnce { label="expected an `FnOnce<{Args}>` closure, found `{Self}`", )] #[fundamental] // so that regex can rely that `&str: !FnMut` -#[must_use] +#[must_use = "closures are lazy and do nothing unless called"] pub trait FnOnce { /// The returned type after the call operator is used. #[stable(feature = "fn_once_output", since = "1.12.0")] diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs index efd233f1f3854..bb25d1b42095a 100644 --- a/src/librustc/mir/interpret/mod.rs +++ b/src/librustc/mir/interpret/mod.rs @@ -27,7 +27,7 @@ pub use self::pointer::{Pointer, PointerArithmetic}; use std::fmt; use crate::mir; use crate::hir::def_id::DefId; -use crate::ty::{self, TyCtxt, Instance}; +use crate::ty::{self, TyCtxt, Instance, subst::UnpackedKind}; use crate::ty::layout::{self, Size}; use std::io; use crate::rustc_serialize::{Encoder, Decodable, Encodable}; @@ -318,14 +318,29 @@ impl<'tcx> AllocMap<'tcx> { id } - /// Functions cannot be identified by pointers, as asm-equal functions can get deduplicated - /// by the linker and functions can be duplicated across crates. - /// We thus generate a new `AllocId` for every mention of a function. This means that - /// `main as fn() == main as fn()` is false, while `let x = main as fn(); x == x` is true. pub fn create_fn_alloc(&mut self, instance: Instance<'tcx>) -> AllocId { - let id = self.reserve(); - self.id_to_kind.insert(id, AllocKind::Function(instance)); - id + // Functions cannot be identified by pointers, as asm-equal functions can get deduplicated + // by the linker (we set the "unnamed_addr" attribute for LLVM) and functions can be + // duplicated across crates. + // We thus generate a new `AllocId` for every mention of a function. This means that + // `main as fn() == main as fn()` is false, while `let x = main as fn(); x == x` is true. + // However, formatting code relies on function identity (see #58320), so we only do + // this for generic functions. Lifetime parameters are ignored. + let is_generic = instance.substs.into_iter().any(|kind| { + match kind.unpack() { + UnpackedKind::Lifetime(_) => false, + _ => true, + } + }); + if is_generic { + // Get a fresh ID + let id = self.reserve(); + self.id_to_kind.insert(id, AllocKind::Function(instance)); + id + } else { + // Deduplicate + self.intern(AllocKind::Function(instance)) + } } /// Returns `None` in case the `AllocId` is dangling. An `EvalContext` can still have a diff --git a/src/librustc_codegen_llvm/back/rpath.rs b/src/librustc_codegen_llvm/back/rpath.rs index aeff23dec41bb..a5c828e089f39 100644 --- a/src/librustc_codegen_llvm/back/rpath.rs +++ b/src/librustc_codegen_llvm/back/rpath.rs @@ -101,9 +101,9 @@ fn get_rpath_relative_to_output(config: &mut RPathConfig, lib: &Path) -> String let cwd = env::current_dir().unwrap(); let mut lib = fs::canonicalize(&cwd.join(lib)).unwrap_or_else(|_| cwd.join(lib)); - lib.pop(); + lib.pop(); // strip filename let mut output = cwd.join(&config.out_filename); - output.pop(); + output.pop(); // strip filename let output = fs::canonicalize(&output).unwrap_or(output); let relative = path_relative_from(&lib, &output).unwrap_or_else(|| panic!("couldn't create relative path from {:?} to {:?}", output, lib)); diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index b356ae38e24ca..f34a7e040b1c3 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -838,7 +838,15 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { early_error(sopts.error_format, "no input filename given"); } 1 => panic!("make_input should have provided valid inputs"), - _ => early_error(sopts.error_format, "multiple input filenames provided"), + _ => + early_error( + sopts.error_format, + &format!( + "multiple input filenames provided (first two filenames are `{}` and `{}`)", + matches.free[0], + matches.free[1], + ), + ) } } diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 9ca7f9d8e27ff..3d6fcae0cab8c 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -823,6 +823,8 @@ where let src = match self.try_read_immediate(src)? { Ok(src_val) => { // Yay, we got a value that we can write directly. + // FIXME: Add a check to make sure that if `src` is indirect, + // it does not overlap with `dest`. return self.write_immediate_no_validate(src_val, dest); } Err(mplace) => mplace, @@ -836,7 +838,8 @@ where self.memory.copy( src_ptr, src_align, dest_ptr, dest_align, - dest.layout.size, false + dest.layout.size, + /*nonoverlapping*/ true, )?; Ok(()) diff --git a/src/librustc_mir/interpret/visitor.rs b/src/librustc_mir/interpret/visitor.rs index 930bcb44374aa..4ff5cde08d086 100644 --- a/src/librustc_mir/interpret/visitor.rs +++ b/src/librustc_mir/interpret/visitor.rs @@ -125,14 +125,14 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Value<'a, 'mir, 'tcx, M> } macro_rules! make_value_visitor { - ($visitor_trait_name:ident, $($mutability:ident)*) => { + ($visitor_trait_name:ident, $($mutability:ident)?) => { // How to traverse a value and what to do when we are at the leaves. pub trait $visitor_trait_name<'a, 'mir, 'tcx: 'mir+'a, M: Machine<'a, 'mir, 'tcx>>: Sized { type V: Value<'a, 'mir, 'tcx, M>; /// The visitor must have an `EvalContext` in it. - fn ecx(&$($mutability)* self) - -> &$($mutability)* EvalContext<'a, 'mir, 'tcx, M>; + fn ecx(&$($mutability)? self) + -> &$($mutability)? EvalContext<'a, 'mir, 'tcx, M>; // Recursive actions, ready to be overloaded. /// Visit the given value, dispatching as appropriate to more specialized visitors. diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index bd0525583f2cd..b0bb033b94b25 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -517,6 +517,7 @@ pub enum ItemEnum { StaticItem(Static), ConstantItem(Constant), TraitItem(Trait), + TraitAliasItem(TraitAlias), ImplItem(Impl), /// A method signature only. Used for required methods in traits (ie, /// non-default-methods). @@ -554,6 +555,7 @@ impl ItemEnum { ItemEnum::TyMethodItem(ref i) => &i.generics, ItemEnum::MethodItem(ref i) => &i.generics, ItemEnum::ForeignFunctionItem(ref f) => &f.generics, + ItemEnum::TraitAliasItem(ref ta) => &ta.generics, _ => return None, }) } @@ -603,6 +605,7 @@ impl Clean for doctree::Module { items.extend(self.impls.iter().flat_map(|x| x.clean(cx))); items.extend(self.macros.iter().map(|x| x.clean(cx))); items.extend(self.proc_macros.iter().map(|x| x.clean(cx))); + items.extend(self.trait_aliases.iter().map(|x| x.clean(cx))); // determine if we should display the inner contents or // the outer `mod` item for the source code. @@ -1724,6 +1727,30 @@ impl FnDecl { pub fn self_type(&self) -> Option { self.inputs.values.get(0).and_then(|v| v.to_self()) } + + /// Returns the sugared return type for an async function. + /// + /// For example, if the return type is `impl std::future::Future`, this function + /// will return `i32`. + /// + /// # Panics + /// + /// This function will panic if the return type does not match the expected sugaring for async + /// functions. + pub fn sugared_async_return_type(&self) -> FunctionRetTy { + match &self.output { + FunctionRetTy::Return(Type::ImplTrait(bounds)) => { + match &bounds[0] { + GenericBound::TraitBound(PolyTrait { trait_, .. }, ..) => { + let bindings = trait_.bindings().unwrap(); + FunctionRetTy::Return(bindings[0].ty.clone()) + } + _ => panic!("unexpected desugaring of async function"), + } + } + _ => panic!("unexpected desugaring of async function"), + } + } } #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)] @@ -1885,13 +1912,38 @@ impl Clean for doctree::Trait { items: self.items.clean(cx), generics: self.generics.clean(cx), bounds: self.bounds.clean(cx), - is_spotlight: is_spotlight, + is_spotlight, is_auto: self.is_auto.clean(cx), }), } } } +#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +pub struct TraitAlias { + pub generics: Generics, + pub bounds: Vec, +} + +impl Clean for doctree::TraitAlias { + fn clean(&self, cx: &DocContext) -> Item { + let attrs = self.attrs.clean(cx); + Item { + name: Some(self.name.clean(cx)), + attrs, + source: self.whence.clean(cx), + def_id: cx.tcx.hir().local_def_id(self.id), + visibility: self.vis.clean(cx), + stability: self.stab.clean(cx), + deprecation: self.depr.clean(cx), + inner: TraitAliasItem(TraitAlias { + generics: self.generics.clean(cx), + bounds: self.bounds.clean(cx), + }), + } + } +} + impl Clean for hir::IsAuto { fn clean(&self, _: &DocContext) -> bool { match *self { @@ -2223,6 +2275,7 @@ pub enum TypeKind { Macro, Attr, Derive, + TraitAlias, } pub trait GetDefId { @@ -2282,6 +2335,21 @@ impl Type { _ => None, } } + + pub fn bindings(&self) -> Option<&[TypeBinding]> { + match *self { + ResolvedPath { ref path, .. } => { + path.segments.last().and_then(|seg| { + if let GenericArgs::AngleBracketed { ref bindings, .. } = seg.args { + Some(&**bindings) + } else { + None + } + }) + } + _ => None + } + } } impl GetDefId for Type { @@ -3819,10 +3887,9 @@ pub fn register_def(cx: &DocContext, def: Def) -> DefId { MacroKind::Derive => (i, TypeKind::Derive), MacroKind::ProcMacroStub => unreachable!(), }, + Def::TraitAlias(i) => (i, TypeKind::TraitAlias), Def::SelfTy(Some(def_id), _) => (def_id, TypeKind::Trait), - Def::SelfTy(_, Some(impl_def_id)) => { - return impl_def_id - } + Def::SelfTy(_, Some(impl_def_id)) => return impl_def_id, _ => return def.def_id() }; if did.is_local() { return did } diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index cc27da70b16d7..e8458385739df 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -38,6 +38,7 @@ pub struct Module { pub foreigns: Vec, pub macros: Vec, pub proc_macros: Vec, + pub trait_aliases: Vec, pub is_crate: bool, } @@ -53,21 +54,22 @@ impl Module { where_inner: syntax_pos::DUMMY_SP, attrs : hir::HirVec::new(), extern_crates: Vec::new(), - imports : Vec::new(), - structs : Vec::new(), - unions : Vec::new(), - enums : Vec::new(), - fns : Vec::new(), - mods : Vec::new(), - typedefs : Vec::new(), - existentials: Vec::new(), - statics : Vec::new(), - constants : Vec::new(), - traits : Vec::new(), - impls : Vec::new(), - foreigns : Vec::new(), - macros : Vec::new(), - proc_macros: Vec::new(), + imports : Vec::new(), + structs : Vec::new(), + unions : Vec::new(), + enums : Vec::new(), + fns : Vec::new(), + mods : Vec::new(), + typedefs : Vec::new(), + existentials: Vec::new(), + statics : Vec::new(), + constants : Vec::new(), + traits : Vec::new(), + impls : Vec::new(), + foreigns : Vec::new(), + macros : Vec::new(), + proc_macros: Vec::new(), + trait_aliases: Vec::new(), is_crate : false, } } @@ -208,6 +210,18 @@ pub struct Trait { pub depr: Option, } +pub struct TraitAlias { + pub name: Name, + pub generics: hir::Generics, + pub bounds: hir::HirVec, + pub attrs: hir::HirVec, + pub id: ast::NodeId, + pub whence: Span, + pub vis: hir::Visibility, + pub stab: Option, + pub depr: Option, +} + #[derive(Debug)] pub struct Impl { pub unsafety: hir::Unsafety, diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 5a3e6984859a2..c03e679bc5194 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -5,6 +5,7 @@ //! assume that HTML output is desired, although it may be possible to redesign //! them in the future to instead emit any format desired. +use std::borrow::Cow; use std::fmt; use rustc::hir::def_id::DefId; @@ -44,14 +45,16 @@ pub struct GenericBounds<'a>(pub &'a [clean::GenericBound]); pub struct CommaSep<'a, T: 'a>(pub &'a [T]); pub struct AbiSpace(pub Abi); -/// Wrapper struct for properly emitting a method declaration. -pub struct Method<'a> { +/// Wrapper struct for properly emitting a function or method declaration. +pub struct Function<'a> { /// The declaration to emit. pub decl: &'a clean::FnDecl, /// The length of the function's "name", used to determine line-wrapping. pub name_len: usize, /// The number of spaces to indent each successive line with, if line-wrapping is necessary. pub indent: usize, + /// Whether the function is async or not. + pub asyncness: hir::IsAsync, } /// Wrapper struct for emitting a where clause from Generics. @@ -829,9 +832,9 @@ impl fmt::Display for clean::FnDecl { } } -impl<'a> fmt::Display for Method<'a> { +impl<'a> fmt::Display for Function<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let &Method { decl, name_len, indent } = self; + let &Function { decl, name_len, indent, asyncness } = self; let amp = if f.alternate() { "&" } else { "&" }; let mut args = String::new(); let mut args_plain = String::new(); @@ -891,11 +894,17 @@ impl<'a> fmt::Display for Method<'a> { args_plain.push_str(", ..."); } - let arrow_plain = format!("{:#}", decl.output); + let output = if let hir::IsAsync::Async = asyncness { + Cow::Owned(decl.sugared_async_return_type()) + } else { + Cow::Borrowed(&decl.output) + }; + + let arrow_plain = format!("{:#}", &output); let arrow = if f.alternate() { - format!("{:#}", decl.output) + format!("{:#}", &output) } else { - decl.output.to_string() + output.to_string() }; let pad = " ".repeat(name_len); diff --git a/src/librustdoc/html/item_type.rs b/src/librustdoc/html/item_type.rs index e20d385c487b3..8a3b5484f395d 100644 --- a/src/librustdoc/html/item_type.rs +++ b/src/librustdoc/html/item_type.rs @@ -42,6 +42,7 @@ pub enum ItemType { Existential = 22, ProcAttribute = 23, ProcDerive = 24, + TraitAlias = 25, } @@ -86,6 +87,7 @@ impl<'a> From<&'a clean::Item> for ItemType { clean::AssociatedTypeItem(..) => ItemType::AssociatedType, clean::ForeignTypeItem => ItemType::ForeignType, clean::KeywordItem(..) => ItemType::Keyword, + clean::TraitAliasItem(..) => ItemType::TraitAlias, clean::ProcMacroItem(ref mac) => match mac.kind { MacroKind::Bang => ItemType::Macro, MacroKind::Attr => ItemType::ProcAttribute, @@ -100,20 +102,21 @@ impl<'a> From<&'a clean::Item> for ItemType { impl From for ItemType { fn from(kind: clean::TypeKind) -> ItemType { match kind { - clean::TypeKind::Struct => ItemType::Struct, - clean::TypeKind::Union => ItemType::Union, - clean::TypeKind::Enum => ItemType::Enum, - clean::TypeKind::Function => ItemType::Function, - clean::TypeKind::Trait => ItemType::Trait, - clean::TypeKind::Module => ItemType::Module, - clean::TypeKind::Static => ItemType::Static, - clean::TypeKind::Const => ItemType::Constant, - clean::TypeKind::Variant => ItemType::Variant, - clean::TypeKind::Typedef => ItemType::Typedef, - clean::TypeKind::Foreign => ItemType::ForeignType, - clean::TypeKind::Macro => ItemType::Macro, - clean::TypeKind::Attr => ItemType::ProcAttribute, - clean::TypeKind::Derive => ItemType::ProcDerive, + clean::TypeKind::Struct => ItemType::Struct, + clean::TypeKind::Union => ItemType::Union, + clean::TypeKind::Enum => ItemType::Enum, + clean::TypeKind::Function => ItemType::Function, + clean::TypeKind::Trait => ItemType::Trait, + clean::TypeKind::Module => ItemType::Module, + clean::TypeKind::Static => ItemType::Static, + clean::TypeKind::Const => ItemType::Constant, + clean::TypeKind::Variant => ItemType::Variant, + clean::TypeKind::Typedef => ItemType::Typedef, + clean::TypeKind::Foreign => ItemType::ForeignType, + clean::TypeKind::Macro => ItemType::Macro, + clean::TypeKind::Attr => ItemType::ProcAttribute, + clean::TypeKind::Derive => ItemType::ProcDerive, + clean::TypeKind::TraitAlias => ItemType::TraitAlias, } } } @@ -146,6 +149,7 @@ impl ItemType { ItemType::Existential => "existential", ItemType::ProcAttribute => "attr", ItemType::ProcDerive => "derive", + ItemType::TraitAlias => "traitalias", } } @@ -160,6 +164,7 @@ impl ItemType { ItemType::Primitive | ItemType::AssociatedType | ItemType::Existential | + ItemType::TraitAlias | ItemType::ForeignType => NameSpace::Type, ItemType::ExternCrate | diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index a85ac19286af5..3a8e8a6a6c840 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -62,7 +62,7 @@ use fold::DocFolder; use html::escape::Escape; use html::format::{AsyncSpace, ConstnessSpace}; use html::format::{GenericBounds, WhereClause, href, AbiSpace}; -use html::format::{VisSpace, Method, UnsafetySpace, MutableSpace}; +use html::format::{VisSpace, Function, UnsafetySpace, MutableSpace}; use html::format::fmt_impl_for_trait_page; use html::item_type::ItemType; use html::markdown::{self, Markdown, MarkdownHtml, MarkdownSummaryLine, ErrorCodes, IdMap}; @@ -1836,6 +1836,7 @@ struct AllTypes { keywords: FxHashSet, attributes: FxHashSet, derives: FxHashSet, + trait_aliases: FxHashSet, } impl AllTypes { @@ -1856,6 +1857,7 @@ impl AllTypes { keywords: new_set(100), attributes: new_set(100), derives: new_set(100), + trait_aliases: new_set(100), } } @@ -1879,6 +1881,7 @@ impl AllTypes { ItemType::Constant => self.constants.insert(ItemEntry::new(new_url, name)), ItemType::ProcAttribute => self.attributes.insert(ItemEntry::new(new_url, name)), ItemType::ProcDerive => self.derives.insert(ItemEntry::new(new_url, name)), + ItemType::TraitAlias => self.trait_aliases.insert(ItemEntry::new(new_url, name)), _ => true, }; } @@ -1922,6 +1925,7 @@ impl fmt::Display for AllTypes { print_entries(f, &self.derives, "Derive Macros", "derives")?; print_entries(f, &self.functions, "Functions", "functions")?; print_entries(f, &self.typedefs, "Typedefs", "typedefs")?; + print_entries(f, &self.trait_aliases, "Trait Aliases", "trait-aliases")?; print_entries(f, &self.existentials, "Existentials", "existentials")?; print_entries(f, &self.statics, "Statics", "statics")?; print_entries(f, &self.constants, "Constants", "constants") @@ -2419,6 +2423,7 @@ impl<'a> fmt::Display for Item<'a> { clean::ForeignTypeItem => write!(fmt, "Foreign Type ")?, clean::KeywordItem(..) => write!(fmt, "Keyword ")?, clean::ExistentialItem(..) => write!(fmt, "Existential Type ")?, + clean::TraitAliasItem(..) => write!(fmt, "Trait Alias ")?, _ => { // We don't generate pages for any other type. unreachable!(); @@ -2457,6 +2462,7 @@ impl<'a> fmt::Display for Item<'a> { clean::ForeignTypeItem => item_foreign_type(fmt, self.cx, self.item), clean::KeywordItem(ref k) => item_keyword(fmt, self.cx, self.item, k), clean::ExistentialItem(ref e, _) => item_existential(fmt, self.cx, self.item, e), + clean::TraitAliasItem(ref ta) => item_trait_alias(fmt, self.cx, self.item, ta), _ => { // We don't generate pages for any other type. unreachable!(); @@ -2977,10 +2983,11 @@ fn item_function(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, name = it.name.as_ref().unwrap(), generics = f.generics, where_clause = WhereClause { gens: &f.generics, indent: 0, end_newline: true }, - decl = Method { + decl = Function { decl: &f.decl, name_len, indent: 0, + asyncness: f.header.asyncness, })?; document(w, cx, it) } @@ -3014,23 +3021,17 @@ fn render_impls(cx: &Context, w: &mut fmt::Formatter, Ok(()) } -fn bounds(t_bounds: &[clean::GenericBound]) -> String { +fn bounds(t_bounds: &[clean::GenericBound], trait_alias: bool) -> String { let mut bounds = String::new(); - let mut bounds_plain = String::new(); if !t_bounds.is_empty() { - if !bounds.is_empty() { - bounds.push(' '); - bounds_plain.push(' '); + if !trait_alias { + bounds.push_str(": "); } - bounds.push_str(": "); - bounds_plain.push_str(": "); for (i, p) in t_bounds.iter().enumerate() { if i > 0 { bounds.push_str(" + "); - bounds_plain.push_str(" + "); } bounds.push_str(&(*p).to_string()); - bounds_plain.push_str(&format!("{:#}", *p)); } } bounds @@ -3050,7 +3051,7 @@ fn item_trait( it: &clean::Item, t: &clean::Trait, ) -> fmt::Result { - let bounds = bounds(&t.bounds); + let bounds = bounds(&t.bounds, false); let types = t.items.iter().filter(|m| m.is_associated_type()).collect::>(); let consts = t.items.iter().filter(|m| m.is_associated_const()).collect::>(); let required = t.items.iter().filter(|m| m.is_ty_method()).collect::>(); @@ -3424,10 +3425,11 @@ fn render_assoc_item(w: &mut fmt::Formatter, href = href, name = name, generics = *g, - decl = Method { + decl = Function { decl: d, name_len: head_len, indent, + asyncness: header.asyncness, }, where_clause = WhereClause { gens: g, @@ -4280,7 +4282,26 @@ fn item_existential( it.name.as_ref().unwrap(), t.generics, where_clause = WhereClause { gens: &t.generics, indent: 0, end_newline: true }, - bounds = bounds(&t.bounds))?; + bounds = bounds(&t.bounds, false))?; + + document(w, cx, it)?; + + // Render any items associated directly to this alias, as otherwise they + // won't be visible anywhere in the docs. It would be nice to also show + // associated items from the aliased type (see discussion in #32077), but + // we need #14072 to make sense of the generics. + render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All) +} + +fn item_trait_alias(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, + t: &clean::TraitAlias) -> fmt::Result { + write!(w, "
")?;
+    render_attributes(w, it)?;
+    write!(w, "trait {}{}{} = {};
", + it.name.as_ref().unwrap(), + t.generics, + WhereClause { gens: &t.generics, indent: 0, end_newline: true }, + bounds(&t.bounds, true))?; document(w, cx, it)?; @@ -4844,6 +4865,7 @@ fn item_ty_to_strs(ty: &ItemType) -> (&'static str, &'static str) { ItemType::Existential => ("existentials", "Existentials"), ItemType::ProcAttribute => ("attributes", "Attribute Macros"), ItemType::ProcDerive => ("derives", "Derive Macros"), + ItemType::TraitAlias => ("trait-aliases", "Trait aliases"), } } diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 877ac9a62bbec..840f943a5972d 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -68,7 +68,8 @@ if (!DOMTokenList.prototype.remove) { "keyword", "existential", "attr", - "derive"]; + "derive", + "traitalias"]; var search_input = document.getElementsByClassName("search-input")[0]; @@ -79,8 +80,6 @@ if (!DOMTokenList.prototype.remove) { // 2 for "In Return Types" var currentTab = 0; - var themesWidth = null; - var titleBeforeSearch = document.title; function getPageId() { @@ -240,7 +239,7 @@ if (!DOMTokenList.prototype.remove) { return String.fromCharCode(c); } - function displayHelp(display, ev) { + function displayHelp(display, ev, help) { if (display === true) { if (hasClass(help, "hidden")) { ev.preventDefault(); @@ -258,7 +257,7 @@ if (!DOMTokenList.prototype.remove) { hideModal(); var search = document.getElementById("search"); if (hasClass(help, "hidden") === false) { - displayHelp(false, ev); + displayHelp(false, ev, help); } else if (hasClass(search, "hidden") === false) { ev.preventDefault(); addClass(search, "hidden"); @@ -289,7 +288,7 @@ if (!DOMTokenList.prototype.remove) { case "s": case "S": - displayHelp(false, ev); + displayHelp(false, ev, help); hideModal(); ev.preventDefault(); focusSearchBar(); @@ -304,7 +303,7 @@ if (!DOMTokenList.prototype.remove) { case "?": if (ev.shiftKey) { hideModal(); - displayHelp(true, ev); + displayHelp(true, ev, help); } break; } @@ -654,7 +653,7 @@ if (!DOMTokenList.prototype.remove) { return MAX_LEV_DISTANCE + 1; } } - return lev_distance;//Math.ceil(total / done); + return Math.ceil(total / done); } } return MAX_LEV_DISTANCE + 1; @@ -1786,6 +1785,7 @@ if (!DOMTokenList.prototype.remove) { block("type", "Type Definitions"); block("foreigntype", "Foreign Types"); block("keyword", "Keywords"); + block("traitalias", "Trait Aliases"); } window.initSidebarItems = initSidebarItems; @@ -2432,7 +2432,7 @@ if (!DOMTokenList.prototype.remove) { // for vertical layout (column-oriented flex layout for divs caused // errors in mobile browsers). if (e.tagName === "H2" || e.tagName === "H3") { - let nextTagName = e.nextElementSibling.tagName; + var nextTagName = e.nextElementSibling.tagName; if (nextTagName == "H2" || nextTagName == "H3") { e.nextElementSibling.style.display = "flex"; } else { diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css index 6935ecde791f8..333fe76a8a4a9 100644 --- a/src/librustdoc/html/static/themes/dark.css +++ b/src/librustdoc/html/static/themes/dark.css @@ -94,6 +94,7 @@ pre { } .content .highlighted a, .content .highlighted span { color: #eee !important; } .content .highlighted.trait { background-color: #013191; } +.content .highlighted.traitalias { background-color: #013191; } .content .highlighted.mod, .content .highlighted.externcrate { background-color: #afc6e4; } .content .highlighted.mod { background-color: #803a1b; } @@ -128,6 +129,7 @@ pre { .content span.externcrate, .content span.mod, .content a.mod, .block a.current.mod { color: #bda000; } .content span.trait, .content a.trait, .block a.current.trait { color: #b78cf2; } +.content span.traitalias, .content a.traitalias, .block a.current.traitalias { color: #b397da; } .content span.fn, .content a.fn, .block a.current.fn, .content span.method, .content a.method, .block a.current.method, .content span.tymethod, .content a.tymethod, .block a.current.tymethod, diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css index 306e8dc15d893..19ae67b29881f 100644 --- a/src/librustdoc/html/static/themes/light.css +++ b/src/librustdoc/html/static/themes/light.css @@ -96,6 +96,7 @@ pre { } .content .highlighted a, .content .highlighted span { color: #000 !important; } .content .highlighted.trait { background-color: #c7b6ff; } +.content .highlighted.traitalias { background-color: #c7b6ff; } .content .highlighted.mod, .content .highlighted.externcrate { background-color: #afc6e4; } .content .highlighted.enum { background-color: #b4d1b9; } @@ -128,6 +129,7 @@ pre { .content span.externcrate, .content span.mod, .content a.mod, .block a.current.mod { color: #4d76ae; } .content span.trait, .content a.trait, .block a.current.trait { color: #7c5af3; } +.content span.traitalias, .content a.traitalias, .block a.current.traitalias { color: #6841f1; } .content span.fn, .content a.fn, .block a.current.fn, .content span.method, .content a.method, .block a.current.method, .content span.tymethod, .content a.tymethod, .block a.current.tymethod, diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs index c9a3a2c003fe0..5f3da4c7b33e0 100644 --- a/src/librustdoc/passes/mod.rs +++ b/src/librustdoc/passes/mod.rs @@ -224,6 +224,7 @@ impl<'a> fold::DocFolder for Stripper<'a> { | clean::ConstantItem(..) | clean::UnionItem(..) | clean::AssociatedConstItem(..) + | clean::TraitAliasItem(..) | clean::ForeignTypeItem => { if i.def_id.is_local() { if !self.access_levels.is_exported(i.def_id) { diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index b8eb777a54ba4..352ff788eedae 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -547,8 +547,19 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> { }; om.traits.push(t); }, - hir::ItemKind::TraitAlias(..) => { - unimplemented!("trait objects are not yet implemented") + hir::ItemKind::TraitAlias(ref gen, ref b) => { + let t = TraitAlias { + name: ident.name, + generics: gen.clone(), + bounds: b.iter().cloned().collect(), + id: item.id, + attrs: item.attrs.clone(), + whence: item.span, + vis: item.vis.clone(), + stab: self.stability(item.id), + depr: self.deprecation(item.id), + }; + om.trait_aliases.push(t); }, hir::ItemKind::Impl(unsafety, diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index f45cd8b8c101a..4e064672fbc40 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -392,8 +392,7 @@ impl Ipv4Addr { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn octets(&self) -> [u8; 4] { - let bits = u32::from_be(self.inner.s_addr); - [(bits >> 24) as u8, (bits >> 16) as u8, (bits >> 8) as u8, bits as u8] + self.inner.s_addr.to_ne_bytes() } /// Returns [`true`] for the special 'unspecified' address (0.0.0.0). diff --git a/src/libstd/sys/unix/stdio.rs b/src/libstd/sys/unix/stdio.rs index 8a6b7b5f876ff..715f2eafb2d9b 100644 --- a/src/libstd/sys/unix/stdio.rs +++ b/src/libstd/sys/unix/stdio.rs @@ -12,7 +12,7 @@ impl Stdin { pub fn read(&self, data: &mut [u8]) -> io::Result { let fd = FileDesc::new(libc::STDIN_FILENO); let ret = fd.read(data); - fd.into_raw(); + fd.into_raw(); // do not close this FD ret } } @@ -23,7 +23,7 @@ impl Stdout { pub fn write(&self, data: &[u8]) -> io::Result { let fd = FileDesc::new(libc::STDOUT_FILENO); let ret = fd.write(data); - fd.into_raw(); + fd.into_raw(); // do not close this FD ret } @@ -38,7 +38,7 @@ impl Stderr { pub fn write(&self, data: &[u8]) -> io::Result { let fd = FileDesc::new(libc::STDERR_FILENO); let ret = fd.write(data); - fd.into_raw(); + fd.into_raw(); // do not close this FD ret } diff --git a/src/test/rustdoc/async-fn.rs b/src/test/rustdoc/async-fn.rs index a0b6c29126092..ba4997a7f9b5b 100644 --- a/src/test/rustdoc/async-fn.rs +++ b/src/test/rustdoc/async-fn.rs @@ -1,14 +1,35 @@ // edition:2018 -// compile-flags:-Z unstable-options - -// FIXME: once `--edition` is stable in rustdoc, remove that `compile-flags` directive #![feature(async_await, futures_api)] -// @has async_fn/struct.S.html -// @has - '//code' 'pub async fn f()' -pub struct S; +// @has async_fn/fn.foo.html '//pre[@class="rust fn"]' 'pub async fn foo() -> Option' +pub async fn foo() -> Option { + None +} + +// @has async_fn/fn.bar.html '//pre[@class="rust fn"]' 'pub async fn bar(a: i32, b: i32) -> i32' +pub async fn bar(a: i32, b: i32) -> i32 { + 0 +} + +// @has async_fn/fn.baz.html '//pre[@class="rust fn"]' 'pub async fn baz(a: T) -> T' +pub async fn baz(a: T) -> T { + a +} + +trait Bar {} + +impl Bar for () {} + +// @has async_fn/fn.quux.html '//pre[@class="rust fn"]' 'pub async fn quux() -> impl Bar' +pub async fn quux() -> impl Bar { + () +} + +// @has async_fn/struct.Foo.html +// @matches - '//code' 'pub async fn f\(\)$' +pub struct Foo; -impl S { +impl Foo { pub async fn f() {} } diff --git a/src/test/rustdoc/trait_alias.rs b/src/test/rustdoc/trait_alias.rs new file mode 100644 index 0000000000000..98b8d879ac078 --- /dev/null +++ b/src/test/rustdoc/trait_alias.rs @@ -0,0 +1,21 @@ +#![feature(trait_alias)] + +#![crate_name = "foo"] + +use std::fmt::Debug; + +// @has foo/all.html '//a[@href="traitalias.CopyAlias.html"]' 'CopyAlias' +// @has foo/all.html '//a[@href="traitalias.Alias2.html"]' 'Alias2' +// @has foo/all.html '//a[@href="traitalias.Foo.html"]' 'Foo' + +// @has foo/index.html '//h2[@id="trait-aliases"]' 'Trait aliases' +// @has foo/index.html '//a[@class="traitalias"]' 'CopyAlias' +// @has foo/index.html '//a[@class="traitalias"]' 'Alias2' +// @has foo/index.html '//a[@class="traitalias"]' 'Foo' + +// @has foo/traitalias.CopyAlias.html '//section[@id="main"]/pre' 'trait CopyAlias = Copy;' +pub trait CopyAlias = Copy; +// @has foo/traitalias.Alias2.html '//section[@id="main"]/pre' 'trait Alias2 = Copy + Debug;' +pub trait Alias2 = Copy + Debug; +// @has foo/traitalias.Foo.html '//section[@id="main"]/pre' 'trait Foo = Into + Debug;' +pub trait Foo = Into + Debug;