Skip to content

Commit b196315

Browse files
committed
Add two new kinds of predicates, WellFormed and ObjectSafe.
1 parent 9289552 commit b196315

File tree

16 files changed

+149
-12
lines changed

16 files changed

+149
-12
lines changed

src/librustc/metadata/tydecode.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -790,6 +790,12 @@ fn parse_predicate_<'a,'tcx, F>(st: &mut PState<'a, 'tcx>,
790790
'o' => ty::Binder(ty::OutlivesPredicate(parse_ty_(st, conv),
791791
parse_region_(st, conv))).to_predicate(),
792792
'p' => ty::Binder(parse_projection_predicate_(st, conv)).to_predicate(),
793+
'w' => ty::Predicate::WellFormed(parse_ty_(st, conv)),
794+
'O' => {
795+
let def_id = parse_def_(st, NominalType, conv);
796+
assert_eq!(next(st), '|');
797+
ty::Predicate::ObjectSafe(def_id)
798+
}
793799
c => panic!("Encountered invalid character in metadata: {}", c)
794800
}
795801
}

src/librustc/metadata/tyencode.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,13 @@ pub fn enc_predicate<'a, 'tcx>(w: &mut Encoder,
457457
mywrite!(w, "p");
458458
enc_projection_predicate(w, cx, data)
459459
}
460+
ty::Predicate::WellFormed(data) => {
461+
mywrite!(w, "w");
462+
enc_ty(w, cx, data);
463+
}
464+
ty::Predicate::ObjectSafe(trait_def_id) => {
465+
mywrite!(w, "O{}|", (cx.ds)(trait_def_id));
466+
}
460467
}
461468
}
462469

src/librustc/middle/free_region.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ impl FreeRegionMap {
5757
ty::Predicate::Projection(..) |
5858
ty::Predicate::Trait(..) |
5959
ty::Predicate::Equate(..) |
60+
ty::Predicate::WellFormed(..) |
61+
ty::Predicate::ObjectSafe(..) |
6062
ty::Predicate::TypeOutlives(..) => {
6163
// No region bounds here
6264
}

src/librustc/middle/implicator.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
use middle::infer::{InferCtxt, GenericKind};
1414
use middle::subst::Substs;
1515
use middle::traits;
16-
use middle::ty::{self, RegionEscape, ToPolyTraitRef, ToPredicate, Ty};
16+
use middle::ty::{self, RegionEscape, ToPredicate, Ty};
1717
use middle::ty_fold::{TypeFoldable, TypeFolder};
1818

1919
use syntax::ast;
@@ -299,6 +299,9 @@ impl<'a, 'tcx> Implicator<'a, 'tcx> {
299299
}
300300
}
301301
}
302+
ty::Predicate::ObjectSafe(_) |
303+
ty::Predicate::WellFormed(_) => {
304+
}
302305
}
303306
}
304307

src/librustc/middle/traits/fulfill.rs

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
use middle::infer::InferCtxt;
1212
use middle::ty::{self, RegionEscape, Ty, HasTypeFlags};
13+
use middle::wf;
1314

1415
use std::collections::HashSet;
1516
use std::fmt;
@@ -20,8 +21,10 @@ use util::nodemap::NodeMap;
2021
use super::CodeAmbiguity;
2122
use super::CodeProjectionError;
2223
use super::CodeSelectionError;
24+
use super::is_object_safe;
2325
use super::FulfillmentError;
2426
use super::ObligationCause;
27+
use super::ObligationCauseCode;
2528
use super::PredicateObligation;
2629
use super::project;
2730
use super::select::SelectionContext;
@@ -472,6 +475,32 @@ fn process_predicate<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
472475
}
473476
}
474477
}
478+
479+
ty::Predicate::ObjectSafe(trait_def_id) => {
480+
if !is_object_safe(selcx.tcx(), trait_def_id) {
481+
errors.push(FulfillmentError::new(
482+
obligation.clone(),
483+
CodeSelectionError(Unimplemented)));
484+
}
485+
true
486+
}
487+
488+
ty::Predicate::WellFormed(ty) => {
489+
let rfc1214 = match obligation.cause.code {
490+
ObligationCauseCode::RFC1214(_) => true,
491+
_ => false,
492+
};
493+
match wf::obligations(selcx.infcx(), obligation.cause.body_id,
494+
ty, obligation.cause.span, rfc1214) {
495+
Some(obligations) => {
496+
new_obligations.extend(obligations);
497+
true
498+
}
499+
None => {
500+
false
501+
}
502+
}
503+
}
475504
}
476505
}
477506

@@ -492,11 +521,12 @@ fn register_region_obligation<'tcx>(t_a: Ty<'tcx>,
492521
sub_region: r_b,
493522
cause: cause };
494523

