Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix checking of auto trait bounds in trait objects. #45772

Merged
merged 2 commits into from
Nov 11, 2017
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
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.
  • Loading branch information
leoyvens committed Nov 5, 2017
commit f46f388cb20962cdf08747132c17448cf9602b5e
27 changes: 5 additions & 22 deletions src/librustc_typeck/astconv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}

Expand Down Expand Up @@ -1311,27 +1311,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) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In principle we could easily extend this to arbitrary marker traits, I suppose?

true
}
_ => false
}
Expand Down
6 changes: 3 additions & 3 deletions src/librustc_typeck/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
4 changes: 2 additions & 2 deletions src/test/compile-fail/E0225.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
2 changes: 1 addition & 1 deletion src/test/compile-fail/bad-sized.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
2 changes: 1 addition & 1 deletion src/test/compile-fail/issue-22560.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() { }
2 changes: 1 addition & 1 deletion src/test/compile-fail/issue-32963.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
3 changes: 3 additions & 0 deletions src/test/run-pass/auto-traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}