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:
commit
d1aed50ab8
RELEASES.md
compiler
rustc_codegen_ssa/src
rustc_error_codes/src/error_codes
rustc_middle/src/hir/map
rustc_mir/src/interpret
rustc_trait_selection/src/traits/error_reporting
rustc_typeck/src/check
library
alloc/src/collections/btree/map
core
src
doc
librustdoc/html/static
test/ui
tools/tidy/src
120
RELEASES.md
120
RELEASES.md
@ -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)
|
||||
============================
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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>`
|
||||
|
@ -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 {
|
||||
|
@ -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() {
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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]
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
@ -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> {
|
||||
|
@ -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)]
|
||||
|
@ -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]
|
||||
|
@ -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;
|
||||
|
@ -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
|
@ -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-
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Local js definitions:
|
||||
/* global getCurrentValue, getVirtualKey, updateLocalStorage, updateSystemTheme */
|
||||
/* global getSettingValue, getVirtualKey, onEachLazy, updateLocalStorage, updateSystemTheme */
|
||||
|
||||
(function () {
|
||||
function changeSetting(settingName, value) {
|
||||
|
@ -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 += "/";
|
||||
|
@ -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
|
||||
);
|
||||
};
|
||||
|
@ -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() { }
|
||||
|
@ -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() { }
|
||||
|
@ -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`.
|
||||
|
32
src/test/ui/consts/issue-79690.rs
Normal file
32
src/test/ui/consts/issue-79690.rs
Normal 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() {}
|
11
src/test/ui/consts/issue-79690.stderr
Normal file
11
src/test/ui/consts/issue-79690.stderr
Normal 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`.
|
13
src/test/ui/suggestions/issue-81098.rs
Normal file
13
src/test/ui/suggestions/issue-81098.rs
Normal 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() {}
|
23
src/test/ui/suggestions/issue-81098.stderr
Normal file
23
src/test/ui/suggestions/issue-81098.stderr
Normal 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`.
|
9
src/test/ui/typeck/issue-81293.rs
Normal file
9
src/test/ui/typeck/issue-81293.rs
Normal 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]
|
||||
}
|
24
src/test/ui/typeck/issue-81293.stderr
Normal file
24
src/test/ui/typeck/issue-81293.stderr
Normal 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`.
|
@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -40,7 +40,6 @@ macro_rules! tidy_error {
|
||||
}
|
||||
|
||||
pub mod bins;
|
||||
pub mod cargo;
|
||||
pub mod debug_artifacts;
|
||||
pub mod deps;
|
||||
pub mod edition;
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user