Skip to content

Commit 6a478bd

Browse files
committed
rustc_typeck: use FnCtxt in coercion, instead of mimicking a combiner.
1 parent f9f3ba5 commit 6a478bd

File tree

3 files changed

+65
-87
lines changed

3 files changed

+65
-87
lines changed

src/librustc_typeck/check/coercion.rs

Lines changed: 63 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,11 @@
6060
//! sort of a minor point so I've opted to leave it for later---after all
6161
//! we may want to adjust precisely when coercions occur.
6262
63-
use middle::infer::{cres, Coercion, InferCtxt, TypeOrigin, TypeTrace};
64-
use middle::infer::combine::{CombineFields, Combine};
65-
use middle::infer::sub::Sub;
63+
use check::FnCtxt;
6664

65+
use middle::infer::{self, cres, Coercion, TypeTrace};
66+
use middle::infer::combine::Combine;
67+
use middle::infer::sub::Sub;
6768
use middle::subst;
6869
use middle::ty::{AutoPtr, AutoDerefRef, AdjustDerefRef, AutoUnsize, AutoUnsafe};
6970
use middle::ty::{mt};
@@ -74,21 +75,31 @@ use util::ppaux::Repr;
7475

7576
use syntax::ast;
7677

77-
// Note: Coerce is not actually a combiner, in that it does not
78-
// conform to the same interface, though it performs a similar
79-
// function.
80-
pub struct Coerce<'f, 'tcx: 'f>(pub CombineFields<'f, 'tcx>);
78+
struct Coerce<'a, 'tcx: 'a> {
79+
fcx: &'a FnCtxt<'a, 'tcx>,
80+
trace: TypeTrace<'tcx>
81+
}
82+
83+
type CoerceResult<'tcx> = cres<'tcx, Option<ty::AutoAdjustment<'tcx>>>;
8184

8285
impl<'f, 'tcx> Coerce<'f, 'tcx> {
83-
pub fn get_ref<'a>(&'a self) -> &'a CombineFields<'f, 'tcx> {
84-
let Coerce(ref v) = *self; v
86+
fn tcx(&self) -> &ty::ctxt<'tcx> {
87+
self.fcx.tcx()
8588
}
8689

87-
fn tcx(&self) -> &ty::ctxt<'tcx> {
88-
self.get_ref().infcx.tcx
90+
fn subtype(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
91+
let sub = Sub(self.fcx.infcx().combine_fields(false, self.trace.clone()));
92+
try!(sub.tys(a, b));
93+
Ok(None) // No coercion required.
8994
}
9095

91-
pub fn tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
96+
fn unpack_actual_value<T, F>(&self, a: Ty<'tcx>, f: F) -> T where
97+
F: FnOnce(Ty<'tcx>) -> T,
98+
{
99+
f(self.fcx.infcx().shallow_resolve(a))
100+
}
101+
102+
fn coerce(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
92103
debug!("Coerce.tys({} => {})",
93104
a.repr(self.tcx()),
94105
b.repr(self.tcx()));
@@ -179,25 +190,12 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
179190
})
180191
}
181192

182-
pub fn subtype(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
183-
match Sub(self.get_ref().clone()).tys(a, b) {
184-
Ok(_) => Ok(None), // No coercion required.
185-
Err(ref e) => Err(*e)
186-
}
187-
}
188-
189-
pub fn unpack_actual_value<T, F>(&self, a: Ty<'tcx>, f: F) -> T where
190-
F: FnOnce(Ty<'tcx>) -> T,
191-
{
192-
f(self.get_ref().infcx.shallow_resolve(a))
193-
}
194-
195193
// ~T -> &T or &mut T -> &T (including where T = [U] or str)
196-
pub fn coerce_borrowed_pointer(&self,
197-
a: Ty<'tcx>,
198-
b: Ty<'tcx>,
199-
mutbl_b: ast::Mutability)
200-
-> CoerceResult<'tcx> {
194+
fn coerce_borrowed_pointer(&self,
195+
a: Ty<'tcx>,
196+
b: Ty<'tcx>,
197+
mutbl_b: ast::Mutability)
198+
-> CoerceResult<'tcx> {
201199
debug!("coerce_borrowed_pointer(a={}, b={})",
202200
a.repr(self.tcx()),
203201
b.repr(self.tcx()));
@@ -208,9 +206,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
208206
// to type check, we will construct the type that `&M*expr` would
209207
// yield.
210208

211-
let sub = Sub(self.get_ref().clone());
212-
let coercion = Coercion(self.get_ref().trace.clone());
213-
let r_borrow = self.get_ref().infcx.next_region_var(coercion);
209+
let coercion = Coercion(self.trace.clone());
210+
let r_borrow = self.fcx.infcx().next_region_var(coercion);
214211

215212
let inner_ty = match a.sty {
216213
ty::ty_uniq(_) => return Err(ty::terr_mismatch),
@@ -220,15 +217,14 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
220217
}
221218
mt_a.ty
222219
}
223-
_ => {
224-
return self.subtype(a, b);
225-
}
220+
_ => return self.subtype(a, b)
226221
};
227222

