'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)
}
}
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));
+ }
}
}
ty::Predicate::Projection(..) |
ty::Predicate::Trait(..) |
ty::Predicate::Equate(..) |
+ ty::Predicate::WellFormed(..) |
+ ty::Predicate::ObjectSafe(..) |
ty::Predicate::TypeOutlives(..) => {
// No region bounds here
}
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;
}
}
}
+ ty::Predicate::ObjectSafe(_) |
+ ty::Predicate::WellFormed(_) => {
+ }
}
}
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;
}
}
}
+
+ 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
+ }
+ }
+ }
}
}
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);
}
}
/// 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,
.any(is_self)
}
ty::Predicate::Projection(..) |
+ ty::Predicate::WellFormed(..) |
+ ty::Predicate::ObjectSafe(..) |
ty::Predicate::TypeOutlives(..) |
ty::Predicate::RegionOutlives(..) |
ty::Predicate::Equate(..) => {
ty::Predicate::Trait(..) |
ty::Predicate::Equate(..) |
ty::Predicate::RegionOutlives(..) |
+ ty::Predicate::WellFormed(..) |
+ ty::Predicate::ObjectSafe(..) |
ty::Predicate::TypeOutlives(..) => {
false
}
use middle::ty_fold::TypeFoldable;
use middle::ty_match;
use middle::ty_relate::TypeRelation;
+use middle::wf;
use std::cell::RefCell;
use std::fmt;
}
}
+ 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());
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;
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)
}
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,
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)
+ }
+}
/// 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> {
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),
}
}
}
.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
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,
}
}
Predicate::Projection(..) |
Predicate::Equate(..) |
Predicate::RegionOutlives(..) |
+ Predicate::WellFormed(..) |
+ Predicate::ObjectSafe(..) |
Predicate::TypeOutlives(..) => {
None
}
ty::Predicate::Projection(..) |
ty::Predicate::Trait(..) |
ty::Predicate::Equate(..) |
+ ty::Predicate::WellFormed(..) |
+ ty::Predicate::ObjectSafe(..) |
ty::Predicate::RegionOutlives(..) => {
None
}
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
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),
}
}
}
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,
}
}
}
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,
}
}
}
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),
}
}
}
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))
+ }),
}
}
}
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))
/// 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);
}
ty::Predicate::Equate(..) |
ty::Predicate::RegionOutlives(..) |
+ ty::Predicate::WellFormed(..) |
+ ty::Predicate::ObjectSafe(..) |
ty::Predicate::Projection(..) => {
false
}
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"),
}
}
}
/// 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`