about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2015-02-18 11:58:44 -0500
committerFlavio Percoco <flaper87@gmail.com>2015-02-22 02:14:26 +0100
commit40fffc9e3fe1664240683a2e86f2d14827417ef5 (patch)
tree301cef96642441482bcaa07025a53fb1642c78b3
parentd215411911c2f6e5a68a12686c930352f68d2031 (diff)
downloadrust-40fffc9e3fe1664240683a2e86f2d14827417ef5.tar.gz
rust-40fffc9e3fe1664240683a2e86f2d14827417ef5.zip
Some nits and cleanup
-rw-r--r--src/librustc/middle/traits/select.rs93
-rw-r--r--src/librustc_typeck/coherence/overlap.rs3
2 files changed, 55 insertions, 41 deletions
diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs
index 6462f3830a1..c5ef55154de 100644
--- a/src/librustc/middle/traits/select.rs
+++ b/src/librustc/middle/traits/select.rs
@@ -152,6 +152,8 @@ enum SelectionCandidate<'tcx> {
 
     ObjectCandidate,
 
+    BuiltinObjectCandidate,
+
     ErrorCandidate,
 }
 
@@ -818,21 +820,24 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 debug!("obligation self ty is {}",
                        obligation.predicate.0.self_ty().repr(self.tcx()));
 
+                // User-defined copy impls are permitted, but only for
+                // structs and enums.
                 try!(self.assemble_candidates_from_impls(obligation, &mut candidates));
 
+                // For other types, we'll use the builtin rules.
                 try!(self.assemble_builtin_bound_candidates(ty::BoundCopy,
                                                             stack,
                                                             &mut candidates));
             }
             Some(bound @ ty::BoundSized) => {
-                // Sized and Copy are always automatically computed.
+                // Sized is never implementable by end-users, it is
+                // always automatically computed.
                 try!(self.assemble_builtin_bound_candidates(bound, stack, &mut candidates));
             }
 
-            _ => {
-                // For the time being, we ignore user-defined impls for builtin-bounds, other than
-                // `Copy`.
-                // (And unboxed candidates only apply to the Fn/FnMut/etc traits.)
+            Some(ty::BoundSend) |
+            Some(ty::BoundSync) |
+            None => {
                 try!(self.assemble_closure_candidates(obligation, &mut candidates));
                 try!(self.assemble_fn_pointer_candidates(obligation, &mut candidates));
                 try!(self.assemble_candidates_from_impls(obligation, &mut candidates));
@@ -1178,7 +1183,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                         if data.bounds.builtin_bounds.contains(&bound) {
                             debug!("assemble_candidates_from_object_ty: matched builtin bound, \
                             pushing candidate");
-                            candidates.vec.push(BuiltinCandidate(bound));
+                            candidates.vec.push(BuiltinObjectCandidate);
                             return;
                         }
                     }
@@ -1272,6 +1277,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             (&ImplCandidate(..), &ParamCandidate(..)) |
             (&ClosureCandidate(..), &ParamCandidate(..)) |
             (&FnPointerCandidate(..), &ParamCandidate(..)) |
+            (&BuiltinObjectCandidate(..), &ParamCandidate(_)) |
             (&BuiltinCandidate(..), &ParamCandidate(..)) => {
                 // We basically prefer always prefer to use a
                 // where-clause over another option. Where clauses
@@ -1359,7 +1365,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 Ok(If(Vec::new()))
             }
 
-            ty::ty_uniq(referent_ty) => {  // Box<T>
+            ty::ty_uniq(_) => {  // Box<T>
                 match bound {
                     ty::BoundCopy => {
                         Err(Unimplemented)
@@ -1369,26 +1375,20 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                         Ok(If(Vec::new()))
                     }
 
-                    ty::BoundSync |
-                    ty::BoundSend => {
-                        Ok(If(vec![referent_ty]))
+                    ty::BoundSync | ty::BoundSend => {
+                        self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()");
                     }
                 }
             }
 
             ty::ty_ptr(..) => {     // *const T, *mut T
                 match bound {
-                    ty::BoundCopy |
-                    ty::BoundSized => {
+                    ty::BoundCopy | ty::BoundSized => {
                         Ok(If(Vec::new()))
                     }
 
-                    ty::BoundSync |
-                    ty::BoundSend => {
-                        self.tcx().sess.bug(
-                            &format!(
-                                "raw pointers should have a negative \
-                                 impl for `Send` and `Sync`")[]);
+                    ty::BoundSync | ty::BoundSend => {
+                        self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()");
                     }
                 }
             }
@@ -1398,7 +1398,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     ty::BoundSized => {
                         Err(Unimplemented)
                     }
-                    ty::BoundCopy | ty::BoundSync | ty::BoundSend => {
+                    ty::BoundCopy => {
                         if data.bounds.builtin_bounds.contains(&bound) {
                             Ok(If(Vec::new()))
                         } else {
@@ -1417,6 +1417,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                             Err(Unimplemented)
                         }
                     }
+                    ty::BoundSync | ty::BoundSend => {
+                        self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()");
+                    }
                 }
             }
 
@@ -1441,9 +1444,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                         Ok(If(Vec::new()))
                     }
 
-                    ty::BoundSync |
-                    ty::BoundSend => {
-                        Ok(If(vec![referent_ty]))
+                    ty::BoundSync | ty::BoundSend => {
+                        self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()");
                     }
                 }
             }
@@ -1472,9 +1474,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                         }
                     }
 
