return Ok(None);
}
+
// If there are *NO* candidates, that there are no impls --
// that we know of, anyway. Note that in the case where there
// are unbound type variables within the obligation, it might
// Just one candidate left.
let candidate = candidates.pop().unwrap();
+
+ match candidate {
+ ImplCandidate(def_id) => {
+ match ty::trait_impl_polarity(self.tcx(), def_id) {
+ Some(ast::ImplPolarity::Negative) => return Err(Unimplemented),
+ _ => {}
+ }
+ }
+ _ => {}
+ }
+
Ok(Some(candidate))
}
debug!("obligation self ty is {}",
obligation.predicate.0.self_ty().repr(self.tcx()));
- try!(self.assemble_candidates_from_impls(obligation, &mut candidates.vec));
+ try!(self.assemble_candidates_from_impls(obligation, &mut candidates));
try!(self.assemble_builtin_bound_candidates(ty::BoundCopy,
stack,
}
Some(bound @ ty::BoundSend) |
Some(bound @ ty::BoundSync) => {
- try!(self.assemble_candidates_from_impls(obligation, &mut candidates.vec));
+ try!(self.assemble_candidates_from_impls(obligation, &mut candidates));
// No explicit impls were declared for this type, consider the fallback rules.
if candidates.vec.is_empty() && !candidates.ambiguous {
// (And unboxed candidates only apply to the Fn/FnMut/etc traits.)
try!(self.assemble_unboxed_closure_candidates(obligation, &mut candidates));
try!(self.assemble_fn_pointer_candidates(obligation, &mut candidates));
- try!(self.assemble_candidates_from_impls(obligation, &mut candidates.vec));
+ try!(self.assemble_candidates_from_impls(obligation, &mut candidates));
self.assemble_candidates_from_object_ty(obligation, &mut candidates);
}
}
/// Search for impls that might apply to `obligation`.
fn assemble_candidates_from_impls(&mut self,
obligation: &TraitObligation<'tcx>,
- candidate_vec: &mut Vec<SelectionCandidate<'tcx>>)
+ candidates: &mut SelectionCandidateSet<'tcx>)
-> Result<(), SelectionError<'tcx>>
{
+ let self_ty = self.infcx.shallow_resolve(obligation.self_ty());
+ debug!("assemble_candidates_from_impls(self_ty={})", self_ty.repr(self.tcx()));
+
let all_impls = self.all_impls(obligation.predicate.def_id());
for &impl_def_id in all_impls.iter() {
self.infcx.probe(|snapshot| {
match self.match_impl(impl_def_id, obligation, snapshot,
&skol_map, skol_obligation_trait_pred.trait_ref.clone()) {
Ok(_) => {
- candidate_vec.push(ImplCandidate(impl_def_id));
+ candidates.vec.push(ImplCandidate(impl_def_id));
}
Err(()) => { }
}
/// Returns set of all impls for a given trait.
fn all_impls(&self, trait_def_id: ast::DefId) -> Vec<ast::DefId> {
- ty::populate_implementations_for_trait_if_necessary(self.tcx(),
- trait_def_id);
- match self.tcx().trait_impls.borrow().get(&trait_def_id) {
+ ty::populate_implementations_for_trait_if_necessary(self.tcx(), trait_def_id);
+
+ let mut trait_impls = match self.tcx().trait_impls.borrow().get(&trait_def_id) {
None => Vec::new(),
Some(impls) => impls.borrow().clone()
- }
+ };
+
+ match self.tcx().trait_negative_impls.borrow().get(&trait_def_id) {
+ None => {},
+ Some(impls) => trait_impls.push_all(impls.borrow().as_slice()),
+ };
+
+ trait_impls
}
fn impl_obligations(&mut self,
ty::item_path_str(ccx.tcx, local_def(item.id)));
match item.node {
- ast::ItemImpl(..) => {
+ /// Right now we check that every default trait implementation
+ /// has an implementation of itself. Basically, a case like:
+ ///
+ /// `impl Trait for T {}`
+ ///
+ /// has a requirement of `T: Trait` which was required for default
+ /// method implementations. Although this could be improved now that
+ /// there's a better infrastructure in place for this, it's being left
+ /// for a follow-up work.
+ ///
+ /// Since there's such a requirement, we need to check *just* positive
+ /// implementations, otherwise things like:
+ ///
+ /// impl !Send for T {}
+ ///
+ /// won't be allowed unless there's an *explicit* implementation of `Send`
+ /// for `T`
+ ast::ItemImpl(_, ast::ImplPolarity::Positive, _, _, _, _) => {
self.check_impl(item);
}
ast::ItemFn(..) => {
+++ /dev/null
-// Copyright 2014 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.
-
-#![feature(optin_builtin_traits)]
-
-struct TestType;
-
-trait TestTrait {}
-
-impl !TestTrait for TestType {}
-//~^ the trait `TestTrait` is not implemented for the type `TestType`
-
-fn main() {}
--- /dev/null
+// Copyright 2015 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.
+
+#![feature(optin_builtin_traits)]
+
+use std::marker::Send;
+
+struct Outer<T: Send>(T);
+
+struct TestType;
+impl !Send for TestType {}
+
+struct Outer2<T>(T);
+
+unsafe impl<T: Send> Sync for Outer2<T> {}
+
+fn is_send<T: Send>(_: T) {}
+fn is_sync<T: Sync>(_: T) {}
+
+fn main() {
+ Outer(TestType);
+ //~^ ERROR the trait `core::marker::Send` is not implemented for the type `TestType`
+
+ is_send(TestType);
+ //~^ ERROR the trait `core::marker::Send` is not implemented for the type `TestType`
+
+ // This will complain about a missing Send impl because `Sync` is implement *just*
+ // for T that are `Send`. Look at #20366 and #19950
+ is_sync(Outer2(TestType));
+ //~^ ERROR the trait `core::marker::Send` is not implemented for the type `TestType`
+}