]> git.lizzy.rs Git - rust.git/commitdiff
Add two new kinds of predicates, WellFormed and ObjectSafe.
authorNiko Matsakis <niko@alum.mit.edu>
Fri, 7 Aug 2015 13:30:19 +0000 (09:30 -0400)
committerNiko Matsakis <niko@alum.mit.edu>
Wed, 12 Aug 2015 21:57:57 +0000 (17:57 -0400)
16 files changed:
src/librustc/metadata/tydecode.rs
src/librustc/metadata/tyencode.rs
src/librustc/middle/free_region.rs
src/librustc/middle/implicator.rs
src/librustc/middle/traits/fulfill.rs
src/librustc/middle/traits/object_safety.rs
src/librustc/middle/traits/select.rs
src/librustc/middle/traits/util.rs
src/librustc/middle/ty.rs
src/librustc/middle/ty_fold.rs
src/librustc/util/ppaux.rs
src/librustc_typeck/check/closure.rs
src/librustc_typeck/check/dropck.rs
src/librustc_typeck/collect.rs
src/librustdoc/clean/mod.rs
src/libsyntax/ast.rs

index 679213874f9646da6b33f6b263dc85ffa82b89a8..a8b22846b786dc3730dfab07613e34aa019d820f 100644 (file)
@@ -790,6 +790,12 @@ fn parse_predicate_<'a,'tcx, F>(st: &mut PState<'a, 'tcx>,
         'o' => ty::Binder(ty::OutlivesPredicate(parse_ty_(st, conv),
                                                 parse_region_(st, conv))).to_predicate(),
         'p' => ty::Binder(parse_projection_predicate_(st, conv)).to_predicate(),
+        'w' => ty::Predicate::WellFormed(parse_ty_(st, conv)),
+        'O' => {
+            let def_id = parse_def_(st, NominalType, conv);
+            assert_eq!(next(st), '|');
+            ty::Predicate::ObjectSafe(def_id)
+        }
         c => panic!("Encountered invalid character in metadata: {}", c)
     }
 }
index 88666be6c2cc2598f254861b4b50299b121a7db9..7170a3681713a28d22d7e18a1798ef56f7602be8 100644 (file)
@@ -457,6 +457,13 @@ pub fn enc_predicate<'a, 'tcx>(w: &mut Encoder,
             mywrite!(w, "p");
             enc_projection_predicate(w, cx, data)
         }
+        ty::Predicate::WellFormed(data) => {
+            mywrite!(w, "w");
+            enc_ty(w, cx, data);
+        }
+        ty::Predicate::ObjectSafe(trait_def_id) => {
+            mywrite!(w, "O{}|", (cx.ds)(trait_def_id));
+        }
     }
 }
 
index 9a5f03672316a6a54330f1c1da2624d8caa218d8..5af37e9530ccea22ba6475fcdc81da8a5f6155bd 100644 (file)
@@ -57,6 +57,8 @@ pub fn relate_free_regions_from_predicates<'tcx>(&mut self,
                 ty::Predicate::Projection(..) |
                 ty::Predicate::Trait(..) |
                 ty::Predicate::Equate(..) |
+                ty::Predicate::WellFormed(..) |
+                ty::Predicate::ObjectSafe(..) |
                 ty::Predicate::TypeOutlives(..) => {
                     // No region bounds here
                 }
index 21f09574a3fc884e38447b1a6b9e5fb9d6d5acf7..1961c15d6e607b6d4339815c649184761d31c0a5 100644 (file)
@@ -13,7 +13,7 @@
 use middle::infer::{InferCtxt, GenericKind};
 use middle::subst::Substs;
 use middle::traits;
-use middle::ty::{self, RegionEscape, ToPolyTraitRef, ToPredicate, Ty};
+use middle::ty::{self, RegionEscape, ToPredicate, Ty};
 use middle::ty_fold::{TypeFoldable, TypeFolder};
 
 use syntax::ast;
@@ -299,6 +299,9 @@ fn accumulate_from_adt(&mut self,
                         }
                     }
                 }
+                ty::Predicate::ObjectSafe(_) |
+                ty::Predicate::WellFormed(_) => {
+                }
             }
         }
 
