Auto merge of #98730 - matthiaskrgr:rollup-2c4d4x5, r=matthiaskrgr

Rollup of 10 pull requests

Successful merges:

 - #97629 ([core] add `Exclusive` to sync)
 - #98503 (fix data race in thread::scope)
 - #98670 (llvm-wrapper: adapt for LLVMConstExtractValue removal)
 - #98671 (Fix source sidebar bugs)
 - #98677 (For diagnostic information of Boolean, remind it as use the type: 'bool')
 - #98684 (add test for 72793)
 - #98688 (interpret: add From<&MplaceTy> for PlaceTy)
 - #98695 (use "or pattern")
 - #98709 (Remove unneeded methods declaration for old web browsers)
 - #98717 (get rid of tidy 'unnecessarily ignored' warnings)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2022-07-01 11:09:35 +00:00
commit ca1e68b322
26 changed files with 364 additions and 79 deletions

View File

@ -109,8 +109,7 @@ impl<'ll> CodegenCx<'ll, '_> {
pub fn const_get_elt(&self, v: &'ll Value, idx: u64) -> &'ll Value {
unsafe {
assert_eq!(idx as c_uint as u64, idx);
let us = &[idx as c_uint];
let r = llvm::LLVMConstExtractValue(v, us.as_ptr(), us.len() as c_uint);
let r = llvm::LLVMGetAggregateElement(v, idx as c_uint).unwrap();
debug!("const_get_elt(v={:?}, idx={}, r={:?})", v, idx, r);

View File

@ -1134,11 +1134,7 @@ extern "C" {
pub fn LLVMConstIntToPtr<'a>(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value;
pub fn LLVMConstBitCast<'a>(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value;
pub fn LLVMConstPointerCast<'a>(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value;
pub fn LLVMConstExtractValue(
AggConstant: &Value,
IdxList: *const c_uint,
NumIdx: c_uint,
) -> &Value;
pub fn LLVMGetAggregateElement(ConstantVal: &Value, Idx: c_uint) -> Option<&Value>;
// Operations on global variables, functions, and aliases (globals)
pub fn LLVMIsDeclaration(Global: &Value) -> Bool;

View File

@ -346,7 +346,7 @@ fn valtree_into_mplace<'tcx>(
ty::FnDef(_, _) => {
ecx.write_immediate(
Immediate::Scalar(ScalarMaybeUninit::Scalar(Scalar::ZST)),
&(*place).into(),
&place.into(),
)
.unwrap();
}
@ -355,7 +355,7 @@ fn valtree_into_mplace<'tcx>(
debug!("writing trivial valtree {:?} to place {:?}", scalar_int, place);
ecx.write_immediate(
Immediate::Scalar(ScalarMaybeUninit::Scalar(scalar_int.into())),
&(*place).into(),
&place.into(),
)
.unwrap();
}
@ -382,7 +382,7 @@ fn valtree_into_mplace<'tcx>(
};
debug!(?imm);
ecx.write_immediate(imm, &(*place).into()).unwrap();
ecx.write_immediate(imm, &place.into()).unwrap();
}
ty::Adt(_, _) | ty::Tuple(_) | ty::Array(_, _) | ty::Str | ty::Slice(_) => {
let branches = valtree.unwrap_branch();
@ -464,11 +464,11 @@ fn valtree_into_mplace<'tcx>(
if let Some(variant_idx) = variant_idx {
// don't forget filling the place with the discriminant of the enum
ecx.write_discriminant(variant_idx, &(*place).into()).unwrap();
ecx.write_discriminant(variant_idx, &place.into()).unwrap();
}
debug!("dump of place after writing discriminant:");
dump_place(ecx, (*place).into());
dump_place(ecx, place.into());
}
_ => bug!("shouldn't have created a ValTree for {:?}", ty),
}

View File

