Skip to content

Commit 2be6c4f

Browse files
committed
Write code for registering region obligations (but don't use it yet).
1 parent 9409bd9 commit 2be6c4f

File tree

8 files changed

+122
-46
lines changed

8 files changed

+122
-46
lines changed

src/librustc/middle/infer/error_reporting.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
366366
infer::MatchExpressionArm(_, _) => "match arms have incompatible types",
367367
infer::IfExpression(_) => "if and else have incompatible types",
368368
infer::IfExpressionWithNoElse(_) => "if may be missing an else clause",
369+
infer::EquatePredicate(_) => "equality predicate not satisfied",
369370
};
370371

371372
self.tcx.sess.span_err(
@@ -1523,6 +1524,9 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> {
15231524
infer::IfExpressionWithNoElse(_) => {
15241525
format!("if may be missing an else clause")
15251526
}
1527+
infer::EquatePredicate(_) => {
1528+
format!("equality where clause is satisfied")
1529+
}
15261530
};
15271531

15281532
match self.values_str(&trace.values) {

src/librustc/middle/infer/mod.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,10 @@ pub enum TypeOrigin {
129129
IfExpression(Span),
130130

131131
// Computing common supertype of an if expression with no else counter-part
132-
IfExpressionWithNoElse(Span)
132+
IfExpressionWithNoElse(Span),
133+
134+
// `where a == b`
135+
EquatePredicate(Span),
133136
}
134137

135138
impl Copy for TypeOrigin {}
@@ -1017,7 +1020,8 @@ impl TypeOrigin {
10171020
RelateOutputImplTypes(span) => span,
10181021
MatchExpressionArm(match_span, _) => match_span,
10191022
IfExpression(span) => span,
1020-
IfExpressionWithNoElse(span) => span
1023+
IfExpressionWithNoElse(span) => span,
1024+
EquatePredicate(span) => span,
10211025
}
10221026
}
10231027
}
@@ -1050,6 +1054,9 @@ impl<'tcx> Repr<'tcx> for TypeOrigin {
10501054
IfExpressionWithNoElse(a) => {
10511055
format!("IfExpressionWithNoElse({})", a.repr(tcx))
10521056
}
1057+
EquatePredicate(a) => {
1058+
format!("EquatePredicate({})", a.repr(tcx))
1059+
}
10531060
}
10541061
}
10551062
}

src/librustc/middle/traits/fulfill.rs

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
use middle::mem_categorization::Typer;
1212
use middle::ty::{mod, Ty};
13-
use middle::infer::{mod, InferCtxt};
13+
use middle::infer::{mod, InferCtxt, ures};
1414
use std::collections::HashSet;
1515
use std::collections::hash_map::{Occupied, Vacant};
1616
use std::default::Default;
@@ -20,6 +20,8 @@ use util::ppaux::Repr;
2020
use util::nodemap::NodeMap;
2121

2222
use super::CodeAmbiguity;
23+
use super::Obligation;
24+
use super::ObligationCause;
2325
use super::TraitObligation;
2426
use super::FulfillmentError;
2527
use super::CodeSelectionError;
@@ -82,7 +84,7 @@ pub struct FulfillmentContext<'tcx> {
8284
pub struct RegionObligation<'tcx> {
8385
pub sub_region: ty::Region,
8486
pub sup_type: Ty<'tcx>,
85-
pub origin: infer::SubregionOrigin<'tcx>,
87+
pub cause: ObligationCause<'tcx>,
8688
}
8789

8890
impl<'tcx> FulfillmentContext<'tcx> {
@@ -95,6 +97,32 @@ impl<'tcx> FulfillmentContext<'tcx> {
9597
}
9698
}
9799