index 44fc6b6b8abdc6dbb32217a79fc199fc6c1770cc..96637b92cef414d65cf5be4d9612bdbccf0f7cf8 100644 (file)
@@ -10,6 +10,7 @@
 
 use middle::infer::InferCtxt;
 use middle::ty::{self, RegionEscape, Ty, HasTypeFlags};
+use middle::wf;
 
 use std::collections::HashSet;
 use std::fmt;
 use super::CodeAmbiguity;
 use super::CodeProjectionError;
 use super::CodeSelectionError;
+use super::is_object_safe;
 use super::FulfillmentError;
 use super::ObligationCause;
+use super::ObligationCauseCode;
 use super::PredicateObligation;
 use super::project;
 use super::select::SelectionContext;
@@ -472,6 +475,32 @@ fn process_predicate<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
                 }
             }
         }
+
+        ty::Predicate::ObjectSafe(trait_def_id) => {
+            if !is_object_safe(selcx.tcx(), trait_def_id) {
+                errors.push(FulfillmentError::new(
+                    obligation.clone(),
+                    CodeSelectionError(Unimplemented)));
+            }
+            true
+        }
+
+        ty::Predicate::WellFormed(ty) => {
+            let rfc1214 = match obligation.cause.code {
+                ObligationCauseCode::RFC1214(_) => true,
+                _ => false,
+            };
+            match wf::obligations(selcx.infcx(), obligation.cause.body_id,
+                                  ty, obligation.cause.span, rfc1214) {
+                Some(obligations) => {
+                    new_obligations.extend(obligations);
+                    true
+                }
+                None => {
+                    false
+                }
+            }
+        }
     }
 }
 
@@ -492,11 +521,12 @@ fn register_region_obligation<'tcx>(t_a: Ty<'tcx>,
                                                sub_region: r_b,
                                                cause: cause };
 
-    debug!("register_region_obligation({:?})",
-           region_obligation);
+    debug!("register_region_obligation({:?}, cause={:?})",
+           region_obligation, region_obligation.cause);
 
-    region_obligations.entry(region_obligation.cause.body_id).or_insert(vec![])
-        .push(region_obligation);
+    region_obligations.entry(region_obligation.cause.body_id)
+                      .or_insert(vec![])
+                      .push(region_obligation);
 
 }
 
index e7f11b06bd132b1d7c82faac784d704cd149f34c..9d300c0973167dc3c2a2c5237c2635424de49ed6 100644 (file)
@@ -40,7 +40,7 @@ pub enum ObjectSafetyViolation<'tcx> {
 }
 
 /// Reasons a method might not be object-safe.
-#[derive(Copy,Clone,Debug)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
 pub enum MethodViolationCode {
     /// e.g., `fn foo()`
     StaticMethod,
@@ -140,6 +140,8 @@ fn supertraits_reference_self<'tcx>(tcx: &ty::ctxt<'tcx>,
                                                  .any(is_self)
                 }
                 ty::Predicate::Projection(..) |
+                ty::Predicate::WellFormed(..) |
+                ty::Predicate::ObjectSafe(..) |
                 ty::Predicate::TypeOutlives(..) |
                 ty::Predicate::RegionOutlives(..) |
                 ty::Predicate::Equate(..) => {
@@ -181,6 +183,8 @@ fn generics_require_sized_self<'tcx>(tcx: &ty::ctxt<'tcx>,
                 ty::Predicate::Trait(..) |
                 ty::Predicate::Equate(..) |
                 ty::Predicate::RegionOutlives(..) |
+                ty::Predicate::WellFormed(..) |
+                ty::Predicate::ObjectSafe(..) |
                 ty::Predicate::TypeOutlives(..) => {
                     false
                 }
index 0c9cf1a68b7320132a30ba1493491266ef848ee2..6c568b656c047b7b9409f555b2c2e55d63cb7aae 100644 (file)
@@ -44,6 +44,7 @@
 use middle::ty_fold::TypeFoldable;
 use middle::ty_match;
 use middle::ty_relate::TypeRelation;
+use middle::wf;
 
 use std::cell::RefCell;
 use std::fmt;
@@ -465,12 +466,31 @@ fn evaluate_predicate_recursively<'o>(&mut self,
                 }
             }
 
