Skip to content

Commit 1736dca

Browse files
committed
---
yaml --- r: 170362 b: refs/heads/try c: de806bc h: refs/heads/master v: v3
1 parent c12d46c commit 1736dca

File tree

4 files changed

+117
-18
lines changed

4 files changed

+117
-18
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
refs/heads/master: 73a25f55ad748b4d3516417c711b99ce446591af
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
44
refs/heads/snap-stage3: 5b3cd3900ceda838f5798c30ab96ceb41f962534
5-
refs/heads/try: 5b53b11ad9aed822ce4c573714de6cb28289f321
5+
refs/heads/try: de806bc057caa599fce959ce56259e6e919f1041
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/dist-snap: ba4081a5a8573875fed17545846f6f6902c8ba8d
88
refs/tags/release-0.2: c870d2dffb391e14efb05aa27898f1f6333a9596

branches/try/src/librustc/middle/traits/project.rs

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use super::VtableImplData;
1919

2020
use middle::infer;
2121
use middle::subst::Subst;
22-
use middle::ty::{mod, ToPolyTraitRef, Ty};
22+
use middle::ty::{mod, AsPredicate, ToPolyTraitRef, Ty};
2323
use std::fmt;
2424
use util::ppaux::Repr;
2525

@@ -46,7 +46,7 @@ pub enum ProjectionError<'tcx> {
4646

4747
#[deriving(Clone)]
4848
pub struct MismatchedProjectionTypes<'tcx> {
49-
pub err: ty::type_err<'tcx> // TODO expected/actual/etc
49+
pub err: ty::type_err<'tcx>
5050
}
5151

5252
pub type ProjectionResult<'tcx, T> = Result<T, ProjectionError<'tcx>>;
@@ -123,9 +123,20 @@ pub fn project_type<'cx,'tcx>(
123123
obligation,
124124
&mut candidates);
125125

126-
let () = try!(assemble_candidates_from_impls(selcx,
127-
obligation,
128-
&mut candidates));
126+
let () = assemble_candidates_from_object_type(selcx,
127+
obligation,
128+
&mut candidates);
129+
130+
if candidates.vec.is_empty() {
131+
// TODO This `if` is not necessarily wrong, but it needs an
132+
// explanation, and it should probably be accompanied by a
133+
// similar rule in `select.rs`. Currently it's *needed*
134+
// because the impl-trait-for-trait branch has not landed.
135+
136+
let () = try!(assemble_candidates_from_impls(selcx,
137+
obligation,
138+
&mut candidates));
139+
}
129140