495-
debug!("register_region_obligation({:?})",
496-
region_obligation);
524+
debug!("register_region_obligation({:?}, cause={:?})",
525+
region_obligation, region_obligation.cause);
497526

498-
region_obligations.entry(region_obligation.cause.body_id).or_insert(vec![])
499-
.push(region_obligation);
527+
region_obligations.entry(region_obligation.cause.body_id)
528+
.or_insert(vec![])
529+
.push(region_obligation);
500530

501531
}
502532

src/librustc/middle/traits/object_safety.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ pub enum ObjectSafetyViolation<'tcx> {
4040
}
4141

4242
/// Reasons a method might not be object-safe.
43-
#[derive(Copy,Clone,Debug)]
43+
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
4444
pub enum MethodViolationCode {
4545
/// e.g., `fn foo()`
4646
StaticMethod,
@@ -140,6 +140,8 @@ fn supertraits_reference_self<'tcx>(tcx: &ty::ctxt<'tcx>,
140140
.any(is_self)
141141
}
142142
ty::Predicate::Projection(..) |
143+
ty::Predicate::WellFormed(..) |
144+
ty::Predicate::ObjectSafe(..) |
143145
ty::Predicate::TypeOutlives(..) |
144146
ty::Predicate::RegionOutlives(..) |
145147
ty::Predicate::Equate(..) => {
@@ -181,6 +183,8 @@ fn generics_require_sized_self<'tcx>(tcx: &ty::ctxt<'tcx>,
181183
ty::Predicate::Trait(..) |
182184
ty::Predicate::Equate(..) |
183185
ty::Predicate::RegionOutlives(..) |
186+
ty::Predicate::WellFormed(..) |
187+
ty::Predicate::ObjectSafe(..) |
184188
ty::Predicate::TypeOutlives(..) => {
185189
false
186190
}

src/librustc/middle/traits/select.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ use middle::infer::{InferCtxt, TypeFreshener};
4444
use middle::ty_fold::TypeFoldable;
4545
use middle::ty_match;
4646
use middle::ty_relate::TypeRelation;
47+
use middle::wf;
4748

4849
use std::cell::RefCell;
4950
use std::fmt;
@@ -465,12 +466,31 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
465466
}
466467
}
467468

469+
ty::Predicate::WellFormed(ty) => {
470+
match wf::obligations(self.infcx, obligation.cause.body_id,
471+
ty, obligation.cause.span,
472+
obligation.cause.code.is_rfc1214()) {
473+
Some(obligations) =>
474+
self.evaluate_predicates_recursively(previous_stack, obligations.iter()),
475+
None =>
476+
EvaluatedToAmbig,
477+
}
478+
}
479+
468480
ty::Predicate::TypeOutlives(..) | ty::Predicate::RegionOutlives(..) => {
469481
// we do not consider region relationships when
470482
// evaluating trait matches
471483
EvaluatedToOk
472484
}
473485

