Skip to content

Commit 8e373b4

Browse files
authored
Auto merge of #37965 - Mark-Simulacrum:trait-obj-to-exis-predicate, r=eddyb
Refactor TraitObject to Slice<ExistentialPredicate> For reference, the primary types changes in this PR are shown below. They may add in the understanding of what is discussed below, though they should not be required. We change `TraitObject` into a list of `ExistentialPredicate`s to allow for a couple of things: - Principal (ExistentialPredicate::Trait) is now optional. - Region bounds are moved out of `TraitObject` into `TyDynamic`. This permits wrapping only the `ExistentialPredicate` list in `Binder`. - `BuiltinBounds` and `BuiltinBound` are removed entirely from the codebase, to permit future non-constrained auto traits. These are replaced with `ExistentialPredicate::AutoTrait`, which only requires a `DefId`. For the time being, only `Send` and `Sync` are supported; this constraint can be lifted in a future pull request. - Binder-related logic is extracted from `ExistentialPredicate` into the parent (`Binder<Slice<EP>>`), so `PolyX`s are inside `TraitObject` are replaced with `X`. The code requires a sorting order for `ExistentialPredicate`s in the interned `Slice`. The sort order is asserted to be correct during interning, but the slices are not sorted at that point. 1. `ExistentialPredicate::Trait` are defined as always equal; **This may be wrong; should we be comparing them and sorting them in some way?** 1. `ExistentialPredicate::Projection`: Compared by `ExistentialProjection::sort_key`. 1. `ExistentialPredicate::AutoTrait`: Compared by `TraitDef.def_path_hash`. Construction of `ExistentialPredicate`s is conducted through `TyCtxt::mk_existential_predicates`, which interns a passed iterator as a `Slice`. There are no convenience functions to construct from a set of separate iterators; callers must pass an iterator chain. The lack of convenience functions is primarily due to few uses and the relative difficulty in defining a nice API due to optional parts and difficulty in recognizing which argument goes where. It is also true that the current situation isn't significantly better than 4 arguments to a constructor function; but the extra work is deemed unnecessary as of this time. ```rust // before this PR struct TraitObject<'tcx> { pub principal: PolyExistentialTraitRef<'tcx>, pub region_bound: &'tcx ty::Region, pub builtin_bounds: BuiltinBounds, pub projection_bounds: Vec<PolyExistentialProjection<'tcx>>, } // after pub enum ExistentialPredicate<'tcx> { // e.g. Iterator Trait(ExistentialTraitRef<'tcx>), // e.g. Iterator::Item = T Projection(ExistentialProjection<'tcx>), // e.g. Send AutoTrait(DefId), } ```
2 parents fa0005f + 8b82fd7 commit 8e373b4

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+896
-904
lines changed

mk/crates.mk

+1-1
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ DEPS_rustc_trans := arena flate getopts graphviz libc rustc rustc_back \
140140
DEPS_rustc_incremental := rustc syntax_pos serialize rustc_data_structures
141141
DEPS_rustc_save_analysis := rustc log syntax syntax_pos serialize
142142
DEPS_rustc_typeck := rustc syntax syntax_pos rustc_platform_intrinsics rustc_const_math \
143-
rustc_const_eval rustc_errors
143+
rustc_const_eval rustc_errors rustc_data_structures
144144

145145
DEPS_rustdoc := rustc rustc_driver native:hoedown serialize getopts test \
146146
rustc_lint rustc_const_eval syntax_pos rustc_data_structures

src/librustc/infer/freshen.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> {
165165
ty::TyRef(..) |
166166
ty::TyFnDef(..) |
167167
ty::TyFnPtr(_) |
168-
ty::TyTrait(..) |
168+
ty::TyDynamic(..) |
169169
ty::TyClosure(..) |
170170
ty::TyNever |
171171
ty::TyTuple(..) |

src/librustc/infer/mod.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ use middle::free_region::FreeRegionMap;
2424
use middle::mem_categorization as mc;
2525
use middle::mem_categorization::McResult;
2626
use middle::region::CodeExtent;
27+
use middle::lang_items;
2728
use mir::tcx::LvalueTy;
2829
use ty::subst::{Kind, Subst, Substs};
2930
use ty::adjustment;
@@ -1492,11 +1493,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
14921493
}
14931494
}
14941495

1496+
let copy_def_id = self.tcx.require_lang_item(lang_items::CopyTraitLangItem);
1497+
14951498
// this can get called from typeck (by euv), and moves_by_default
14961499
// rightly refuses to work with inference variables, but
14971500
// moves_by_default has a cache, which we want to use in other
14981501
// cases.
1499-
!traits::type_known_to_meet_builtin_bound(self, ty, ty::BoundCopy, span)
1502+
!traits::type_known_to_meet_bound(self, ty, copy_def_id, span)
15001503
}
15011504

