Add two new kinds of predicates, WellFormed and ObjectSafe.
This commit is contained in:
parent
928955296e
commit
b1963154a1
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -57,6 +57,8 @@ impl FreeRegionMap {
|
||||
ty::Predicate::Projection(..) |
|
||||
ty::Predicate::Trait(..) |
|
||||
ty::Predicate::Equate(..) |
|
||||
ty::Predicate::WellFormed(..) |
|
||||
ty::Predicate::ObjectSafe(..) |
|
||||
ty::Predicate::TypeOutlives(..) => {
|
||||
// No region bounds here
|
||||
}
|
||||
|
@ -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 @@ impl<'a, 'tcx> Implicator<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
}
|
||||
ty::Predicate::ObjectSafe(_) |
|
||||
ty::Predicate::WellFormed(_) => {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
@ -20,8 +21,10 @@ use util::nodemap::NodeMap;
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -44,6 +44,7 @@ use middle::infer::{InferCtxt, TypeFreshener};
|
||||
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 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
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());
|
||||
|
@ -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 @@ impl<'a,'tcx> PredicateSet<'a,'tcx> {
|
||||
|
||||
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 @@ impl<'cx, 'tcx> Elaborator<'cx, '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 @@ impl<'tcx> fmt::Debug for super::MismatchedProjectionTypes<'tcx> {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -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 @@ impl<'tcx> Predicate<'tcx> {
|
||||
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 @@ impl<'tcx> Predicate<'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 @@ impl<'tcx> Predicate<'tcx> {
|
||||
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 @@ impl<'tcx> Predicate<'tcx> {
|
||||
Predicate::Projection(..) |
|
||||
Predicate::Equate(..) |
|
||||
Predicate::RegionOutlives(..) |
|
||||
Predicate::WellFormed(..) |
|
||||
Predicate::ObjectSafe(..) |
|
||||
Predicate::TypeOutlives(..) => {
|
||||
None
|
||||
}
|
||||
@ -6211,6 +6231,8 @@ impl<'tcx> ctxt<'tcx> {
|
||||
ty::Predicate::Projection(..) |
|
||||
ty::Predicate::Trait(..) |
|
||||
ty::Predicate::Equate(..) |
|
||||
ty::Predicate::WellFormed(..) |
|
||||
ty::Predicate::ObjectSafe(..) |
|
||||
ty::Predicate::RegionOutlives(..) => {
|
||||
None
|
||||
}
|
||||
@ -6712,6 +6734,8 @@ impl<'tcx> ctxt<'tcx> {
|
||||
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 @@ impl<'tcx> fmt::Debug for ty::Predicate<'tcx> {
|
||||
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 @@ impl<'tcx> RegionEscape for Predicate<'tcx> {
|
||||
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 @@ impl<'tcx> HasTypeFlags for Predicate<'tcx> {
|
||||
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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -394,6 +394,10 @@ impl<'tcx> TypeFoldable<'tcx> for 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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -831,6 +831,11 @@ impl<'tcx> fmt::Display for ty::Predicate<'tcx> {
|
||||
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))
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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))
|
||||
|
@ -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);
|
||||
|
||||
|
@ -490,6 +490,8 @@ impl<'tcx> GetTypeParameterBounds<'tcx> for ty::GenericPredicates<'tcx> {
|
||||
}
|
||||
ty::Predicate::Equate(..) |
|
||||
ty::Predicate::RegionOutlives(..) |
|
||||
ty::Predicate::WellFormed(..) |
|
||||
ty::Predicate::ObjectSafe(..) |
|
||||
ty::Predicate::Projection(..) => {
|
||||
false
|
||||
}
|
||||
|
@ -818,7 +818,9 @@ impl<'a> Clean<WherePredicate> for ty::Predicate<'a> {
|
||||
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"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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`
|
||||
|
Loading…
x
Reference in New Issue
Block a user