130141
debug!("{} candidates, ambiguous={}",
131142
candidates.vec.len(),
@@ -155,9 +166,21 @@ fn assemble_candidates_from_param_env<'cx,'tcx>(
155166
obligation: &ProjectionTyObligation<'tcx>,
156167
candidate_set: &mut ProjectionTyCandidateSet<'tcx>)
157168
{
158-
let infcx = selcx.infcx();
159169
let env_predicates = selcx.param_env().caller_bounds.predicates.clone();
160170
let env_predicates = env_predicates.iter().cloned().collect();
171+
assemble_candidates_from_predicates(selcx, obligation, candidate_set, env_predicates);
172+
}
173+
174+
fn assemble_candidates_from_predicates<'cx,'tcx>(
175+
selcx: &mut SelectionContext<'cx,'tcx>,
176+
obligation: &ProjectionTyObligation<'tcx>,
177+
candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
178+
env_predicates: Vec<ty::Predicate<'tcx>>)
179+
{
180+
debug!("assemble_candidates_from_predicates(obligation={}, env_predicates={})",
181+
obligation.repr(selcx.tcx()),
182+
env_predicates.repr(selcx.tcx()));
183+
let infcx = selcx.infcx();
161184
for predicate in elaborate_predicates(selcx.tcx(), env_predicates) {
162185
match predicate {
163186
ty::Predicate::Projection(ref data) => {
@@ -183,6 +206,26 @@ fn assemble_candidates_from_param_env<'cx,'tcx>(
183206
}
184207
}
185208

209+
fn assemble_candidates_from_object_type<'cx,'tcx>(
210+
selcx: &mut SelectionContext<'cx,'tcx>,
211+
obligation: &ProjectionTyObligation<'tcx>,
212+
candidate_set: &mut ProjectionTyCandidateSet<'tcx>)
213+
{
214+
let infcx = selcx.infcx();
215+
let trait_ref = infcx.resolve_type_vars_if_possible(&obligation.predicate.trait_ref);
216+
debug!("assemble_candidates_from_object_type(trait_ref={})",
217+
trait_ref.repr(infcx.tcx));
218+
let self_ty = trait_ref.self_ty();
219+
let data = match self_ty.sty {
220+
ty::ty_trait(ref data) => data,
221+
_ => { return; }
222+
};
223+
let env_predicates = data.projection_bounds_with_self_ty(self_ty).iter()
224+
.map(|p| p.as_predicate())
225+
.collect();
226+
assemble_candidates_from_predicates(selcx, obligation, candidate_set, env_predicates)
227+
}
228+
186229
fn assemble_candidates_from_impls<'cx,'tcx>(
187230
selcx: &mut SelectionContext<'cx,'tcx>,
188231
obligation: &ProjectionTyObligation<'tcx>,

branches/try/src/librustc/middle/ty.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1401,6 +1401,31 @@ impl<'tcx> TyTrait<'tcx> {
14011401
substs: tcx.mk_substs(self.principal.0.substs.with_self_ty(self_ty)),
14021402
}))
14031403
}
1404+
1405+
pub fn projection_bounds_with_self_ty(&self, self_ty: Ty<'tcx>)
1406+
-> Vec<ty::PolyProjectionPredicate<'tcx>>
1407+
{
1408+
// otherwise the escaping regions would be captured by the binders
1409+
assert!(!self_ty.has_escaping_regions());
1410+
1411+
self.bounds.projection_bounds.iter()
1412+
.map(|in_poly_projection_predicate| {
1413+
let in_projection_ty = &in_poly_projection_predicate.0.projection_ty;
1414+
let trait_ref =
1415+
Rc::new(ty::TraitRef::new(
1416+
in_projection_ty.trait_ref.def_id,
1417+
in_projection_ty.trait_ref.substs.with_self_ty(self_ty)));
1418+
let projection_ty = ty::ProjectionTy {
1419+
trait_ref: trait_ref,
1420+
item_name: in_projection_ty.item_name
1421+
};
1422+
ty::Binder(ty::ProjectionPredicate {
1423+
projection_ty: projection_ty,
1424+
ty: in_poly_projection_predicate.0.ty
1425+
})
1426+
})
1427+
.collect()
1428+
}
14041429
}
14051430

14061431
/// A complete reference to a trait. These take numerous guises in syntax,

branches/try/src/librustc_typeck/check/vtable.rs

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@ use middle::subst::{FnSpace, SelfSpace};
1313
use middle::traits;
1414
use middle::traits::{Obligation, ObligationCause};
1515
use middle::traits::report_fulfillment_errors;
16-
use middle::ty::{mod, Ty, AsPredicate, ToPolyTraitRef};
16+
use middle::ty::{mod, Ty, AsPredicate};
1717
use middle::infer;
18-
use std::rc::Rc;
1918
use syntax::ast;
2019
use syntax::codemap::Span;
21-
use util::ppaux::{Repr, ty_to_string};
20+
use util::nodemap::FnvHashSet;
21+
use util::ppaux::{Repr, UserString};
2222

2323
pub fn check_object_cast<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2424
cast_expr: &ast::Expr,
@@ -133,10 +133,33 @@ pub fn check_object_safety<'tcx>(tcx: &ty::ctxt<'tcx>,
133133
object_trait: &ty::TyTrait<'tcx>,
134134
span: Span)
135135
{
136+
// Also check that the type `object_trait` specifies all
137+
// associated types for all supertraits.
138+
let mut associated_types: FnvHashSet<(ast::DefId, ast::Name)> = FnvHashSet::new();
139+
136140
let object_trait_ref =
137141
object_trait.principal_trait_ref_with_self_ty(tcx, tcx.types.err);
138-
for tr in traits::supertraits(tcx, object_trait_ref) {
142+
for tr in traits::supertraits(tcx, object_trait_ref.clone()) {
139143
check_object_safety_inner(tcx, &tr, span);
144+
145+
let trait_def = ty::lookup_trait_def(tcx, object_trait_ref.def_id());
146+
for &associated_type_name in trait_def.associated_type_names.iter() {
147+
associated_types.insert((object_trait_ref.def_id(), associated_type_name));
148+
}
149+
}
150+
151+
for projection_bound in object_trait.bounds.projection_bounds.iter() {
152+
let pair = (projection_bound.0.projection_ty.trait_ref.def_id,
153+
projection_bound.0.projection_ty.item_name);
154+
associated_types.remove(&pair);
155+
}
156+
157+
for (trait_def_id, name) in associated_types.into_iter() {
158+
tcx.sess.span_err(
159+
span,
160+
format!("the value of the associated type `{}` (from the trait `{}`) must be specified",
161+
name.user_string(tcx),
162+
ty::item_path_str(tcx, trait_def_id)).as_slice());
140163
}
141164
}
142165

@@ -201,7 +224,7 @@ fn check_object_safety_inner<'tcx>(tcx: &ty::ctxt<'tcx>,
201224
Some(format!(
202225
"cannot call a method (`{}`) whose type contains \
203226
a self-type (`{}`) through a trait object",
204-
method_name, ty_to_string(tcx, ty)))
227+
method_name, ty.user_string(tcx)))
205228
} else {
206229
None
207230
}
@@ -343,15 +366,15 @@ pub fn register_object_cast_obligations<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
343366
referent_ty.repr(fcx.tcx()),
344367
object_trait_ty.repr(fcx.tcx()));
345368

369+
let cause = ObligationCause::new(span,
370+
fcx.body_id,
371+
traits::ObjectCastObligation(object_trait_ty));
372+
346373
// Create the obligation for casting from T to Trait.
347374
let object_trait_ref =
348375
object_trait.principal_trait_ref_with_self_ty(fcx.tcx(), referent_ty);
349376
let object_obligation =
350-
Obligation::new(
351-
ObligationCause::new(span,
352-
fcx.body_id,
353-
traits::ObjectCastObligation(object_trait_ty)),
354-
object_trait_ref.as_predicate());
377+
Obligation::new(cause.clone(), object_trait_ref.as_predicate());
355378
fcx.register_predicate(object_obligation);
356379

357380
// Create additional obligations for all the various builtin
@@ -362,7 +385,15 @@ pub fn register_object_cast_obligations<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
362385
fcx.register_builtin_bound(
363386
referent_ty,
364387
builtin_bound,
365-
ObligationCause::new(span, fcx.body_id, traits::ObjectCastObligation(object_trait_ty)));
388+
cause.clone());
389+
}
390+
391+
// Finally, create obligations for the projection predicates.
392+
let projection_bounds = object_trait.projection_bounds_with_self_ty(referent_ty);
393+
for projection_bound in projection_bounds.iter() {
394+
let projection_obligation =
395+
Obligation::new(cause.clone(), projection_bound.as_predicate());
396+
fcx.register_predicate(projection_obligation);
366397
}
367398

368399
object_trait_ref

0 commit comments

Comments
 (0)