15021505
pub fn node_method_ty(&self, method_call: ty::MethodCall)

src/librustc/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
#![feature(const_fn)]
3333
#![feature(core_intrinsics)]
3434
#![cfg_attr(stage0, feature(dotdot_in_tuple_patterns))]
35-
#![feature(enumset)]
3635
#![cfg_attr(stage0, feature(item_like_imports))]
3736
#![feature(libc)]
3837
#![feature(nonzero)]

src/librustc/middle/lang_items.rs

+8-25
Original file line numberDiff line numberDiff line change
@@ -90,31 +90,6 @@ impl LanguageItems {
9090
self.require(OwnedBoxLangItem)
9191
}
9292

93-
pub fn from_builtin_kind(&self, bound: ty::BuiltinBound)
94-
-> Result<DefId, String>
95-
{
96-
match bound {
97-
ty::BoundSend => self.require(SendTraitLangItem),
98-
ty::BoundSized => self.require(SizedTraitLangItem),
99-
ty::BoundCopy => self.require(CopyTraitLangItem),
100-
ty::BoundSync => self.require(SyncTraitLangItem),
101-
}
102-
}
103-
104-
pub fn to_builtin_kind(&self, id: DefId) -> Option<ty::BuiltinBound> {
105-
if Some(id) == self.send_trait() {
106-
Some(ty::BoundSend)
107-
} else if Some(id) == self.sized_trait() {
108-
Some(ty::BoundSized)
109-
} else if Some(id) == self.copy_trait() {
110-
Some(ty::BoundCopy)
111-
} else if Some(id) == self.sync_trait() {
112-
Some(ty::BoundSync)
113-
} else {
114-
None
115-
}
116-
}
117-
11893
pub fn fn_trait_kind(&self, id: DefId) -> Option<ty::ClosureKind> {
11994
let def_id_kinds = [
12095
(self.fn_trait(), ty::ClosureKind::Fn),
@@ -381,3 +356,11 @@ language_item_table! {
381356

382357
DebugTraitLangItem, "debug_trait", debug_trait;
383358
}
359+
360+
impl<'a, 'tcx, 'gcx> ty::TyCtxt<'a, 'tcx, 'gcx> {
361+
pub fn require_lang_item(&self, lang_item: LangItem) -> DefId {
362+
self.lang_items.require(lang_item).unwrap_or_else(|msg| {
363+
self.sess.fatal(&msg)
364+
})
365+
}
366+
}

src/librustc/traits/coherence.rs

+8-10
Original file line numberDiff line numberDiff line change
@@ -225,14 +225,12 @@ fn ty_is_local(tcx: TyCtxt, ty: Ty, infer_is_local: InferIsLocal) -> bool {
225225

226226
fn fundamental_ty(tcx: TyCtxt, ty: Ty) -> bool {
227227
match ty.sty {
228-
ty::TyBox(..) | ty::TyRef(..) =>
229-
true,
230-
ty::TyAdt(def, _) =>
231-
def.is_fundamental(),
232-
ty::TyTrait(ref data) =>
233-
tcx.has_attr(data.principal.def_id(), "fundamental"),
234-
_ =>
235-
false
228+
ty::TyBox(..) | ty::TyRef(..) => true,
229+
ty::TyAdt(def, _) => def.is_fundamental(),
230+
ty::TyDynamic(ref data, ..) => {
231+
data.principal().map_or(false, |p| tcx.has_attr(p.def_id(), "fundamental"))
232+
}
233+
_ => false
236234
}
237235
}
238236

@@ -272,8 +270,8 @@ fn ty_is_local_constructor(tcx: TyCtxt, ty: Ty, infer_is_local: InferIsLocal)->
272270
krate == Some(LOCAL_CRATE)
273271
}
274272

275-
ty::TyTrait(ref tt) => {
276-
tt.principal.def_id().is_local()
273+
ty::TyDynamic(ref tt, ..) => {
274+
tt.principal().map_or(false, |p| p.def_id().is_local())
277275
}
278276

279277
ty::TyError => {

src/librustc/traits/error_reporting.rs

+1-11
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
156156
ty::TyBox(..) | ty::TyRef(..) | ty::TyRawPtr(..) => Some(5),
157157
ty::TyArray(..) | ty::TySlice(..) => Some(6),
158158
ty::TyFnDef(..) | ty::TyFnPtr(..) => Some(7),
159-
ty::TyTrait(..) => Some(8),
159+
ty::TyDynamic(..) => Some(8),
160160
ty::TyClosure(..) => Some(9),
161161
ty::TyTuple(..) => Some(10),
162162
ty::TyProjection(..) => Some(11),
@@ -905,16 +905,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
905905
ObligationCauseCode::StructInitializerSized => {
906906
err.note("structs must have a statically known size to be initialized");
907907
}
908-
ObligationCauseCode::ClosureCapture(var_id, _, builtin_bound) => {
909-
let def_id = tcx.lang_items.from_builtin_kind(builtin_bound).unwrap();
910-
let trait_name = tcx.item_path_str(def_id);
911-
let name = tcx.local_var_name_str(var_id);
912-
err.note(
913-
&format!("the closure that captures `{}` requires that all captured variables \
914-
implement the trait `{}`",
915-
name,
916-
trait_name));
917-
}
918908
ObligationCauseCode::FieldSized => {
919909
err.note("only the last field of a struct may have a dynamically sized type");
920910
}

src/librustc/traits/fulfill.rs

+15-12
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ use rustc_data_structures::obligation_forest::{ForestObligation, ObligationProce
1717
use std::marker::PhantomData;
1818
use std::mem;
1919
use syntax::ast;
20-
use util::common::ErrorReported;
2120
use util::nodemap::{FxHashSet, NodeMap};
21+
use hir::def_id::DefId;
2222

2323
use super::CodeAmbiguity;
2424
use super::CodeProjectionError;
@@ -230,18 +230,21 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> {
230230
normalized.value
231231
}
232232

233-
pub fn register_builtin_bound(&mut self,
234-
infcx: &InferCtxt<'a, 'gcx, 'tcx>,
235-
ty: Ty<'tcx>,
236-
builtin_bound: ty::BuiltinBound,
237-
cause: ObligationCause<'tcx>)
233+
pub fn register_bound(&mut self,
234+
infcx: &InferCtxt<'a, 'gcx, 'tcx>,
235+
ty: Ty<'tcx>,
236+
def_id: DefId,
237+
cause: ObligationCause<'tcx>)
238238
{
239-
match infcx.tcx.predicate_for_builtin_bound(cause, builtin_bound, 0, ty) {
240-
Ok(predicate) => {
241-
self.register_predicate_obligation(infcx, predicate);
242-
}
243-
Err(ErrorReported) => { }
244-
}
239+
let trait_ref = ty::TraitRef {
240+
def_id: def_id,
241+
substs: infcx.tcx.mk_substs_trait(ty, &[]),
242+
};
243+
self.register_predicate_obligation(infcx, Obligation {
244+
cause: cause,
245+
recursion_depth: 0,
246+
predicate: trait_ref.to_predicate()
247+
});
245248
}
246249

247250
pub fn register_region_obligation(&mut self,

src/librustc/traits/mod.rs

+25-26
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use hir;
1919
use hir::def_id::DefId;
2020
use middle::free_region::FreeRegionMap;
2121
use ty::subst::Substs;
22-
use ty::{self, Ty, TyCtxt, TypeFoldable};
22+
use ty::{self, Ty, TyCtxt, TypeFoldable, ToPredicate};
2323
use infer::InferCtxt;
2424

2525
use std::rc::Rc;
@@ -125,10 +125,6 @@ pub enum ObligationCauseCode<'tcx> {
125125
ReturnType, // Return type must be Sized
126126
RepeatVec, // [T,..n] --> T must be Copy
127127

128-
// Captures of variable the given id by a closure (span is the
129-
// span of the closure)
130-
ClosureCapture(ast::NodeId, Span, ty::BuiltinBound),
131-
132128
// Types of fields (other than the last) in a struct must be sized.
133129
FieldSized,
134130

@@ -369,27 +365,30 @@ pub fn predicates_for_generics<'tcx>(cause: ObligationCause<'tcx>,
369365
/// `bound` or is not known to meet bound (note that this is
370366
/// conservative towards *no impl*, which is the opposite of the
371367
/// `evaluate` methods).
372-
pub fn type_known_to_meet_builtin_bound<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
373-
ty: Ty<'tcx>,
374-
bound: ty::BuiltinBound,
375-
span: Span)
376-
-> bool
368+
pub fn type_known_to_meet_bound<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
369+
ty: Ty<'tcx>,
370+
def_id: DefId,
371+
span: Span)
372+
-> bool
377373
{
378-
debug!("type_known_to_meet_builtin_bound(ty={:?}, bound={:?})",
374+
debug!("type_known_to_meet_bound(ty={:?}, bound={:?})",
379375
ty,
380-
bound);
381-
382-
let cause = ObligationCause::misc(span, ast::DUMMY_NODE_ID);
383-
let obligation =
384-
infcx.tcx.predicate_for_builtin_bound(cause, bound, 0, ty);
385-
let obligation = match obligation {
386-
Ok(o) => o,
387-
Err(..) => return false
376+
infcx.tcx.item_path_str(def_id));
377+
378+
let trait_ref = ty::TraitRef {
379+
def_id: def_id,
380+
substs: infcx.tcx.mk_substs_trait(ty, &[]),
388381
};
382+
let obligation = Obligation {
383+
cause: ObligationCause::misc(span, ast::DUMMY_NODE_ID),
384+
recursion_depth: 0,
385+
predicate: trait_ref.to_predicate(),
386+
};
387+
389388
let result = SelectionContext::new(infcx)
390389
.evaluate_obligation_conservatively(&obligation);
391-
debug!("type_known_to_meet_builtin_bound: ty={:?} bound={:?} => {:?}",
392-
ty, bound, result);
390+
debug!("type_known_to_meet_ty={:?} bound={} => {:?}",
391+
ty, infcx.tcx.item_path_str(def_id), result);
393392

394393
if result && (ty.has_infer_types() || ty.has_closure_types()) {
395394
// Because of inference "guessing", selection can sometimes claim
@@ -404,22 +403,22 @@ pub fn type_known_to_meet_builtin_bound<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'g
404403
// anyhow).
405404
let cause = ObligationCause::misc(span, ast::DUMMY_NODE_ID);
406405

407-
fulfill_cx.register_builtin_bound(infcx, ty, bound, cause);
406+
fulfill_cx.register_bound(infcx, ty, def_id, cause);
408407

409408
// Note: we only assume something is `Copy` if we can
410409
// *definitively* show that it implements `Copy`. Otherwise,
411410
// assume it is move; linear is always ok.
412411
match fulfill_cx.select_all_or_error(infcx) {
413412
Ok(()) => {
414-
debug!("type_known_to_meet_builtin_bound: ty={:?} bound={:?} success",
413+
debug!("type_known_to_meet_bound: ty={:?} bound={} success",
415414
ty,
416-
bound);
415+
infcx.tcx.item_path_str(def_id));
417416
true
418417
}
419418
Err(e) => {
420-
debug!("type_known_to_meet_builtin_bound: ty={:?} bound={:?} errors={:?}",
419+
debug!("type_known_to_meet_bound: ty={:?} bound={} errors={:?}",
421420
ty,
422-
bound,
421+
infcx.tcx.item_path_str(def_id),
423422
e);
424423
false
425424
}

src/librustc/traits/project.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1123,15 +1123,15 @@ fn confirm_object_candidate<'cx, 'gcx, 'tcx>(
11231123
debug!("confirm_object_candidate(object_ty={:?})",
11241124
object_ty);
11251125
let data = match object_ty.sty {
1126-
ty::TyTrait(ref data) => data,
1126+
ty::TyDynamic(ref data, ..) => data,
11271127
_ => {
11281128
span_bug!(
11291129
obligation.cause.span,
11301130
"confirm_object_candidate called with non-object: {:?}",
11311131
object_ty)
11321132
}
11331133
};
1134-
let env_predicates = data.projection_bounds.iter().map(|p| {
1134+
let env_predicates = data.projection_bounds().map(|p| {
11351135
p.with_self_ty(selcx.tcx(), object_ty).to_predicate()
11361136
}).collect();
11371137
let env_predicate = {

0 commit comments

Comments
 (0)