+            ty::Predicate::WellFormed(ty) => {
+                match wf::obligations(self.infcx, obligation.cause.body_id,
+                                      ty, obligation.cause.span,
+                                      obligation.cause.code.is_rfc1214()) {
+                    Some(obligations) =>
+                        self.evaluate_predicates_recursively(previous_stack, obligations.iter()),
+                    None =>
+                        EvaluatedToAmbig,
+                }
+            }
+
             ty::Predicate::TypeOutlives(..) | ty::Predicate::RegionOutlives(..) => {
                 // we do not consider region relationships when
                 // evaluating trait matches
                 EvaluatedToOk
             }
 
+            ty::Predicate::ObjectSafe(trait_def_id) => {
+                if object_safety::is_object_safe(self.tcx(), trait_def_id) {
+                    EvaluatedToOk
+                } else {
+                    EvaluatedToErr(Unimplemented)
+                }
+            }
+
             ty::Predicate::Projection(ref data) => {
                 self.infcx.probe(|_| {
                     let project_obligation = obligation.with(data.clone());
index af9d5e5157d28e8567b3ecf2a72602e208184cbb..6df13a3bdaf554c8bd106cdd689d8f4204068970 100644 (file)
@@ -10,7 +10,7 @@
 
 use middle::subst::Substs;
 use middle::infer::InferCtxt;
-use middle::ty::{self, Ty, ToPredicate, ToPolyTraitRef};
+use middle::ty::{self, HasTypeFlags, Ty, ToPredicate, ToPolyTraitRef};
 use std::fmt;
 use syntax::ast;
 use syntax::codemap::Span;
@@ -56,6 +56,12 @@ fn insert(&mut self, pred: &ty::Predicate<'tcx>) -> bool {
 
             ty::Predicate::Projection(ref data) =>
                 ty::Predicate::Projection(self.tcx.anonymize_late_bound_regions(data)),
+
+            ty::Predicate::WellFormed(data) =>
+                ty::Predicate::WellFormed(data),
+
+            ty::Predicate::ObjectSafe(data) =>
+                ty::Predicate::ObjectSafe(data),
         };
         self.set.insert(normalized_pred)
     }
@@ -136,6 +142,14 @@ fn push(&mut self, predicate: &ty::Predicate<'tcx>) {
 
                 self.stack.extend(predicates);
             }
+            ty::Predicate::WellFormed(..) => {
+                // Currently, we do not elaborate WF predicates,
+                // although we easily could.
+            }
+            ty::Predicate::ObjectSafe(..) => {
+                // Currently, we do not elaborate object-safe
+                // predicates.
+            }
             ty::Predicate::Equate(..) => {
                 // Currently, we do not "elaborate" predicates like
                 // `X == Y`, though conceivably we might. For example,
@@ -562,3 +576,9 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "MismatchedProjectionTypes({:?})", self.err)
     }
 }
+
+impl<'tcx, T: HasTypeFlags> HasTypeFlags for Obligation<'tcx, T> {
+    fn has_type_flags(&self, flags: ty::TypeFlags) -> bool {
+        self.predicate.has_type_flags(flags)
+    }
+}
index 7d807bf2431ff0adc39cba8cf270c5214c60efd0..393bb83067cc806cb65183e39a1f45c6e625f010 100644 (file)
@@ -2417,6 +2417,12 @@ pub enum Predicate<'tcx> {
     /// where <T as TraitRef>::Name == X, approximately.
     /// See `ProjectionPredicate` struct for details.
     Projection(PolyProjectionPredicate<'tcx>),
+
+    /// no syntax: T WF
+    WellFormed(Ty<'tcx>),
+
+    /// trait must be object-safe
+    ObjectSafe(ast::DefId),
 }
 
 impl<'tcx> Predicate<'tcx> {
@@ -2502,6 +2508,10 @@ pub fn subst_supertrait(&self,
                 Predicate::TypeOutlives(ty::Binder(data.subst(tcx, substs))),
             Predicate::Projection(ty::Binder(ref data)) =>
                 Predicate::Projection(ty::Binder(data.subst(tcx, substs))),
+            Predicate::WellFormed(data) =>
+                Predicate::WellFormed(data.subst(tcx, substs)),
+            Predicate::ObjectSafe(trait_def_id) =>
+                Predicate::ObjectSafe(trait_def_id),
         }
     }
 }
@@ -2689,6 +2699,12 @@ pub fn walk_tys(&self) -> IntoIter<Ty<'tcx>> {
                             .chain(Some(data.0.ty))
                             .collect()
             }
