Auto merge of #81417 - JohnTitor:rollup-yi3q05s, r=JohnTitor

Rollup of 14 pull requests

Successful merges:

 - #80812 (Update RELEASES.md for 1.50.0)
 - #80876 (Add `unwrap_unchecked()` methods for `Option` and `Result`)
 - #80900 (Fix ICE with `ReadPointerAsBytes` validation error)
 - #81191 (BTreeMap: test all borrowing interfaces and test more chaotic order behavior)
 - #81195 (Account for generics when suggesting bound)
 - #81299 (Fix some bugs reported by eslint)
 - #81325 (typeck: Don't suggest converting LHS exprs)
 - #81353 (Fix spelling in documentation for error E0207)
 - #81369 (rustc_codegen_ssa: use wall time for codegen_to_LLVM_IR time-passes entry)
 - #81389 (rustdoc: Document CommonMark extensions.)
 - #81399 (Update books)
 - #81401 (tidy: Some code cleanup.)
 - #81407 (Refine "remove semicolon" suggestion in trait selection)
 - #81412 (Fix assertion in `MaybeUninit::array_assume_init()` for zero-length arrays)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2021-01-26 19:44:26 +00:00
commit d1aed50ab8
38 changed files with 748 additions and 187 deletions

View File

@ -1,3 +1,123 @@
Version 1.50.0 (2021-02-11)
============================
Language
-----------------------
- [You can now use `const` values for `x` in `[x; N]` array expressions.][79270]
This has been technically possible since 1.38.0, as it was unintentionally stabilized.
- [Assignments to `ManuallyDrop<T>` union fields are now considered safe.][78068]
Compiler
-----------------------
- [Added tier 3\* support for the `armv5te-unknown-linux-uclibceabi` target.][78142]
- [Added tier 3 support for the `aarch64-apple-ios-macabi` target.][77484]
- [The `x86_64-unknown-freebsd` is now built with the full toolset.][79484]
\* Refer to Rust's [platform support page][forge-platform-support] for more
information on Rust's tiered platform support.
Libraries
-----------------------
- [`proc_macro::Punct` now implements `PartialEq<char>`.][78636]
- [`ops::{Index, IndexMut}` are now implemented for fixed sized arrays of any length.][74989]
- [On Unix platforms, the `std::fs::File` type now has a "niche" of `-1`.][74699]
This value cannot be a valid file descriptor, and now means `Option<File>` takes
up the same amount of space as `File`.
Stabilized APIs
---------------
- [`bool::then`]
- [`btree_map::Entry::or_insert_with_key`]
- [`f32::clamp`]
- [`f64::clamp`]
- [`hash_map::Entry::or_insert_with_key`]
- [`Ord::clamp`]
- [`RefCell::take`]
- [`slice::fill`]
- [`UnsafeCell::get_mut`]
The following previously stable methods are now `const`.
- [`IpAddr::is_ipv4`]
- [`IpAddr::is_ipv6`]
- [`Layout::size`]
- [`Layout::align`]
- [`Layout::from_size_align`]
- `pow` for all integer types.
- `checked_pow` for all integer types.
- `saturating_pow` for all integer types.
- `wrapping_pow` for all integer types.
- `next_power_of_two` for all unsigned integer types.
- `checked_power_of_two` for all unsigned integer types.
Cargo
-----------------------
- [Added the `[build.rustc-workspace-wrapper]` option.][cargo/8976]
This option sets a wrapper to execute instead of `rustc`, for workspace members only.
- [`cargo:rerun-if-changed` will now, if provided a directory, scan the entire
contents of that directory for changes.][cargo/8973]
- [Added the `--workspace` flag to the `cargo update` command.][cargo/8725]
Misc
----
- [The search results tab and the help button are focusable with keyboard in rustdoc.][79896]
- [Running tests will now print the total time taken to execute.][75752]
Compatibility Notes
-------------------
- [The `compare_and_swap` method on atomics has been deprecated.][79261] It's
recommended to use the `compare_exchange` and `compare_exchange_weak` methods instead.
- [Changes in how `TokenStream`s are checked have fixed some cases where you could write
unhygenic `macro_rules!` macros.][79472]
- [`#![test]` as an inner attribute is now considered unstable like other inner macro
attributes, and reports an error by default through the `soft_unstable` lint.][79003]
- [Overriding a `forbid` lint at the same level that it was set is now a hard error.][78864]
- [Dropped support for all cloudabi targets.][78439]
- [You can no longer intercept `panic!` calls by supplying your own macro.][78343] It's
recommended to use the `#[panic_handler]` attribute to provide your own implementation.
- [Semi-colons after item statements (e.g. `struct Foo {};`) now produce a warning.][78296]
[74989]: https://github.com/rust-lang/rust/pull/74989
[79261]: https://github.com/rust-lang/rust/pull/79261
[79896]: https://github.com/rust-lang/rust/pull/79896
[79484]: https://github.com/rust-lang/rust/pull/79484
[79472]: https://github.com/rust-lang/rust/pull/79472
[79270]: https://github.com/rust-lang/rust/pull/79270
[79003]: https://github.com/rust-lang/rust/pull/79003
[78864]: https://github.com/rust-lang/rust/pull/78864
[78636]: https://github.com/rust-lang/rust/pull/78636
[78439]: https://github.com/rust-lang/rust/pull/78439
[78343]: https://github.com/rust-lang/rust/pull/78343
[78296]: https://github.com/rust-lang/rust/pull/78296
[78068]: https://github.com/rust-lang/rust/pull/78068
[75752]: https://github.com/rust-lang/rust/pull/75752
[74699]: https://github.com/rust-lang/rust/pull/74699
[78142]: https://github.com/rust-lang/rust/pull/78142
[77484]: https://github.com/rust-lang/rust/pull/77484
[cargo/8976]: https://github.com/rust-lang/cargo/pull/8976
[cargo/8973]: https://github.com/rust-lang/cargo/pull/8973
[cargo/8725]: https://github.com/rust-lang/cargo/pull/8725
[`IpAddr::is_ipv4`]: https://doc.rust-lang.org/stable/std/net/enum.IpAddr.html#method.is_ipv4
[`IpAddr::is_ipv6`]: https://doc.rust-lang.org/stable/std/net/enum.IpAddr.html#method.is_ipv6
[`Layout::align`]: https://doc.rust-lang.org/stable/std/alloc/struct.Layout.html#method.align
[`Layout::from_size_align`]: https://doc.rust-lang.org/stable/std/alloc/struct.Layout.html#method.from_size_align
[`Layout::size`]: https://doc.rust-lang.org/stable/std/alloc/struct.Layout.html#method.size
[`Ord::clamp`]: https://doc.rust-lang.org/stable/std/cmp/trait.Ord.html#method.clamp
[`RefCell::take`]: https://doc.rust-lang.org/stable/std/cell/struct.RefCell.html#method.take
[`UnsafeCell::get_mut`]: https://doc.rust-lang.org/stable/std/cell/struct.UnsafeCell.html#method.get_mut
[`bool::then`]: https://doc.rust-lang.org/stable/std/primitive.bool.html#method.then
[`btree_map::Entry::or_insert_with_key`]: https://doc.rust-lang.org/stable/std/collections/btree_map/enum.Entry.html#method.or_insert_with_key
[`f32::clamp`]: https://doc.rust-lang.org/stable/std/primitive.f32.html#method.clamp
[`f64::clamp`]: https://doc.rust-lang.org/stable/std/primitive.f64.html#method.clamp
[`hash_map::Entry::or_insert_with_key`]: https://doc.rust-lang.org/stable/std/collections/hash_map/enum.Entry.html#method.or_insert_with_key
[`slice::fill`]: https://doc.rust-lang.org/stable/std/primitive.slice.html#method.fill
Version 1.49.0 (2020-12-31)
============================