486+
ty::Predicate::ObjectSafe(trait_def_id) => {
487+
if object_safety::is_object_safe(self.tcx(), trait_def_id) {
488+
EvaluatedToOk
489+
} else {
490+
EvaluatedToErr(Unimplemented)
491+
}
492+
}
493+
474494
ty::Predicate::Projection(ref data) => {
475495
self.infcx.probe(|_| {
476496
let project_obligation = obligation.with(data.clone());

src/librustc/middle/traits/util.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
use middle::subst::Substs;
1212
use middle::infer::InferCtxt;
13-
use middle::ty::{self, Ty, ToPredicate, ToPolyTraitRef};
13+
use middle::ty::{self, HasTypeFlags, Ty, ToPredicate, ToPolyTraitRef};
1414
use std::fmt;
1515
use syntax::ast;
1616
use syntax::codemap::Span;
@@ -56,6 +56,12 @@ impl<'a,'tcx> PredicateSet<'a,'tcx> {
5656

5757
ty::Predicate::Projection(ref data) =>
5858
ty::Predicate::Projection(self.tcx.anonymize_late_bound_regions(data)),
59+
60+
ty::Predicate::WellFormed(data) =>
61+
ty::Predicate::WellFormed(data),
62+
63+
ty::Predicate::ObjectSafe(data) =>
64+
ty::Predicate::ObjectSafe(data),
5965
};
6066
self.set.insert(normalized_pred)
6167
}
@@ -136,6 +142,14 @@ impl<'cx, 'tcx> Elaborator<'cx, 'tcx> {
136142

137143
self.stack.extend(predicates);
138144
}
145+
ty::Predicate::WellFormed(..) => {
146+
// Currently, we do not elaborate WF predicates,
147+
// although we easily could.
148+
}
149+
ty::Predicate::ObjectSafe(..) => {
150+
// Currently, we do not elaborate object-safe
151+
// predicates.
152+
}
139153
ty::Predicate::Equate(..) => {
140154
// Currently, we do not "elaborate" predicates like
141155
// `X == Y`, though conceivably we might. For example,
@@ -562,3 +576,9 @@ impl<'tcx> fmt::Debug for super::MismatchedProjectionTypes<'tcx> {
562576
write!(f, "MismatchedProjectionTypes({:?})", self.err)
563577
}
564578
}
579+
580+
impl<'tcx, T: HasTypeFlags> HasTypeFlags for Obligation<'tcx, T> {
581+
fn has_type_flags(&self, flags: ty::TypeFlags) -> bool {
582+
self.predicate.has_type_flags(flags)
583+
}
584+
}

src/librustc/middle/ty.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2417,6 +2417,12 @@ pub enum Predicate<'tcx> {
24172417
/// where <T as TraitRef>::Name == X, approximately.
24182418
/// See `ProjectionPredicate` struct for details.
24192419
Projection(PolyProjectionPredicate<'tcx>),
2420+
2421+
/// no syntax: T WF
2422+
WellFormed(Ty<'tcx>),
2423+
2424+
/// trait must be object-safe
2425+
ObjectSafe(ast::DefId),
24202426
}
24212427

24222428
impl<'tcx> Predicate<'tcx> {
@@ -2502,6 +2508,10 @@ impl<'tcx> Predicate<'tcx> {
25022508
Predicate::TypeOutlives(ty::Binder(data.subst(tcx, substs))),
25032509
Predicate::Projection(ty::Binder(ref data)) =>
25042510
Predicate::Projection(ty::Binder(data.subst(tcx, substs))),
2511+
Predicate::WellFormed(data) =>
2512+
Predicate::WellFormed(data.subst(tcx, substs)),
2513+
Predicate::ObjectSafe(trait_def_id) =>
2514+
Predicate::ObjectSafe(trait_def_id),
25052515
}
25062516
}
25072517
}
@@ -2689,6 +2699,12 @@ impl<'tcx> Predicate<'tcx> {
26892699
.chain(Some(data.0.ty))
26902700
.collect()
26912701
}
2702+
ty::Predicate::WellFormed(data) => {
2703+
vec![data]
2704+
}
2705+
ty::Predicate::ObjectSafe(_trait_def_id) => {
2706+
vec![]
2707+
}
26922708
};
26932709

26942710
// The only reason to collect into a vector here is that I was
@@ -2706,6 +2722,8 @@ impl<'tcx> Predicate<'tcx> {
27062722
Predicate::RegionOutlives(ref p) => p.has_escaping_regions(),
27072723
Predicate::TypeOutlives(ref p) => p.has_escaping_regions(),
27082724
Predicate::Projection(ref p) => p.has_escaping_regions(),
2725+
Predicate::WellFormed(p) => p.has_escaping_regions(),
2726+
Predicate::ObjectSafe(_trait_def_id) => false,
27092727
}
27102728
}
27112729

