Skip to content

Commit dabd750

Browse files
committed
Ensure that, for every trait Foo, the predicate Foo : Foo holds.
1 parent 19dcecb commit dabd750

File tree

8 files changed

+335
-39
lines changed

8 files changed

+335
-39
lines changed

src/libcore/fmt/mod.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -605,9 +605,6 @@ impl<'a, Sized? T: Show> Show for &'a T {
605605
impl<'a, Sized? T: Show> Show for &'a mut T {
606606
fn fmt(&self, f: &mut Formatter) -> Result { (**self).fmt(f) }
607607
}
608-
impl<'a> Show for &'a (Show+'a) {
609-
fn fmt(&self, f: &mut Formatter) -> Result { (*self).fmt(f) }
610-
}
611608

612609
impl Show for bool {
613610
fn fmt(&self, f: &mut Formatter) -> Result {

src/librustc/middle/traits/mod.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,9 @@ pub enum Vtable<'tcx, N> {
217217
/// for some type parameter.
218218
VtableParam,
219219

220+
/// Virtual calls through an object
221+
VtableObject(VtableObjectData<'tcx>),
222+
220223
/// Successful resolution for a builtin trait.
221224
VtableBuiltin(VtableBuiltinData<N>),
222225

@@ -252,6 +255,13 @@ pub struct VtableBuiltinData<N> {
252255
pub nested: subst::VecPerParamSpace<N>
253256
}
254257

258+
/// A vtable for some object-safe trait `Foo` automatically derived
259+
/// for the object type `Foo`.
260+
#[deriving(PartialEq,Eq,Clone)]
261+
pub struct VtableObjectData<'tcx> {
262+
pub object_ty: Ty<'tcx>,
263+
}
264+
255265
/// True if neither the trait nor self type is local. Note that `impl_def_id` must refer to an impl
256266
/// of a trait, not an inherent impl.
257267
pub fn is_orphan_impl(tcx: &ty::ctxt,
@@ -372,6 +382,7 @@ impl<'tcx, N> Vtable<'tcx, N> {
372382
VtableFnPointer(..) => (&[]).iter(),
373383
VtableUnboxedClosure(..) => (&[]).iter(),
374384
VtableParam => (&[]).iter(),
385+
VtableObject(_) => (&[]).iter(),
375386
VtableBuiltin(ref i) => i.iter_nested(),
376387
}
377388
}
@@ -382,6 +393,7 @@ impl<'tcx, N> Vtable<'tcx, N> {
382393
VtableFnPointer(ref sig) => VtableFnPointer((*sig).clone()),
383394
VtableUnboxedClosure(d, ref s) => VtableUnboxedClosure(d, s.clone()),
384395
VtableParam => VtableParam,
396+
VtableObject(ref p) => VtableObject(p.clone()),
385397
VtableBuiltin(ref b) => VtableBuiltin(b.map_nested(op)),
386398
}
387399
}
@@ -394,6 +406,7 @@ impl<'tcx, N> Vtable<'tcx, N> {
394406
VtableFnPointer(sig) => VtableFnPointer(sig),
395407
VtableUnboxedClosure(d, s) => VtableUnboxedClosure(d, s),
396408
VtableParam => VtableParam,
409+
VtableObject(p) => VtableObject(p),
397410
VtableBuiltin(no) => VtableBuiltin(no.map_move_nested(op)),
398411
}
399412
}

src/librustc/middle/traits/project.rs

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -377,20 +377,14 @@ fn project_type<'cx,'tcx>(
377377
ambiguous: false,
378378
};
379379

380-
assemble_candidates_from_object_type(selcx,
381-
obligation,
382-
&mut candidates);
383-
384-
if candidates.vec.is_empty() {
385-
assemble_candidates_from_param_env(selcx,
386-
obligation,
387-
&mut candidates);
388-
389-
if let Err(e) = assemble_candidates_from_impls(selcx,
390-
obligation,
391-
&mut candidates) {
392-
return Err(ProjectionTyError::TraitSelectionError(e));
393-
}
380+
assemble_candidates_from_param_env(selcx,
381+
obligation,
382+
&mut candidates);
383+
384+
if let Err(e) = assemble_candidates_from_impls(selcx,
385+
obligation,
386+
&mut candidates) {
387+
return Err(ProjectionTyError::TraitSelectionError(e));
394388
}
395389

396390
debug!("{} candidates, ambiguous={}",
@@ -467,18 +461,22 @@ fn assemble_candidates_from_predicates<'cx,'tcx>(
467461
fn assemble_candidates_from_object_type<'cx,'tcx>(
468462
selcx: &mut SelectionContext<'cx,'tcx>,
469463
obligation: &ProjectionTyObligation<'tcx>,
470-
candidate_set: &mut ProjectionTyCandidateSet<'tcx>)
464+
candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
465+
object_ty: Ty<'tcx>)
471466
{
472467
let infcx = selcx.infcx();
473-
let trait_ref = infcx.resolve_type_vars_if_possible(&obligation.predicate.trait_ref);
474-
debug!("assemble_candidates_from_object_type(trait_ref={})",
475-
trait_ref.repr(infcx.tcx));
476-
let self_ty = trait_ref.self_ty();
477-
let data = match self_ty.sty {
468+
debug!("assemble_candidates_from_object_type(object_ty={})",
469+
object_ty.repr(infcx.tcx));
470+
let data = match object_ty.sty {
478471
ty::ty_trait(ref data) => data,
479-
_ => { return; }
472+
_ => {
473+
selcx.tcx().sess.span_bug(
474+
obligation.cause.span,
475+
format!("assemble_candidates_from_object_type called with non-object: {}",
476+
object_ty.repr(selcx.tcx()))[]);
477+
}
480478
};
481-
let projection_bounds = data.projection_bounds_with_self_ty(selcx.tcx(), self_ty);
479+
let projection_bounds = data.projection_bounds_with_self_ty(selcx.tcx(), object_ty);
482480
let env_predicates = projection_bounds.iter()
483481
.map(|p| p.as_predicate())
484482
.collect();
@@ -515,6 +513,10 @@ fn assemble_candidates_from_impls<'cx,'tcx>(
515513
candidate_set.vec.push(
516514
ProjectionTyCandidate::Impl(data));
517515
}
516+
super::VtableObject(data) => {
517+
assemble_candidates_from_object_type(
518+
selcx, obligation, candidate_set, data.object_ty);
519+
}
518520
super::VtableParam(..) => {
519521
// This case tell us nothing about the value of an
520522
// associated type. Consider:

src/librustc/middle/traits/select.rs

Lines changed: 125 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,10 @@ use super::{ObligationCauseCode, BuiltinDerivedObligation};
2424
use super::{SelectionError, Unimplemented, Overflow, OutputTypeParameterMismatch};
2525
use super::{Selection};
2626
use super::{SelectionResult};
27-
use super::{VtableBuiltin, VtableImpl, VtableParam, VtableUnboxedClosure, VtableFnPointer};
28-
use super::{VtableImplData, VtableBuiltinData};
27+
use super::{VtableBuiltin, VtableImpl, VtableParam, VtableUnboxedClosure,
28+
VtableFnPointer, VtableObject};
29+
use super::{VtableImplData, VtableObjectData, VtableBuiltinData};
30+
use super::object_safety;
2931
use super::{util};
3032

3133
use middle::fast_reject;
@@ -147,6 +149,8 @@ enum SelectionCandidate<'tcx> {
147149
/// types generated for a fn pointer type (e.g., `fn(int)->int`)
148150
FnPointerCandidate,
149151

152+
ObjectCandidate,
153+
150154
ErrorCandidate,
151155
}
152156

@@ -717,6 +721,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
717721
try!(self.assemble_unboxed_closure_candidates(obligation, &mut candidates));
718722
try!(self.assemble_fn_pointer_candidates(obligation, &mut candidates));
719723
try!(self.assemble_candidates_from_impls(obligation, &mut candidates.vec));
724+
self.assemble_candidates_from_object_ty(obligation, &mut candidates);
720725
}
721726
}
722727

@@ -878,7 +883,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
878883
let matching_bounds =
879884
all_bounds.filter(
880885
|bound| self.infcx.probe(
881-
|_| self.match_where_clause(obligation, bound.clone())).is_ok());
886+
|_| self.match_poly_trait_ref(obligation, bound.clone())).is_ok());
882887

883888
let param_candidates =
884889
matching_bounds.map(|bound| ParamCandidate(bound));
@@ -945,7 +950,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
945950

946951
let self_ty = self.infcx.shallow_resolve(obligation.self_ty());
947952
match self_ty.sty {
948-
ty::ty_infer(..) => {
953+
ty::ty_infer(ty::TyVar(_)) => {
949954
candidates.ambiguous = true; // could wind up being a fn() type
950955
}
951956

@@ -991,6 +996,67 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
991996
Ok(())
992997
}
993998

999+
/// Search for impls that might apply to `obligation`.
1000+
fn assemble_candidates_from_object_ty(&mut self,
1001+
obligation: &TraitObligation<'tcx>,
1002+
candidates: &mut SelectionCandidateSet<'tcx>)
1003+
{
1004+
let self_ty = self.infcx.shallow_resolve(obligation.self_ty());
1005+
1006+
debug!("assemble_candidates_from_object_ty(self_ty={})",
1007+
self_ty.repr(self.tcx()));
1008+
1009+
// Object-safety candidates are only applicable to object-safe
1010+
// traits. Including this check is useful because it helps
1011+
// inference in cases of traits like `BorrowFrom`, which are
1012+
// not object-safe, and which rely on being able to infer the
1013+
// self-type from one of the other inputs. Without this check,
1014+
// these cases wind up being considered ambiguous due to a
1015+
// (spurious) ambiguity introduced here.
1016+
if !object_safety::is_object_safe(self.tcx(), obligation.predicate.to_poly_trait_ref()) {
1017+
return;
1018+
}
1019+
1020+
let poly_trait_ref = match self_ty.sty {
1021+
ty::ty_trait(ref data) => {
1022+
data.principal_trait_ref_with_self_ty(self.tcx(), self_ty)
1023+
}
1024+
ty::ty_infer(ty::TyVar(_)) => {
1025+
debug!("assemble_candidates_from_object_ty: ambiguous");
1026+
candidates.ambiguous = true; // could wind up being an object type
1027+
return;
1028+
}
1029+
_ => {
1030+
return;
1031+
}
1032+
};
1033+
1034+
debug!("assemble_candidates_from_object_ty: poly_trait_ref={}",
1035+
poly_trait_ref.repr(self.tcx()));
1036+
1037+
// see whether the object trait can be upcast to the trait we are looking for
1038+
let obligation_def_id = obligation.predicate.def_id();
1039+
let upcast_trait_ref = match util::upcast(self.tcx(), poly_trait_ref, obligation_def_id) {
1040+
Some(r) => r,
1041+
None => { return; }
1042+
};
1043+
1044+
debug!("assemble_candidates_from_object_ty: upcast_trait_ref={}",
1045+
upcast_trait_ref.repr(self.tcx()));
1046+
1047+
// check whether the upcast version of the trait-ref matches what we are looking for
1048+
match
1049+
self.infcx.probe(
1050+
|_| self.match_poly_trait_ref(obligation, upcast_trait_ref.clone()))
1051+
{
1052+
Ok(()) => {
1053+
debug!("assemble_candidates_from_object_ty: matched, pushing candidate");
1054+
candidates.vec.push(ObjectCandidate);
1055+
}
1056+
Err(()) => { }
1057+
}
1058+
}
1059+
9941060
///////////////////////////////////////////////////////////////////////////
9951061
// WINNOW
9961062
//
@@ -1544,6 +1610,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
15441610
Ok(VtableUnboxedClosure(closure_def_id, substs))
15451611
}
15461612

1613+
ObjectCandidate => {
1614+
let data = self.confirm_object_candidate(obligation);
1615+
Ok(VtableObject(data))
1616+
}
1617+
15471618
FnPointerCandidate => {
15481619
let fn_type =
15491620
try!(self.confirm_fn_pointer_candidate(obligation));
@@ -1727,6 +1798,48 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
17271798
nested: impl_predicates }
17281799
}
17291800

1801+
fn confirm_object_candidate(&mut self,
1802+
obligation: &TraitObligation<'tcx>)
1803+
-> VtableObjectData<'tcx>
1804+
{
1805+
debug!("confirm_object_candidate({})",
1806+
obligation.repr(self.tcx()));
1807+
1808+
let self_ty = self.infcx.shallow_resolve(obligation.self_ty());
1809+
let poly_trait_ref = match self_ty.sty {
1810+
ty::ty_trait(ref data) => {
1811+
data.principal_trait_ref_with_self_ty(self.tcx(), self_ty)
1812+
}
1813+
_ => {
1814+
self.tcx().sess.span_bug(obligation.cause.span,
1815+
"object candidate with non-object");
1816+
}
1817+
};
1818+
1819+
let obligation_def_id = obligation.predicate.def_id();
1820+
let upcast_trait_ref = match util::upcast(self.tcx(),
1821+
poly_trait_ref.clone(),
1822+
obligation_def_id) {
1823+
Some(r) => r,
1824+
None => {
1825+
self.tcx().sess.span_bug(obligation.cause.span,
1826+
format!("unable to upcast from {} to {}",
1827+
poly_trait_ref.repr(self.tcx()),
1828+
obligation_def_id.repr(self.tcx())).as_slice());
1829+
}
1830+
};
1831+
1832+
match self.match_poly_trait_ref(obligation, upcast_trait_ref) {
1833+
Ok(()) => { }
1834+
Err(()) => {
1835+
self.tcx().sess.span_bug(obligation.cause.span,
1836+
"failed to match trait refs");
1837+
}
1838+
}
1839+
1840+
VtableObjectData { object_ty: self_ty }
1841+
}
1842+
17301843
fn confirm_fn_pointer_candidate(&mut self,
17311844
obligation: &TraitObligation<'tcx>)
17321845
-> Result<ty::Ty<'tcx>,SelectionError<'tcx>>
@@ -1962,12 +2075,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
19622075
})
19632076
}
19642077

1965-
fn match_where_clause(&mut self,
1966-
obligation: &TraitObligation<'tcx>,
1967-
where_clause_trait_ref: ty::PolyTraitRef<'tcx>)
1968-
-> Result<(),()>
2078+
fn match_poly_trait_ref(&mut self,
2079+
obligation: &TraitObligation<'tcx>,
2080+
where_clause_trait_ref: ty::PolyTraitRef<'tcx>)
2081+
-> Result<(),()>
19692082
{
1970-
debug!("match_where_clause: obligation={} where_clause_trait_ref={}",
2083+
debug!("match_poly_trait_ref: obligation={} where_clause_trait_ref={}",
19712084
obligation.repr(self.tcx()),
19722085
where_clause_trait_ref.repr(self.tcx()));
19732086

@@ -2161,6 +2274,9 @@ impl<'tcx> Repr<'tcx> for SelectionCandidate<'tcx> {
21612274
ImplCandidate(a) => format!("ImplCandidate({})", a.repr(tcx)),
21622275
ProjectionCandidate => format!("ProjectionCandidate"),
21632276
FnPointerCandidate => format!("FnPointerCandidate"),
2277+
ObjectCandidate => {
2278+
format!("ObjectCandidate")
2279+
}
21642280
UnboxedClosureCandidate(c, ref s) => {
21652281
format!("UnboxedClosureCandidate({},{})", c, s.repr(tcx))
21662282
}

src/librustc/middle/traits/util.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,12 @@ impl<'tcx, N> fmt::Show for VtableImplData<'tcx, N> {
238238
}
239239
}
240240

241+
impl<'tcx> fmt::Show for super::VtableObjectData<'tcx> {
242+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
243+
write!(f, "VtableObject(...)")
244+
}
245+
}
246+
241247
/// See `super::obligations_for_generics`
242248
pub fn predicates_for_generics<'tcx>(tcx: &ty::ctxt<'tcx>,
243249
cause: ObligationCause<'tcx>,
@@ -366,6 +372,10 @@ impl<'tcx, N:Repr<'tcx>> Repr<'tcx> for super::Vtable<'tcx, N> {
366372
format!("VtableFnPointer({})",
367373
d.repr(tcx)),
368374

375+
super::VtableObject(ref d) =>
376+
format!("VtableObject({})",
377+
d.repr(tcx)),
378+
369379
super::VtableParam =>
370380
format!("VtableParam"),
371381

@@ -391,6 +401,13 @@ impl<'tcx, N:Repr<'tcx>> Repr<'tcx> for super::VtableBuiltinData<N> {
391401
}
392402
}
393403

404+
impl<'tcx> Repr<'tcx> for super::VtableObjectData<'tcx> {
405+
fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
406+
format!("VtableObject(object_ty={})",
407+
self.object_ty.repr(tcx))
408+
}
409+
}
410+
394411
impl<'tcx> Repr<'tcx> for super::SelectionError<'tcx> {
395412
fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
396413
match *self {

src/librustc/middle/ty_fold.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,15 @@ impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Vtable<'tcx, N>
503503
}
504504
traits::VtableParam => traits::VtableParam,
505505
traits::VtableBuiltin(ref d) => traits::VtableBuiltin(d.fold_with(folder)),
506+
traits::VtableObject(ref d) => traits::VtableObject(d.fold_with(folder)),
507+
}
508+
}
509+
}
510+
511+
impl<'tcx> TypeFoldable<'tcx> for traits::VtableObjectData<'tcx> {
512+
fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::VtableObjectData<'tcx> {
513+
traits::VtableObjectData {
514+
object_ty: self.object_ty.fold_with(folder)
506515
}
507516
}
508517
}

0 commit comments

Comments
 (0)