View File

@ -13,7 +13,7 @@ use crate::{CachedModuleCodegen, CrateInfo, MemFlags, ModuleCodegen, ModuleKind}
use rustc_attr as attr;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::profiling::print_time_passes_entry;
use rustc_data_structures::sync::{par_iter, Lock, ParallelIterator};
use rustc_data_structures::sync::{par_iter, ParallelIterator};
use rustc_hir as hir;
use rustc_hir::def_id::{LocalDefId, LOCAL_CRATE};
use rustc_hir::lang_items::LangItem;
@ -554,8 +554,6 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
codegen_units
};
let total_codegen_time = Lock::new(Duration::new(0, 0));
// The non-parallel compiler can only translate codegen units to LLVM IR
// on a single thread, leading to a staircase effect where the N LLVM
// threads have to wait on the single codegen threads to generate work
@ -578,23 +576,25 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
.collect();
// Compile the found CGUs in parallel.
par_iter(cgus)
let start_time = Instant::now();
let pre_compiled_cgus = par_iter(cgus)
.map(|(i, _)| {
let start_time = Instant::now();
let module = backend.compile_codegen_unit(tcx, codegen_units[i].name());
let mut time = total_codegen_time.lock();
*time += start_time.elapsed();
(i, module)
})
.collect()
.collect();
(pre_compiled_cgus, start_time.elapsed())
})
} else {
FxHashMap::default()
(FxHashMap::default(), Duration::new(0, 0))
}
};
let mut cgu_reuse = Vec::new();
let mut pre_compiled_cgus: Option<FxHashMap<usize, _>> = None;
let mut total_codegen_time = Duration::new(0, 0);
for (i, cgu) in codegen_units.iter().enumerate() {
ongoing_codegen.wait_for_signal_to_codegen_item();
@ -607,7 +607,9 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
codegen_units.iter().map(|cgu| determine_cgu_reuse(tcx, &cgu)).collect()
});
// Pre compile some CGUs
pre_compiled_cgus = Some(pre_compile_cgus(&cgu_reuse));
let (compiled_cgus, codegen_time) = pre_compile_cgus(&cgu_reuse);
pre_compiled_cgus = Some(compiled_cgus);
total_codegen_time += codegen_time;
}
let cgu_reuse = cgu_reuse[i];
@ -621,8 +623,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
} else {
let start_time = Instant::now();
let module = backend.compile_codegen_unit(tcx, cgu.name());
let mut time = total_codegen_time.lock();
*time += start_time.elapsed();
total_codegen_time += start_time.elapsed();
module
};
submit_codegened_module_to_llvm(
@ -663,11 +664,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
// Since the main thread is sometimes blocked during codegen, we keep track
// -Ztime-passes output manually.
print_time_passes_entry(
tcx.sess.time_passes(),
"codegen_to_LLVM_IR",
total_codegen_time.into_inner(),
);
print_time_passes_entry(tcx.sess.time_passes(), "codegen_to_LLVM_IR", total_codegen_time);
ongoing_codegen.check_for_errors(tcx.sess);

View File

@ -14,7 +14,7 @@ impl<T: Default> Foo {
}
```
Any type parameter parameter of an `impl` must meet at least one of
Any type parameter of an `impl` must meet at least one of
the following criteria:
- it appears in the _implementing type_ of the impl, e.g. `impl<T> Foo<T>`

View File

@ -566,6 +566,17 @@ impl<'hir> Map<'hir> {
)
}
/// Checks if the node is left-hand side of an assignment.
pub fn is_lhs(&self, id: HirId) -> bool {
match self.find(self.get_parent_node(id)) {
Some(Node::Expr(expr)) => match expr.kind {
ExprKind::Assign(lhs, _rhs, _span) => lhs.hir_id == id,
_ => false,
},
_ => false,
}
}
/// Whether the expression pointed at by `hir_id` belongs to a `const` evaluation context.
/// Used exclusively for diagnostics, to avoid suggestion function calls.
pub fn is_inside_const_context(&self, hir_id: HirId) -> bool {

View File

@ -515,7 +515,11 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
Ok(true)
}
ty::Float(_) | ty::Int(_) | ty::Uint(_) => {
let value = self.ecx.read_scalar(value)?;
let value = try_validation!(
self.ecx.read_scalar(value),
self.path,
err_unsup!(ReadPointerAsBytes) => { "read of part of a pointer" },
);
// NOTE: Keep this in sync with the array optimization for int/float
// types below!
if self.ctfe_mode.is_some() {

View File

@ -286,21 +286,32 @@ fn suggest_restriction(
);
} else {
// Trivial case: `T` needs an extra bound: `T: Bound`.
let (sp, suggestion) = match super_traits {
None => predicate_constraint(
let (sp, suggestion) = match (
generics
.params
.iter()
.filter(
|p| !matches!(p.kind, hir::GenericParamKind::Type { synthetic: Some(_), ..}),
)
.next(),
super_traits,
) {
(_, None) => predicate_constraint(
generics,
trait_ref.without_const().to_predicate(tcx).to_string(),
),
Some((ident, bounds)) => match bounds {
[.., bound] => (
bound.span().shrink_to_hi(),
format!(" + {}", trait_ref.print_only_trait_path().to_string()),
),
[] => (
ident.span.shrink_to_hi(),
format!(": {}", trait_ref.print_only_trait_path().to_string()),
),
},
(None, Some((ident, []))) => (
ident.span.shrink_to_hi(),
format!(": {}", trait_ref.print_only_trait_path().to_string()),
),
(_, Some((_, [.., bounds]))) => (
bounds.span().shrink_to_hi(),
format!(" + {}", trait_ref.print_only_trait_path().to_string()),
),
(Some(_), Some((_, []))) => (
generics.span.shrink_to_hi(),
format!(": {}", trait_ref.print_only_trait_path().to_string()),
),
};
err.span_suggestion_verbose(
@ -888,8 +899,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
// no return, suggest removal of semicolon on last statement.
// Once that is added, close #54771.
if let Some(ref stmt) = blk.stmts.last() {
let sp = self.tcx.sess.source_map().end_point(stmt.span);
err.span_label(sp, "consider removing this semicolon");
if let hir::StmtKind::Semi(_) = stmt.kind {
let sp = self.tcx.sess.source_map().end_point(stmt.span);
err.span_label(sp, "consider removing this semicolon");
}
}
}
}

View File

@ -816,6 +816,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|err: &mut DiagnosticBuilder<'_>,
found_to_exp_is_fallible: bool,
exp_to_found_is_fallible: bool| {
let exp_is_lhs =
expected_ty_expr.map(|e| self.tcx.hir().is_lhs(e.hir_id)).unwrap_or(false);
if exp_is_lhs {
return;
}
let always_fallible = found_to_exp_is_fallible
&& (exp_to_found_is_fallible || expected_ty_expr.is_none());
let msg = if literal_is_ty_suffixed(expr) {

View File

@ -777,7 +777,7 @@ fn test_range_backwards_4() {
#[test]
#[should_panic]
fn test_range_backwards_5() {
fn test_range_finding_ill_order_in_map() {
let mut map = BTreeMap::new();
map.insert(Cyclic3::B, ());
// Lacking static_assert, call `range` conditionally, to emphasise that
@ -788,6 +788,47 @@ fn test_range_backwards_5() {
}
}
#[test]
#[should_panic]
fn test_range_finding_ill_order_in_range_ord() {
// Has proper order the first time asked, then flips around.
struct EvilTwin(i32);
impl PartialOrd for EvilTwin {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
static COMPARES: AtomicUsize = AtomicUsize::new(0);
impl Ord for EvilTwin {
fn cmp(&self, other: &Self) -> Ordering {
let ord = self.0.cmp(&other.0);
if COMPARES.fetch_add(1, SeqCst) > 0 { ord.reverse() } else { ord }
}
}
impl PartialEq for EvilTwin {
fn eq(&self, other: &Self) -> bool {
self.0.eq(&other.0)
}
}
impl Eq for EvilTwin {}
#[derive(PartialEq, Eq, PartialOrd, Ord)]
struct CompositeKey(i32, EvilTwin);
impl Borrow<EvilTwin> for CompositeKey {
fn borrow(&self) -> &EvilTwin {
&self.1
}
}
let map = (0..12).map(|i| (CompositeKey(i, EvilTwin(i)), ())).collect::<BTreeMap<_, _>>();
map.range(EvilTwin(5)..=EvilTwin(7));
}
#[test]
fn test_range_1000() {
// Miri is too slow
@ -1222,6 +1263,51 @@ fn test_borrow() {
map.insert(Rc::new(0), 1);
assert_eq!(map[&0], 1);
}
#[allow(dead_code)]
fn get<T: Ord>(v: &BTreeMap<Box<T>, ()>, t: &T) {
v.get(t);
}
#[allow(dead_code)]
fn get_mut<T: Ord>(v: &mut BTreeMap<Box<T>, ()>, t: &T) {
v.get_mut(t);
}
#[allow(dead_code)]
fn get_key_value<T: Ord>(v: &BTreeMap<Box<T>, ()>, t: &T) {
v.get_key_value(t);
}
#[allow(dead_code)]
fn contains_key<T: Ord>(v: &BTreeMap<Box<T>, ()>, t: &T) {
v.contains_key(t);
}
#[allow(dead_code)]
fn range<T: Ord>(v: &BTreeMap<Box<T>, ()>, t: T) {
v.range(t..);
}
#[allow(dead_code)]
fn range_mut<T: Ord>(v: &mut BTreeMap<Box<T>, ()>, t: T) {
v.range_mut(t..);
}
#[allow(dead_code)]
fn remove<T: Ord>(v: &mut BTreeMap<Box<T>, ()>, t: &T) {
v.remove(t);
}
#[allow(dead_code)]
fn remove_entry<T: Ord>(v: &mut BTreeMap<Box<T>, ()>, t: &T) {
v.remove_entry(t);
}
#[allow(dead_code)]
fn split_off<T: Ord>(v: &mut BTreeMap<Box<T>, ()>, t: &T) {
v.split_off(t);
}
}
#[test]

View File

@ -839,7 +839,7 @@ impl<T> MaybeUninit<T> {
// * MaybeUnint does not drop, so there are no double-frees
// And thus the conversion is safe
unsafe {
intrinsics::assert_inhabited::<T>();
intrinsics::assert_inhabited::<[T; N]>();
(&array as *const _ as *const [T; N]).read()
}
}

View File

@ -428,6 +428,40 @@ impl<T> Option<T> {
}
}
/// Returns the contained [`Some`] value, consuming the `self` value,
/// without checking that the value is not [`None`].
///
/// # Safety
///
/// Calling this method on [`None`] is *[undefined behavior]*.
///
/// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
///
/// # Examples
///
/// ```
/// #![feature(option_result_unwrap_unchecked)]
/// let x = Some("air");
/// assert_eq!(unsafe { x.unwrap_unchecked() }, "air");
/// ```
///
/// ```no_run
/// #![feature(option_result_unwrap_unchecked)]
/// let x: Option<&str> = None;
/// assert_eq!(unsafe { x.unwrap_unchecked() }, "air"); // Undefined behavior!
/// ```
#[inline]
#[track_caller]
#[unstable(feature = "option_result_unwrap_unchecked", reason = "newly added", issue = "81383")]
pub unsafe fn unwrap_unchecked(self) -> T {
debug_assert!(self.is_some());
match self {
Some(val) => val,
// SAFETY: the safety contract must be upheld by the caller.
None => unsafe { hint::unreachable_unchecked() },
}
}
/////////////////////////////////////////////////////////////////////////
// Transforming contained values
/////////////////////////////////////////////////////////////////////////

View File

@ -229,7 +229,7 @@
use crate::iter::{self, FromIterator, FusedIterator, TrustedLen};
use crate::ops::{self, Deref, DerefMut};
use crate::{convert, fmt};
use crate::{convert, fmt, hint};
/// `Result` is a type that represents either success ([`Ok`]) or failure ([`Err`]).
///
@ -821,6 +821,74 @@ impl<T, E> Result<T, E> {
Err(e) => op(e),
}
}
/// Returns the contained [`Ok`] value, consuming the `self` value,
/// without checking that the value is not an [`Err`].
///
/// # Safety
///
/// Calling this method on an [`Err`] is *[undefined behavior]*.
///
/// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
///
/// # Examples
///
/// ```
/// #![feature(option_result_unwrap_unchecked)]
/// let x: Result<u32, &str> = Ok(2);
/// assert_eq!(unsafe { x.unwrap_unchecked() }, 2);
/// ```
///
/// ```no_run
/// #![feature(option_result_unwrap_unchecked)]
/// let x: Result<u32, &str> = Err("emergency failure");
/// unsafe { x.unwrap_unchecked(); } // Undefined behavior!
/// ```
#[inline]
#[track_caller]
#[unstable(feature = "option_result_unwrap_unchecked", reason = "newly added", issue = "81383")]
pub unsafe fn unwrap_unchecked(self) -> T {
debug_assert!(self.is_ok());
match self {
Ok(t) => t,
// SAFETY: the safety contract must be upheld by the caller.
Err(_) => unsafe { hint::unreachable_unchecked() },
}
}
/// Returns the contained [`Err`] value, consuming the `self` value,
/// without checking that the value is not an [`Ok`].
///
/// # Safety
///
/// Calling this method on an [`Ok`] is *[undefined behavior]*.
///
/// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
///
/// # Examples
///
/// ```no_run
/// #![feature(option_result_unwrap_unchecked)]
/// let x: Result<u32, &str> = Ok(2);
/// unsafe { x.unwrap_err_unchecked() }; // Undefined behavior!
/// ```
///
/// ```
/// #![feature(option_result_unwrap_unchecked)]
/// let x: Result<u32, &str> = Err("emergency failure");
/// assert_eq!(unsafe { x.unwrap_err_unchecked() }, "emergency failure");
/// ```
#[inline]
#[track_caller]
#[unstable(feature = "option_result_unwrap_unchecked", reason = "newly added", issue = "81383")]
pub unsafe fn unwrap_err_unchecked(self) -> E {
debug_assert!(self.is_err());
match self {
// SAFETY: the safety contract must be upheld by the caller.
Ok(_) => unsafe { hint::unreachable_unchecked() },
Err(e) => e,
}
}
}
impl<T: Copy, E> Result<&T, E> {

View File

@ -64,6 +64,7 @@
#![feature(const_raw_ptr_deref)]
#![feature(never_type)]
#![feature(unwrap_infallible)]
#![feature(option_result_unwrap_unchecked)]
#![feature(option_unwrap_none)]
#![feature(peekable_next_if)]
#![feature(peekable_peek_mut)]

View File

@ -152,6 +152,8 @@ fn uninit_array_assume_init() {
let array = unsafe { MaybeUninit::array_assume_init(array) };
assert_eq!(array, [3, 1, 4, 1, 5]);
let [] = unsafe { MaybeUninit::<!>::array_assume_init([]) };
}
#[test]

View File

@ -160,6 +160,13 @@ fn test_unwrap_or_else() {
assert_eq!(x.unwrap_or_else(|| 2), 2);
}
#[test]
fn test_unwrap_unchecked() {
assert_eq!(unsafe { Some(1).unwrap_unchecked() }, 1);
let s = unsafe { Some("hello".to_string()).unwrap_unchecked() };
assert_eq!(s, "hello");
}
#[test]
fn test_iter() {
let val = 5;

View File

@ -119,6 +119,18 @@ pub fn test_unwrap_or_else_panic() {
let _: isize = bad_err.unwrap_or_else(handler);
}
#[test]
fn test_unwrap_unchecked() {
let ok: Result<isize, &'static str> = Ok(100);
assert_eq!(unsafe { ok.unwrap_unchecked() }, 100);
}
#[test]
fn test_unwrap_err_unchecked() {
let ok_err: Result<isize, &'static str> = Err("Err");
assert_eq!(unsafe { ok_err.unwrap_err_unchecked() }, "Err");
}
#[test]
pub fn test_expect_ok() {
let ok: Result<isize, &'static str> = Ok(100);

@ -1 +1 @@
Subproject commit ac57a0ddd23d173b26731ccf939f3ba729753275
Subproject commit e724bd826580ff95df48a8533af7dec1080693d4

@ -1 +1 @@
Subproject commit a8584998eacdea7106a1dfafcbf6c1c06fcdf925
Subproject commit bbf06ad39d1f45654047e9596b750cc6e6d1b693

@ -1 +1 @@
Subproject commit 50af691f838937c300b47812d0507c6d88c14f97
Subproject commit f02b09eb6e8af340ad1256a54adb7aae2ff3163e

@ -1 +1 @@
Subproject commit 03e23af01f0b4f83a3a513da280e1ca92587f2ec
Subproject commit f633769acef68574427a6fae6c06f13bc2199573

View File

@ -153,11 +153,73 @@ and finally provides a code example.
## Markdown
`rustdoc` uses the [commonmark markdown specification]. You might be
`rustdoc` uses the [CommonMark markdown specification]. You might be
interested into taking a look at their website to see what's possible to do.
- [commonmark quick reference]
- [current spec]
In addition to the standard CommonMark syntax, `rustdoc` supports several
extensions:
### Strikethrough
Text may be rendered with a horizontal line through the center by wrapping the
text with two tilde characters on each side:
```text
An example of ~~strikethrough text~~.
```
This example will render as:
> An example of ~~strikethrough text~~.
This follows the [GitHub Strikethrough extension][strikethrough].
### Footnotes
A footnote generates a small numbered link in the text which when clicked
takes the reader to the footnote text at the bottom of the item. The footnote
label is written similarly to a link reference with a caret at the front. The
footnote text is written like a link reference definition, with the text
following the label. Example:
```text
This is an example of a footnote[^note].
[^note]: This text is the contents of the footnote, which will be rendered
towards the bottom.
```
This example will render as:
> This is an example of a footnote[^note].
>
> [^note]: This text is the contents of the footnote, which will be rendered
> towards the bottom.
The footnotes are automatically numbered based on the order the footnotes are
written.
### Tables
Tables can be written using pipes and dashes to draw the rows and columns of
the table. These will be translated to HTML table matching the shape. Example:
```text
| Header1 | Header2 |
|---------|---------|
| abc | def |
```
This example will render similarly to this:
> | Header1 | Header2 |
> |---------|---------|
> | abc | def |
See the specification for the [GitHub Tables extension][tables] for more
details on the exact syntax supported.
[`backtrace`]: https://docs.rs/backtrace/0.3.50/backtrace/
[commonmark markdown specification]: https://commonmark.org/
@ -170,3 +232,5 @@ interested into taking a look at their website to see what's possible to do.
[standard library]: https://doc.rust-lang.org/stable/std/index.html
[current spec]: https://spec.commonmark.org/current/
[`std::env`]: https://doc.rust-lang.org/stable/std/env/index.html#functions
[strikethrough]: https://github.github.com/gfm/#strikethrough-extension-
[tables]: https://github.github.com/gfm/#tables-extension-

View File

@ -1,9 +1,6 @@
// From rust:
/* global ALIASES */
// Local js definitions:
/* global addClass, getCurrentValue, hasClass */
/* global onEachLazy, hasOwnProperty, removeClass, updateLocalStorage */
/* global addClass, getSettingValue, hasClass */
/* global onEach, onEachLazy, hasOwnProperty, removeClass, updateLocalStorage */
/* global hideThemeButtonState, showThemeButtonState */
if (!String.prototype.startsWith) {
@ -2214,7 +2211,7 @@ function defocusSearchBar() {
}
}
function toggleAllDocs(pageId, fromAutoCollapse) {
function toggleAllDocs(fromAutoCollapse) {
var innerToggle = document.getElementById(toggleAllDocsId);
if (!innerToggle) {
return;
@ -2257,14 +2254,14 @@ function defocusSearchBar() {
}
if (!parent || !superParent || superParent.id !== "main" ||
hasClass(parent, "impl") === false) {
collapseDocs(e, "hide", pageId);
collapseDocs(e, "hide");
}
});
}
}
}
function collapseDocs(toggle, mode, pageId) {
function collapseDocs(toggle, mode) {
if (!toggle || !toggle.parentNode) {
return;
}
@ -2384,27 +2381,27 @@ function defocusSearchBar() {
}
}
function collapser(pageId, e, collapse) {
function collapser(e, collapse) {
// inherent impl ids are like "impl" or impl-<number>'.
// they will never be hidden by default.
var n = e.parentElement;
if (n.id.match(/^impl(?:-\d+)?$/) === null) {
// Automatically minimize all non-inherent impls
if (collapse || hasClass(n, "impl")) {
collapseDocs(e, "hide", pageId);
collapseDocs(e, "hide");
}
}
}
function autoCollapse(pageId, collapse) {
function autoCollapse(collapse) {
if (collapse) {
toggleAllDocs(pageId, true);
toggleAllDocs(true);
} else if (getSettingValue("auto-hide-trait-implementations") !== "false") {
var impl_list = document.getElementById("trait-implementations-list");
if (impl_list !== null) {
onEachLazy(impl_list.getElementsByClassName("collapse-toggle"), function(e) {
collapser(pageId, e, collapse);
collapser(e, collapse);
});
}
@ -2412,7 +2409,7 @@ function defocusSearchBar() {
if (blanket_list !== null) {
onEachLazy(blanket_list.getElementsByClassName("collapse-toggle"), function(e) {
collapser(pageId, e, collapse);
collapser(e, collapse);
});
}
}
@ -2475,7 +2472,6 @@ function defocusSearchBar() {
var toggle = createSimpleToggle(false);
var hideMethodDocs = getSettingValue("auto-hide-method-docs") === "true";
var hideImplementors = getSettingValue("auto-collapse-implementors") !== "false";
var pageId = getPageId();
var func = function(e) {
var next = e.nextElementSibling;
@ -2489,7 +2485,7 @@ function defocusSearchBar() {
var newToggle = toggle.cloneNode(true);
insertAfter(newToggle, e.childNodes[e.childNodes.length - 1]);
if (hideMethodDocs === true && hasClass(e, "method") === true) {
collapseDocs(newToggle, "hide", pageId);
collapseDocs(newToggle, "hide");
}
}
};
@ -2513,7 +2509,7 @@ function defocusSearchBar() {
// In case the option "auto-collapse implementors" is not set to false, we collapse
// all implementors.
if (hideImplementors === true && e.parentNode.id === "implementors-list") {
collapseDocs(newToggle, "hide", pageId);
collapseDocs(newToggle, "hide");
}
}
};
@ -2527,7 +2523,7 @@ function defocusSearchBar() {
if (e.id.match(/^impl(?:-\d+)?$/) === null) {
// Automatically minimize all non-inherent impls
if (hasClass(e, "impl") === true) {
collapseDocs(newToggle, "hide", pageId);
collapseDocs(newToggle, "hide");
}
}
};
@ -2562,14 +2558,12 @@ function defocusSearchBar() {
}
onEachLazy(document.getElementsByClassName("impl-items"), function(e) {
onEachLazy(e.getElementsByClassName("associatedconstant"), func);
var hiddenElems = e.getElementsByClassName("hidden");
var needToggle = false;
var needToggle = onEachLazy(e.getElementsByClassName("hidden"), function(hiddenElem) {
if (hasClass(hiddenElem, "content") === false &&
hasClass(hiddenElem, "docblock") === false) {
return true;
}
// We transform the DOM iterator into a vec of DOM elements to prevent performance
// issues on webkit browsers.
var hiddenElems = Array.prototype.slice.call(e.getElementsByClassName("hidden"));
var needToggle = hiddenElems.some(function(hiddenElem) {
return hasClass(hiddenElem, "content") === false &&
hasClass(hiddenElem, "docblock") === false;
});
if (needToggle === true) {
var inner_toggle = newToggle.cloneNode(true);
@ -2672,10 +2666,10 @@ function defocusSearchBar() {
onEachLazy(document.getElementsByClassName("docblock"), buildToggleWrapper);
onEachLazy(document.getElementsByClassName("sub-variant"), buildToggleWrapper);
autoCollapse(getSettingValue("collapse") === "true");
var pageId = getPageId();
autoCollapse(pageId, getSettingValue("collapse") === "true");
if (pageId !== null) {
expandSection(pageId);
}

View File

@ -1,5 +1,5 @@
// Local js definitions:
/* global getCurrentValue, getVirtualKey, updateLocalStorage, updateSystemTheme */
/* global getSettingValue, getVirtualKey, onEachLazy, updateLocalStorage, updateSystemTheme */
(function () {
function changeSetting(settingName, value) {

View File

@ -113,6 +113,8 @@ function createSidebarToggle() {
return sidebarToggle;
}
// This function is called from "source-files.js", generated in `html/render/mod.rs`.
// eslint-disable-next-line no-unused-vars
function createSourceSidebar() {
if (window.rootPath.endsWith("/") === false) {
window.rootPath += "/";

View File

@ -1,5 +1,5 @@
// From rust:
/* global resourcesSuffix, getSettingValue */
/* global resourcesSuffix */
var darkThemes = ["dark", "ayu"];
var currentTheme = document.getElementById("themeStyle");
@ -35,10 +35,12 @@ var localStoredTheme = getSettingValue("theme");
var savedHref = [];
// eslint-disable-next-line no-unused-vars
function hasClass(elem, className) {
return elem && elem.classList && elem.classList.contains(className);
}
// eslint-disable-next-line no-unused-vars
function addClass(elem, className) {
if (!elem || !elem.classList) {
return;
@ -46,6 +48,7 @@ function addClass(elem, className) {
elem.classList.add(className);
}
// eslint-disable-next-line no-unused-vars
function removeClass(elem, className) {
if (!elem || !elem.classList) {
return;
@ -81,6 +84,7 @@ function onEachLazy(lazyArray, func, reversed) {
reversed);
}
// eslint-disable-next-line no-unused-vars
function hasOwnProperty(obj, property) {
return Object.prototype.hasOwnProperty.call(obj, property);
}
@ -148,6 +152,8 @@ function switchTheme(styleElem, mainStyleElem, newTheme, saveTheme) {
}
}
// This function is called from "theme.js", generated in `html/render/mod.rs`.
// eslint-disable-next-line no-unused-vars
function useSystemTheme(value) {
if (value === undefined) {
value = true;
@ -172,7 +178,7 @@ var updateSystemTheme = (function() {
switchTheme(
currentTheme,
mainTheme,
JSON.parse(cssTheme) || light,
JSON.parse(cssTheme) || "light",
true
);
};

View File

@ -40,4 +40,29 @@ fn test_many_bounds_where<X>(x: X) where X: Sized, X: Sized, X: Debug {
//~^ ERROR doesn't implement
}
pub fn main() { }
trait Foo<T>: Sized {
const SIZE: usize = core::mem::size_of::<Self>();
//~^ ERROR the size for values of type `Self` cannot be known at compilation time
}
trait Bar: std::fmt::Display + Sized {
const SIZE: usize = core::mem::size_of::<Self>();
//~^ ERROR the size for values of type `Self` cannot be known at compilation time
}
trait Baz: Sized where Self: std::fmt::Display {
const SIZE: usize = core::mem::size_of::<Self>();
//~^ ERROR the size for values of type `Self` cannot be known at compilation time
}
trait Qux<T>: Sized where Self: std::fmt::Display {
const SIZE: usize = core::mem::size_of::<Self>();
//~^ ERROR the size for values of type `Self` cannot be known at compilation time
}
trait Bat<T>: std::fmt::Display + Sized {
const SIZE: usize = core::mem::size_of::<Self>();
//~^ ERROR the size for values of type `Self` cannot be known at compilation time
}
fn main() { }

View File

@ -40,4 +40,29 @@ fn test_many_bounds_where<X>(x: X) where X: Sized, X: Sized {
//~^ ERROR doesn't implement
}
pub fn main() { }
trait Foo<T> {
const SIZE: usize = core::mem::size_of::<Self>();
//~^ ERROR the size for values of type `Self` cannot be known at compilation time
}
trait Bar: std::fmt::Display {
const SIZE: usize = core::mem::size_of::<Self>();
//~^ ERROR the size for values of type `Self` cannot be known at compilation time
}
trait Baz where Self: std::fmt::Display {
const SIZE: usize = core::mem::size_of::<Self>();
//~^ ERROR the size for values of type `Self` cannot be known at compilation time
}
trait Qux<T> where Self: std::fmt::Display {
const SIZE: usize = core::mem::size_of::<Self>();
//~^ ERROR the size for values of type `Self` cannot be known at compilation time
}
trait Bat<T>: std::fmt::Display {
const SIZE: usize = core::mem::size_of::<Self>();
//~^ ERROR the size for values of type `Self` cannot be known at compilation time
}
fn main() { }

View File

@ -76,6 +76,86 @@ help: consider further restricting type parameter `X`
LL | fn test_many_bounds_where<X>(x: X) where X: Sized, X: Sized, X: Debug {
| ^^^^^^^^^^
error: aborting due to 6 previous errors
error[E0277]: the size for values of type `Self` cannot be known at compilation time
--> $DIR/bound-suggestions.rs:44:46
|
LL | const SIZE: usize = core::mem::size_of::<Self>();
| ^^^^ doesn't have a size known at compile-time
|
::: $SRC_DIR/core/src/mem/mod.rs:LL:COL
|
LL | pub const fn size_of<T>() -> usize {
| - required by this bound in `std::mem::size_of`
|
help: consider further restricting `Self`
|
LL | trait Foo<T>: Sized {
| ^^^^^^^
error[E0277]: the size for values of type `Self` cannot be known at compilation time
--> $DIR/bound-suggestions.rs:49:46
|
LL | const SIZE: usize = core::mem::size_of::<Self>();
| ^^^^ doesn't have a size known at compile-time
|
::: $SRC_DIR/core/src/mem/mod.rs:LL:COL
|
LL | pub const fn size_of<T>() -> usize {
| - required by this bound in `std::mem::size_of`
|
help: consider further restricting `Self`
|
LL | trait Bar: std::fmt::Display + Sized {
| ^^^^^^^
error[E0277]: the size for values of type `Self` cannot be known at compilation time
--> $DIR/bound-suggestions.rs:54:46
|
LL | const SIZE: usize = core::mem::size_of::<Self>();
| ^^^^ doesn't have a size known at compile-time
|
::: $SRC_DIR/core/src/mem/mod.rs:LL:COL
|
LL | pub const fn size_of<T>() -> usize {
| - required by this bound in `std::mem::size_of`
|
help: consider further restricting `Self`
|
LL | trait Baz: Sized where Self: std::fmt::Display {
| ^^^^^^^
error[E0277]: the size for values of type `Self` cannot be known at compilation time
--> $DIR/bound-suggestions.rs:59:46
|
LL | const SIZE: usize = core::mem::size_of::<Self>();
| ^^^^ doesn't have a size known at compile-time
|
::: $SRC_DIR/core/src/mem/mod.rs:LL:COL
|
LL | pub const fn size_of<T>() -> usize {
| - required by this bound in `std::mem::size_of`
|
help: consider further restricting `Self`
|
LL | trait Qux<T>: Sized where Self: std::fmt::Display {
| ^^^^^^^
error[E0277]: the size for values of type `Self` cannot be known at compilation time
--> $DIR/bound-suggestions.rs:64:46
|
LL | const SIZE: usize = core::mem::size_of::<Self>();
| ^^^^ doesn't have a size known at compile-time
|
::: $SRC_DIR/core/src/mem/mod.rs:LL:COL
|
LL | pub const fn size_of<T>() -> usize {
| - required by this bound in `std::mem::size_of`
|
help: consider further restricting `Self`
|
LL | trait Bat<T>: std::fmt::Display + Sized {
| ^^^^^^^
error: aborting due to 11 previous errors
For more information about this error, try `rustc --explain E0277`.

View File

@ -0,0 +1,32 @@
// ignore-32bit
// This test gives a different error on 32-bit architectures.
union Transmute<T: Copy, U: Copy> {
t: T,
u: U,
}
trait Bar {
fn bar(&self) -> u32;
}
struct Foo {
foo: u32,
bar: bool,
}
impl Bar for Foo {
fn bar(&self) -> u32 {
self.foo
}
}
#[derive(Copy, Clone)]
struct Fat<'a>(&'a Foo, &'static VTable);
struct VTable {
size: Foo,
}
const FOO: &dyn Bar = &Foo {
foo: 128,
bar: false,
};
const G: Fat = unsafe { Transmute { t: FOO }.u };
//~^ ERROR it is undefined behavior to use this value
fn main() {}

View File

@ -0,0 +1,11 @@
error[E0080]: it is undefined behavior to use this value
--> $DIR/issue-79690.rs:29:1
|
LL | const G: Fat = unsafe { Transmute { t: FOO }.u };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered read of part of a pointer at .1.<deref>.size.foo
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
error: aborting due to previous error
For more information about this error, try `rustc --explain E0080`.

View File

@ -0,0 +1,13 @@
// Don't suggest removing a semicolon if the last statement isn't an expression with semicolon
// (#81098)
fn wat() -> impl core::fmt::Display { //~ ERROR: `()` doesn't implement `std::fmt::Display`
fn why() {}
}
// Do it if the last statement is an expression with semicolon
// (#54771)
fn ok() -> impl core::fmt::Display { //~ ERROR: `()` doesn't implement `std::fmt::Display`
1;
}
fn main() {}

View File

@ -0,0 +1,23 @@
error[E0277]: `()` doesn't implement `std::fmt::Display`
--> $DIR/issue-81098.rs:3:13
|
LL | fn wat() -> impl core::fmt::Display {
| ^^^^^^^^^^^^^^^^^^^^^^^ `()` cannot be formatted with the default formatter
|
= help: the trait `std::fmt::Display` is not implemented for `()`
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
error[E0277]: `()` doesn't implement `std::fmt::Display`
--> $DIR/issue-81098.rs:9:12
|
LL | fn ok() -> impl core::fmt::Display {
| ^^^^^^^^^^^^^^^^^^^^^^^ `()` cannot be formatted with the default formatter
LL | 1;
| - consider removing this semicolon
|
= help: the trait `std::fmt::Display` is not implemented for `()`
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0277`.

View File

@ -0,0 +1,9 @@
fn main() {
let a: u16;
let b: u16 = 42;
let c: usize = 5;
a = c + b * 5; //~ ERROR: mismatched types [E0308]
//~| ERROR: mismatched types [E0308]
//~| ERROR: cannot add `u16` to `usize` [E0277]
}

View File

@ -0,0 +1,24 @@
error[E0308]: mismatched types
--> $DIR/issue-81293.rs:6:13
|
LL | a = c + b * 5;
| ^^^^^ expected `usize`, found `u16`
error[E0308]: mismatched types
--> $DIR/issue-81293.rs:6:9
|
LL | a = c + b * 5;
| ^^^^^^^^^ expected `u16`, found `usize`
error[E0277]: cannot add `u16` to `usize`
--> $DIR/issue-81293.rs:6:11
|
LL | a = c + b * 5;
| ^ no implementation for `usize + u16`
|
= help: the trait `Add<u16>` is not implemented for `usize`
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0277, E0308.
For more information about an error, try `rustc --explain E0277`.

View File

@ -1,90 +0,0 @@
//! Tidy check to ensure that `[dependencies]` and `extern crate` are in sync.
//!
//! This tidy check ensures that all crates listed in the `[dependencies]`
//! section of a `Cargo.toml` are present in the corresponding `lib.rs` as
//! `extern crate` declarations. This should help us keep the DAG correctly
//! structured through various refactorings to prune out unnecessary edges.
use std::fs;
use std::path::Path;
pub fn check(path: &Path, bad: &mut bool) {
if !super::filter_dirs(path) {
return;
}
for entry in t!(path.read_dir(), path).map(|e| t!(e)) {
// Look for `Cargo.toml` with a sibling `src/lib.rs` or `lib.rs`.
if entry.file_name().to_str() == Some("Cargo.toml") {
if path.join("src/lib.rs").is_file() {
verify(&entry.path(), &path.join("src/lib.rs"), bad)
}
if path.join("lib.rs").is_file() {
verify(&entry.path(), &path.join("lib.rs"), bad)
}
} else if t!(entry.file_type()).is_dir() {
check(&entry.path(), bad);
}
}
}
/// Verifies that the dependencies in Cargo.toml at `tomlfile` are synced with
/// the `extern crate` annotations in the lib.rs at `libfile`.
fn verify(tomlfile: &Path, libfile: &Path, bad: &mut bool) {
let toml = t!(fs::read_to_string(&tomlfile));
let librs = t!(fs::read_to_string(&libfile));
if toml.contains("name = \"bootstrap\"") {
return;
}
// "Poor man's TOML parser" -- just assume we use one syntax for now.
//
// We just look for:
//
// ````
// [dependencies]
// name = ...
// name2 = ...
// name3 = ...
// ```
//
// If we encounter a line starting with `[` then we assume it's the end of
// the dependency section and bail out.
let deps = match toml.find("[dependencies]") {
Some(i) => &toml[i + 1..],
None => return,
};
for line in deps.lines() {
if line.starts_with('[') {
break;
}
let krate = match line.split_once('=') {
None => continue,
Some((krate, _)) => krate.trim(),
};
// Don't worry about depending on core/std while not writing `extern crate
// core/std` -- that's intentional.
if krate == "core" || krate == "std" {
continue;
}
// This is intentional -- this dependency just makes the crate available
// for others later on.
let allowed = krate.starts_with("panic");
if toml.contains("name = \"std\"") && allowed {
continue;
}
if !librs.contains(&format!("extern crate {}", krate)) {
tidy_error!(
bad,
"{} doesn't have `extern crate {}`, but Cargo.toml \
depends on it",
libfile.display(),
krate
);
}
}
}

View File

@ -2,20 +2,6 @@
use std::path::Path;
fn filter_dirs(path: &Path) -> bool {
// FIXME: just use super::filter_dirs after the submodules are updated.
if super::filter_dirs(path) {
return true;
}
let skip = [
"src/doc/book/second-edition",
"src/doc/book/2018-edition",
"src/doc/book/ci/stable-check",
"src/doc/reference/stable-check",
];
skip.iter().any(|p| path.ends_with(p))
}
fn is_edition_2018(mut line: &str) -> bool {
line = line.trim();
line == "edition = \"2018\"" || line == "edition = \'2018\'"
@ -24,7 +10,7 @@ fn is_edition_2018(mut line: &str) -> bool {
pub fn check(path: &Path, bad: &mut bool) {
super::walk(
path,
&mut |path| filter_dirs(path) || path.ends_with("src/test"),
&mut |path| super::filter_dirs(path) || path.ends_with("src/test"),
&mut |entry, contents| {
let file = entry.path();
let filename = file.file_name().unwrap();

View File

@ -422,7 +422,7 @@ fn map_lib_features(
mf(Err($msg), file, i + 1);
continue;
}};
};
}
if let Some((ref name, ref mut f)) = becoming_feature {
if f.tracking_issue.is_none() {
f.tracking_issue = find_attr_val(line, "issue").and_then(handle_issue_none);

View File

@ -40,7 +40,6 @@ macro_rules! tidy_error {
}
pub mod bins;
pub mod cargo;
pub mod debug_artifacts;
pub mod deps;
pub mod edition;

View File

@ -49,10 +49,6 @@ fn main() {
style::check(&compiler_path, &mut bad);
style::check(&library_path, &mut bad);
cargo::check(&src_path, &mut bad);
cargo::check(&compiler_path, &mut bad);
cargo::check(&library_path, &mut bad);
edition::check(&src_path, &mut bad);
edition::check(&compiler_path, &mut bad);
edition::check(&library_path, &mut bad);