Forbid cross-polarity specializations

This commit is contained in:
Aaron Turon 2016-02-23 07:48:34 -08:00
parent 2651f8c147
commit 386f8eefc0
2 changed files with 19 additions and 9 deletions

View File

@ -41,6 +41,7 @@ pub struct Overlap<'a, 'tcx: 'a> {
/// Given a subst for the requested impl, translate it to a subst /// Given a subst for the requested impl, translate it to a subst
/// appropriate for the actual item definition (whether it be in that impl, /// appropriate for the actual item definition (whether it be in that impl,
/// a parent impl, or the trait). /// a parent impl, or the trait).
//
// When we have selected one impl, but are actually using item definitions from // When we have selected one impl, but are actually using item definitions from
// a parent impl providing a default, we need a way to translate between the // a parent impl providing a default, we need a way to translate between the
// type parameters of the two impls. Here the `source_impl` is the one we've // type parameters of the two impls. Here the `source_impl` is the one we've
@ -153,6 +154,11 @@ pub fn specializes(tcx: &ty::ctxt, impl1_def_id: DefId, impl2_def_id: DefId) ->
// //
// See RFC 1210 for more details and justification. // See RFC 1210 for more details and justification.
// Currently we do not allow e.g. a negative impl to specialize a positive one
if tcx.trait_impl_polarity(impl1_def_id) != tcx.trait_impl_polarity(impl2_def_id) {
return false
}
let mut infcx = infer::normalizing_infer_ctxt(tcx, &tcx.tables); let mut infcx = infer::normalizing_infer_ctxt(tcx, &tcx.tables);
// Skiolemize impl1: we want to prove that "for all types matched by impl1, // Skiolemize impl1: we want to prove that "for all types matched by impl1,

View File

@ -8,19 +8,23 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
// Make sure specialization cannot change impl polarity
#![feature(optin_builtin_traits)] #![feature(optin_builtin_traits)]
#![feature(specialization)] #![feature(specialization)]
struct TestType<T>(T); trait Foo {}
// TODO: nail down the rules here with @nikomatsakis impl Foo for .. {}
unsafe impl<T> Send for TestType<T> {} impl<T> Foo for T {}
impl !Send for TestType<u8> {} impl !Foo for u8 {} //~ ERROR E0119
fn assert_send<T: Send>() {} trait Bar {}
fn main() { impl Bar for .. {}
assert_send::<TestType<()>>();
assert_send::<TestType<u8>>(); //~ ERROR impl<T> !Bar for T {}
} impl Bar for u8 {} //~ ERROR E0119
fn main() {}