@@ -2717,6 +2735,8 @@ impl<'tcx> Predicate<'tcx> {
27172735
Predicate::Projection(..) |
27182736
Predicate::Equate(..) |
27192737
Predicate::RegionOutlives(..) |
2738+
Predicate::WellFormed(..) |
2739+
Predicate::ObjectSafe(..) |
27202740
Predicate::TypeOutlives(..) => {
27212741
None
27222742
}
@@ -6211,6 +6231,8 @@ impl<'tcx> ctxt<'tcx> {
62116231
ty::Predicate::Projection(..) |
62126232
ty::Predicate::Trait(..) |
62136233
ty::Predicate::Equate(..) |
6234+
ty::Predicate::WellFormed(..) |
6235+
ty::Predicate::ObjectSafe(..) |
62146236
ty::Predicate::RegionOutlives(..) => {
62156237
None
62166238
}
@@ -6712,6 +6734,8 @@ impl<'tcx> ctxt<'tcx> {
67126734
ty::Predicate::Equate(..) |
67136735
ty::Predicate::RegionOutlives(..) |
67146736
ty::Predicate::TypeOutlives(..) |
6737+
ty::Predicate::WellFormed(..) |
6738+
ty::Predicate::ObjectSafe(..) |
67156739
ty::Predicate::Projection(..) => {
67166740
// For now, assume all these where-clauses
67176741
// may give drop implementation capabilty
@@ -6956,6 +6980,8 @@ impl<'tcx> fmt::Debug for ty::Predicate<'tcx> {
69566980
Predicate::RegionOutlives(ref pair) => write!(f, "{:?}", pair),
69576981
Predicate::TypeOutlives(ref pair) => write!(f, "{:?}", pair),
69586982
Predicate::Projection(ref pair) => write!(f, "{:?}", pair),
6983+
Predicate::WellFormed(ty) => write!(f, "WF({:?})", ty),
6984+
Predicate::ObjectSafe(trait_def_id) => write!(f, "ObjectSafe({:?})", trait_def_id),
69596985
}
69606986
}
69616987
}
@@ -7080,6 +7106,8 @@ impl<'tcx> RegionEscape for Predicate<'tcx> {
70807106
Predicate::RegionOutlives(ref data) => data.has_regions_escaping_depth(depth),
70817107
Predicate::TypeOutlives(ref data) => data.has_regions_escaping_depth(depth),
70827108
Predicate::Projection(ref data) => data.has_regions_escaping_depth(depth),
7109+
Predicate::WellFormed(ty) => ty.has_regions_escaping_depth(depth),
7110+
Predicate::ObjectSafe(_trait_def_id) => false,
70837111
}
70847112
}
70857113
}
@@ -7238,6 +7266,8 @@ impl<'tcx> HasTypeFlags for Predicate<'tcx> {
72387266
Predicate::RegionOutlives(ref data) => data.has_type_flags(flags),
72397267
Predicate::TypeOutlives(ref data) => data.has_type_flags(flags),
72407268
Predicate::Projection(ref data) => data.has_type_flags(flags),
7269+
Predicate::WellFormed(data) => data.has_type_flags(flags),
7270+
Predicate::ObjectSafe(_trait_def_id) => false,
72417271
}
72427272
}
72437273
}

src/librustc/middle/ty_fold.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,10 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'tcx> {
394394
ty::Predicate::TypeOutlives(binder.fold_with(folder)),
395395
ty::Predicate::Projection(ref binder) =>
396396
ty::Predicate::Projection(binder.fold_with(folder)),
397+
ty::Predicate::WellFormed(data) =>
398+
ty::Predicate::WellFormed(data.fold_with(folder)),
399+
ty::Predicate::ObjectSafe(trait_def_id) =>
400+
ty::Predicate::ObjectSafe(trait_def_id),
397401
}
398402
}
399403
}

src/librustc/util/ppaux.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -831,6 +831,11 @@ impl<'tcx> fmt::Display for ty::Predicate<'tcx> {
831831
ty::Predicate::RegionOutlives(ref predicate) => write!(f, "{}", predicate),
832832
ty::Predicate::TypeOutlives(ref predicate) => write!(f, "{}", predicate),
833833
ty::Predicate::Projection(ref predicate) => write!(f, "{}", predicate),
834+
ty::Predicate::WellFormed(ty) => write!(f, "{} well-formed", ty),
835+
ty::Predicate::ObjectSafe(trait_def_id) =>
836+
ty::tls::with(|tcx| {
837+
write!(f, "the trait `{}` is object-safe", tcx.item_path_str(trait_def_id))
838+
}),
834839
}
835840
}
836841
}

src/librustc_typeck/check/closure.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,8 @@ fn deduce_expectations_from_obligations<'a,'tcx>(
177177
ty::Predicate::Equate(..) => None,
178178
ty::Predicate::RegionOutlives(..) => None,
179179
ty::Predicate::TypeOutlives(..) => None,
180+
ty::Predicate::WellFormed(..) => None,
181+
ty::Predicate::ObjectSafe(..) => None,
180182
};
181183
opt_trait_ref
182184
.and_then(|trait_ref| self_type_matches_expected_vid(fcx, trait_ref, expected_vid))

src/librustc_typeck/check/dropck.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -254,9 +254,9 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
254254
/// This function is meant to by applied to the type for every
255255
/// expression in the program.
256256
pub fn check_safety_of_destructor_if_necessary<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>,
257-
typ: ty::Ty<'tcx>,
258-
span: Span,
259-
scope: region::CodeExtent) {
257+
typ: ty::Ty<'tcx>,
258+
span: Span,
259+
scope: region::CodeExtent) {
260260
debug!("check_safety_of_destructor_if_necessary typ: {:?} scope: {:?}",
261261
typ, scope);
262262

src/librustc_typeck/collect.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,8 @@ impl<'tcx> GetTypeParameterBounds<'tcx> for ty::GenericPredicates<'tcx> {
490490
}
491491
ty::Predicate::Equate(..) |
492492
ty::Predicate::RegionOutlives(..) |
493+
ty::Predicate::WellFormed(..) |
494+
ty::Predicate::ObjectSafe(..) |
493495
ty::Predicate::Projection(..) => {
494496
false
495497
}

0 commit comments

Comments
 (0)