+            ty::Predicate::WellFormed(data) => {
+                vec![data]
+            }
+            ty::Predicate::ObjectSafe(_trait_def_id) => {
+                vec![]
+            }
         };
 
         // The only reason to collect into a vector here is that I was
@@ -2706,6 +2722,8 @@ pub fn has_escaping_regions(&self) -> bool {
             Predicate::RegionOutlives(ref p) => p.has_escaping_regions(),
             Predicate::TypeOutlives(ref p) => p.has_escaping_regions(),
             Predicate::Projection(ref p) => p.has_escaping_regions(),
+            Predicate::WellFormed(p) => p.has_escaping_regions(),
+            Predicate::ObjectSafe(_trait_def_id) => false,
         }
     }
 
@@ -2717,6 +2735,8 @@ pub fn to_opt_poly_trait_ref(&self) -> Option<PolyTraitRef<'tcx>> {
             Predicate::Projection(..) |
             Predicate::Equate(..) |
             Predicate::RegionOutlives(..) |
+            Predicate::WellFormed(..) |
+            Predicate::ObjectSafe(..) |
             Predicate::TypeOutlives(..) => {
                 None
             }
@@ -6211,6 +6231,8 @@ pub fn required_region_bounds(&self,
                     ty::Predicate::Projection(..) |
                     ty::Predicate::Trait(..) |
                     ty::Predicate::Equate(..) |
+                    ty::Predicate::WellFormed(..) |
+                    ty::Predicate::ObjectSafe(..) |
                     ty::Predicate::RegionOutlives(..) => {
                         None
                     }
@@ -6712,6 +6734,8 @@ fn is_adt_dtorck(&self, adt: AdtDef<'tcx>) -> bool {
                     ty::Predicate::Equate(..) |
                     ty::Predicate::RegionOutlives(..) |
                     ty::Predicate::TypeOutlives(..) |
+                    ty::Predicate::WellFormed(..) |
+                    ty::Predicate::ObjectSafe(..) |
                     ty::Predicate::Projection(..) => {
                         // For now, assume all these where-clauses
                         // may give drop implementation capabilty
@@ -6956,6 +6980,8 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
             Predicate::RegionOutlives(ref pair) => write!(f, "{:?}", pair),
             Predicate::TypeOutlives(ref pair) => write!(f, "{:?}", pair),
             Predicate::Projection(ref pair) => write!(f, "{:?}", pair),
+            Predicate::WellFormed(ty) => write!(f, "WF({:?})", ty),
+            Predicate::ObjectSafe(trait_def_id) => write!(f, "ObjectSafe({:?})", trait_def_id),
         }
     }
 }
@@ -7080,6 +7106,8 @@ fn has_regions_escaping_depth(&self, depth: u32) -> bool {
             Predicate::RegionOutlives(ref data) => data.has_regions_escaping_depth(depth),
             Predicate::TypeOutlives(ref data) => data.has_regions_escaping_depth(depth),
             Predicate::Projection(ref data) => data.has_regions_escaping_depth(depth),
+            Predicate::WellFormed(ty) => ty.has_regions_escaping_depth(depth),
+            Predicate::ObjectSafe(_trait_def_id) => false,
         }
     }
 }
@@ -7238,6 +7266,8 @@ fn has_type_flags(&self, flags: TypeFlags) -> bool {
             Predicate::RegionOutlives(ref data) => data.has_type_flags(flags),
             Predicate::TypeOutlives(ref data) => data.has_type_flags(flags),
             Predicate::Projection(ref data) => data.has_type_flags(flags),
+            Predicate::WellFormed(data) => data.has_type_flags(flags),
+            Predicate::ObjectSafe(_trait_def_id) => false,
         }
     }
 }
index cc1efeaea080f39e1e633bb4bad2e684b56b1381..809ee8928afd76d0edb69ebc42239871137f6ab8 100644 (file)
@@ -394,6 +394,10 @@ fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::Predicate<'tcx>
                 ty::Predicate::TypeOutlives(binder.fold_with(folder)),
             ty::Predicate::Projection(ref binder) =>
                 ty::Predicate::Projection(binder.fold_with(folder)),