228223
let a_borrowed = ty::mk_rptr(self.tcx(),
229224
self.tcx().mk_region(r_borrow),
230225
mt {ty: inner_ty, mutbl: mutbl_b});
231-
try!(sub.tys(a_borrowed, b));
226+
try!(self.subtype(a_borrowed, b));
227+
if let Err(original_err) = self.subtype(a_borrowed, b) {
232228

233229
Ok(Some(AdjustDerefRef(AutoDerefRef {
234230
autoderefs: 1,
@@ -253,8 +249,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
253249
// we can't unify [T] with U. But to properly support DST, we need to allow
254250
// that, at which point we will need extra checks on b here.
255251

256-
let sub = Sub(self.get_ref().clone());
257-
258252
match (&a.sty, &b.sty) {
259253
(&ty::ty_rptr(_, ty::mt{ty: t_a, mutbl: mutbl_a}), &ty::ty_rptr(_, mt_b)) => {
260254
self.unpack_actual_value(t_a, |a| {
@@ -264,12 +258,12 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
264258
return Err(ty::terr_mutability);
265259
}
266260

267-
let coercion = Coercion(self.get_ref().trace.clone());
268-
let r_borrow = self.get_ref().infcx.next_region_var(coercion);
261+
let coercion = Coercion(self.trace.clone());
262+
let r_borrow = self.fcx.infcx().next_region_var(coercion);
269263
let ty = ty::mk_rptr(self.tcx(),
270264
self.tcx().mk_region(r_borrow),
271265
ty::mt{ty: ty, mutbl: mt_b.mutbl});
272-
try!(self.get_ref().infcx.try(|_| sub.tys(ty, b)));
266+
try!(self.fcx.infcx().try(|_| self.subtype(ty, b)));
273267
debug!("Success, coerced with AutoDerefRef(1, \
274268
AutoPtr(AutoUnsize({:?})))", kind);
275269
Ok(Some(AdjustDerefRef(AutoDerefRef {
@@ -292,7 +286,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
292286

293287
let ty = ty::mk_ptr(self.tcx(),
294288
ty::mt{ty: ty, mutbl: mt_b.mutbl});
295-
try!(self.get_ref().infcx.try(|_| sub.tys(ty, b)));
289+
try!(self.fcx.infcx().try(|_| self.subtype(ty, b)));
296290
debug!("Success, coerced with AutoDerefRef(1, \
297291
AutoPtr(AutoUnsize({:?})))", kind);
298292
Ok(Some(AdjustDerefRef(AutoDerefRef {
@@ -310,7 +304,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
310304
match self.unsize_ty(t_a, a, t_b) {
311305
Some((ty, kind)) => {
312306
let ty = ty::mk_uniq(self.tcx(), ty);
313-
try!(self.get_ref().infcx.try(|_| sub.tys(ty, b)));
307+
try!(self.fcx.infcx().try(|_| self.subtype(ty, b)));
314308
debug!("Success, coerced with AutoDerefRef(1, \
315309
AutoUnsizeUniq({:?}))", kind);
316310
Ok(Some(AdjustDerefRef(AutoDerefRef {
@@ -362,12 +356,10 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
362356
let ty_substs_b = substs_b.types.get_slice(subst::TypeSpace);
363357
assert!(ty_substs_a.len() == ty_substs_b.len());
364358

365-
let sub = Sub(self.get_ref().clone());
366-
367359
let mut result = None;
368360
let mut tps = ty_substs_a.iter().zip(ty_substs_b.iter()).enumerate();
369361
for (i, (tp_a, tp_b)) in tps {
370-
if self.get_ref().infcx.try(|_| sub.tys(*tp_a, *tp_b)).is_ok() {
362+
if self.fcx.infcx().try(|_| self.subtype(*tp_a, *tp_b)).is_ok() {
371363
continue;
372364
}
373365
match
@@ -380,7 +372,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
380372
let mut new_substs = substs_a.clone();
381373
new_substs.types.get_mut_slice(subst::TypeSpace)[i] = new_tp;
382374
let ty = ty::mk_struct(tcx, did_a, tcx.mk_substs(new_substs));
383-
if self.get_ref().infcx.try(|_| sub.tys(ty, ty_b)).is_err() {
375+
if self.fcx.infcx().try(|_| self.subtype(ty, ty_b)).is_err() {
384376
debug!("Unsized type parameter '{}', but still \
385377
could not match types {} and {}",
386378
ppaux::ty_to_string(tcx, *tp_a),
@@ -416,8 +408,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
416408
a.repr(tcx),
417409
b.repr(tcx), b_mutbl);
418410

419-
let coercion = Coercion(self.get_ref().trace.clone());
420-
let r_a = self.get_ref().infcx.next_region_var(coercion);
411+
let coercion = Coercion(self.trace.clone());
412+
let r_a = self.fcx.infcx().next_region_var(coercion);
421413

422414
self.coerce_object(a, b, b_mutbl,
423415
|tr| ty::mk_rptr(tcx, tcx.mk_region(r_a),
@@ -501,11 +493,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
501493
})
502494
}
503495

504-
pub fn coerce_unsafe_ptr(&self,
505-
a: Ty<'tcx>,
506-
b: Ty<'tcx>,
507-
mutbl_b: ast::Mutability)
508-
-> CoerceResult<'tcx> {
496+
fn coerce_unsafe_ptr(&self,
497+
a: Ty<'tcx>,
498+
b: Ty<'tcx>,
499+
mutbl_b: ast::Mutability)
500+
-> CoerceResult<'tcx> {
509501
debug!("coerce_unsafe_ptr(a={}, b={})",
510502
a.repr(self.tcx()),
511503
b.repr(self.tcx()));
@@ -534,21 +526,25 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
534526
}
535527
}
536528

537-
pub type CoerceResult<'tcx> = cres<'tcx, Option<ty::AutoAdjustment<'tcx>>>;
538-
539-
pub fn mk_coercety<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
540-
a_is_expected: bool,
541-
origin: TypeOrigin,
529+
pub fn mk_assignty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
530+
expr: &ast::Expr,
542531
a: Ty<'tcx>,
543532
b: Ty<'tcx>)
544-
-> CoerceResult<'tcx> {
545-
debug!("mk_coercety({} -> {})", a.repr(cx.tcx), b.repr(cx.tcx));
546-
indent(|| {
547-
cx.commit_if_ok(|| {
548-
let trace = TypeTrace::types(origin, a_is_expected, a, b);
549-
Coerce(cx.combine_fields(a_is_expected, trace)).tys(a, b)
533+
-> cres<'tcx, ()> {
534+
debug!("mk_assignty({} -> {})", a.repr(fcx.tcx()), b.repr(fcx.tcx()));
535+
let adjustment = try!(indent(|| {
536+
fcx.infcx().commit_if_ok(|| {
537+
let origin = infer::ExprAssignable(expr.span);
538+
Coerce {
539+
fcx: fcx,
540+
trace: infer::TypeTrace::types(origin, false, a, b)
541+
}.coerce(a, b)
550542
})
551-
})
543+
}));
544+
if let Some(adjustment) = adjustment {
545+
fcx.write_adjustment(expr.id, expr.span, adjustment);
546+
}
547+
Ok(())
552548
}
553549

554550
fn can_coerce_mutbls(from_mutbl: ast::Mutability,

src/librustc_typeck/check/demand.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// except according to those terms.
1010

1111

12-
use check::FnCtxt;
12+
use check::{coercion, FnCtxt};
1313
use middle::ty::{self, Ty};
1414
use middle::infer;
1515

@@ -62,7 +62,7 @@ pub fn coerce<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
6262
expr_ty.repr(fcx.ccx.tcx));
6363
let expr_ty = fcx.resolve_type_vars_if_possible(expr_ty);
6464
let expected = fcx.resolve_type_vars_if_possible(expected);
65-
match fcx.mk_assignty(expr, expr_ty, expected) {
65+
match coercion::mk_assignty(fcx, expr, expr_ty, expected) {
6666
Ok(()) => { /* ok */ }
6767
Err(ref err) => {
6868
fcx.report_mismatched_types(sp, expected, expr_ty, err);

src/librustc_typeck/check/mod.rs

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1726,24 +1726,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
17261726
infer::mk_subty(self.infcx(), a_is_expected, origin, sub, sup)
17271727
}
17281728

1729-
pub fn mk_assignty(&self,
1730-
expr: &ast::Expr,
1731-
sub: Ty<'tcx>,
1732-
sup: Ty<'tcx>)
1733-
-> Result<(), ty::type_err<'tcx>> {
1734-
match try!(coercion::mk_coercety(self.infcx(),
1735-
false,
1736-
infer::ExprAssignable(expr.span),
1737-
sub,
1738-
sup)) {
1739-
None => {}
1740-
Some(adjustment) => {
1741-
self.write_adjustment(expr.id, expr.span, adjustment);
1742-
}
1743-
}
1744-
Ok(())
1745-
}
1746-
17471729
pub fn mk_eqty(&self,
17481730
a_is_expected: bool,
17491731
origin: infer::TypeOrigin,

0 commit comments

Comments
 (0)