Skip to content

Commit 6349a61

Browse files
committed
Port coherence to use the new trait matching code
1 parent c5754f3 commit 6349a61

File tree

6 files changed

+400
-309
lines changed

6 files changed

+400
-309
lines changed

src/librustc/middle/dead.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,7 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> {
470470
match self.tcx.inherent_impls.borrow().find(&local_def(id)) {
471471
None => (),
472472
Some(impl_list) => {
473-
for impl_did in impl_list.borrow().iter() {
473+
for impl_did in impl_list.iter() {
474474
for item_did in impl_items.get(impl_did).iter() {
475475
if self.live_symbols.contains(&item_did.def_id()
476476
.node) {
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
/*! See `doc.rs` for high-level documentation */
12+
13+
use super::DUMMY_CAUSE;
14+
use super::{EvaluatedToMatch, EvaluatedToAmbiguity, EvaluatedToUnmatch};
15+
use super::{evaluate_impl};
16+
use super::util;
17+
18+
use middle::subst;
19+
use middle::subst::Subst;
20+
use middle::ty;
21+
use middle::typeck::infer::InferCtxt;
22+
use syntax::ast;
23+
use syntax::codemap::DUMMY_SP;
24+
use util::nodemap::DefIdMap;
25+
use util::ppaux::Repr;
26+
27+
pub fn impl_can_satisfy(infcx: &InferCtxt,
28+
impl1_def_id: ast::DefId,
29+
impl2_def_id: ast::DefId)
30+
-> bool
31+
{
32+
// `impl1` provides an implementation of `Foo<X,Y> for Z`.
33+
let impl1_substs =
34+
util::fresh_substs_for_impl(infcx, DUMMY_SP, impl1_def_id);
35+
let impl1_self_ty =
36+
ty::impl_trait_ref(infcx.tcx, impl1_def_id).unwrap()
37+
.self_ty()
38+
.subst(infcx.tcx, &impl1_substs);
39+
40+
// Determine whether `impl2` can provide an implementation for those
41+
// same types.
42+
let param_env = ty::empty_parameter_environment();
43+
let unboxed_closures = DefIdMap::new();
44+
match evaluate_impl(infcx, &param_env, &unboxed_closures, DUMMY_CAUSE,
45+
impl2_def_id, impl1_self_ty) {
46+
EvaluatedToMatch | EvaluatedToAmbiguity => true,
47+
EvaluatedToUnmatch => false,
48+
}
49+
}
50+
51+
pub fn impl_is_local(tcx: &ty::ctxt,
52+
impl_def_id: ast::DefId)
53+
-> bool
54+
{
55+
debug!("impl_is_local({})", impl_def_id.repr(tcx));
56+
57+
// We only except this routine to be invoked on implementations
58+
// of a trait, not inherent implementations.
59+
let trait_ref = ty::impl_trait_ref(tcx, impl_def_id).unwrap();
60+
debug!("trait_ref={}", trait_ref.repr(tcx));
61+
62+
// If the trait is local to the crate, ok.
63+
if trait_ref.def_id.krate == ast::LOCAL_CRATE {
64+
debug!("trait {} is local to current crate",
65+
trait_ref.def_id.repr(tcx));
66+
return true;
67+
}
68+
69+
// Otherwise, self type must be local to the crate.
70+
let self_ty = ty::lookup_item_type(tcx, impl_def_id).ty;
71+
return ty_is_local(tcx, self_ty);
72+
}
73+
74+
pub fn ty_is_local(tcx: &ty::ctxt,
75+
ty: ty::t)
76+
-> bool
77+
{
78+
debug!("ty_is_local({})", ty.repr(tcx));
79+
80+
match ty::get(ty).sty {
81+
ty::ty_nil |
82+
ty::ty_bot |
83+
ty::ty_bool |
84+
ty::ty_char |
85+
ty::ty_int(..) |
86+
ty::ty_uint(..) |
87+
ty::ty_float(..) |
88+
ty::ty_str(..) => {
89+
false
90+
}
91+
92+
ty::ty_unboxed_closure(..) => {
93+
// This routine is invoked on types specified by users as
94+
// part of an impl and hence an unboxed closure type
95+
// cannot appear.
96+
tcx.sess.bug("ty_is_local applied to unboxed closure type")
97+
}
98+
99+
ty::ty_bare_fn(..) |
100+
ty::ty_closure(..) => {
101+
false
102+
}
103+
104+
ty::ty_uniq(t) => {
105+
let krate = tcx.lang_items.owned_box().map(|d| d.krate);
106+
krate == Some(ast::LOCAL_CRATE) || ty_is_local(tcx, t)
107+
}
108+
109+
ty::ty_box(t) => {
110+
let krate = tcx.lang_items.gc().map(|d| d.krate);
111+
krate == Some(ast::LOCAL_CRATE) || ty_is_local(tcx, t)
112+
}
113+
114+
ty::ty_vec(t, _) |
115+
ty::ty_ptr(ty::mt { ty: t, .. }) |
116+
ty::ty_rptr(_, ty::mt { ty: t, .. }) => {
117+
ty_is_local(tcx, t)
118+
}
119+
120+
ty::ty_tup(ref ts) => {
121+
ts.iter().any(|&t| ty_is_local(tcx, t))
122+
}
123+
124+
ty::ty_enum(def_id, ref substs) |
125+
ty::ty_struct(def_id, ref substs) => {
126+
def_id.krate == ast::LOCAL_CRATE || {
127+
let variances = ty::item_variances(tcx, def_id);
128+
subst::ParamSpace::all().iter().any(|&space| {
129+
substs.types.get_slice(space).iter().enumerate().any(
130+
|(i, &t)| {
131+
match *variances.types.get(space, i) {
132+
ty::Bivariant => {
133+
// If Foo<T> is bivariant with respect to
134+
// T, then it doesn't matter whether T is
135+
// local or not, because `Foo<U>` for any
136+
// U will be a subtype of T.
137+
false
138+
}
139+
ty::Contravariant |
140+
ty::Covariant |
141+
ty::Invariant => {
142+
ty_is_local(tcx, t)
143+
}
144+
}
145+
})
146+
})
147+
}
148+
}
149+
150+
ty::ty_trait(ref tt) => {
151+
tt.def_id.krate == ast::LOCAL_CRATE
152+
}
153+
154+
// Type parameters may be bound to types that are not local to
155+
// the crate.
156+
ty::ty_param(..) => {
157+
false
158+
}
159+
160+
ty::ty_infer(..) |
161+
ty::ty_open(..) |
162+
ty::ty_err => {
163+
tcx.sess.bug(
164+
format!("ty_is_local invoked on unexpected type: {}",
165+
ty.repr(tcx)).as_slice())
166+
}
167+
}
168+
}

0 commit comments

Comments
 (0)