diff options
| author | bors <bors@rust-lang.org> | 2017-01-20 04:55:01 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2017-01-20 04:55:01 +0000 |
| commit | b53d37479079d820290e21c424f0a6f9af112afe (patch) | |
| tree | 024664de02e9a09764a050f46409be5a6e4e5d2a | |
| parent | f0b42075981d9914c39e848377a3e12f0adf37d7 (diff) | |
| parent | c85fb1933f0924401f89f935f8f0b436bf177b14 (diff) | |
Auto merge of #38603 - arielb1:supertrait-self-3, r=nikomatsakis
traits with self-containing supertraits are not object safe This should be the last time I fix this function. Fixes #38404.
| -rw-r--r-- | src/librustc/traits/object_safety.rs | 20 | ||||
| -rw-r--r-- | src/test/compile-fail/issue-38404.rs | 16 | ||||
| -rw-r--r-- | src/test/compile-fail/issue-38604.rs | 26 |
3 files changed, 57 insertions, 5 deletions
diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index 0d5c9b98941..60808fbc741 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -81,8 +81,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { { let mut violations = vec![]; - if self.supertraits_reference_self(trait_def_id) { - violations.push(ObjectSafetyViolation::SupertraitSelf); + for def_id in traits::supertrait_def_ids(self, trait_def_id) { + if self.predicates_reference_self(def_id, true) { + violations.push(ObjectSafetyViolation::SupertraitSelf); + } } debug!("astconv_object_safety_violations(trait_def_id={:?}) = {:?}", @@ -115,7 +117,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { if self.trait_has_sized_self(trait_def_id) { violations.push(ObjectSafetyViolation::SizedSelf); } - if self.supertraits_reference_self(trait_def_id) { + if self.predicates_reference_self(trait_def_id, false) { violations.push(ObjectSafetyViolation::SupertraitSelf); } @@ -126,12 +128,20 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { violations } - fn supertraits_reference_self(self, trait_def_id: DefId) -> bool { + fn predicates_reference_self( + self, + trait_def_id: DefId, + supertraits_only: bool) -> bool + { let trait_ref = ty::Binder(ty::TraitRef { def_id: trait_def_id, substs: Substs::identity_for_item(self, trait_def_id) }); - let predicates = self.item_super_predicates(trait_def_id); + let predicates = if supertraits_only { + self.item_super_predicates(trait_def_id) + } else { + self.item_predicates(trait_def_id) + }; predicates .predicates .into_iter() diff --git a/src/test/compile-fail/issue-38404.rs b/src/test/compile-fail/issue-38404.rs new file mode 100644 index 00000000000..a2b0d0a60c0 --- /dev/null +++ b/src/test/compile-fail/issue-38404.rs @@ -0,0 +1,16 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +trait A<T>: std::ops::Add<Self> + Sized {} +trait B<T>: A<T> {} +trait C<T>: A<B<T, Output=usize>> {} +//~^ ERROR the trait `B` cannot be made into an object + +fn main() {} diff --git a/src/test/compile-fail/issue-38604.rs b/src/test/compile-fail/issue-38604.rs new file mode 100644 index 00000000000..c1939a7707f --- /dev/null +++ b/src/test/compile-fail/issue-38604.rs @@ -0,0 +1,26 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +trait Q<T:?Sized> {} +trait Foo where u32: Q<Self> { + fn foo(&self); +} + +impl Q<()> for u32 {} +impl Foo for () { + fn foo(&self) { + println!("foo!"); + } +} + +fn main() { + let _f: Box<Foo> = //~ ERROR `Foo` cannot be made into an object + Box::new(()); //~ ERROR `Foo` cannot be made into an object +} |