@ -195,7 +195,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx, const_eval::Memory
let tcx = self.ecx.tcx;
let ty = mplace.layout.ty;
if let ty::Ref(_, referenced_ty, ref_mutability) = *ty.kind() {
let value = self.ecx.read_immediate(&(*mplace).into())?;
let value = self.ecx.read_immediate(&mplace.into())?;
let mplace = self.ecx.ref_to_mplace(&value)?;
assert_eq!(mplace.layout.ty, referenced_ty);
// Handle trait object vtables.

View File

@ -204,6 +204,13 @@ impl<'tcx, Tag: Provenance> From<&'_ MPlaceTy<'tcx, Tag>> for OpTy<'tcx, Tag> {
}
}
impl<'tcx, Tag: Provenance> From<&'_ mut MPlaceTy<'tcx, Tag>> for OpTy<'tcx, Tag> {
#[inline(always)]
fn from(mplace: &mut MPlaceTy<'tcx, Tag>) -> Self {
OpTy { op: Operand::Indirect(**mplace), layout: mplace.layout }
}
}
impl<'tcx, Tag: Provenance> From<ImmTy<'tcx, Tag>> for OpTy<'tcx, Tag> {
#[inline(always)]
fn from(val: ImmTy<'tcx, Tag>) -> Self {

View File

@ -118,7 +118,21 @@ impl<'tcx, Tag: Provenance> std::ops::Deref for MPlaceTy<'tcx, Tag> {
impl<'tcx, Tag: Provenance> From<MPlaceTy<'tcx, Tag>> for PlaceTy<'tcx, Tag> {
#[inline(always)]
fn from(mplace: MPlaceTy<'tcx, Tag>) -> Self {
PlaceTy { place: Place::Ptr(mplace.mplace), layout: mplace.layout }
PlaceTy { place: Place::Ptr(*mplace), layout: mplace.layout }
}
}
impl<'tcx, Tag: Provenance> From<&'_ MPlaceTy<'tcx, Tag>> for PlaceTy<'tcx, Tag> {
#[inline(always)]
fn from(mplace: &MPlaceTy<'tcx, Tag>) -> Self {
PlaceTy { place: Place::Ptr(**mplace), layout: mplace.layout }
}
}
impl<'tcx, Tag: Provenance> From<&'_ mut MPlaceTy<'tcx, Tag>> for PlaceTy<'tcx, Tag> {
#[inline(always)]
fn from(mplace: &mut MPlaceTy<'tcx, Tag>) -> Self {
PlaceTy { place: Place::Ptr(**mplace), layout: mplace.layout }
}
}

View File

@ -92,7 +92,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> Value<'mir, 'tcx, M>
&self,
_ecx: &InterpCx<'mir, 'tcx, M>,
) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
Ok((*self).into())
Ok(self.into())
}
#[inline(always)]

View File