100+
pub fn register_predicate<'a>(&mut self,
101+
infcx: &InferCtxt<'a,'tcx>,
102+
predicate: &Obligation<'tcx, ty::Predicate<'tcx>>)
103+
-> ures<'tcx>
104+
{
105+
match predicate.trait_ref {
106+
ty::Predicate::Trait(ref trait_ref) => {
107+
let trait_obligation = Obligation { cause: predicate.cause,
108+
recursion_depth: predicate.recursion_depth,
109+
trait_ref: (*trait_ref).clone() };
110+
Ok(self.register_obligation(infcx.tcx, trait_obligation))
111+
}
112+
ty::Predicate::Equate(a, b) => {
113+
let origin = infer::EquatePredicate(predicate.cause.span);
114+
infer::mk_eqty(infcx, false, origin, a, b) // `a == b` ==> ``
115+
}
116+
ty::Predicate::RegionOutlives(r_a, r_b) => {
117+
let origin = infer::RelateRegionParamBound(predicate.cause.span);
118+
Ok(infer::mk_subr(infcx, origin, r_b, r_a)) // `b : a` ==> `a <= b`
119+
}
120+
ty::Predicate::TypeOutlives(t_a, r_b) => {
121+
Ok(self.register_region_obligation(t_a, r_b, predicate.cause))
122+
}
123+
}
124+
}
125+
98126
pub fn register_obligation(&mut self,
99127
tcx: &ty::ctxt<'tcx>,
100128
obligation: TraitObligation<'tcx>)
@@ -109,10 +137,14 @@ impl<'tcx> FulfillmentContext<'tcx> {
109137
}
110138

111139
pub fn register_region_obligation(&mut self,
112-
body_id: ast::NodeId,
113-
region_obligation: RegionObligation<'tcx>)
140+
sup_type: Ty<'tcx>,
141+
sub_region: ty::Region,
142+
cause: ObligationCause<'tcx>)
114143
{
115-
match self.region_obligations.entry(body_id) {
144+
let region_obligation = RegionObligation { sup_type: sup_type,
145+
sub_region: sub_region,
146+
cause: cause };
147+
match self.region_obligations.entry(cause.body_id) {
116148
Vacant(entry) => { entry.set(vec![region_obligation]); },
117149
Occupied(mut entry) => { entry.get_mut().push(region_obligation); },
118150
}
@@ -268,9 +300,8 @@ impl<'tcx> FulfillmentContext<'tcx> {
268300

269301
impl<'tcx> Repr<'tcx> for RegionObligation<'tcx> {
270302
fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
271-
format!("RegionObligation(sub_region={}, sup_type={}, origin={})",
303+
format!("RegionObligation(sub_region={}, sup_type={})",
272304
self.sub_region.repr(tcx),
273-
self.sup_type.repr(tcx),
274-
self.origin.repr(tcx))
305+
self.sup_type.repr(tcx))
275306
}
276307
}

src/librustc/middle/traits/mod.rs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,10 @@ pub use self::select::SelectionCache;
3131
pub use self::select::{MethodMatchResult, MethodMatched, MethodAmbiguous, MethodDidNotMatch};
3232
pub use self::select::{MethodMatchedData}; // intentionally don't export variants
3333
pub use self::util::supertraits;
34-
pub use self::util::transitive_bounds;
3534
pub use self::util::Supertraits;
3635
pub use self::util::search_trait_and_supertraits_from_bound;
36+
pub use self::util::transitive_bounds;
37+
pub use self::util::trait_ref_for_builtin_bound;
3738

3839
mod coherence;
3940
mod fulfill;
@@ -61,7 +62,7 @@ pub struct ObligationCause<'tcx> {
6162
pub span: Span,
6263

6364
// the id of XXX
64-
pub scope_id: ast::NodeId,
65+
pub body_id: ast::NodeId,
6566

6667
pub code: ObligationCauseCode<'tcx>
6768
}
@@ -307,8 +308,8 @@ impl<'tcx,O> Obligation<'tcx,O> {
307308
trait_ref: trait_ref }
308309
}
309310

310-
pub fn misc(span: Span, scope_id: ast::NodeId, trait_ref: O) -> Obligation<'tcx, O> {
311-
Obligation::new(ObligationCause::misc(span, scope_id), trait_ref)
311+
pub fn misc(span: Span, body_id: ast::NodeId, trait_ref: O) -> Obligation<'tcx, O> {
312+
Obligation::new(ObligationCause::misc(span, body_id), trait_ref)
312313
}
313314
}
314315

@@ -320,18 +321,18 @@ impl<'tcx> Obligation<'tcx,Rc<ty::TraitRef<'tcx>>> {
320321

321322
impl<'tcx> ObligationCause<'tcx> {
322323
pub fn new(span: Span,
323-
scope_id: ast::NodeId,
324+
body_id: ast::NodeId,
324325
code: ObligationCauseCode<'tcx>)
325326
-> ObligationCause<'tcx> {
326-
ObligationCause { span: span, scope_id: scope_id, code: code }
327+
ObligationCause { span: span, body_id: body_id, code: code }
327328
}
328329

329-
pub fn misc(span: Span, scope_id: ast::NodeId) -> ObligationCause<'tcx> {
330-
ObligationCause { span: span, scope_id: scope_id, code: MiscObligation }
330+
pub fn misc(span: Span, body_id: ast::NodeId) -> ObligationCause<'tcx> {
331+
ObligationCause { span: span, body_id: body_id, code: MiscObligation }
331332
}
332333

