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:
bors 2019-01-15 13:56:16 +00:00
commit 14ea6e50c1
21 changed files with 417 additions and 35 deletions

View File

@ -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
/// ///

View File

@ -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);

View File

@ -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};

View File

@ -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>`.
/// ///

View File

@ -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)]

View File

@ -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>();

View File

@ -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)]

View File

@ -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")
} }
} }

View File

@ -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,

View File

@ -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.

View File

@ -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`)?
} }
} }

View File

@ -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);

View File

@ -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,

View File

@ -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)| {}));
}

View File

@ -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() { }

View File

@ -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`.

View File

@ -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() { }

View File

@ -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`.

View 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)));
}

View 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

View File

@ -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.