@ -1447,7 +1447,7 @@ impl HandlerInner {
self.flags.treat_err_as_bug.map(|c| c.get()).unwrap_or(0),
) {
(1, 1) => panic!("aborting due to `-Z treat-err-as-bug=1`"),
(0, _) | (1, _) => {}
(0 | 1, _) => {}
(count, as_bug) => panic!(
"aborting after {} errors due to `-Z treat-err-as-bug={}`",
count, as_bug,

View File

@ -1865,3 +1865,11 @@ extern "C" void LLVMRustGetMangledName(LLVMValueRef V, RustStringRef Str) {
GlobalValue *GV = unwrap<GlobalValue>(V);
Mangler().getNameWithPrefix(OS, GV, true);
}
// LLVMGetAggregateElement was added in LLVM 15. For earlier LLVM versions just
// use its implementation.
#if LLVM_VERSION_LT(15, 0)
extern "C" LLVMValueRef LLVMGetAggregateElement(LLVMValueRef C, unsigned Idx) {
return wrap(unwrap<Constant>(C)->getAggregateElement(Idx));
}
#endif

View File

@ -1503,6 +1503,8 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
Some(match name {
"byte" => sym::u8, // In Java, bytes are signed, but in practice one almost always wants unsigned bytes.
"short" => sym::i16,
"Bool" => sym::bool,
"Boolean" => sym::bool,
"boolean" => sym::bool,
"int" => sym::i32,
"long" => sym::i64,

View File

@ -0,0 +1,173 @@
//! Defines [`Exclusive`].
use core::fmt;
use core::future::Future;
use core::pin::Pin;
use core::task::{Context, Poll};
/// `Exclusive` provides only _mutable_ access, also referred to as _exclusive_
/// access to the underlying value. It provides no _immutable_, or _shared_
/// access to the underlying value.
///
/// While this may seem not very useful, it allows `Exclusive` to _unconditionally_
/// implement [`Sync`]. Indeed, the safety requirements of `Sync` state that for `Exclusive`
/// to be `Sync`, it must be sound to _share_ across threads, that is, it must be sound
/// for `&Exclusive` to cross thread boundaries. By design, a `&Exclusive` has no API
/// whatsoever, making it useless, thus harmless, thus memory safe.
///
/// Certain constructs like [`Future`]s can only be used with _exclusive_ access,
/// and are often `Send` but not `Sync`, so `Exclusive` can be used as hint to the
/// rust compiler that something is `Sync` in practice.
///
/// ## Examples
/// Using a non-`Sync` future prevents the wrapping struct from being `Sync`
/// ```compile_fail
/// use core::cell::Cell;
///
/// async fn other() {}
/// fn assert_sync<T: Sync>(t: T) {}
/// struct State<F> {
/// future: F
/// }
///
/// assert_sync(State {
/// future: async {
/// let cell = Cell::new(1);
/// let cell_ref = &cell;
/// other().await;
/// let value = cell_ref.get();
/// }
/// });
/// ```
///
/// `Exclusive` ensures the struct is `Sync` without stripping the future of its
/// functionality.
/// ```
/// #![feature(exclusive_wrapper)]
/// use core::cell::Cell;
/// use core::sync::Exclusive;
///
/// async fn other() {}
/// fn assert_sync<T: Sync>(t: T) {}
/// struct State<F> {
/// future: Exclusive<F>
/// }
///
/// assert_sync(State {
/// future: Exclusive::new(async {
/// let cell = Cell::new(1);
/// let cell_ref = &cell;
/// other().await;
/// let value = cell_ref.get();
/// })
/// });
/// ```
///
/// ## Parallels with a mutex
/// In some sense, `Exclusive` can be thought of as a _compile-time_ version of
/// a mutex, as the borrow-checker guarantees that only one `&mut` can exist
/// for any value. This is a parallel with the fact that
/// `&` and `&mut` references together can be thought of as a _compile-time_
/// version of a read-write lock.
///
///
/// [`Sync`]: core::marker::Sync
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
#[doc(alias = "SyncWrapper")]
#[doc(alias = "SyncCell")]
#[doc(alias = "Unique")]
// `Exclusive` can't have `PartialOrd`, `Clone`, etc. impls as they would
// use `&` access to the inner value, violating the `Sync` impl's safety
// requirements.
#[derive(Default)]
#[repr(transparent)]
pub struct Exclusive<T: ?Sized> {
inner: T,
}
// See `Exclusive`'s docs for justification.
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
unsafe impl<T: ?Sized> Sync for Exclusive<T> {}
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
impl<T: ?Sized> fmt::Debug for Exclusive<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
f.debug_struct("Exclusive").finish_non_exhaustive()
}
}
impl<T: Sized> Exclusive<T> {
/// Wrap a value in an `Exclusive`
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
#[must_use]
pub const fn new(t: T) -> Self {
Self { inner: t }
}
/// Unwrap the value contained in the `Exclusive`
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
#[must_use]
pub const fn into_inner(self) -> T {
self.inner
}
}
impl<T: ?Sized> Exclusive<T> {
/// Get exclusive access to the underlying value.
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
#[must_use]
pub const fn get_mut(&mut self) -> &mut T {
&mut self.inner
}
/// Get pinned exclusive access to the underlying value.
///
/// `Exclusive` is considered to _structurally pin_ the underlying
/// value, which means _unpinned_ `Exclusive`s can produce _unpinned_
/// access to the underlying value, but _pinned_ `Exclusive`s only
/// produce _pinned_ access to the underlying value.
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
#[must_use]
pub const fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T> {
// SAFETY: `Exclusive` can only produce `&mut T` if itself is unpinned
// `Pin::map_unchecked_mut` is not const, so we do this conversion manually
unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().inner) }
}
/// Build a _mutable_ references to an `Exclusive<T>` from
/// a _mutable_ reference to a `T`. This allows you to skip
/// building an `Exclusive` with [`Exclusive::new`].
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
#[must_use]
pub const fn from_mut(r: &'_ mut T) -> &'_ mut Exclusive<T> {
// SAFETY: repr is ≥ C, so refs have the same layout; and `Exclusive` properties are `&mut`-agnostic
unsafe { &mut *(r as *mut T as *mut Exclusive<T>) }
}
/// Build a _pinned mutable_ references to an `Exclusive<T>` from
/// a _pinned mutable_ reference to a `T`. This allows you to skip
/// building an `Exclusive` with [`Exclusive::new`].
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
#[must_use]
pub const fn from_pin_mut(r: Pin<&'_ mut T>) -> Pin<&'_ mut Exclusive<T>> {
// SAFETY: `Exclusive` can only produce `&mut T` if itself is unpinned
// `Pin::map_unchecked_mut` is not const, so we do this conversion manually
unsafe { Pin::new_unchecked(Self::from_mut(r.get_unchecked_mut())) }
}
}
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
impl<T> From<T> for Exclusive<T> {
fn from(t: T) -> Self {
Self::new(t)
}
}
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
impl<T: Future + ?Sized> Future for Exclusive<T> {
type Output = T::Output;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
self.get_pin_mut().poll(cx)
}
}

View File

@ -3,3 +3,6 @@
#![stable(feature = "rust1", since = "1.0.0")]
pub mod atomic;
mod exclusive;
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
pub use exclusive::Exclusive;

View File

@ -270,6 +270,7 @@
#![feature(duration_checked_float)]
#![feature(duration_constants)]
#![feature(exact_size_is_empty)]
#![feature(exclusive_wrapper)]
#![feature(extend_one)]
#![feature(float_minimum_maximum)]
#![feature(hasher_prefixfree_extras)]

View File

@ -155,6 +155,8 @@
pub use alloc_crate::sync::{Arc, Weak};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::sync::atomic;
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
pub use core::sync::Exclusive;
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::barrier::{Barrier, BarrierWaitResult};

View File

@ -159,6 +159,7 @@ use crate::cell::UnsafeCell;
use crate::ffi::{CStr, CString};
use crate::fmt;
use crate::io;
use crate::marker::PhantomData;
use crate::mem;
use crate::num::NonZeroU64;
use crate::num::NonZeroUsize;
@ -462,7 +463,7 @@ impl Builder {
unsafe fn spawn_unchecked_<'a, 'scope, F, T>(
self,
f: F,
scope_data: Option<&'scope scoped::ScopeData>,
scope_data: Option<Arc<scoped::ScopeData>>,
) -> io::Result<JoinInner<'scope, T>>
where
F: FnOnce() -> T,
@ -479,8 +480,11 @@ impl Builder {
}));
let their_thread = my_thread.clone();
let my_packet: Arc<Packet<'scope, T>> =
Arc::new(Packet { scope: scope_data, result: UnsafeCell::new(None) });
let my_packet: Arc<Packet<'scope, T>> = Arc::new(Packet {
scope: scope_data,
result: UnsafeCell::new(None),
_marker: PhantomData,
});
let their_packet = my_packet.clone();
let output_capture = crate::io::set_output_capture(None);
@ -507,7 +511,7 @@ impl Builder {
unsafe { *their_packet.result.get() = Some(try_result) };
};
if let Some(scope_data) = scope_data {
if let Some(scope_data) = &my_packet.scope {
scope_data.increment_num_running_threads();
}
@ -1298,8 +1302,9 @@ pub type Result<T> = crate::result::Result<T, Box<dyn Any + Send + 'static>>;
// An Arc to the packet is stored into a `JoinInner` which in turns is placed
// in `JoinHandle`.
struct Packet<'scope, T> {
scope: Option<&'scope scoped::ScopeData>,
scope: Option<Arc<scoped::ScopeData>>,
result: UnsafeCell<Option<Result<T>>>,
_marker: PhantomData<Option<&'scope scoped::ScopeData>>,
}
// Due to the usage of `UnsafeCell` we need to manually implement Sync.
@ -1330,7 +1335,7 @@ impl<'scope, T> Drop for Packet<'scope, T> {
rtabort!("thread result panicked on drop");
}
// Book-keeping so the scope knows when it's done.
if let Some(scope) = self.scope {
if let Some(scope) = &self.scope {
// Now that there will be no more user code running on this thread
// that can use 'scope, mark the thread as 'finished'.
// It's important we only do this after the `result` has been dropped,

View File

@ -11,7 +11,7 @@ use crate::sync::Arc;
/// See [`scope`] for details.
#[stable(feature = "scoped_threads", since = "1.63.0")]
pub struct Scope<'scope, 'env: 'scope> {
data: ScopeData,
data: Arc<ScopeData>,
/// Invariance over 'scope, to make sure 'scope cannot shrink,
/// which is necessary for soundness.
///
@ -130,12 +130,14 @@ pub fn scope<'env, F, T>(f: F) -> T
where
F: for<'scope> FnOnce(&'scope Scope<'scope, 'env>) -> T,
{
// We put the `ScopeData` into an `Arc` so that other threads can finish their
// `decrement_num_running_threads` even after this function returns.
let scope = Scope {
data: ScopeData {
data: Arc::new(ScopeData {
num_running_threads: AtomicUsize::new(0),
main_thread: current(),
a_thread_panicked: AtomicBool::new(false),
},
}),
env: PhantomData,
scope: PhantomData,
};
@ -250,7 +252,7 @@ impl Builder {
F: FnOnce() -> T + Send + 'scope,
T: Send + 'scope,
{
Ok(ScopedJoinHandle(unsafe { self.spawn_unchecked_(f, Some(&scope.data)) }?))
Ok(ScopedJoinHandle(unsafe { self.spawn_unchecked_(f, Some(scope.data.clone())) }?))
}
}

View File

@ -1772,9 +1772,11 @@ details.rustdoc-toggle[open] > summary.hideme::after {
/* The source view uses a different design for the sidebar toggle, and doesn't have a topbar,
so don't bump down the main content or the sidebar. */
.source main,
.source .sidebar {
.rustdoc.source .sidebar {
top: 0;
padding: 0;
height: 100vh;
border: 0;
}
.sidebar.shown,
@ -1924,6 +1926,9 @@ details.rustdoc-toggle[open] > summary.hideme::after {
width: unset;
border-top-right-radius: unset;
border-bottom-right-radius: unset;
position: sticky;
border: 0;
border-bottom: 1px solid;
}
#source-sidebar {

View File

@ -4,40 +4,6 @@
"use strict";
if (!String.prototype.startsWith) {
String.prototype.startsWith = function(searchString, position) {
position = position || 0;
return this.indexOf(searchString, position) === position;
};
}
if (!String.prototype.endsWith) {
String.prototype.endsWith = function(suffix, length) {
const l = length || this.length;
return this.indexOf(suffix, l - suffix.length) !== -1;
};
}
if (!DOMTokenList.prototype.add) {
DOMTokenList.prototype.add = function(className) {
if (className && !hasClass(this, className)) {
if (this.className && this.className.length > 0) {
this.className += " " + className;
} else {
this.className = className;
}
}
};
}
if (!DOMTokenList.prototype.remove) {
DOMTokenList.prototype.remove = function(className) {
if (className && this.className) {
this.className = (" " + this.className + " ").replace(" " + className + " ", " ")
.trim();
}
};
}
// Get a value from the rustdoc-vars div, which is used to convey data from
// Rust to the JS. If there is no such element, return null.
function getVar(name) {

View File

@ -10,6 +10,7 @@
(function() {
const rootPath = document.getElementById("rustdoc-vars").attributes["data-root-path"].value;
let oldScrollPosition = 0;
function createDirEntry(elem, parent, fullPath, hasFoundFile) {
const name = document.createElement("div");
@ -65,10 +66,24 @@ function createDirEntry(elem, parent, fullPath, hasFoundFile) {
function toggleSidebar() {
const child = this.children[0];
if (child.innerText === ">") {
if (window.innerWidth < 701) {
// This is to keep the scroll position on mobile.
oldScrollPosition = window.scrollY;
document.body.style.position = "fixed";
document.body.style.top = `-${oldScrollPosition}px`;
}
addClass(document.documentElement, "source-sidebar-expanded");
child.innerText = "<";
updateLocalStorage("source-sidebar-show", "true");
} else {
if (window.innerWidth < 701) {
// This is to keep the scroll position on mobile.
document.body.style.position = "";
document.body.style.top = "";
// The scroll position is lost when resetting the style, hence why we store it in
// `oldScroll`.
window.scrollTo(0, oldScrollPosition);
}
removeClass(document.documentElement, "source-sidebar-expanded");
child.innerText = ">";
updateLocalStorage("source-sidebar-show", "false");

View File

@ -116,3 +116,39 @@ assert-css: (
"#source-sidebar .expand + .children .folders .name",
{"color": "rgb(255, 180, 76)", "background-color": "rgb(20, 25, 31)"},
)
// Now checking on mobile devices.
size: (500, 700)
reload:
// Waiting for the sidebar to be displayed...
wait-for-css: ("#sidebar-toggle", {"visibility": "visible", "opacity": 1})
// We now check it takes the full size of the display.
assert-property: ("body", {"clientWidth": "500", "clientHeight": "700"})
assert-property: (".sidebar", {"clientWidth": "500", "clientHeight": "700"})
// We now check the display of the toggle once the sidebar is expanded.
assert-property: ("#sidebar-toggle", {"clientWidth": "500", "clientHeight": "39"})
assert-css: (
"#sidebar-toggle",
{
"border-top-width": "0px",
"border-right-width": "0px",
"border-left-width": "0px",
"border-bottom-width": "1px",
},
)
// We now check that the scroll position is kept when opening the sidebar.
click: "#sidebar-toggle"
wait-for-css: (".sidebar", {"width": "0px"})
// We scroll to line 117 to change the scroll position.
scroll-to: '//*[@id="117"]'
assert-window-property: {"pageYOffset": "2519"}
// Expanding the sidebar...
click: "#sidebar-toggle"
wait-for-css: (".sidebar", {"width": "500px"})
click: "#sidebar-toggle"
wait-for-css: (".sidebar", {"width": "0px"})
// The "scrollTop" property should be the same.
assert-window-property: {"pageYOffset": "2519"}

View File

@ -18,8 +18,8 @@ assert: "nav.sidebar"
// We now switch to mobile mode.
size: (600, 600)
// We check that the sidebar has the expected width (0 and 1px for the border).
assert-css: ("nav.sidebar", {"width": "1px"})
// We check that the sidebar has the expected width (0).
assert-css: ("nav.sidebar", {"width": "0px"})
// We expand the sidebar.
click: "#sidebar-toggle"
assert-css: (".source-sidebar-expanded nav.sidebar", {"width": "600px"})

View File

@ -7,6 +7,13 @@ fn main() {
let y: long = 74802374902374923;
//~^ ERROR cannot find type `long` in this scope
//~| HELP perhaps you intended to use this type
let v1: Boolean = true;
//~^ ERROR: cannot find type `Boolean` in this scope [E0412]
//~| HELP perhaps you intended to use this type
let v2: Bool = true;
//~^ ERROR: cannot find type `Bool` in this scope [E0412]
//~| HELP a builtin type with a similar name exists
//~| HELP perhaps you intended to use this type
}
fn z(a: boolean) {

View File

@ -16,8 +16,32 @@ LL | let y: long = 74802374902374923;
| not found in this scope
| help: perhaps you intended to use this type: `i64`
error[E0412]: cannot find type `Boolean` in this scope
--> $DIR/recommend-literal.rs:10:13
|
LL | let v1: Boolean = true;
| ^^^^^^^
| |
| not found in this scope
| help: perhaps you intended to use this type: `bool`
error[E0412]: cannot find type `Bool` in this scope
--> $DIR/recommend-literal.rs:13:13
|
LL | let v2: Bool = true;
| ^^^^
|
help: a builtin type with a similar name exists
|
LL | let v2: bool = true;
| ~~~~
help: perhaps you intended to use this type
|
LL | let v2: bool = true;
| ~~~~
error[E0412]: cannot find type `boolean` in this scope
--> $DIR/recommend-literal.rs:12:9
--> $DIR/recommend-literal.rs:19:9
|
LL | fn z(a: boolean) {
| ^^^^^^^
@ -26,7 +50,7 @@ LL | fn z(a: boolean) {
| help: perhaps you intended to use this type: `bool`
error[E0412]: cannot find type `byte` in this scope
--> $DIR/recommend-literal.rs:17:11
--> $DIR/recommend-literal.rs:24:11
|
LL | fn a() -> byte {
| ^^^^
@ -35,7 +59,7 @@ LL | fn a() -> byte {
| help: perhaps you intended to use this type: `u8`
error[E0412]: cannot find type `float` in this scope
--> $DIR/recommend-literal.rs:24:12
--> $DIR/recommend-literal.rs:31:12
|
LL | width: float,
| ^^^^^
@ -44,7 +68,7 @@ LL | width: float,
| help: perhaps you intended to use this type: `f32`
error[E0412]: cannot find type `int` in this scope
--> $DIR/recommend-literal.rs:27:19
--> $DIR/recommend-literal.rs:34:19
|
LL | depth: Option<int>,
| ^^^ not found in this scope
@ -59,7 +83,7 @@ LL | struct Data<int> {
| +++++
error[E0412]: cannot find type `short` in this scope
--> $DIR/recommend-literal.rs:33:16
--> $DIR/recommend-literal.rs:40:16
|
LL | impl Stuff for short {}
| ^^^^^
@ -67,6 +91,6 @@ LL | impl Stuff for short {}
| not found in this scope
| help: perhaps you intended to use this type: `i16`
error: aborting due to 7 previous errors
error: aborting due to 9 previous errors
For more information about this error, try `rustc --explain E0412`.

View File

@ -0,0 +1,25 @@
// check-pass
// compile-flags: -Zmir-opt-level=3
#![feature(type_alias_impl_trait)]
trait T { type Item; }
type Alias<'a> = impl T<Item = &'a ()>;
struct S;
impl<'a> T for &'a S {
type Item = &'a ();
}
fn filter_positive<'a>() -> Alias<'a> {
&S
}
fn with_positive(fun: impl Fn(Alias<'_>)) {
fun(filter_positive());
}
fn main() {
with_positive(|_| ());
}

View File

@ -395,9 +395,6 @@ pub fn check(path: &Path, bad: &mut bool) {
);
};
suppressible_tidy_err!(err, skip_file_length, "");
} else if lines > (LINES * 7) / 10 {
// Just set it to something that doesn't trigger the "unnecessarily ignored" warning.
skip_file_length = Directive::Ignore(true);
}
if let Directive::Ignore(false) = skip_cr {
@ -406,12 +403,6 @@ pub fn check(path: &Path, bad: &mut bool) {
if let Directive::Ignore(false) = skip_tab {
tidy_error!(bad, "{}: ignoring tab characters unnecessarily", file.display());
}
if let Directive::Ignore(false) = skip_line_length {
tidy_error!(bad, "{}: ignoring line length unnecessarily", file.display());
}
if let Directive::Ignore(false) = skip_file_length {
tidy_error!(bad, "{}: ignoring file length unnecessarily", file.display());
}
if let Directive::Ignore(false) = skip_end_whitespace {
tidy_error!(bad, "{}: ignoring trailing whitespace unnecessarily", file.display());
}
@ -424,5 +415,9 @@ pub fn check(path: &Path, bad: &mut bool) {
if let Directive::Ignore(false) = skip_copyright {
tidy_error!(bad, "{}: ignoring copyright unnecessarily", file.display());
}
// We deliberately do not warn about these being unnecessary,
// that would just lead to annoying churn.
let _unused = skip_line_length;
let _unused = skip_file_length;
})
}