-                    ty::BoundSync |
-                    ty::BoundSend => {
-                        Ok(If(vec![element_ty]))
+                    ty::BoundSync | ty::BoundSend => {
+                        self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()");
                     }
                 }
             }
@@ -1482,13 +1483,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             ty::ty_str => {
                 // Equivalent to [u8]
                 match bound {
-                    ty::BoundSync |
-                    ty::BoundSend => {
-                        Ok(If(Vec::new()))
+                    ty::BoundSync | ty::BoundSend => {
+                        self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()");
                     }
 
-                    ty::BoundCopy |
-                    ty::BoundSized => {
+                    ty::BoundCopy | ty::BoundSized => {
                         Err(Unimplemented)
                     }
                 }
@@ -1576,15 +1575,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 // "opened" unsized/existential type (one that has
                 // been dereferenced)
                 match bound {
-                    ty::BoundCopy |
-                    ty::BoundSync |
-                    ty::BoundSend => {
+                    ty::BoundCopy => {
                         Ok(If(vec!(ty)))
                     }
 
                     ty::BoundSized => {
                         Err(Unimplemented)
                     }
+
+                    ty::BoundSync |
+                    ty::BoundSend => {
+                        self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()");
+                    }
                 }
             }
             ty::ty_err => {
@@ -1606,16 +1608,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         {
             // First check for markers and other nonsense.
             match bound {
-                ty::BoundCopy => {
-                    return Ok(ParameterBuiltin)
-                }
+                // Fallback to whatever user-defined impls exist in this case.
+                ty::BoundCopy => Ok(ParameterBuiltin),
 
-                ty::BoundSend |
-                ty::BoundSync |
-                ty::BoundSized => { }
-            }
+                // Sized if all the component types are sized.
+                ty::BoundSized => Ok(If(types)),
 
-            Ok(If(types))
+                // Shouldn't be coming through here.
+                ty::BoundSend | ty::BoundSync => unreachable!(),
+            }
         }
     }
 
@@ -1739,6 +1740,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 Ok(VtableClosure(closure_def_id, substs))
             }
 
+            BuiltinObjectCandidate => {
+                // This indicates something like `(Trait+Send) :
+                // Send`. In this case, we know that this holds
+                // because that's what the object type is telling us,
+                // and there's really no additional obligations to
+                // prove and no types in particular to unify etc.
+                Ok(VtableParam(Vec::new()))
+            }
+
             ObjectCandidate => {
                 let data = self.confirm_object_candidate(obligation);
                 Ok(VtableObject(data))
@@ -2449,6 +2459,7 @@ impl<'tcx> Repr<'tcx> for SelectionCandidate<'tcx> {
             PhantomFnCandidate => format!("PhantomFnCandidate"),
             ErrorCandidate => format!("ErrorCandidate"),
             BuiltinCandidate(b) => format!("BuiltinCandidate({:?})", b),
+            BuiltinObjectCandidate => format!("BuiltinObjectCandidate"),
             ParamCandidate(ref a) => format!("ParamCandidate({})", a.repr(tcx)),
             ImplCandidate(a) => format!("ImplCandidate({})", a.repr(tcx)),
             DefaultImplCandidate(t) => format!("DefaultImplCandidate({:?})", t),
diff --git a/src/librustc_typeck/coherence/overlap.rs b/src/librustc_typeck/coherence/overlap.rs
index 4a2660fcf46..26624c051c9 100644
--- a/src/librustc_typeck/coherence/overlap.rs
+++ b/src/librustc_typeck/coherence/overlap.rs
@@ -25,6 +25,9 @@ use util::ppaux::Repr;
 pub fn check(tcx: &ty::ctxt) {
     let mut overlap = OverlapChecker { tcx: tcx };
     overlap.check_for_overlapping_impls();
+
+    // this secondary walk specifically checks for impls of defaulted
+    // traits, for which additional overlap rules exist
     visit::walk_crate(&mut overlap, tcx.map.krate());
 }