333334
pub fn dummy() -> ObligationCause<'tcx> {
334-
ObligationCause { span: DUMMY_SP, scope_id: 0, code: MiscObligation }
335+
ObligationCause { span: DUMMY_SP, body_id: 0, code: MiscObligation }
335336
}
336337
}
337338

src/librustc/middle/traits/util.rs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,10 @@ impl<'cx, 'tcx> Supertraits<'cx, 'tcx> {
8181
let bound_trait_ref = trait_ref_for_builtin_bound(self.tcx,
8282
builtin_bound,
8383
trait_ref.self_ty());
84-
bound_trait_ref.map(|trait_ref| trait_bounds.push(trait_ref));
84+
match bound_trait_ref {
85+
Ok(trait_ref) => { trait_bounds.push(trait_ref); }
86+
Err(ErrorReported) => { }
87+
}
8588
}
8689

8790
// Only keep those bounds that we haven't already seen. This
@@ -240,18 +243,18 @@ pub fn trait_ref_for_builtin_bound<'tcx>(
240243
tcx: &ty::ctxt<'tcx>,
241244
builtin_bound: ty::BuiltinBound,
242245
param_ty: Ty<'tcx>)
243-
-> Option<Rc<ty::TraitRef<'tcx>>>
246+
-> Result<Rc<ty::TraitRef<'tcx>>, ErrorReported>
244247
{
245248
match tcx.lang_items.from_builtin_kind(builtin_bound) {
246249
Ok(def_id) => {
247-
Some(Rc::new(ty::TraitRef {
250+
Ok(Rc::new(ty::TraitRef {
248251
def_id: def_id,
249252
substs: Substs::empty().with_self_ty(param_ty)
250253
}))
251254
}
252255
Err(e) => {
253256
tcx.sess.err(e.as_slice());
254-
None
257+
Err(ErrorReported)
255258
}
256259
}
257260
}
@@ -264,15 +267,12 @@ pub fn obligation_for_builtin_bound<'tcx>(
264267
param_ty: Ty<'tcx>)
265268
-> Result<TraitObligation<'tcx>, ErrorReported>
266269
{
267-
let trait_ref = trait_ref_for_builtin_bound(tcx, builtin_bound, param_ty);
268-
match trait_ref {
269-
Some(trait_ref) => Ok(Obligation {
270-
cause: cause,
271-
recursion_depth: recursion_depth,
272-
trait_ref: trait_ref
273-
}),
274-
None => Err(ErrorReported)
275-
}
270+
let trait_ref = try!(trait_ref_for_builtin_bound(tcx, builtin_bound, param_ty));
271+
Ok(Obligation {
272+
cause: cause,
273+
recursion_depth: recursion_depth,
274+
trait_ref: trait_ref
275+
})
276276
}
277277

278278
/// Starting from a caller obligation `caller_bound` (which has coordinates `space`/`i` in the list

src/librustc_typeck/check/mod.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1729,8 +1729,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
17291729

17301730
// If the type is `Foo+'a`, ensures that the type
17311731
// being cast to `Foo+'a` outlives `'a`:
1732-
let origin = infer::RelateObjectBound(span);
1733-
self.register_region_obligation(origin, self_ty, ty_trait.bounds.region_bound);
1732+
let cause = traits::ObligationCause { span: span,
1733+
body_id: self.body_id,
1734+
code: traits::ObjectCastObligation(self_ty) };
1735+
self.register_region_obligation(self_ty, ty_trait.bounds.region_bound, cause);
17341736
}
17351737
}
17361738
}
@@ -1951,15 +1953,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
19511953
/// Registers an obligation for checking later, during regionck, that the type `ty` must
19521954
/// outlive the region `r`.
19531955
pub fn register_region_obligation(&self,
1954-
origin: infer::SubregionOrigin<'tcx>,
19551956
ty: Ty<'tcx>,
1956-
r: ty::Region)
1957+
region: ty::Region,
1958+
cause: traits::ObligationCause<'tcx>)
19571959
{
19581960
let mut fulfillment_cx = self.inh.fulfillment_cx.borrow_mut();
1959-
let region_obligation = traits::RegionObligation { sub_region: r,
1960-
sup_type: ty,
1961-
origin: origin };
1962-
fulfillment_cx.register_region_obligation(self.body_id, region_obligation);
1961+
fulfillment_cx.register_region_obligation(ty, region, cause);
19631962
}
19641963

