Skip to content

Commit effb363

Browse files
committed
Integrate builtin bounds fully into the trait checker
1 parent d299baf commit effb363

28 files changed

+821
-404
lines changed

src/libcore/kinds.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,19 @@ pub use self::Sync as Share;
2525

2626
/// Types able to be transferred across task boundaries.
2727
#[lang="send"]
28-
pub trait Send {
28+
pub trait Send for Sized? {
2929
// empty.
3030
}
3131

3232
/// Types with a constant size known at compile-time.
3333
#[lang="sized"]
34-
pub trait Sized {
34+
pub trait Sized for Sized? {
3535
// Empty.
3636
}
3737

3838
/// Types that can be copied by simply copying bits (i.e. `memcpy`).
3939
#[lang="copy"]
40-
pub trait Copy {
40+
pub trait Copy for Sized? {
4141
// Empty.
4242
}
4343

@@ -87,7 +87,7 @@ pub trait Copy {
8787
/// reference; not doing this is undefined behaviour (for example,
8888
/// `transmute`-ing from `&T` to `&mut T` is illegal).
8989
#[lang="sync"]
90-
pub trait Sync {
90+
pub trait Sync for Sized? {
9191
// Empty
9292
}
9393

src/librustc/middle/traits/coherence.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ use middle::ty;
2121
use middle::typeck::infer::InferCtxt;
2222
use syntax::ast;
2323
use syntax::codemap::DUMMY_SP;
24-
use util::nodemap::DefIdMap;
2524
use util::ppaux::Repr;
2625

2726
pub fn impl_can_satisfy(infcx: &InferCtxt,
@@ -40,8 +39,7 @@ pub fn impl_can_satisfy(infcx: &InferCtxt,
4039
// Determine whether `impl2` can provide an implementation for those
4140
// same types.
4241
let param_env = ty::empty_parameter_environment();
43-
let unboxed_closures = DefIdMap::new();
44-
match evaluate_impl(infcx, &param_env, &unboxed_closures, DUMMY_CAUSE,
42+
match evaluate_impl(infcx, &param_env, infcx.tcx, DUMMY_CAUSE,
4543
impl2_def_id, impl1_self_ty) {
4644
EvaluatedToMatch | EvaluatedToAmbiguity => true,
4745
EvaluatedToUnmatch => false,

src/librustc/middle/traits/fulfill.rs

Lines changed: 15 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,16 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
use middle::mem_categorization::Typer;
1112
use middle::ty;
12-
use middle::typeck::infer::{InferCtxt, skolemize};
13-
use util::nodemap::DefIdMap;
13+
use middle::typeck::infer::InferCtxt;
1414
use util::ppaux::Repr;
1515

1616
use super::CodeAmbiguity;
1717
use super::Obligation;
1818
use super::FulfillmentError;
1919
use super::CodeSelectionError;
2020
use super::select::SelectionContext;
21-
use super::Unimplemented;
2221

2322
/**
2423
* The fulfillment context is used to drive trait resolution. It
@@ -36,17 +35,12 @@ pub struct FulfillmentContext {
3635
// A list of all obligations that have been registered with this
3736
// fulfillment context.
3837
trait_obligations: Vec<Obligation>,
39-
40-
// For semi-hacky reasons (see FIXME below) we keep the builtin
41-
// trait obligations segregated.
42-
builtin_obligations: Vec<Obligation>,
4338
}
4439

4540
impl FulfillmentContext {
4641
pub fn new() -> FulfillmentContext {
4742
FulfillmentContext {
4843
trait_obligations: Vec::new(),
49-
builtin_obligations: Vec::new()
5044
}
5145
}
5246

@@ -55,24 +49,16 @@ impl FulfillmentContext {
5549
obligation: Obligation)
5650
{
5751
debug!("register_obligation({})", obligation.repr(tcx));
58-
match tcx.lang_items.to_builtin_kind(obligation.trait_ref.def_id) {
59-
Some(_) => {
60-
self.builtin_obligations.push(obligation);
61-
}
62-
None => {
63-
self.trait_obligations.push(obligation);
64-
}
65-
}
52+
self.trait_obligations.push(obligation);
6653
}
6754

68-
pub fn select_all_or_error(&mut self,
69-
infcx: &InferCtxt,
70-
param_env: &ty::ParameterEnvironment,
71-
unboxed_closures: &DefIdMap<ty::UnboxedClosure>)
72-
-> Result<(),Vec<FulfillmentError>>
55+
pub fn select_all_or_error<'a,'tcx>(&mut self,
56+
infcx: &InferCtxt<'a,'tcx>,
57+
param_env: &ty::ParameterEnvironment,
58+
typer: &Typer<'tcx>)
59+
-> Result<(),Vec<FulfillmentError>>
7360
{
74-
try!(self.select_where_possible(infcx, param_env,
75-
unboxed_closures));
61+
try!(self.select_where_possible(infcx, param_env, typer));
7662

7763
// Anything left is ambiguous.
7864
let errors: Vec<FulfillmentError> =
@@ -88,15 +74,14 @@ impl FulfillmentContext {
8874
}
8975
}
9076

91-
pub fn select_where_possible(&mut self,
92-
infcx: &InferCtxt,
93-
param_env: &ty::ParameterEnvironment,
94-
unboxed_closures: &DefIdMap<ty::UnboxedClosure>)
95-
-> Result<(),Vec<FulfillmentError>>
77+
pub fn select_where_possible<'a,'tcx>(&mut self,
78+
infcx: &InferCtxt<'a,'tcx>,
79+
param_env: &ty::ParameterEnvironment,
80+
typer: &Typer<'tcx>)
81+
-> Result<(),Vec<FulfillmentError>>
9682
{
9783
let tcx = infcx.tcx;
98-
let selcx = SelectionContext::new(infcx, param_env,
99-
unboxed_closures);
84+
let mut selcx = SelectionContext::new(infcx, param_env, typer);
10085

10186
debug!("select_where_possible({} obligations) start",
10287
self.trait_obligations.len());
@@ -158,92 +143,4 @@ impl FulfillmentContext {
158143
Err(errors)
159144
}
160145
}
161-
162-
pub fn check_builtin_bound_obligations(
163-
&self,
164-
infcx: &InferCtxt)
165-
-> Result<(),Vec<FulfillmentError>>
166-
{
167-
let tcx = infcx.tcx;
168-
let mut errors = Vec::new();
169-
debug!("check_builtin_bound_obligations");
170-
for obligation in self.builtin_obligations.iter() {
171-
debug!("obligation={}", obligation.repr(tcx));
172-
173-
let def_id = obligation.trait_ref.def_id;
174-
let bound = match tcx.lang_items.to_builtin_kind(def_id) {
175-
Some(bound) => { bound }
176-
None => { continue; }
177-
};
178-
179-
let unskol_self_ty = obligation.self_ty();
180-
181-
// Skolemize the self-type so that it no longer contains
182-
// inference variables. Note that this also replaces
183-
// regions with 'static. You might think that this is not
184-
// ok, because checking whether something is `Send`
185-
// implies checking whether it is 'static: that's true,
186-
// but in fact the region bound is fed into region
187-
// inference separately and enforced there (and that has
188-
// even already been done before this code executes,
189-
// generally speaking).
190-
let self_ty = skolemize(infcx, unskol_self_ty);
191-
192-
debug!("bound={} self_ty={}", bound, self_ty.repr(tcx));
193-
if ty::type_is_error(self_ty) {
194-
// Indicates an error that was/will-be
195-
// reported elsewhere.
196-
continue;
197-
}
198-
199-
// Determine if builtin bound is met.
200-
let tc = ty::type_contents(tcx, self_ty);
201-
debug!("tc={}", tc);
202-
let met = match bound {
203-
ty::BoundSend => tc.is_sendable(tcx),
204-
ty::BoundSized => tc.is_sized(tcx),
205-
ty::BoundCopy => tc.is_copy(tcx),
206-
ty::BoundSync => tc.is_sync(tcx),
207-
};
208-
209-
if met {
210-
continue;
211-
}
212-
213-
// FIXME -- This is kind of a hack: it requently happens
214-
// that some earlier error prevents types from being fully
215-
// inferred, and then we get a bunch of uninteresting
216-
// errors saying something like "<generic #0> doesn't
217-
// implement Sized". It may even be true that we could
218-
// just skip over all checks where the self-ty is an
219-
// inference variable, but I was afraid that there might
220-
// be an inference variable created, registered as an
221-
// obligation, and then never forced by writeback, and
222-
// hence by skipping here we'd be ignoring the fact that
223-
// we don't KNOW the type works out. Though even that
224-
// would probably be harmless, given that we're only
225-
// talking about builtin traits, which are known to be
226-
// inhabited. But in any case I just threw in this check
227-
// for has_errors() to be sure that compilation isn't
228-
// happening anyway. In that case, why inundate the user.
229-
if ty::type_needs_infer(self_ty) &&
230-
tcx.sess.has_errors()
231-
{
232-
debug!("skipping printout because self_ty={}",
233-
self_ty.repr(tcx));
234-
continue;
235-
}
236-
237-
errors.push(
238-
FulfillmentError::new(
239-
(*obligation).clone(),
240-
CodeSelectionError(Unimplemented)));
241-
}
242-
243-
if errors.is_empty() {
244-
Ok(())
245-
} else {
246-
Err(errors)
247-
}
248-
}
249146
}

src/librustc/middle/traits/mod.rs

Lines changed: 23 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@
1212
* Trait Resolution. See doc.rs.
1313
*/
1414

15+
use middle::mem_categorization::Typer;
1516
use middle::subst;
1617
use middle::ty;
1718
use middle::typeck::infer::InferCtxt;
1819
use std::rc::Rc;
1920
use syntax::ast;
2021
use syntax::codemap::{Span, DUMMY_SP};
21-
use util::nodemap::DefIdMap;
2222

2323
pub use self::fulfill::FulfillmentContext;
2424
pub use self::select::SelectionContext;
@@ -208,50 +208,29 @@ pub struct VtableParamData {
208208
pub bound: Rc<ty::TraitRef>,
209209
}
210210

211-
pub fn try_select_obligation(infcx: &InferCtxt,
212-
param_env: &ty::ParameterEnvironment,
213-
unboxed_closures: &DefIdMap<ty::UnboxedClosure>,
214-
obligation: &Obligation)
215-
-> SelectionResult<Selection>
216-
{
217-
/*!
218-
* Attempts to select the impl/bound/etc for the obligation
219-
* given. Returns `None` if we are unable to resolve, either
220-
* because of ambiguity or due to insufficient inference. Note
221-
* that selection is a shallow process and hence the result may
222-
* contain nested obligations that must be resolved. The caller is
223-
* responsible for ensuring that those get resolved. (But see
224-
* `try_select_obligation_deep` below.)
225-
*/
226-
227-
let selcx = select::SelectionContext::new(infcx, param_env, unboxed_closures);
228-
selcx.select(obligation)
229-
}
230-
231-
pub fn evaluate_obligation(infcx: &InferCtxt,
232-
param_env: &ty::ParameterEnvironment,
233-
obligation: &Obligation,
234-
unboxed_closures: &DefIdMap<ty::UnboxedClosure>)
235-
-> EvaluationResult
211+
pub fn evaluate_obligation<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
212+
param_env: &ty::ParameterEnvironment,
213+
obligation: &Obligation,
214+
typer: &Typer<'tcx>)
215+
-> EvaluationResult
236216
{
237217
/*!
238218
* Attempts to resolve the obligation given. Returns `None` if
239219
* we are unable to resolve, either because of ambiguity or
240220
* due to insufficient inference.
241221
*/
242222

243-
let selcx = select::SelectionContext::new(infcx, param_env,
244-
unboxed_closures);
223+
let mut selcx = select::SelectionContext::new(infcx, param_env, typer);
245224
selcx.evaluate_obligation(obligation)
246225
}
247226

248-
pub fn evaluate_impl(infcx: &InferCtxt,
249-
param_env: &ty::ParameterEnvironment,
250-
unboxed_closures: &DefIdMap<ty::UnboxedClosure>,
251-
cause: ObligationCause,
252-
impl_def_id: ast::DefId,
253-
self_ty: ty::t)
254-
-> EvaluationResult
227+
pub fn evaluate_impl<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
228+
param_env: &ty::ParameterEnvironment,
229+
typer: &Typer<'tcx>,
230+
cause: ObligationCause,
231+
impl_def_id: ast::DefId,
232+
self_ty: ty::t)
233+
-> EvaluationResult
255234
{
256235
/*!
257236
* Tests whether the impl `impl_def_id` can be applied to the self
@@ -264,17 +243,17 @@ pub fn evaluate_impl(infcx: &InferCtxt,
264243
* (yes/no/unknown).
265244
*/
266245

267-
let selcx = select::SelectionContext::new(infcx, param_env, unboxed_closures);
246+
let mut selcx = select::SelectionContext::new(infcx, param_env, typer);
268247
selcx.evaluate_impl(impl_def_id, cause, self_ty)
269248
}
270249

271-
pub fn select_inherent_impl(infcx: &InferCtxt,
272-
param_env: &ty::ParameterEnvironment,
273-
unboxed_closures: &DefIdMap<ty::UnboxedClosure>,
274-
cause: ObligationCause,
275-
impl_def_id: ast::DefId,
276-
self_ty: ty::t)
277-
-> SelectionResult<VtableImplData<Obligation>>
250+
pub fn select_inherent_impl<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
251+
param_env: &ty::ParameterEnvironment,
252+
typer: &Typer<'tcx>,
253+
cause: ObligationCause,
254+
impl_def_id: ast::DefId,
255+
self_ty: ty::t)
256+
-> SelectionResult<VtableImplData<Obligation>>
278257
{
279258
/*!
280259
* Matches the self type of the inherent impl `impl_def_id`
@@ -293,8 +272,7 @@ pub fn select_inherent_impl(infcx: &InferCtxt,
293272
// `try_resolve_obligation()`.
294273
assert!(ty::impl_trait_ref(infcx.tcx, impl_def_id).is_none());
295274

296-
let selcx = select::SelectionContext::new(infcx, param_env,
297-
unboxed_closures);
275+
let mut selcx = select::SelectionContext::new(infcx, param_env, typer);
298276
selcx.select_inherent_impl(impl_def_id, cause, self_ty)
299277
}
300278

0 commit comments

Comments
 (0)