+            ty::Predicate::WellFormed(data) =>
+                ty::Predicate::WellFormed(data.fold_with(folder)),
+            ty::Predicate::ObjectSafe(trait_def_id) =>
+                ty::Predicate::ObjectSafe(trait_def_id),
         }
     }
 }
index da20f730babab3bef80cae4c11de67fb4ab75ee5..3e9a64a8eb61e05163ac2d79e4743a99ca05910d 100644 (file)
@@ -831,6 +831,11 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
             ty::Predicate::RegionOutlives(ref predicate) => write!(f, "{}", predicate),
             ty::Predicate::TypeOutlives(ref predicate) => write!(f, "{}", predicate),
             ty::Predicate::Projection(ref predicate) => write!(f, "{}", predicate),
+            ty::Predicate::WellFormed(ty) => write!(f, "{} well-formed", ty),
+            ty::Predicate::ObjectSafe(trait_def_id) =>
+                ty::tls::with(|tcx| {
+                    write!(f, "the trait `{}` is object-safe", tcx.item_path_str(trait_def_id))
+                }),
         }
     }
 }
index cb5875ec8bcea89e9c7602c56af547331e77a21d..9098b241e5b1d34e08e9cd0fee07637aab5945f5 100644 (file)
@@ -177,6 +177,8 @@ fn deduce_expectations_from_obligations<'a,'tcx>(
                 ty::Predicate::Equate(..) => None,
                 ty::Predicate::RegionOutlives(..) => None,
                 ty::Predicate::TypeOutlives(..) => None,
+                ty::Predicate::WellFormed(..) => None,
+                ty::Predicate::ObjectSafe(..) => None,
             };
             opt_trait_ref
                 .and_then(|trait_ref| self_type_matches_expected_vid(fcx, trait_ref, expected_vid))
index 39e67beab583d18c8d77e88dcd302efa02a1b23c..30a9d65661a36abd2547e94225a4e25b87c827a3 100644 (file)
@@ -254,9 +254,9 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
 /// This function is meant to by applied to the type for every
 /// expression in the program.
 pub fn check_safety_of_destructor_if_necessary<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>,
-                                                     typ: ty::Ty<'tcx>,
-                                                     span: Span,
-                                                     scope: region::CodeExtent) {
+                                                         typ: ty::Ty<'tcx>,
+                                                         span: Span,
+                                                         scope: region::CodeExtent) {
     debug!("check_safety_of_destructor_if_necessary typ: {:?} scope: {:?}",
            typ, scope);
 
index dabc09db68d8e80faa2bb9446f77d82aaf0efb5b..3c315e335c6376b2686860f1ea5b116e18695521 100644 (file)
@@ -490,6 +490,8 @@ fn get_type_parameter_bounds(&self,
                     }
                     ty::Predicate::Equate(..) |
                     ty::Predicate::RegionOutlives(..) |
+                    ty::Predicate::WellFormed(..) |
+                    ty::Predicate::ObjectSafe(..) |
                     ty::Predicate::Projection(..) => {
                         false
                     }
index 52f69784b5cc761d80a2c1fbdad76460900ff22f..04b1f8ee1b1d39f94c0031e425236db6450ce336 100644 (file)
@@ -818,7 +818,9 @@ fn clean(&self, cx: &DocContext) -> WherePredicate {
             Predicate::Equate(ref pred) => pred.clean(cx),
             Predicate::RegionOutlives(ref pred) => pred.clean(cx),
             Predicate::TypeOutlives(ref pred) => pred.clean(cx),
-            Predicate::Projection(ref pred) => pred.clean(cx)
+            Predicate::Projection(ref pred) => pred.clean(cx),
+            Predicate::WellFormed(_) => panic!("not user writable"),
+            Predicate::ObjectSafe(_) => panic!("not user writable"),
         }
     }
 }
index bcc90dc47d9dfde480323161bfd60ed518c59a52..08c6dcc7f872a7c626da92b0d1ff1e642153d991 100644 (file)
@@ -475,7 +475,7 @@ pub enum WherePredicate {
     /// A lifetime predicate, e.g. `'a: 'b+'c`
     RegionPredicate(WhereRegionPredicate),
     /// An equality predicate (unsupported)
-    EqPredicate(WhereEqPredicate)
+    EqPredicate(WhereEqPredicate),
 }
 
 /// A type bound, eg `for<'c> Foo: Send+Clone+'c`