Auto merge of #45772 - leodasvacas:fix-auto-bounds-in-trait-objects, r=nikomatsakis

Fix checking of auto trait bounds in trait objects.

Any auto trait is allowed in trait object bounds. Fix duplicate check of type and lifetime parameter count, which we were [emitting twice](https://play.rust-lang.org/?gist=37dbbdbbec62dec423bb8f6d92f137cc&version=stable).

Note: This was the last use of `Send` in the compiler, meaning after a new `stage0` we could remove the `send` lang item.
This commit is contained in:
bors 2017-11-11 09:56:22 +00:00
commit 69ee5a8a97
9 changed files with 17 additions and 32 deletions

View File

@ -39,7 +39,7 @@ use hash::Hasher;
/// [arc]: ../../std/sync/struct.Arc.html
/// [ub]: ../../reference/behavior-considered-undefined.html
#[stable(feature = "rust1", since = "1.0.0")]
#[lang = "send"]
#[cfg_attr(stage0, lang = "send")]
#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
pub unsafe trait Send {
// empty.

View File

@ -229,7 +229,6 @@ language_item_table! {
F32ImplItem, "f32", f32_impl;
F64ImplItem, "f64", f64_impl;
SendTraitLangItem, "send", send_trait;
SizedTraitLangItem, "sized", sized_trait;
UnsizeTraitLangItem, "unsize", unsize_trait;
CopyTraitLangItem, "copy", copy_trait;

View File

@ -572,8 +572,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
let b = &trait_bounds[0];
let span = b.trait_ref.path.span;
struct_span_err!(self.tcx().sess, span, E0225,
"only Send/Sync traits can be used as additional traits in a trait object")
.span_label(span, "non-Send/Sync additional trait")
"only auto traits can be used as additional traits in a trait object")
.span_label(span, "non-auto additional trait")
.emit();
}
@ -1257,27 +1257,10 @@ fn split_auto_traits<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
-> (Vec<DefId>, Vec<&'b hir::PolyTraitRef>)
{
let (auto_traits, trait_bounds): (Vec<_>, _) = trait_bounds.iter().partition(|bound| {
// Checks whether `trait_did` is an auto trait and adds it to `auto_traits` if so.
match bound.trait_ref.path.def {
Def::Trait(trait_did) => {
// Checks whether `trait_did` refers to one of the builtin
// traits, like `Send`, and adds it to `auto_traits` if so.
if Some(trait_did) == tcx.lang_items().send_trait() ||
Some(trait_did) == tcx.lang_items().sync_trait() {
let segments = &bound.trait_ref.path.segments;
segments[segments.len() - 1].with_parameters(|parameters| {
if !parameters.types.is_empty() {
check_type_argument_count(tcx, bound.trait_ref.path.span,
parameters.types.len(), &[]);
}
if !parameters.lifetimes.is_empty() {
report_lifetime_number_error(tcx, bound.trait_ref.path.span,
parameters.lifetimes.len(), 0);
}
});
true
} else {
false
}
Def::Trait(trait_did) if tcx.trait_is_auto(trait_did) => {
true
}
_ => false
}

View File

@ -2455,9 +2455,9 @@ fn main() {
}
```
Send and Sync are an exception to this rule: it's possible to have bounds of
one non-builtin trait, plus either or both of Send and Sync. For example, the
following compiles correctly:
Auto traits such as Send and Sync are an exception to this rule:
It's possible to have bounds of one non-builtin trait, plus any number of
auto traits. For example, the following compiles correctly:
```
fn main() {

View File

@ -10,6 +10,6 @@
fn main() {
let _: Box<std::io::Read + std::io::Write>;
//~^ ERROR only Send/Sync traits can be used as additional traits in a trait object [E0225]
//~| NOTE non-Send/Sync additional trait
//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
//~| NOTE non-auto additional trait
}

View File

@ -12,7 +12,7 @@ trait Trait {}
pub fn main() {
let x: Vec<Trait + Sized> = Vec::new();
//~^ ERROR only Send/Sync traits can be used as additional traits in a trait object
//~^ ERROR only auto traits can be used as additional traits in a trait object
//~| ERROR the trait bound `Trait: std::marker::Sized` is not satisfied
//~| ERROR the trait bound `Trait: std::marker::Sized` is not satisfied
}

View File

@ -23,6 +23,6 @@ type Test = Add +
//~| NOTE missing reference to `RHS`
//~| NOTE because of the default `Self` reference, type parameters must be specified on object types
//~| ERROR E0225
//~| NOTE non-Send/Sync additional trait
//~| NOTE non-auto additional trait
fn main() { }

View File

@ -16,6 +16,6 @@ fn size_of_copy<T: Copy+?Sized>() -> usize { mem::size_of::<T>() }
fn main() {
size_of_copy::<Misc+Copy>();
//~^ ERROR only Send/Sync traits can be used as additional traits in a trait object
//~^ ERROR only auto traits can be used as additional traits in a trait object
//~| ERROR the trait bound `Misc: std::marker::Copy` is not satisfied
}

View File

@ -33,4 +33,7 @@ fn main() {
take_auto(AutoBool(true));
take_auto_unsafe(0);
take_auto_unsafe(AutoBool(true));
/// Auto traits are allowed in trait object bounds.
let _: &(Send + Auto) = &0;
}