From 93c1f2472bd627955e44970de075c2e90f246501 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Mon, 15 May 2017 22:11:16 +0200 Subject: [PATCH 01/11] Stabilize the loop_break_value feature --- src/doc/unstable-book/src/SUMMARY.md | 1 - .../src/language-features/loop-break-value.md | 83 ------------------- src/librustc/lib.rs | 2 +- src/librustc_driver/lib.rs | 2 +- src/librustc_typeck/lib.rs | 2 +- src/libsyntax/feature_gate.rs | 9 +- .../feature-gate-loop-break-value.rs | 15 ---- src/test/compile-fail/loop-break-value.rs | 1 - .../diverging-fallback-control-flow.rs | 1 - src/test/run-pass/loop-break-value.rs | 1 - src/test/ui/loop-break-value-no-repeat.rs | 1 - src/test/ui/loop-break-value-no-repeat.stderr | 4 +- 12 files changed, 7 insertions(+), 115 deletions(-) delete mode 100644 src/doc/unstable-book/src/language-features/loop-break-value.md delete mode 100644 src/test/compile-fail/feature-gate-loop-break-value.rs diff --git a/src/doc/unstable-book/src/SUMMARY.md b/src/doc/unstable-book/src/SUMMARY.md index 39f800591483b..deed3c50ee1c6 100644 --- a/src/doc/unstable-book/src/SUMMARY.md +++ b/src/doc/unstable-book/src/SUMMARY.md @@ -49,7 +49,6 @@ - [link_llvm_intrinsics](language-features/link-llvm-intrinsics.md) - [linkage](language-features/linkage.md) - [log_syntax](language-features/log-syntax.md) - - [loop_break_value](language-features/loop-break-value.md) - [macro_reexport](language-features/macro-reexport.md) - [macro_vis_matcher](language-features/macro-vis-matcher.md) - [main](language-features/main.md) diff --git a/src/doc/unstable-book/src/language-features/loop-break-value.md b/src/doc/unstable-book/src/language-features/loop-break-value.md deleted file mode 100644 index e8fefe3b73344..0000000000000 --- a/src/doc/unstable-book/src/language-features/loop-break-value.md +++ /dev/null @@ -1,83 +0,0 @@ -# `loop_break_value` - -The tracking issue for this feature is: [#37339] - -[#37339]: https://github.com/rust-lang/rust/issues/37339 - -Documentation to be appended to section G of the book. - ------------------------- - -### Loops as expressions - -Like most things in Rust, loops are expressions, and have a value; normally `()` unless the loop -never exits. -A `loop` can instead evaluate to a useful value via *break with value*: - -```rust -#![feature(loop_break_value)] - -// Find the first square number over 1000: -let mut n = 1; -let square = loop { - if n * n > 1000 { - break n * n; - } - n += 1; -}; -``` - -The evaluation type may be specified externally: - -```rust -#![feature(loop_break_value)] - -// Declare that value returned is unsigned 64-bit: -let n: u64 = loop { - break 1; -}; -``` - -It is an error if types do not agree, either between a "break" value and an external requirement, -or between multiple "break" values: - -```no_compile -#![feature(loop_break_value)] - -loop { - if true { - break 1u32; - } else { - break 0u8; // error: types do not agree - } -}; - -let n: i32 = loop { - break 0u32; // error: type does not agree with external requirement -}; -``` - -#### Break: label, value - -Four forms of `break` are available, where EXPR is some expression which evaluates to a value: - -1. `break;` -2. `break 'label;` -3. `break EXPR;` -4. `break 'label EXPR;` - -When no value is given, the value `()` is assumed, thus `break;` is equivalent to `break ();`. - -Using a label allows returning a value from an inner loop: - -```rust -#![feature(loop_break_value)] - -let result = 'outer: loop { - for n in 1..10 { - if n > 4 { - break 'outer n; - } - } -}; -``` diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index f32ee7900646b..2b4b5cc73337b 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -30,7 +30,6 @@ #![feature(core_intrinsics)] #![feature(i128_type)] #![feature(libc)] -#![feature(loop_break_value)] #![feature(never_type)] #![feature(nonzero)] #![feature(quote)] @@ -45,6 +44,7 @@ #![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))] #![cfg_attr(stage0, feature(rustc_private))] #![cfg_attr(stage0, feature(staged_api))] +#![cfg_attr(stage0, feature(loop_break_value))] #![recursion_limit="128"] diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 34f636d0b9a12..7742634ffb709 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -23,7 +23,6 @@ #![deny(warnings)] #![feature(box_syntax)] -#![feature(loop_break_value)] #![feature(libc)] #![feature(quote)] #![feature(rustc_diagnostic_macros)] @@ -32,6 +31,7 @@ #![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))] #![cfg_attr(stage0, feature(rustc_private))] #![cfg_attr(stage0, feature(staged_api))] +#![cfg_attr(stage0, feature(loop_break_value))] extern crate arena; extern crate getopts; diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 99ee1cff7fd22..6f2c73b892567 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -76,7 +76,6 @@ This API is completely unstable and subject to change. #![feature(box_patterns)] #![feature(box_syntax)] #![feature(conservative_impl_trait)] -#![feature(loop_break_value)] #![feature(never_type)] #![feature(quote)] #![feature(rustc_diagnostic_macros)] @@ -84,6 +83,7 @@ This API is completely unstable and subject to change. #![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))] #![cfg_attr(stage0, feature(rustc_private))] #![cfg_attr(stage0, feature(staged_api))] +#![cfg_attr(stage0, feature(loop_break_value))] #[macro_use] extern crate log; #[macro_use] extern crate syntax; diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 09090ab873130..297c8e00ea3c8 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -297,9 +297,6 @@ declare_features! ( (active, use_extern_macros, "1.15.0", Some(35896)), - // Allows `break {expr}` with a value inside `loop`s. - (active, loop_break_value, "1.14.0", Some(37339)), - // Allows #[target_feature(...)] (active, target_feature, "1.15.0", None), @@ -423,6 +420,8 @@ declare_features! ( (accepted, pub_restricted, "1.18.0", Some(32409)), // The #![windows_subsystem] attribute (accepted, windows_subsystem, "1.18.0", Some(37499)), + // Allows `break {expr}` with a value inside `loop`s. + (accepted, loop_break_value, "1.19.0", Some(37339)), ); // If you change this, please modify src/doc/unstable-book as well. You must // move that documentation into the relevant place in the other docs, and @@ -1301,10 +1300,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } } } - ast::ExprKind::Break(_, Some(_)) => { - gate_feature_post!(&self, loop_break_value, e.span, - "`break` with a value is experimental"); - } ast::ExprKind::Lit(ref lit) => { if let ast::LitKind::Int(_, ref ty) = lit.node { match *ty { diff --git a/src/test/compile-fail/feature-gate-loop-break-value.rs b/src/test/compile-fail/feature-gate-loop-break-value.rs deleted file mode 100644 index 1632c40d59fdf..0000000000000 --- a/src/test/compile-fail/feature-gate-loop-break-value.rs +++ /dev/null @@ -1,15 +0,0 @@ -// 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. - -fn main() { - loop { - break 123; //~ ERROR `break` with a value is experimental - } -} diff --git a/src/test/compile-fail/loop-break-value.rs b/src/test/compile-fail/loop-break-value.rs index a414321899203..938f7fba2a032 100644 --- a/src/test/compile-fail/loop-break-value.rs +++ b/src/test/compile-fail/loop-break-value.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(loop_break_value)] #![feature(never_type)] fn main() { diff --git a/src/test/run-pass/diverging-fallback-control-flow.rs b/src/test/run-pass/diverging-fallback-control-flow.rs index 656e90d2d52d7..723a98bcdfa0d 100644 --- a/src/test/run-pass/diverging-fallback-control-flow.rs +++ b/src/test/run-pass/diverging-fallback-control-flow.rs @@ -15,7 +15,6 @@ // like to revisit these and potentially change them. --nmatsakis #![feature(never_type)] -#![feature(loop_break_value)] trait BadDefault { fn default() -> Self; diff --git a/src/test/run-pass/loop-break-value.rs b/src/test/run-pass/loop-break-value.rs index 4906a8e71d7a4..1d5c83bc20d95 100644 --- a/src/test/run-pass/loop-break-value.rs +++ b/src/test/run-pass/loop-break-value.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(loop_break_value)] #![feature(never_type)] #[allow(unused)] diff --git a/src/test/ui/loop-break-value-no-repeat.rs b/src/test/ui/loop-break-value-no-repeat.rs index 790f796fae07f..b52d540fd7511 100644 --- a/src/test/ui/loop-break-value-no-repeat.rs +++ b/src/test/ui/loop-break-value-no-repeat.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(loop_break_value)] #![allow(unused_variables)] use std::ptr; diff --git a/src/test/ui/loop-break-value-no-repeat.stderr b/src/test/ui/loop-break-value-no-repeat.stderr index 0d99abd3907d8..c154ea6f8c2d6 100644 --- a/src/test/ui/loop-break-value-no-repeat.stderr +++ b/src/test/ui/loop-break-value-no-repeat.stderr @@ -1,7 +1,7 @@ error[E0571]: `break` with value from a `for` loop - --> $DIR/loop-break-value-no-repeat.rs:23:9 + --> $DIR/loop-break-value-no-repeat.rs:22:9 | -23 | break 22 +22 | break 22 | ^^^^^^^^ can only break with a value inside `loop` error: aborting due to previous error From 0c97d6c85550d795407a5c7cbaf6d1553c338b9d Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Sat, 20 May 2017 09:38:45 -0400 Subject: [PATCH 02/11] Add basic Unstable Book entry for `on_unimplemented`. --- .../src/language-features/on-unimplemented.md | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/doc/unstable-book/src/language-features/on-unimplemented.md b/src/doc/unstable-book/src/language-features/on-unimplemented.md index 81f284d0a6a3e..9eea3fccbbc17 100644 --- a/src/doc/unstable-book/src/language-features/on-unimplemented.md +++ b/src/doc/unstable-book/src/language-features/on-unimplemented.md @@ -6,5 +6,42 @@ The tracking issue for this feature is: [#29628] ------------------------ +The `on_unimplemented` feature provides the `#[rustc_on_unimplemented]` +attribute, which allows trait definitions to add specialized notes to error +messages when an implementation was expected but not found. +For example: + +```rust,compile_fail +#![feature(on_unimplemented)] + +#[rustc_on_unimplemented="a collection of type `{Self}` cannot be built from an \ + iterator over elements of type `{A}`"] +trait MyIterator { + fn next(&mut self) -> A; +} + +fn iterate_chars>(i: I) { + // ... +} + +fn main() { + iterate_chars(&[1, 2, 3][..]); +} +``` + +When the user compiles this, they will see the following; + +```txt +error[E0277]: the trait bound `&[{integer}]: MyIterator` is not satisfied + --> :14:5 + | +14 | iterate_chars(&[1, 2, 3][..]); + | ^^^^^^^^^^^^^ the trait `MyIterator` is not implemented for `&[{integer}]` + | + = note: a collection of type `&[{integer}]` cannot be built from an iterator over elements of type `char` + = note: required by `iterate_chars` + +error: aborting due to previous error +``` From d1f499309979fb53f4fa6d791cbfac803431579d Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Sat, 20 May 2017 11:47:51 -0400 Subject: [PATCH 03/11] Add basic Unstable Book entry for `catch_expr`. --- .../src/language-features/catch-expr.md | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/doc/unstable-book/src/language-features/catch-expr.md b/src/doc/unstable-book/src/language-features/catch-expr.md index 44eb2a6dd4fdb..fbd213dca5699 100644 --- a/src/doc/unstable-book/src/language-features/catch-expr.md +++ b/src/doc/unstable-book/src/language-features/catch-expr.md @@ -5,3 +5,26 @@ The tracking issue for this feature is: [#31436] [#31436]: https://github.com/rust-lang/rust/issues/31436 ------------------------ + +The `catch_expr` feature adds support for a `catch` expression. The `catch` +expression creates a new scope one can use the `?` operator in. + +```rust +#![feature(catch_expr)] + +use std::num::ParseIntError; + +let result: Result = do catch { + Ok("1".parse::()? + + "2".parse::()? + + "3".parse::()?) +}; +assert_eq!(result, Ok(6)); + +let result: Result = do catch { + Ok("1".parse::()? + + "foo".parse::()? + + "3".parse::()?) +}; +assert!(result.is_err()); +``` From 2d3438d35f8db4de0326f56232169b0bdbd6051c Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Sat, 20 May 2017 12:08:28 -0400 Subject: [PATCH 04/11] Add basic Unstable Book entry for `attr_literals`. --- .../src/language-features/attr-literals.md | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/doc/unstable-book/src/language-features/attr-literals.md b/src/doc/unstable-book/src/language-features/attr-literals.md index 67eee214a4f24..60741a74400d2 100644 --- a/src/doc/unstable-book/src/language-features/attr-literals.md +++ b/src/doc/unstable-book/src/language-features/attr-literals.md @@ -6,5 +6,25 @@ The tracking issue for this feature is: [#34981] ------------------------ +At present, literals are only accepted as the value of a key-value pair in +attributes. What's more, only _string_ literals are accepted. This means that +literals can only appear in forms of `#[attr(name = "value")]` or +`#[attr = "value"]`. +The `attr_literals` unstable feature allows other types of literals to be used +in attributes. Here are some examples of attributes that can now be used with +this feature enabled: + ++```rust,ignore ++#[attr] ++#[attr(true)] ++#[attr(ident)] ++#[attr(ident, 100, true, "true", ident = 100, ident = "hello", ident(100))] ++#[attr(100)] ++#[attr(enabled = true)] ++#[enabled(true)] ++#[attr("hello")] ++#[repr(C, align = 4)] ++#[repr(C, align(4))] ++``` From 9111d07a6ea8dad2685e8d39bffd654f231a24c2 Mon Sep 17 00:00:00 2001 From: Cengiz Can Date: Mon, 22 May 2017 01:34:36 +0300 Subject: [PATCH 05/11] make ui test output patch compatible #41948 --- src/tools/compiletest/src/runtest.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 911f3c51f5f60..1bec6f6af8381 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2415,11 +2415,11 @@ actual:\n\ println!("expected {}:\n{}\n", kind, expected); println!("diff of {}:\n", kind); - for diff in diff::lines(actual, expected) { + for diff in diff::lines(expected, actual) { match diff { - diff::Result::Left(l) => println!("+{}", l), + diff::Result::Left(l) => println!("-{}", l), diff::Result::Both(l, _) => println!(" {}", l), - diff::Result::Right(r) => println!("-{}", r), + diff::Result::Right(r) => println!("+{}", r), } } From 0cb6a1fad3f5ee54f05028c7f2fdd7844c8d16a8 Mon Sep 17 00:00:00 2001 From: Oliver Middleton Date: Mon, 22 May 2017 02:05:16 +0100 Subject: [PATCH 06/11] rustdoc: Fix names of items in cross crate reexported modules For renamed reexports the new name should be used. --- src/librustdoc/clean/inline.rs | 28 ++++----------- src/librustdoc/clean/mod.rs | 2 +- .../auxiliary/renamed-via-module.rs | 19 +++++++++++ .../inline_cross/renamed-via-module.rs | 34 +++++++++++++++++++ 4 files changed, 60 insertions(+), 23 deletions(-) create mode 100644 src/test/rustdoc/inline_cross/auxiliary/renamed-via-module.rs create mode 100644 src/test/rustdoc/inline_cross/renamed-via-module.rs diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 9dea0e3d83088..141efe471af5f 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -41,26 +41,11 @@ use super::Clean; /// /// The returned value is `None` if the definition could not be inlined, /// and `Some` of a vector of items if it was successfully expanded. -pub fn try_inline(cx: &DocContext, def: Def, into: Option) +pub fn try_inline(cx: &DocContext, def: Def, name: ast::Name) -> Option> { if def == Def::Err { return None } let did = def.def_id(); if did.is_local() { return None } - try_inline_def(cx, def).map(|vec| { - vec.into_iter().map(|mut item| { - match into { - Some(into) if item.name.is_some() => { - item.name = Some(into.clean(cx)); - } - _ => {} - } - item - }).collect() - }) -} - -fn try_inline_def(cx: &DocContext, def: Def) -> Option> { - let tcx = cx.tcx; let mut ret = Vec::new(); let inner = match def { Def::Trait(did) => { @@ -112,16 +97,15 @@ fn try_inline_def(cx: &DocContext, def: Def) -> Option> { } _ => return None, }; - let did = def.def_id(); cx.renderinfo.borrow_mut().inlined.insert(did); ret.push(clean::Item { - source: tcx.def_span(did).clean(cx), - name: Some(tcx.item_name(did).to_string()), + source: cx.tcx.def_span(did).clean(cx), + name: Some(name.clean(cx)), attrs: load_attrs(cx, did), inner: inner, visibility: Some(clean::Public), - stability: tcx.lookup_stability(did).clean(cx), - deprecation: tcx.lookup_deprecation(did).clean(cx), + stability: cx.tcx.lookup_stability(did).clean(cx), + deprecation: cx.tcx.lookup_deprecation(did).clean(cx), def_id: did, }); Some(ret) @@ -463,7 +447,7 @@ fn build_module(cx: &DocContext, did: DefId) -> clean::Module { let def_id = item.def.def_id(); if cx.tcx.sess.cstore.visibility(def_id) == ty::Visibility::Public { if !visited.insert(def_id) { continue } - if let Some(i) = try_inline_def(cx, item.def) { + if let Some(i) = try_inline(cx, item.def, item.name) { items.extend(i) } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 61f941e57b2d8..48d387f812d25 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2618,7 +2618,7 @@ impl Clean> for doctree::Import { } else { let name = self.name; if !denied { - if let Some(items) = inline::try_inline(cx, path.def, Some(name)) { + if let Some(items) = inline::try_inline(cx, path.def, name) { return items; } } diff --git a/src/test/rustdoc/inline_cross/auxiliary/renamed-via-module.rs b/src/test/rustdoc/inline_cross/auxiliary/renamed-via-module.rs new file mode 100644 index 0000000000000..9f7a259a7db03 --- /dev/null +++ b/src/test/rustdoc/inline_cross/auxiliary/renamed-via-module.rs @@ -0,0 +1,19 @@ +// Copyright 2017 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"] + +pub mod iter { + mod range { + pub struct StepBy; + } + pub use self::range::StepBy as DeprecatedStepBy; + pub struct StepBy; +} diff --git a/src/test/rustdoc/inline_cross/renamed-via-module.rs b/src/test/rustdoc/inline_cross/renamed-via-module.rs new file mode 100644 index 0000000000000..a4e0154376142 --- /dev/null +++ b/src/test/rustdoc/inline_cross/renamed-via-module.rs @@ -0,0 +1,34 @@ +// Copyright 2017 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. + +// aux-build:renamed-via-module.rs +// build-aux-docs +// ignore-cross-compile + +#![crate_name = "bar"] + +extern crate foo; + +// @has foo/iter/index.html +// @has - '//a/[@href="struct.DeprecatedStepBy.html"]' "DeprecatedStepBy" +// @has - '//a/[@href="struct.StepBy.html"]' "StepBy" +// @has foo/iter/struct.DeprecatedStepBy.html +// @has - '//h1' "Struct foo::iter::DeprecatedStepBy" +// @has foo/iter/struct.StepBy.html +// @has - '//h1' "Struct foo::iter::StepBy" + +// @has bar/iter/index.html +// @has - '//a/[@href="struct.DeprecatedStepBy.html"]' "DeprecatedStepBy" +// @has - '//a/[@href="struct.StepBy.html"]' "StepBy" +// @has bar/iter/struct.DeprecatedStepBy.html +// @has - '//h1' "Struct bar::iter::DeprecatedStepBy" +// @has bar/iter/struct.StepBy.html +// @has - '//h1' "Struct bar::iter::StepBy" +pub use foo::iter; From 78bdda1573878676c8ec4c3d6957d3adabda0c56 Mon Sep 17 00:00:00 2001 From: Colin Wallace Date: Mon, 22 May 2017 05:23:47 -0700 Subject: [PATCH 07/11] Mention Vec::into_boxed_slice in docs for [T]::into_vec. `Vec::into_boxed_slice` and `[T]::into_vec` are inverses, so it makes sense to mention the other in their respective documentation for visibility. `Vec::into_boxed_slice` already mentions `[T]::into_vec`, but not the other way around until now. --- src/libcollections/slice.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index 3efda1faa3b56..3012dcf0e392b 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -1410,6 +1410,11 @@ impl [T] { /// Converts `self` into a vector without clones or allocation. /// + /// The resulting vector can be converted back into a box via + /// the [`into_boxed_slice`] method. + /// + /// [`into_boxed_slice`]: vec/struct.Vec.html#method.into_boxed_slice + /// /// # Examples /// /// ``` From 819acb51412ef328542edafc02d233280dbcf26b Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 22 May 2017 16:55:00 +0200 Subject: [PATCH 08/11] Add missing links for CStr and CString --- src/libstd/ffi/c_str.rs | 104 ++++++++++++++++++++++++++++------------ 1 file changed, 74 insertions(+), 30 deletions(-) diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index f40475a41422b..1167c39dba8ee 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -23,18 +23,20 @@ use ptr; use slice; use str::{self, Utf8Error}; -/// A type representing an owned C-compatible string +/// A type representing an owned C-compatible string. /// /// This type serves the primary purpose of being able to safely generate a /// C-compatible string from a Rust byte slice or vector. An instance of this /// type is a static guarantee that the underlying bytes contain no interior 0 /// bytes and the final byte is 0. /// -/// A `CString` is created from either a byte slice or a byte vector. A `u8` -/// slice can be obtained with the `as_bytes` method. Slices produced from a +/// A `CString` is created from either a byte slice or a byte vector. A [`u8`] +/// slice can be obtained with the `as_bytes` method. Slices produced from a /// `CString` do *not* contain the trailing nul terminator unless otherwise /// specified. /// +/// [`u8`]: ../primitive.u8.html +/// /// # Examples /// /// ```no_run @@ -81,12 +83,14 @@ pub struct CString { /// /// Note that this structure is **not** `repr(C)` and is not recommended to be /// placed in the signatures of FFI functions. Instead safe wrappers of FFI -/// functions may leverage the unsafe `from_ptr` constructor to provide a safe +/// functions may leverage the unsafe [`from_ptr`] constructor to provide a safe /// interface to other consumers. /// +/// [`from_ptr`]: #method.from_ptr +/// /// # Examples /// -/// Inspecting a foreign C string +/// Inspecting a foreign C string: /// /// ```no_run /// use std::ffi::CStr; @@ -100,7 +104,7 @@ pub struct CString { /// } /// ``` /// -/// Passing a Rust-originating C string +/// Passing a Rust-originating C string: /// /// ```no_run /// use std::ffi::{CString, CStr}; @@ -116,7 +120,9 @@ pub struct CString { /// work(&s); /// ``` /// -/// Converting a foreign C string into a Rust `String` +/// Converting a foreign C string into a Rust [`String`]: +/// +/// [`String`]: ../string/struct.String.html /// /// ```no_run /// use std::ffi::CStr; @@ -142,14 +148,18 @@ pub struct CStr { inner: [c_char] } -/// An error returned from `CString::new` to indicate that a nul byte was found +/// An error returned from [`CString::new`] to indicate that a nul byte was found /// in the vector provided. +/// +/// [`CString::new`]: struct.CString.html#method.new #[derive(Clone, PartialEq, Eq, Debug)] #[stable(feature = "rust1", since = "1.0.0")] pub struct NulError(usize, Vec); -/// An error returned from `CStr::from_bytes_with_nul` to indicate that a nul +/// An error returned from [`CStr::from_bytes_with_nul`] to indicate that a nul /// byte was found too early in the slice provided or one wasn't found at all. +/// +/// [`CStr::from_bytes_with_nul`]: struct.CStr.html#method.from_bytes_with_nul #[derive(Clone, PartialEq, Eq, Debug)] #[stable(feature = "cstr_from_bytes", since = "1.10.0")] pub struct FromBytesWithNulError { @@ -175,8 +185,10 @@ impl FromBytesWithNulError { } } -/// An error returned from `CString::into_string` to indicate that a UTF-8 error +/// An error returned from [`CString::into_string`] to indicate that a UTF-8 error /// was encountered during the conversion. +/// +/// [`CString::into_string`]: struct.CString.html#method.into_string #[derive(Clone, PartialEq, Eq, Debug)] #[stable(feature = "cstring_into", since = "1.7.0")] pub struct IntoStringError { @@ -224,10 +236,12 @@ impl CString { /// Creates a C-compatible string from a byte vector without checking for /// interior 0 bytes. /// - /// This method is equivalent to `new` except that no runtime assertion + /// This method is equivalent to [`new`] except that no runtime assertion /// is made that `v` contains no 0 bytes, and it requires an actual /// byte vector, not anything that can be converted to one with Into. /// + /// [`new`]: #method.new + /// /// # Examples /// /// ``` @@ -252,9 +266,11 @@ impl CString { /// # Safety /// /// This should only ever be called with a pointer that was earlier - /// obtained by calling `into_raw` on a `CString`. Other usage (e.g. trying to take + /// obtained by calling [`into_raw`] on a `CString`. Other usage (e.g. trying to take /// ownership of a string that was allocated by foreign code) is likely to lead /// to undefined behavior or allocator corruption. + /// + /// [`into_raw`]: #method.into_raw #[stable(feature = "cstr_memory", since = "1.4.0")] pub unsafe fn from_raw(ptr: *mut c_char) -> CString { let len = libc::strlen(ptr) + 1; // Including the NUL byte @@ -265,19 +281,23 @@ impl CString { /// Transfers ownership of the string to a C caller. /// /// The pointer must be returned to Rust and reconstituted using - /// `from_raw` to be properly deallocated. Specifically, one + /// [`from_raw`] to be properly deallocated. Specifically, one /// should *not* use the standard C `free` function to deallocate /// this string. /// - /// Failure to call `from_raw` will lead to a memory leak. + /// Failure to call [`from_raw`] will lead to a memory leak. + /// + /// [`from_raw`]: #method.from_raw #[stable(feature = "cstr_memory", since = "1.4.0")] pub fn into_raw(self) -> *mut c_char { Box::into_raw(self.into_inner()) as *mut c_char } - /// Converts the `CString` into a `String` if it contains valid Unicode data. + /// Converts the `CString` into a [`String`] if it contains valid Unicode data. /// /// On failure, ownership of the original `CString` is returned. + /// + /// [`String`]: ../string/struct.String.html #[stable(feature = "cstring_into", since = "1.7.0")] pub fn into_string(self) -> Result { String::from_utf8(self.into_bytes()) @@ -299,8 +319,10 @@ impl CString { vec } - /// Equivalent to the `into_bytes` function except that the returned vector + /// Equivalent to the [`into_bytes`] function except that the returned vector /// includes the trailing nul byte. + /// + /// [`into_bytes`]: #method.into_bytes #[stable(feature = "cstring_into", since = "1.7.0")] pub fn into_bytes_with_nul(self) -> Vec { self.into_inner().into_vec() @@ -315,26 +337,34 @@ impl CString { &self.inner[..self.inner.len() - 1] } - /// Equivalent to the `as_bytes` function except that the returned slice + /// Equivalent to the [`as_bytes`] function except that the returned slice /// includes the trailing nul byte. + /// + /// [`as_bytes`]: #method.as_bytes #[stable(feature = "rust1", since = "1.0.0")] pub fn as_bytes_with_nul(&self) -> &[u8] { &self.inner } - /// Extracts a `CStr` slice containing the entire string. + /// Extracts a [`CStr`] slice containing the entire string. + /// + /// [`CStr`]: struct.CStr.html #[unstable(feature = "as_c_str", issue = "40380")] pub fn as_c_str(&self) -> &CStr { &*self } - /// Converts this `CString` into a boxed `CStr`. + /// Converts this `CString` into a boxed [`CStr`]. + /// + /// [`CStr`]: struct.CStr.html #[unstable(feature = "into_boxed_c_str", issue = "40380")] pub fn into_boxed_c_str(self) -> Box { unsafe { mem::transmute(self.into_inner()) } } - // Bypass "move out of struct which implements `Drop` trait" restriction. + // Bypass "move out of struct which implements [`Drop`] trait" restriction. + /// + /// [`Drop`]: ../ops/trait.Drop.html fn into_inner(self) -> Box<[u8]> { unsafe { let result = ptr::read(&self.inner); @@ -443,7 +473,9 @@ impl Default for Box { impl NulError { /// Returns the position of the nul byte in the slice that was provided to - /// `CString::new`. + /// [`CString::new`]. + /// + /// [`CString::new`]: struct.CString.html#method.new /// /// # Examples /// @@ -518,8 +550,10 @@ impl fmt::Display for FromBytesWithNulError { } impl IntoStringError { - /// Consumes this error, returning original `CString` which generated the + /// Consumes this error, returning original [`CString`] which generated the /// error. + /// + /// [`CString`]: struct.CString.html #[stable(feature = "cstring_into", since = "1.7.0")] pub fn into_cstring(self) -> CString { self.inner @@ -557,9 +591,9 @@ impl CStr { /// allows inspection and interoperation of non-owned C strings. This method /// is unsafe for a number of reasons: /// - /// * There is no guarantee to the validity of `ptr` + /// * There is no guarantee to the validity of `ptr`. /// * The returned lifetime is not guaranteed to be the actual lifetime of - /// `ptr` + /// `ptr`. /// * There is no guarantee that the memory pointed to by `ptr` contains a /// valid nul terminator byte at the end of the string. /// @@ -703,26 +737,30 @@ impl CStr { /// Converts this C string to a byte slice containing the trailing 0 byte. /// - /// This function is the equivalent of `to_bytes` except that it will retain + /// This function is the equivalent of [`to_bytes`] except that it will retain /// the trailing nul instead of chopping it off. /// /// > **Note**: This method is currently implemented as a 0-cost cast, but /// > it is planned to alter its definition in the future to perform the /// > length calculation whenever this method is called. + /// + /// [`to_bytes`]: #method.to_bytes #[stable(feature = "rust1", since = "1.0.0")] pub fn to_bytes_with_nul(&self) -> &[u8] { unsafe { mem::transmute(&self.inner) } } - /// Yields a `&str` slice if the `CStr` contains valid UTF-8. + /// Yields a [`&str`] slice if the `CStr` contains valid UTF-8. /// /// This function will calculate the length of this string and check for - /// UTF-8 validity, and then return the `&str` if it's valid. + /// UTF-8 validity, and then return the [`&str`] if it's valid. /// /// > **Note**: This method is currently implemented to check for validity /// > after a 0-cost cast, but it is planned to alter its definition in the /// > future to perform the length calculation in addition to the UTF-8 /// > check whenever this method is called. + /// + /// [`&str`]: ../primitive.str.html #[stable(feature = "cstr_to_str", since = "1.4.0")] pub fn to_str(&self) -> Result<&str, str::Utf8Error> { // NB: When CStr is changed to perform the length check in .to_bytes() @@ -732,23 +770,29 @@ impl CStr { str::from_utf8(self.to_bytes()) } - /// Converts a `CStr` into a `Cow`. + /// Converts a `CStr` into a [`Cow`]`<`[`str`]`>`. /// /// This function will calculate the length of this string (which normally /// requires a linear amount of work to be done) and then return the - /// resulting slice as a `Cow`, replacing any invalid UTF-8 sequences + /// resulting slice as a [`Cow`]`<`[`str`]`>`, replacing any invalid UTF-8 sequences /// with `U+FFFD REPLACEMENT CHARACTER`. /// /// > **Note**: This method is currently implemented to check for validity /// > after a 0-cost cast, but it is planned to alter its definition in the /// > future to perform the length calculation in addition to the UTF-8 /// > check whenever this method is called. + /// + /// [`Cow`]: ../borrow/enum.Cow.html + /// [`str`]: ../primitive.str.html #[stable(feature = "cstr_to_str", since = "1.4.0")] pub fn to_string_lossy(&self) -> Cow { String::from_utf8_lossy(self.to_bytes()) } - /// Converts a `Box` into a `CString` without copying or allocating. + /// Converts a [`Box`]`` into a [`CString`] without copying or allocating. + /// + /// [`Box`]: ../boxed/struct.Box.html + /// [`CString`]: struct.CString.html #[unstable(feature = "into_boxed_c_str", issue = "40380")] pub fn into_c_string(self: Box) -> CString { unsafe { mem::transmute(self) } From d2ef70f50c58bc8d87f6c71c2ce5e3802d7822f6 Mon Sep 17 00:00:00 2001 From: Venkata Giri Reddy Date: Mon, 22 May 2017 17:09:18 -0600 Subject: [PATCH 09/11] regression test for #38821 Closes #38821 r? @Mark-Simulacrum --- src/test/compile-fail/isssue-38821.rs | 43 +++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 src/test/compile-fail/isssue-38821.rs diff --git a/src/test/compile-fail/isssue-38821.rs b/src/test/compile-fail/isssue-38821.rs new file mode 100644 index 0000000000000..63de780e109eb --- /dev/null +++ b/src/test/compile-fail/isssue-38821.rs @@ -0,0 +1,43 @@ +// Copyright 2017 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. + +pub struct Nullable(T); + +pub trait NotNull {} + +pub trait IntoNullable { + type Nullable; +} + +impl IntoNullable for T { + type Nullable = Nullable; +} + +impl IntoNullable for Nullable { + type Nullable = Nullable; +} + +pub trait Expression { + type SqlType; +} + +pub trait Column: Expression {} + +#[derive(Debug, Copy, Clone)] +//~^ ERROR the trait bound `::SqlType: NotNull` is not satisfied +pub enum ColumnInsertValue where + Col: Column, + Expr: Expression::Nullable>, +{ + Expression(Col, Expr), + Default(Col), +} + +fn main() {} From 6e8e5c9fd72c7f793a65b710fe1ce346fd59d593 Mon Sep 17 00:00:00 2001 From: Colin Wallace Date: Mon, 22 May 2017 16:39:31 -0700 Subject: [PATCH 10/11] Slice::into_vec: Don't link to Vec::into_boxed_slice The documentation for this method appears on multiple different pages, which causes the relative links to not always work. --- src/libcollections/slice.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index 3012dcf0e392b..5696f5fe6a7ba 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -1411,9 +1411,7 @@ impl [T] { /// Converts `self` into a vector without clones or allocation. /// /// The resulting vector can be converted back into a box via - /// the [`into_boxed_slice`] method. - /// - /// [`into_boxed_slice`]: vec/struct.Vec.html#method.into_boxed_slice + /// `Vec`'s `into_boxed_slice` method. /// /// # Examples /// From 6e27bd8c0168c88f41866a6af75c2de08cbdb349 Mon Sep 17 00:00:00 2001 From: projektir Date: Mon, 22 May 2017 21:59:42 -0400 Subject: [PATCH 11/11] Adding links to option::Option --- src/libcore/option.rs | 86 ++++++++++++++++++++++++++++++------------- 1 file changed, 60 insertions(+), 26 deletions(-) diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 515f49d6f0bdd..e825acad4713e 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -174,7 +174,7 @@ impl Option { // Querying the contained values ///////////////////////////////////////////////////////////////////////// - /// Returns `true` if the option is a `Some` value. + /// Returns `true` if the option is a [`Some`] value. /// /// # Examples /// @@ -185,6 +185,8 @@ impl Option { /// let x: Option = None; /// assert_eq!(x.is_some(), false); /// ``` + /// + /// [`Some`]: #variant.Some #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn is_some(&self) -> bool { @@ -194,7 +196,7 @@ impl Option { } } - /// Returns `true` if the option is a `None` value. + /// Returns `true` if the option is a [`None`] value. /// /// # Examples /// @@ -205,6 +207,8 @@ impl Option { /// let x: Option = None; /// assert_eq!(x.is_none(), true); /// ``` + /// + /// [`None`]: #variant.None #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn is_none(&self) -> bool { @@ -269,13 +273,14 @@ impl Option { // Getting to contained values ///////////////////////////////////////////////////////////////////////// - /// Unwraps an option, yielding the content of a `Some`. + /// Unwraps an option, yielding the content of a [`Some`]. /// /// # Panics /// /// Panics if the value is a [`None`] with a custom panic message provided by /// `msg`. /// + /// [`Some`]: #variant.Some /// [`None`]: #variant.None /// /// # Examples @@ -298,16 +303,17 @@ impl Option { } } - /// Moves the value `v` out of the `Option` if it is `Some(v)`. + /// Moves the value `v` out of the `Option` if it is [`Some(v)`]. /// /// In general, because this function may panic, its use is discouraged. - /// Instead, prefer to use pattern matching and handle the `None` + /// Instead, prefer to use pattern matching and handle the [`None`] /// case explicitly. /// /// # Panics /// /// Panics if the self value equals [`None`]. /// + /// [`Some(v)`]: #variant.Some /// [`None`]: #variant.None /// /// # Examples @@ -395,7 +401,9 @@ impl Option { } /// Applies a function to the contained value (if any), - /// or returns a `default` (if not). + /// or returns a [`default`][] (if not). + /// + /// [`default`]: ../default/trait.Default.html#tymethod.default /// /// # Examples /// @@ -416,7 +424,9 @@ impl Option { } /// Applies a function to the contained value (if any), - /// or computes a `default` (if not). + /// or computes a [`default`][] (if not). + /// + /// [`default`]: ../default/trait.Default.html#tymethod.default /// /// # Examples /// @@ -438,12 +448,14 @@ impl Option { } } - /// Transforms the `Option` into a [`Result`], mapping `Some(v)` to - /// [`Ok(v)`] and `None` to [`Err(err)`][Err]. + /// Transforms the `Option` into a [`Result`], mapping [`Some(v)`] to + /// [`Ok(v)`] and [`None`] to [`Err(err)`]. /// /// [`Result`]: ../../std/result/enum.Result.html /// [`Ok(v)`]: ../../std/result/enum.Result.html#variant.Ok - /// [Err]: ../../std/result/enum.Result.html#variant.Err + /// [`Err(err)`]: ../../std/result/enum.Result.html#variant.Err + /// [`None`]: #variant.None + /// [`Some(v)`]: #variant.Some /// /// # Examples /// @@ -463,12 +475,14 @@ impl Option { } } - /// Transforms the `Option` into a [`Result`], mapping `Some(v)` to - /// [`Ok(v)`] and `None` to [`Err(err())`][Err]. + /// Transforms the `Option` into a [`Result`], mapping [`Some(v)`] to + /// [`Ok(v)`] and [`None`] to [`Err(err())`]. /// /// [`Result`]: ../../std/result/enum.Result.html /// [`Ok(v)`]: ../../std/result/enum.Result.html#variant.Ok - /// [Err]: ../../std/result/enum.Result.html#variant.Err + /// [`Err(err())`]: ../../std/result/enum.Result.html#variant.Err + /// [`None`]: #variant.None + /// [`Some(v)`]: #variant.Some /// /// # Examples /// @@ -534,7 +548,9 @@ impl Option { // Boolean operations on the values, eager and lazy ///////////////////////////////////////////////////////////////////////// - /// Returns `None` if the option is `None`, otherwise returns `optb`. + /// Returns [`None`] if the option is [`None`], otherwise returns `optb`. + /// + /// [`None`]: #variant.None /// /// # Examples /// @@ -564,11 +580,13 @@ impl Option { } } - /// Returns `None` if the option is `None`, otherwise calls `f` with the + /// Returns [`None`] if the option is [`None`], otherwise calls `f` with the /// wrapped value and returns the result. /// /// Some languages call this operation flatmap. /// + /// [`None`]: #variant.None + /// /// # Examples /// /// ``` @@ -645,9 +663,11 @@ impl Option { // Entry-like operations to insert if None and return a reference ///////////////////////////////////////////////////////////////////////// - /// Inserts `v` into the option if it is `None`, then + /// Inserts `v` into the option if it is [`None`], then /// returns a mutable reference to the contained value. /// + /// [`None`]: #variant.None + /// /// # Examples /// /// ``` @@ -678,9 +698,11 @@ impl Option { } } - /// Inserts a value computed from `f` into the option if it is `None`, then + /// Inserts a value computed from `f` into the option if it is [`None`], then /// returns a mutable reference to the contained value. /// + /// [`None`]: #variant.None + /// /// # Examples /// /// ``` @@ -715,7 +737,9 @@ impl Option { // Misc ///////////////////////////////////////////////////////////////////////// - /// Takes the value out of the option, leaving a `None` in its place. + /// Takes the value out of the option, leaving a [`None`] in its place. + /// + /// [`None`]: #variant.None /// /// # Examples /// @@ -757,16 +781,16 @@ impl<'a, T: Clone> Option<&'a T> { impl Option { /// Returns the contained value or a default /// - /// Consumes the `self` argument then, if `Some`, returns the contained - /// value, otherwise if `None`, returns the default value for that + /// Consumes the `self` argument then, if [`Some`], returns the contained + /// value, otherwise if [`None`], returns the default value for that /// type. /// /// # Examples /// /// Convert a string to an integer, turning poorly-formed strings - /// into 0 (the default value for integers). `parse` converts - /// a string to any other type that implements `FromStr`, returning - /// `None` on error. + /// into 0 (the default value for integers). [`parse`] converts + /// a string to any other type that implements [`FromStr`], returning + /// [`None`] on error. /// /// ``` /// let good_year_from_input = "1909"; @@ -777,6 +801,11 @@ impl Option { /// assert_eq!(1909, good_year); /// assert_eq!(0, bad_year); /// ``` + /// + /// [`Some`]: #variant.Some + /// [`None`]: #variant.None + /// [`parse`]: ../../std/primitive.str.html#method.parse + /// [`FromStr`]: ../../std/str/trait.FromStr.html #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn unwrap_or_default(self) -> T { @@ -801,7 +830,9 @@ fn expect_failed(msg: &str) -> ! { #[stable(feature = "rust1", since = "1.0.0")] impl Default for Option { - /// Returns None. + /// Returns [`None`]. + /// + /// [`None`]: #variant.None #[inline] fn default() -> Option { None } } @@ -1020,8 +1051,8 @@ unsafe impl TrustedLen for IntoIter {} #[stable(feature = "rust1", since = "1.0.0")] impl> FromIterator> for Option { - /// Takes each element in the `Iterator`: if it is `None`, no further - /// elements are taken, and the `None` is returned. Should no `None` occur, a + /// Takes each element in the [`Iterator`]: if it is [`None`], no further + /// elements are taken, and the [`None`] is returned. Should no [`None`] occur, a /// container with the values of each `Option` is returned. /// /// Here is an example which increments every integer in a vector, @@ -1037,6 +1068,9 @@ impl> FromIterator> for Option { /// ).collect(); /// assert!(res == Some(vec![2, 3])); /// ``` + /// + /// [`Iterator`]: ../iter/trait.Iterator.html + /// [`None`]: enum.Option.html#variant.None #[inline] fn from_iter>>(iter: I) -> Option { // FIXME(#11084): This could be replaced with Iterator::scan when this