Auto merge of #57630 - Centril:rollup, r=Centril
Rollup of 8 pull requests Successful merges: - #56044 (Drop partially bound function parameters in the expected order) - #57352 (forbid manually impl'ing one of an object type's marker traits) - #57456 (RawVec doesn't always abort on allocation errors) - #57467 (Implement `check_attribute` to forbid `#[allow_internal_unsafe]`) - #57579 (Add core::iter::once_with()) - #57587 (Add 'rustc-env:RUST_BACKTRACE=0' to const-pat-ice test) - #57608 (Simplify 'product' factorial example) - #57614 ([rustdoc] Fix crates filtering box not being filled) Failed merges: r? @ghost
This commit is contained in:
commit
14ea6e50c1
@ -22,7 +22,7 @@ use boxed::Box;
|
|||||||
/// * Catches all overflows in capacity computations (promotes them to "capacity overflow" panics)
|
/// * Catches all overflows in capacity computations (promotes them to "capacity overflow" panics)
|
||||||
/// * Guards against 32-bit systems allocating more than isize::MAX bytes
|
/// * Guards against 32-bit systems allocating more than isize::MAX bytes
|
||||||
/// * Guards against overflowing your length
|
/// * Guards against overflowing your length
|
||||||
/// * Aborts on OOM
|
/// * Aborts on OOM or calls handle_alloc_error as applicable
|
||||||
/// * Avoids freeing Unique::empty()
|
/// * Avoids freeing Unique::empty()
|
||||||
/// * Contains a ptr::Unique and thus endows the user with all related benefits
|
/// * Contains a ptr::Unique and thus endows the user with all related benefits
|
||||||
///
|
///
|
||||||
|
@ -2358,7 +2358,7 @@ pub trait Iterator {
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// fn factorial(n: u32) -> u32 {
|
/// fn factorial(n: u32) -> u32 {
|
||||||
/// (1..).take_while(|&i| i <= n).product()
|
/// (1..=n).product()
|
||||||
/// }
|
/// }
|
||||||
/// assert_eq!(factorial(0), 1);
|
/// assert_eq!(factorial(0), 1);
|
||||||
/// assert_eq!(factorial(1), 1);
|
/// assert_eq!(factorial(1), 1);
|
||||||
|
@ -329,6 +329,8 @@ pub use self::sources::{RepeatWith, repeat_with};
|
|||||||
pub use self::sources::{Empty, empty};
|
pub use self::sources::{Empty, empty};
|
||||||
#[stable(feature = "iter_once", since = "1.2.0")]
|
#[stable(feature = "iter_once", since = "1.2.0")]
|
||||||
pub use self::sources::{Once, once};
|
pub use self::sources::{Once, once};
|
||||||
|
#[unstable(feature = "iter_once_with", issue = "57581")]
|
||||||
|
pub use self::sources::{OnceWith, once_with};
|
||||||
#[unstable(feature = "iter_unfold", issue = "55977")]
|
#[unstable(feature = "iter_unfold", issue = "55977")]
|
||||||
pub use self::sources::{Unfold, unfold, Successors, successors};
|
pub use self::sources::{Unfold, unfold, Successors, successors};
|
||||||
|
|
||||||
|
@ -377,6 +377,119 @@ pub fn once<T>(value: T) -> Once<T> {
|
|||||||
Once { inner: Some(value).into_iter() }
|
Once { inner: Some(value).into_iter() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An iterator that repeats elements of type `A` endlessly by
|
||||||
|
/// applying the provided closure `F: FnMut() -> A`.
|
||||||
|
///
|
||||||
|
/// This `struct` is created by the [`once_with`] function.
|
||||||
|
/// See its documentation for more.
|
||||||
|
///
|
||||||
|
/// [`once_with`]: fn.once_with.html
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
#[unstable(feature = "iter_once_with", issue = "57581")]
|
||||||
|
pub struct OnceWith<F> {
|
||||||
|
gen: Option<F>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "iter_once_with", issue = "57581")]
|
||||||
|
impl<A, F: FnOnce() -> A> Iterator for OnceWith<F> {
|
||||||
|
type Item = A;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn next(&mut self) -> Option<A> {
|
||||||
|
self.gen.take().map(|f| f())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
|
self.gen.iter().size_hint()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "iter_once_with", issue = "57581")]
|
||||||
|
impl<A, F: FnOnce() -> A> DoubleEndedIterator for OnceWith<F> {
|
||||||
|
fn next_back(&mut self) -> Option<A> {
|
||||||
|
self.next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "iter_once_with", issue = "57581")]
|
||||||
|
impl<A, F: FnOnce() -> A> ExactSizeIterator for OnceWith<F> {
|
||||||
|
fn len(&self) -> usize {
|
||||||
|
self.gen.iter().len()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "iter_once_with", issue = "57581")]
|
||||||
|
impl<A, F: FnOnce() -> A> FusedIterator for OnceWith<F> {}
|
||||||
|
|
||||||
|
#[unstable(feature = "iter_once_with", issue = "57581")]
|
||||||
|
unsafe impl<A, F: FnOnce() -> A> TrustedLen for OnceWith<F> {}
|
||||||
|
|
||||||
|
/// Creates an iterator that lazily generates a value exactly once by invoking
|
||||||
|
/// the provided closure.
|
||||||
|
///
|
||||||
|
/// This is commonly used to adapt a single value generator into a [`chain`] of
|
||||||
|
/// other kinds of iteration. Maybe you have an iterator that covers almost
|
||||||
|
/// everything, but you need an extra special case. Maybe you have a function
|
||||||
|
/// which works on iterators, but you only need to process one value.
|
||||||
|
///
|
||||||
|
/// Unlike [`once`], this function will lazily generate the value on request.
|
||||||
|
///
|
||||||
|
/// [`once`]: fn.once.html
|
||||||
|
/// [`chain`]: trait.Iterator.html#method.chain
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// Basic usage:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(iter_once_with)]
|
||||||
|
///
|
||||||
|
/// use std::iter;
|
||||||
|
///
|
||||||
|
/// // one is the loneliest number
|
||||||
|
/// let mut one = iter::once_with(|| 1);
|
||||||
|
///
|
||||||
|
/// assert_eq!(Some(1), one.next());
|
||||||
|
///
|
||||||
|
/// // just one, that's all we get
|
||||||
|
/// assert_eq!(None, one.next());
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Chaining together with another iterator. Let's say that we want to iterate
|
||||||
|
/// over each file of the `.foo` directory, but also a configuration file,
|
||||||
|
/// `.foorc`:
|
||||||
|
///
|
||||||
|
/// ```no_run
|
||||||
|
/// #![feature(iter_once_with)]
|
||||||
|
///
|
||||||
|
/// use std::iter;
|
||||||
|
/// use std::fs;
|
||||||
|
/// use std::path::PathBuf;
|
||||||
|
///
|
||||||
|
/// let dirs = fs::read_dir(".foo").unwrap();
|
||||||
|
///
|
||||||
|
/// // we need to convert from an iterator of DirEntry-s to an iterator of
|
||||||
|
/// // PathBufs, so we use map
|
||||||
|
/// let dirs = dirs.map(|file| file.unwrap().path());
|
||||||
|
///
|
||||||
|
/// // now, our iterator just for our config file
|
||||||
|
/// let config = iter::once_with(|| PathBuf::from(".foorc"));
|
||||||
|
///
|
||||||
|
/// // chain the two iterators together into one big iterator
|
||||||
|
/// let files = dirs.chain(config);
|
||||||
|
///
|
||||||
|
/// // this will give us all of the files in .foo as well as .foorc
|
||||||
|
/// for f in files {
|
||||||
|
/// println!("{:?}", f);
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
#[unstable(feature = "iter_once_with", issue = "57581")]
|
||||||
|
pub fn once_with<A, F: FnOnce() -> A>(gen: F) -> OnceWith<F> {
|
||||||
|
OnceWith { gen: Some(gen) }
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates a new iterator where each iteration calls the provided closure
|
/// Creates a new iterator where each iteration calls the provided closure
|
||||||
/// `F: FnMut(&mut St) -> Option<T>`.
|
/// `F: FnMut(&mut St) -> Option<T>`.
|
||||||
///
|
///
|
||||||
|
@ -79,6 +79,7 @@
|
|||||||
#![feature(extern_types)]
|
#![feature(extern_types)]
|
||||||
#![feature(fundamental)]
|
#![feature(fundamental)]
|
||||||
#![feature(intrinsics)]
|
#![feature(intrinsics)]
|
||||||
|
#![feature(iter_once_with)]
|
||||||
#![feature(lang_items)]
|
#![feature(lang_items)]
|
||||||
#![feature(link_llvm_intrinsics)]
|
#![feature(link_llvm_intrinsics)]
|
||||||
#![feature(never_type)]
|
#![feature(never_type)]
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use core::cell::Cell;
|
||||||
use core::iter::*;
|
use core::iter::*;
|
||||||
use core::{i8, i16, isize};
|
use core::{i8, i16, isize};
|
||||||
use core::usize;
|
use core::usize;
|
||||||
@ -1906,6 +1907,23 @@ fn test_once() {
|
|||||||
assert_eq!(it.next(), None);
|
assert_eq!(it.next(), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_once_with() {
|
||||||
|
let count = Cell::new(0);
|
||||||
|
let mut it = once_with(|| {
|
||||||
|
count.set(count.get() + 1);
|
||||||
|
42
|
||||||
|
});
|
||||||
|
|
||||||
|
assert_eq!(count.get(), 0);
|
||||||
|
assert_eq!(it.next(), Some(42));
|
||||||
|
assert_eq!(count.get(), 1);
|
||||||
|
assert_eq!(it.next(), None);
|
||||||
|
assert_eq!(count.get(), 1);
|
||||||
|
assert_eq!(it.next(), None);
|
||||||
|
assert_eq!(count.get(), 1);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_empty() {
|
fn test_empty() {
|
||||||
let mut it = empty::<i32>();
|
let mut it = empty::<i32>();
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#![feature(hashmap_internals)]
|
#![feature(hashmap_internals)]
|
||||||
#![feature(iter_copied)]
|
#![feature(iter_copied)]
|
||||||
#![feature(iter_nth_back)]
|
#![feature(iter_nth_back)]
|
||||||
|
#![feature(iter_once_with)]
|
||||||
#![feature(iter_unfold)]
|
#![feature(iter_unfold)]
|
||||||
#![feature(pattern)]
|
#![feature(pattern)]
|
||||||
#![feature(range_is_empty)]
|
#![feature(range_is_empty)]
|
||||||
|
@ -40,9 +40,9 @@ use syntax_pos::{BytePos, Span, SyntaxContext};
|
|||||||
use syntax::symbol::keywords;
|
use syntax::symbol::keywords;
|
||||||
use syntax::errors::{Applicability, DiagnosticBuilder};
|
use syntax::errors::{Applicability, DiagnosticBuilder};
|
||||||
use syntax::print::pprust::expr_to_string;
|
use syntax::print::pprust::expr_to_string;
|
||||||
|
use syntax::visit::FnKind;
|
||||||
|
|
||||||
use rustc::hir::{self, GenericParamKind, PatKind};
|
use rustc::hir::{self, GenericParamKind, PatKind};
|
||||||
use rustc::hir::intravisit::FnKind;
|
|
||||||
|
|
||||||
use nonstandard_style::{MethodLateContext, method_context};
|
use nonstandard_style::{MethodLateContext, method_context};
|
||||||
|
|
||||||
@ -216,7 +216,7 @@ impl LintPass for UnsafeCode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl UnsafeCode {
|
impl UnsafeCode {
|
||||||
fn report_unsafe(&self, cx: &LateContext, span: Span, desc: &'static str) {
|
fn report_unsafe(&self, cx: &EarlyContext, span: Span, desc: &'static str) {
|
||||||
// This comes from a macro that has #[allow_internal_unsafe].
|
// This comes from a macro that has #[allow_internal_unsafe].
|
||||||
if span.allows_unsafe() {
|
if span.allows_unsafe() {
|
||||||
return;
|
return;
|
||||||
@ -226,23 +226,31 @@ impl UnsafeCode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnsafeCode {
|
impl EarlyLintPass for UnsafeCode {
|
||||||
fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
|
fn check_attribute(&mut self, cx: &EarlyContext, attr: &ast::Attribute) {
|
||||||
if let hir::ExprKind::Block(ref blk, _) = e.node {
|
if attr.check_name("allow_internal_unsafe") {
|
||||||
|
self.report_unsafe(cx, attr.span, "`allow_internal_unsafe` allows defining \
|
||||||
|
macros using unsafe without triggering \
|
||||||
|
the `unsafe_code` lint at their call site");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_expr(&mut self, cx: &EarlyContext, e: &ast::Expr) {
|
||||||
|
if let ast::ExprKind::Block(ref blk, _) = e.node {
|
||||||
// Don't warn about generated blocks, that'll just pollute the output.
|
// Don't warn about generated blocks, that'll just pollute the output.
|
||||||
if blk.rules == hir::UnsafeBlock(hir::UserProvided) {
|
if blk.rules == ast::BlockCheckMode::Unsafe(ast::UserProvided) {
|
||||||
self.report_unsafe(cx, blk.span, "usage of an `unsafe` block");
|
self.report_unsafe(cx, blk.span, "usage of an `unsafe` block");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
|
fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) {
|
||||||
match it.node {
|
match it.node {
|
||||||
hir::ItemKind::Trait(_, hir::Unsafety::Unsafe, ..) => {
|
ast::ItemKind::Trait(_, ast::Unsafety::Unsafe, ..) => {
|
||||||
self.report_unsafe(cx, it.span, "declaration of an `unsafe` trait")
|
self.report_unsafe(cx, it.span, "declaration of an `unsafe` trait")
|
||||||
}
|
}
|
||||||
|
|
||||||
hir::ItemKind::Impl(hir::Unsafety::Unsafe, ..) => {
|
ast::ItemKind::Impl(ast::Unsafety::Unsafe, ..) => {
|
||||||
self.report_unsafe(cx, it.span, "implementation of an `unsafe` trait")
|
self.report_unsafe(cx, it.span, "implementation of an `unsafe` trait")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,19 +259,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnsafeCode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn check_fn(&mut self,
|
fn check_fn(&mut self,
|
||||||
cx: &LateContext,
|
cx: &EarlyContext,
|
||||||
fk: FnKind<'tcx>,
|
fk: FnKind,
|
||||||
_: &hir::FnDecl,
|
_: &ast::FnDecl,
|
||||||
_: &hir::Body,
|
|
||||||
span: Span,
|
span: Span,
|
||||||
_: ast::NodeId) {
|
_: ast::NodeId) {
|
||||||
match fk {
|
match fk {
|
||||||
FnKind::ItemFn(_, _, hir::FnHeader { unsafety: hir::Unsafety::Unsafe, .. }, ..) => {
|
FnKind::ItemFn(_, ast::FnHeader { unsafety: ast::Unsafety::Unsafe, .. }, ..) => {
|
||||||
self.report_unsafe(cx, span, "declaration of an `unsafe` function")
|
self.report_unsafe(cx, span, "declaration of an `unsafe` function")
|
||||||
}
|
}
|
||||||
|
|
||||||
FnKind::Method(_, sig, ..) => {
|
FnKind::Method(_, sig, ..) => {
|
||||||
if sig.header.unsafety == hir::Unsafety::Unsafe {
|
if sig.header.unsafety == ast::Unsafety::Unsafe {
|
||||||
self.report_unsafe(cx, span, "implementation of an `unsafe` method")
|
self.report_unsafe(cx, span, "implementation of an `unsafe` method")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -272,9 +279,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnsafeCode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_trait_item(&mut self, cx: &LateContext, item: &hir::TraitItem) {
|
fn check_trait_item(&mut self, cx: &EarlyContext, item: &ast::TraitItem) {
|
||||||
if let hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Required(_)) = item.node {
|
if let ast::TraitItemKind::Method(ref sig, None) = item.node {
|
||||||
if sig.header.unsafety == hir::Unsafety::Unsafe {
|
if sig.header.unsafety == ast::Unsafety::Unsafe {
|
||||||
self.report_unsafe(cx, item.span, "declaration of an `unsafe` method")
|
self.report_unsafe(cx, item.span, "declaration of an `unsafe` method")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -111,6 +111,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
|
|||||||
add_early_builtin!(sess,
|
add_early_builtin!(sess,
|
||||||
UnusedParens,
|
UnusedParens,
|
||||||
UnusedImportBraces,
|
UnusedImportBraces,
|
||||||
|
UnsafeCode,
|
||||||
AnonymousParameters,
|
AnonymousParameters,
|
||||||
UnusedDocComment,
|
UnusedDocComment,
|
||||||
BadRepr,
|
BadRepr,
|
||||||
@ -134,7 +135,6 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
|
|||||||
NonSnakeCase: NonSnakeCase,
|
NonSnakeCase: NonSnakeCase,
|
||||||
NonUpperCaseGlobals: NonUpperCaseGlobals,
|
NonUpperCaseGlobals: NonUpperCaseGlobals,
|
||||||
NonShorthandFieldPatterns: NonShorthandFieldPatterns,
|
NonShorthandFieldPatterns: NonShorthandFieldPatterns,
|
||||||
UnsafeCode: UnsafeCode,
|
|
||||||
UnusedAllocation: UnusedAllocation,
|
UnusedAllocation: UnusedAllocation,
|
||||||
MissingCopyImplementations: MissingCopyImplementations,
|
MissingCopyImplementations: MissingCopyImplementations,
|
||||||
UnstableFeatures: UnstableFeatures,
|
UnstableFeatures: UnstableFeatures,
|
||||||
|
@ -910,6 +910,13 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||||||
let place = Place::Local(local);
|
let place = Place::Local(local);
|
||||||
let &ArgInfo(ty, opt_ty_info, pattern, ref self_binding) = arg_info;
|
let &ArgInfo(ty, opt_ty_info, pattern, ref self_binding) = arg_info;
|
||||||
|
|
||||||
|
// Make sure we drop (parts of) the argument even when not matched on.
|
||||||
|
self.schedule_drop(
|
||||||
|
pattern.as_ref().map_or(ast_body.span, |pat| pat.span),
|
||||||
|
argument_scope, &place, ty,
|
||||||
|
DropKind::Value { cached_block: CachedBlock::default() },
|
||||||
|
);
|
||||||
|
|
||||||
if let Some(pattern) = pattern {
|
if let Some(pattern) = pattern {
|
||||||
let pattern = self.hir.pattern_from_hir(pattern);
|
let pattern = self.hir.pattern_from_hir(pattern);
|
||||||
let span = pattern.span;
|
let span = pattern.span;
|
||||||
@ -941,13 +948,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure we drop (parts of) the argument even when not matched on.
|
|
||||||
self.schedule_drop(
|
|
||||||
pattern.as_ref().map_or(ast_body.span, |pat| pat.span),
|
|
||||||
argument_scope, &place, ty,
|
|
||||||
DropKind::Value { cached_block: CachedBlock::default() },
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enter the argument pattern bindings source scope, if it exists.
|
// Enter the argument pattern bindings source scope, if it exists.
|
||||||
|
@ -171,13 +171,23 @@ fn check_impl_overlap<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: ast::NodeI
|
|||||||
// This is something like impl Trait1 for Trait2. Illegal
|
// This is something like impl Trait1 for Trait2. Illegal
|
||||||
// if Trait1 is a supertrait of Trait2 or Trait2 is not object safe.
|
// if Trait1 is a supertrait of Trait2 or Trait2 is not object safe.
|
||||||
|
|
||||||
if let Some(principal_def_id) = data.principal_def_id() {
|
let component_def_ids = data.iter().flat_map(|predicate| {
|
||||||
if !tcx.is_object_safe(principal_def_id) {
|
match predicate.skip_binder() {
|
||||||
|
ty::ExistentialPredicate::Trait(tr) => Some(tr.def_id),
|
||||||
|
ty::ExistentialPredicate::AutoTrait(def_id) => Some(*def_id),
|
||||||
|
// An associated type projection necessarily comes with
|
||||||
|
// an additional `Trait` requirement.
|
||||||
|
ty::ExistentialPredicate::Projection(..) => None,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
for component_def_id in component_def_ids {
|
||||||
|
if !tcx.is_object_safe(component_def_id) {
|
||||||
// This is an error, but it will be reported by wfcheck. Ignore it here.
|
// This is an error, but it will be reported by wfcheck. Ignore it here.
|
||||||
// This is tested by `coherence-impl-trait-for-trait-object-safe.rs`.
|
// This is tested by `coherence-impl-trait-for-trait-object-safe.rs`.
|
||||||
} else {
|
} else {
|
||||||
let mut supertrait_def_ids =
|
let mut supertrait_def_ids =
|
||||||
traits::supertrait_def_ids(tcx, principal_def_id);
|
traits::supertrait_def_ids(tcx, component_def_id);
|
||||||
if supertrait_def_ids.any(|d| d == trait_def_id) {
|
if supertrait_def_ids.any(|d| d == trait_def_id) {
|
||||||
let sp = tcx.sess.source_map().def_span(tcx.span_of_impl(impl_def_id).unwrap());
|
let sp = tcx.sess.source_map().def_span(tcx.span_of_impl(impl_def_id).unwrap());
|
||||||
struct_span_err!(tcx.sess,
|
struct_span_err!(tcx.sess,
|
||||||
@ -193,6 +203,5 @@ fn check_impl_overlap<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: ast::NodeI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// FIXME: also check auto-trait def-ids? (e.g. `impl Sync for Foo+Sync`)?
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2431,7 +2431,7 @@ if (!DOMTokenList.prototype.remove) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var crates_text = [];
|
var crates_text = [];
|
||||||
if (crates.length > 1) {
|
if (Object.keys(crates).length > 1) {
|
||||||
for (var crate in crates) {
|
for (var crate in crates) {
|
||||||
if (crates.hasOwnProperty(crate)) {
|
if (crates.hasOwnProperty(crate)) {
|
||||||
crates_text.push(crate);
|
crates_text.push(crate);
|
||||||
|
@ -853,13 +853,13 @@ pub struct Field {
|
|||||||
|
|
||||||
pub type SpannedIdent = Spanned<Ident>;
|
pub type SpannedIdent = Spanned<Ident>;
|
||||||
|
|
||||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy)]
|
#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)]
|
||||||
pub enum BlockCheckMode {
|
pub enum BlockCheckMode {
|
||||||
Default,
|
Default,
|
||||||
Unsafe(UnsafeSource),
|
Unsafe(UnsafeSource),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy)]
|
#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)]
|
||||||
pub enum UnsafeSource {
|
pub enum UnsafeSource {
|
||||||
CompilerGenerated,
|
CompilerGenerated,
|
||||||
UserProvided,
|
UserProvided,
|
||||||
|
@ -0,0 +1,68 @@
|
|||||||
|
// Check that partially moved from function parameters are dropped after the
|
||||||
|
// named bindings that move from them.
|
||||||
|
|
||||||
|
// ignore-wasm32-bare compiled with panic=abort by default
|
||||||
|
|
||||||
|
use std::{panic, cell::RefCell};
|
||||||
|
|
||||||
|
struct LogDrop<'a>(i32, Context<'a>);
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
struct Context<'a> {
|
||||||
|
panic_on: i32,
|
||||||
|
drops: &'a RefCell<Vec<i32>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Context<'a> {
|
||||||
|
fn record_drop(self, index: i32) {
|
||||||
|
self.drops.borrow_mut().push(index);
|
||||||
|
if index == self.panic_on {
|
||||||
|
panic!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Drop for LogDrop<'a> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
self.1.record_drop(self.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bindings_in_params((_x, _): (LogDrop, LogDrop), (_, _y): (LogDrop, LogDrop)) {}
|
||||||
|
fn bindings_with_let(a: (LogDrop, LogDrop), b: (LogDrop, LogDrop)) {
|
||||||
|
// Drop order in foo is the same as the following bindings.
|
||||||
|
// _temp2 is declared after _x to avoid a difference between `_: T` and
|
||||||
|
// `x: T` in function parameters.
|
||||||
|
let _temp1 = a;
|
||||||
|
let (_x, _) = _temp1;
|
||||||
|
|
||||||
|
let _temp2 = b;
|
||||||
|
let (_, _y) = _temp2;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_drop_order(panic_on: i32, fun: fn((LogDrop, LogDrop), (LogDrop, LogDrop))) {
|
||||||
|
let context = Context {
|
||||||
|
panic_on,
|
||||||
|
drops: &RefCell::new(Vec::new()),
|
||||||
|
};
|
||||||
|
let one = LogDrop(1, context);
|
||||||
|
let two = LogDrop(2, context);
|
||||||
|
let three = LogDrop(3, context);
|
||||||
|
let four = LogDrop(4, context);
|
||||||
|
|
||||||
|
let res = panic::catch_unwind(panic::AssertUnwindSafe(|| {
|
||||||
|
fun((three, four), (two, one));
|
||||||
|
}));
|
||||||
|
if panic_on == 0 {
|
||||||
|
assert!(res.is_ok(), "should not have panicked");
|
||||||
|
} else {
|
||||||
|
assert!(res.is_err(), "should have panicked");
|
||||||
|
}
|
||||||
|
assert_eq!(*context.drops.borrow(), [1, 2, 3, 4], "incorrect drop order");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
(0..=4).for_each(|i| test_drop_order(i, bindings_in_params));
|
||||||
|
(0..=4).for_each(|i| test_drop_order(i, bindings_with_let));
|
||||||
|
(0..=4).for_each(|i| test_drop_order(i, |(_x, _), (_, _y)| {}));
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
#![feature(optin_builtin_traits)]
|
||||||
|
|
||||||
|
// Test for issue #56934 - that it is impossible to redundantly
|
||||||
|
// implement an auto-trait for a trait object type that contains it.
|
||||||
|
|
||||||
|
// Negative impl variant.
|
||||||
|
|
||||||
|
auto trait Marker1 {}
|
||||||
|
auto trait Marker2 {}
|
||||||
|
|
||||||
|
trait Object: Marker1 {}
|
||||||
|
|
||||||
|
// A supertrait marker is illegal...
|
||||||
|
impl !Marker1 for dyn Object + Marker2 { } //~ ERROR E0371
|
||||||
|
// ...and also a direct component.
|
||||||
|
impl !Marker2 for dyn Object + Marker2 { } //~ ERROR E0371
|
||||||
|
|
||||||
|
// But implementing a marker if it is not present is OK.
|
||||||
|
impl !Marker2 for dyn Object {} // OK
|
||||||
|
|
||||||
|
// A non-principal trait-object type is orphan even in its crate.
|
||||||
|
impl !Send for dyn Marker2 {} //~ ERROR E0117
|
||||||
|
|
||||||
|
// And impl'ing a remote marker for a local trait object is forbidden
|
||||||
|
// by one of these special orphan-like rules.
|
||||||
|
impl !Send for dyn Object {} //~ ERROR E0321
|
||||||
|
impl !Send for dyn Object + Marker2 {} //~ ERROR E0321
|
||||||
|
|
||||||
|
fn main() { }
|
@ -0,0 +1,37 @@
|
|||||||
|
error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1`
|
||||||
|
--> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:14:1
|
||||||
|
|
|
||||||
|
LL | impl !Marker1 for dyn Object + Marker2 { } //~ ERROR E0371
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1`
|
||||||
|
|
||||||
|
error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2`
|
||||||
|
--> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:16:1
|
||||||
|
|
|
||||||
|
LL | impl !Marker2 for dyn Object + Marker2 { } //~ ERROR E0371
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2`
|
||||||
|
|
||||||
|
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
|
||||||
|
--> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:22:1
|
||||||
|
|
|
||||||
|
LL | impl !Send for dyn Marker2 {} //~ ERROR E0117
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
||||||
|
|
|
||||||
|
= note: the impl does not reference only types defined in this crate
|
||||||
|
= note: define and implement a trait or new type instead
|
||||||
|
|
||||||
|
error[E0321]: cross-crate traits with a default impl, like `std::marker::Send`, can only be implemented for a struct/enum type, not `(dyn Object + 'static)`
|
||||||
|
--> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:26:1
|
||||||
|
|
|
||||||
|
LL | impl !Send for dyn Object {} //~ ERROR E0321
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type
|
||||||
|
|
||||||
|
error[E0321]: cross-crate traits with a default impl, like `std::marker::Send`, can only be implemented for a struct/enum type, not `(dyn Object + Marker2 + 'static)`
|
||||||
|
--> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:27:1
|
||||||
|
|
|
||||||
|
LL | impl !Send for dyn Object + Marker2 {} //~ ERROR E0321
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type
|
||||||
|
|
||||||
|
error: aborting due to 5 previous errors
|
||||||
|
|
||||||
|
Some errors occurred: E0117, E0321, E0371.
|
||||||
|
For more information about an error, try `rustc --explain E0117`.
|
@ -0,0 +1,29 @@
|
|||||||
|
#![feature(optin_builtin_traits)]
|
||||||
|
|
||||||
|
// Test for issue #56934 - that it is impossible to redundantly
|
||||||
|
// implement an auto-trait for a trait object type that contains it.
|
||||||
|
|
||||||
|
// Positive impl variant.
|
||||||
|
|
||||||
|
auto trait Marker1 {}
|
||||||
|
auto trait Marker2 {}
|
||||||
|
|
||||||
|
trait Object: Marker1 {}
|
||||||
|
|
||||||
|
// A supertrait marker is illegal...
|
||||||
|
impl Marker1 for dyn Object + Marker2 { } //~ ERROR E0371
|
||||||
|
// ...and also a direct component.
|
||||||
|
impl Marker2 for dyn Object + Marker2 { } //~ ERROR E0371
|
||||||
|
|
||||||
|
// But implementing a marker if it is not present is OK.
|
||||||
|
impl Marker2 for dyn Object {} // OK
|
||||||
|
|
||||||
|
// A non-principal trait-object type is orphan even in its crate.
|
||||||
|
unsafe impl Send for dyn Marker2 {} //~ ERROR E0117
|
||||||
|
|
||||||
|
// And impl'ing a remote marker for a local trait object is forbidden
|
||||||
|
// by one of these special orphan-like rules.
|
||||||
|
unsafe impl Send for dyn Object {} //~ ERROR E0321
|
||||||
|
unsafe impl Send for dyn Object + Marker2 {} //~ ERROR E0321
|
||||||
|
|
||||||
|
fn main() { }
|
@ -0,0 +1,37 @@
|
|||||||
|
error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1`
|
||||||
|
--> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:14:1
|
||||||
|
|
|
||||||
|
LL | impl Marker1 for dyn Object + Marker2 { } //~ ERROR E0371
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1`
|
||||||
|
|
||||||
|
error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2`
|
||||||
|
--> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:16:1
|
||||||
|
|
|
||||||
|
LL | impl Marker2 for dyn Object + Marker2 { } //~ ERROR E0371
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2`
|
||||||
|
|
||||||
|
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
|
||||||
|
--> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:22:1
|
||||||
|
|
|
||||||
|
LL | unsafe impl Send for dyn Marker2 {} //~ ERROR E0117
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
||||||
|
|
|
||||||
|
= note: the impl does not reference only types defined in this crate
|
||||||
|
= note: define and implement a trait or new type instead
|
||||||
|
|
||||||
|
error[E0321]: cross-crate traits with a default impl, like `std::marker::Send`, can only be implemented for a struct/enum type, not `(dyn Object + 'static)`
|
||||||
|
--> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:26:1
|
||||||
|
|
|
||||||
|
LL | unsafe impl Send for dyn Object {} //~ ERROR E0321
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type
|
||||||
|
|
||||||
|
error[E0321]: cross-crate traits with a default impl, like `std::marker::Send`, can only be implemented for a struct/enum type, not `(dyn Object + Marker2 + 'static)`
|
||||||
|
--> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:27:1
|
||||||
|
|
|
||||||
|
LL | unsafe impl Send for dyn Object + Marker2 {} //~ ERROR E0321
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type
|
||||||
|
|
||||||
|
error: aborting due to 5 previous errors
|
||||||
|
|
||||||
|
Some errors occurred: E0117, E0321, E0371.
|
||||||
|
For more information about an error, try `rustc --explain E0117`.
|
16
src/test/ui/lint/lint-forbid-internal-unsafe.rs
Normal file
16
src/test/ui/lint/lint-forbid-internal-unsafe.rs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#![forbid(unsafe_code)]
|
||||||
|
#![feature(allow_internal_unsafe)]
|
||||||
|
|
||||||
|
#[allow_internal_unsafe]
|
||||||
|
//~^ ERROR: `allow_internal_unsafe` allows defining
|
||||||
|
macro_rules! evil {
|
||||||
|
($e:expr) => {
|
||||||
|
unsafe {
|
||||||
|
$e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
println!("{}", evil!(*(0 as *const u8)));
|
||||||
|
}
|
14
src/test/ui/lint/lint-forbid-internal-unsafe.stderr
Normal file
14
src/test/ui/lint/lint-forbid-internal-unsafe.stderr
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
error: `allow_internal_unsafe` allows defining macros using unsafe without triggering the `unsafe_code` lint at their call site
|
||||||
|
--> $DIR/lint-forbid-internal-unsafe.rs:4:1
|
||||||
|
|
|
||||||
|
LL | #[allow_internal_unsafe]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
note: lint level defined here
|
||||||
|
--> $DIR/lint-forbid-internal-unsafe.rs:1:11
|
||||||
|
|
|
||||||
|
LL | #![forbid(unsafe_code)]
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
@ -1,4 +1,5 @@
|
|||||||
// failure-status: 101
|
// failure-status: 101
|
||||||
|
// rustc-env:RUST_BACKTRACE=0
|
||||||
|
|
||||||
// This is a repro test for an ICE in our pattern handling of constants.
|
// This is a repro test for an ICE in our pattern handling of constants.
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user