19651964
pub fn add_default_region_param_bounds(&self,
@@ -1968,8 +1967,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
19681967
{
19691968
for &ty in substs.types.iter() {
19701969
let default_bound = ty::ReScope(CodeExtent::from_node_id(expr.id));
1971-
let origin = infer::RelateDefaultParamBound(expr.span, ty);
1972-
self.register_region_obligation(origin, ty, default_bound);
1970+
let cause = traits::ObligationCause::new(expr.span, self.body_id,
1971+
traits::MiscObligation);
1972+
self.register_region_obligation(ty, default_bound, cause);
19731973
}
19741974
}
19751975

@@ -2061,8 +2061,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
20612061
param_bound.builtin_bounds,
20622062
param_bound.trait_bounds.as_slice());
20632063
for &r in region_bounds.iter() {
2064-
let origin = infer::RelateParamBound(span, ty);
2065-
self.register_region_obligation(origin, ty, r);
2064+
let cause = traits::ObligationCause::new(span, self.body_id, traits::MiscObligation);
2065+
self.register_region_obligation(ty, r, cause);
20662066
}
20672067
}
20682068

src/librustc_typeck/check/regionck.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -358,8 +358,8 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> {
358358
debug!("visit_region_obligations: r_o={}",
359359
r_o.repr(self.tcx()));
360360
let sup_type = self.resolve_type(r_o.sup_type);
361-
type_must_outlive(self, r_o.origin.clone(),
362-
sup_type, r_o.sub_region);
361+
let origin = infer::RelateRegionParamBound(r_o.cause.span);
362+
type_must_outlive(self, origin, sup_type, r_o.sub_region);
363363
}
364364
}
365365

src/librustc_typeck/collect.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,15 @@ use middle::region;
4242
use middle::resolve_lifetime;
4343
use middle::subst;
4444
use middle::subst::{Substs};
45+
use middle::traits;
4546
use middle::ty::{ImplContainer, ImplOrTraitItemContainer, TraitContainer};
4647
use middle::ty::{Polytype};
4748
use middle::ty::{mod, Ty};
4849
use middle::ty_fold::TypeFolder;
4950
use middle::infer;
5051
use rscope::*;
5152
use {CrateCtxt, lookup_def_tcx, no_params, write_ty_to_tcx};
53+
use util::common::ErrorReported;
5254
use util::nodemap::{FnvHashMap, FnvHashSet};
5355
use util::ppaux;
5456
use util::ppaux::{Repr,UserString};
@@ -1806,6 +1808,10 @@ fn ty_generics<'tcx,AC>(this: &AC,
18061808
result.types.push(space, (*associated_type_param).clone());
18071809
}
18081810

1811+
// Just for fun, also push the bounds from the type parameters
1812+
// into the predicates list. This is currently kind of non-DRY.
1813+
create_predicates(this.tcx(), &mut result, space);
1814+
18091815
return result;
18101816

18111817
fn create_type_parameters_for_associated_types<'tcx, AC>(
@@ -1892,6 +1898,33 @@ fn ty_generics<'tcx,AC>(this: &AC,
18921898
}
18931899
}
18941900
}
1901+
1902+
fn create_predicates<'tcx>(
1903+
tcx: &ty::ctxt<'tcx>,
1904+
result: &mut ty::Generics<'tcx>,
1905+
space: subst::ParamSpace)
1906+
{
1907+
for (index, type_param_def) in result.types.get_slice(space).iter().enumerate() {
1908+
let param_ty = ty::mk_param(tcx, space, index, type_param_def.def_id);
1909+
1910+
for builtin_bound in type_param_def.bounds.builtin_bounds.iter() {
1911+
match traits::trait_ref_for_builtin_bound(tcx, builtin_bound, param_ty) {
1912+
Ok(trait_ref) => {
1913+
result.predicates.push(space, ty::Predicate::Trait(trait_ref));
1914+
}
1915+
Err(ErrorReported) => { }
1916+
}
1917+
}
1918+
1919+
for &region_bound in type_param_def.bounds.region_bounds.iter() {
1920+
result.predicates.push(space, ty::Predicate::TypeOutlives(param_ty, region_bound));
1921+
}
1922+
1923+
for bound_trait_ref in type_param_def.bounds.trait_bounds.iter() {
1924+
result.predicates.push(space, ty::Predicate::Trait((*bound_trait_ref).clone()));
1925+
}
1926+
}
1927+
}
18951928
}
18961929

18971930
fn get_or_create_type_parameter_def<'tcx,AC>(this: &AC,

0 commit comments

Comments
 (0)