Skip to content

Commit 046e97b

Browse files
committed
---
yaml --- r: 192496 b: refs/heads/auto c: 9374c21 h: refs/heads/master v: v3
1 parent 5329392 commit 046e97b

File tree

2 files changed

+164
-148
lines changed

2 files changed

+164
-148
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ refs/tags/release-0.3: b5f0d0f648d9a6153664837026ba1be43d3e2503
1010
refs/tags/release-0.3.1: 495bae036dfe5ec6ceafd3312b4dca48741e845b
1111
refs/tags/release-0.4: e828ea2080499553b97dfe33b3f4d472b4562ad7
1212
refs/tags/release-0.5: 7e3bcfbf21278251ee936ad53e92e9b719702d73
13-
refs/heads/auto: 95602a759d9190cad92279aa5929d30166f2255c
13+
refs/heads/auto: 9374c216f6040189301aeb043d317c12ffb17a0b
1414
refs/heads/servo: af82457af293e2a842ba6b7759b70288da276167
1515
refs/tags/release-0.6: b4ebcfa1812664df5e142f0134a5faea3918544c
1616
refs/tags/0.1: b19db808c2793fe2976759b85a355c3ad8c8b336

branches/auto/src/librustc_typeck/check/coercion.rs

Lines changed: 163 additions & 147 deletions
Original file line numberDiff line numberDiff line change
@@ -258,70 +258,64 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
258258

259259
match (&a.sty, &b.sty) {
260260
(&ty::ty_rptr(_, ty::mt{ty: t_a, mutbl: mutbl_a}), &ty::ty_rptr(_, mt_b)) => {
261-
self.unpack_actual_value(t_a, |a| {
262-
match self.unsize_ty(t_a, a, mt_b.ty) {
263-
Some((ty, kind)) => {
264-
if !can_coerce_mutbls(mutbl_a, mt_b.mutbl) {
265-
return Err(ty::terr_mutability);
266-
}
267-
268-
let coercion = Coercion(self.trace.clone());
269-
let r_borrow = self.fcx.infcx().next_region_var(coercion);
270-
let ty = ty::mk_rptr(self.tcx(),
271-
self.tcx().mk_region(r_borrow),
272-
ty::mt{ty: ty, mutbl: mt_b.mutbl});
273-
try!(self.fcx.infcx().try(|_| self.subtype(ty, b)));
274-
debug!("Success, coerced with AutoDerefRef(1, \
275-
AutoPtr(AutoUnsize({:?})))", kind);
276-
Ok(Some(AdjustDerefRef(AutoDerefRef {
277-
autoderefs: 1,
278-
autoref: Some(ty::AutoPtr(r_borrow, mt_b.mutbl,
279-
Some(box AutoUnsize(kind))))
280-
})))
261+
match self.unsize_ty(t_a, mt_b.ty) {
262+
Some((ty, kind)) => {
263+
if !can_coerce_mutbls(mutbl_a, mt_b.mutbl) {
264+
return Err(ty::terr_mutability);
281265
}
282-
_ => Err(ty::terr_mismatch)
266+
267+
let coercion = Coercion(self.trace.clone());
268+
let r_borrow = self.fcx.infcx().next_region_var(coercion);
269+
let ty = ty::mk_rptr(self.tcx(),
270+
self.tcx().mk_region(r_borrow),
271+
ty::mt{ty: ty, mutbl: mt_b.mutbl});
272+
try!(self.fcx.infcx().try(|_| self.subtype(ty, b)));
273+
debug!("Success, coerced with AutoDerefRef(1, \
274+
AutoPtr(AutoUnsize({:?})))", kind);
275+
Ok(Some(AdjustDerefRef(AutoDerefRef {
276+
autoderefs: 1,
277+
autoref: Some(ty::AutoPtr(r_borrow, mt_b.mutbl,
278+
Some(box AutoUnsize(kind))))
279+
})))
283280
}
284-
})
281+
_ => Err(ty::terr_mismatch)
282+
}
285283
}
286284
(&ty::ty_rptr(_, ty::mt{ty: t_a, mutbl: mutbl_a}), &ty::ty_ptr(mt_b)) => {
287-
self.unpack_actual_value(t_a, |a| {
288-
match self.unsize_ty(t_a, a, mt_b.ty) {
289-
Some((ty, kind)) => {
290-
if !can_coerce_mutbls(mutbl_a, mt_b.mutbl) {
291-
return Err(ty::terr_mutability);
292-
}
293-
294-
let ty = ty::mk_ptr(self.tcx(),
295-
ty::mt{ty: ty, mutbl: mt_b.mutbl});
296-
try!(self.fcx.infcx().try(|_| self.subtype(ty, b)));
297-
debug!("Success, coerced with AutoDerefRef(1, \
298-
AutoPtr(AutoUnsize({:?})))", kind);
299-
Ok(Some(AdjustDerefRef(AutoDerefRef {
300-
autoderefs: 1,
301-
autoref: Some(ty::AutoUnsafe(mt_b.mutbl,
302-
Some(box AutoUnsize(kind))))
303-
})))
285+
match self.unsize_ty(t_a, mt_b.ty) {
286+
Some((ty, kind)) => {
287+
if !can_coerce_mutbls(mutbl_a, mt_b.mutbl) {
288+
return Err(ty::terr_mutability);
304289
}
305-
_ => Err(ty::terr_mismatch)
290+
291+
let ty = ty::mk_ptr(self.tcx(),
292+
ty::mt{ty: ty, mutbl: mt_b.mutbl});
293+
try!(self.fcx.infcx().try(|_| self.subtype(ty, b)));
294+
debug!("Success, coerced with AutoDerefRef(1, \
295+
AutoPtr(AutoUnsize({:?})))", kind);
296+
Ok(Some(AdjustDerefRef(AutoDerefRef {
297+
autoderefs: 1,
298+
autoref: Some(ty::AutoUnsafe(mt_b.mutbl,
299+
Some(box AutoUnsize(kind))))
300+
})))
306301
}
307-
})
302+
_ => Err(ty::terr_mismatch)
303+
}
308304
}
309305
(&ty::ty_uniq(t_a), &ty::ty_uniq(t_b)) => {
310-
self.unpack_actual_value(t_a, |a| {
311-
match self.unsize_ty(t_a, a, t_b) {
312-
Some((ty, kind)) => {
313-
let ty = ty::mk_uniq(self.tcx(), ty);
314-
try!(self.fcx.infcx().try(|_| self.subtype(ty, b)));
315-
debug!("Success, coerced with AutoDerefRef(1, \
316-
AutoUnsizeUniq({:?}))", kind);
317-
Ok(Some(AdjustDerefRef(AutoDerefRef {
318-
autoderefs: 1,
319-
autoref: Some(ty::AutoUnsizeUniq(kind))
320-
})))
321-
}
322-
_ => Err(ty::terr_mismatch)
306+
match self.unsize_ty(t_a, t_b) {
307+
Some((ty, kind)) => {
308+
let ty = ty::mk_uniq(self.tcx(), ty);
309+
try!(self.fcx.infcx().try(|_| self.subtype(ty, b)));
310+
debug!("Success, coerced with AutoDerefRef(1, \
311+
AutoUnsizeUniq({:?}))", kind);
312+
Ok(Some(AdjustDerefRef(AutoDerefRef {
313+
autoderefs: 1,
314+
autoref: Some(ty::AutoUnsizeUniq(kind))
315+
})))
323316
}
324-
})
317+
_ => Err(ty::terr_mismatch)
318+
}
325319
}
326320
_ => Err(ty::terr_mismatch)
327321
}
@@ -332,112 +326,134 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
332326
// E.g., `[T, ..n]` -> `([T], UnsizeLength(n))`
333327
fn unsize_ty(&self,
334328
ty_a: Ty<'tcx>,
335-
a: Ty<'tcx>, // TODO unwrap ty_a here, not in the caller
336329
ty_b: Ty<'tcx>)
337330
-> Option<(Ty<'tcx>, ty::UnsizeKind<'tcx>)>
338331
{
339332
let tcx = self.tcx();
340333

341-
self.unpack_actual_value(ty_b, |b| {
342-
debug!("unsize_ty(a={}, b={})", a.repr(self.tcx()), b.repr(self.tcx()));
343-
match (&a.sty, &b.sty) {
344-
(&ty::ty_vec(t_a, Some(len)), &ty::ty_vec(_, None)) => {
345-
let ty = ty::mk_vec(tcx, t_a, None);
346-
Some((ty, ty::UnsizeLength(len)))
347-
}
348-
(&ty::ty_trait(ref data_a), &ty::ty_trait(ref data_b)) => {
349-
// Upcasts permit two things:
350-
//
351-
// 1. Dropping builtin bounds, e.g. `Foo+Send` to `Foo`
352-
// 2. Tightening the region bound, e.g. `Foo+'a` to `Foo+'b` if `'a : 'b`
353-
//
354-
// Note that neither of these changes requires any
355-
// change at runtime. Eventually this will be
356-
// generalized.
357-
//
358-
// We always upcast when we can because of reason
359-
// #2 (region bounds).
360-
if data_a.bounds.builtin_bounds.is_superset(&data_b.bounds.builtin_bounds) {
361-
// construct a type `a1` which is a version of
362-
// `a` using the upcast bounds from `b`
363-
let bounds_a1 = ty::ExistentialBounds {
364-
// From type b
365-
region_bound: data_b.bounds.region_bound,
366-
builtin_bounds: data_b.bounds.builtin_bounds,
367-
368-
// From type a
369-
projection_bounds: data_a.bounds.projection_bounds.clone(),
370-
};
371-
let ty_a1 = ty::mk_trait(tcx, data_a.principal.clone(), bounds_a1);
372-
373-
// relate `a1` to `b`
374-
let result = self.fcx.infcx().try(|_| {
375-
// it's ok to upcast from Foo+'a to Foo+'b so long as 'a : 'b
376-
try!(self.outlives(data_a.bounds.region_bound,
377-
data_b.bounds.region_bound));
378-
self.subtype(ty_a1, ty_b)
379-
});
380-
381-
// if that was successful, we have a coercion
382-
match result {
383-
Ok(_) => Some((ty_b, ty::UnsizeUpcast(ty_b))),
384-
Err(_) => None,
385-
}
386-
} else {
387-
None
334+
self.unpack_actual_value(ty_a, |a| {
335+
self.unpack_actual_value(ty_b, |b| {
336+
debug!("unsize_ty(a={}, b={})", a.repr(self.tcx()), b.repr(self.tcx()));
337+
match (&a.sty, &b.sty) {
338+
(&ty::ty_vec(t_a, Some(len)), &ty::ty_vec(_, None)) => {
339+
let ty = ty::mk_vec(tcx, t_a, None);
340+
Some((ty, ty::UnsizeLength(len)))
388341
}
389-
}
390-
(_, &ty::ty_trait(ref data)) => {
391-
Some((ty_b, ty::UnsizeVtable(ty::TyTrait { principal: data.principal.clone(),
392-
bounds: data.bounds.clone() },
393-
ty_a)))
394-
}
395-
(&ty::ty_struct(did_a, substs_a), &ty::ty_struct(did_b, substs_b))
396-
if did_a == did_b => {
397-
debug!("unsizing a struct");
398-
// Try unsizing each type param in turn to see if we end up with ty_b.
399-
let ty_substs_a = substs_a.types.get_slice(subst::TypeSpace);
400-
let ty_substs_b = substs_b.types.get_slice(subst::TypeSpace);
401-
assert!(ty_substs_a.len() == ty_substs_b.len());
402-
403-
let mut result = None;
404-
let tps = ty_substs_a.iter().zip(ty_substs_b.iter()).enumerate();
405-
for (i, (tp_a, tp_b)) in tps {
406-
if self.fcx.infcx().try(|_| self.subtype(*tp_a, *tp_b)).is_ok() {
407-
continue;
342+
(&ty::ty_trait(ref data_a), &ty::ty_trait(ref data_b)) => {
343+
// Upcasts permit two things:
344+
//
345+
// 1. Dropping builtin bounds, e.g. `Foo+Send` to `Foo`
346+
// 2. Tightening the region bound, e.g. `Foo+'a` to `Foo+'b` if `'a : 'b`
347+
//
348+
// Note that neither of these changes requires any
349+
// change at runtime. Eventually this will be
350+
// generalized.
351+
//
352+
// We always upcast when we can because of reason
353+
// #2 (region bounds).
354+
if data_a.bounds.builtin_bounds.is_superset(&data_b.bounds.builtin_bounds) {
355+
// construct a type `a1` which is a version of
356+
// `a` using the upcast bounds from `b`
357+
let bounds_a1 = ty::ExistentialBounds {
358+
// From type b
359+
region_bound: data_b.bounds.region_bound,
360+
builtin_bounds: data_b.bounds.builtin_bounds,
361+
362+
// From type a
363+
projection_bounds: data_a.bounds.projection_bounds.clone(),
364+
};
365+
let ty_a1 = ty::mk_trait(tcx, data_a.principal.clone(), bounds_a1);
366+
367+
// relate `a1` to `b`
368+
let result = self.fcx.infcx().try(|_| {
369+
// it's ok to upcast from Foo+'a to Foo+'b so long as 'a : 'b
370+
try!(self.outlives(data_a.bounds.region_bound,
371+
data_b.bounds.region_bound));
372+
self.subtype(ty_a1, ty_b)
373+
});
374+
375+
// if that was successful, we have a coercion
376+
match result {
377+
Ok(_) => Some((ty_b, ty::UnsizeUpcast(ty_b))),
378+
Err(_) => None,
379+
}
380+
} else {
381+
None
408382
}
409-
match
410-
self.unpack_actual_value(
411-
*tp_a,
412-
|tp| self.unsize_ty(*tp_a, tp, *tp_b))
383+
}
384+
(&ty::ty_trait(ref data_a), &ty::ty_trait(ref data_b)) => {
385+
// For now, we only support upcasts from
386+
// `Foo+Send` to `Foo` (really, any time there are
387+
// fewer builtin bounds then before). These are
388+
// convenient because they don't require any sort
389+
// of change to the vtable at runtime.
390+
if data_a.bounds.builtin_bounds != data_b.bounds.builtin_bounds &&
391+
data_a.bounds.builtin_bounds.is_superset(&data_b.bounds.builtin_bounds)
413392
{
414-
Some((new_tp, k)) => {
415-
// Check that the whole types match.
416-
let mut new_substs = substs_a.clone();
417-
new_substs.types.get_mut_slice(subst::TypeSpace)[i] = new_tp;
418-
let ty = ty::mk_struct(tcx, did_a, tcx.mk_substs(new_substs));
419-
if self.fcx.infcx().try(|_| self.subtype(ty, ty_b)).is_err() {
420-
debug!("Unsized type parameter '{}', but still \
421-
could not match types {} and {}",
422-
ppaux::ty_to_string(tcx, *tp_a),
423-
ppaux::ty_to_string(tcx, ty),
424-
ppaux::ty_to_string(tcx, ty_b));
425-
// We can only unsize a single type parameter, so
426-
// if we unsize one and it doesn't give us the
427-
// type we want, then we won't succeed later.
393+
let bounds_a1 = ty::ExistentialBounds {
394+
region_bound: data_a.bounds.region_bound,
395+
builtin_bounds: data_b.bounds.builtin_bounds,
396+
projection_bounds: data_a.bounds.projection_bounds.clone(),
397+
};
398+
let ty_a1 = ty::mk_trait(tcx, data_a.principal.clone(), bounds_a1);
399+
match self.fcx.infcx().try(|_| self.subtype(ty_a1, ty_b)) {
400+
Ok(_) => Some((ty_b, ty::UnsizeUpcast(ty_b))),
401+
Err(_) => None,
402+
}
403+
} else {
404+
None
405+
}
406+
}
407+
(_, &ty::ty_trait(ref data)) => {
408+
Some((ty_b, ty::UnsizeVtable(ty::TyTrait {
409+
principal: data.principal.clone(),
410+
bounds: data.bounds.clone()
411+
},
412+
ty_a)))
413+
}
414+
(&ty::ty_struct(did_a, substs_a), &ty::ty_struct(did_b, substs_b))
415+
if did_a == did_b => {
416+
debug!("unsizing a struct");
417+
// Try unsizing each type param in turn to see if we end up with ty_b.
418+
let ty_substs_a = substs_a.types.get_slice(subst::TypeSpace);
419+
let ty_substs_b = substs_b.types.get_slice(subst::TypeSpace);
420+
assert!(ty_substs_a.len() == ty_substs_b.len());
421+
422+
let mut result = None;
423+
let tps = ty_substs_a.iter().zip(ty_substs_b.iter()).enumerate();
424+
for (i, (tp_a, tp_b)) in tps {
425+
if self.fcx.infcx().try(|_| self.subtype(*tp_a, *tp_b)).is_ok() {
426+
continue;
427+
}
428+
match self.unsize_ty(*tp_a, *tp_b) {
429+
Some((new_tp, k)) => {
430+
// Check that the whole types match.
431+
let mut new_substs = substs_a.clone();
432+
new_substs.types.get_mut_slice(subst::TypeSpace)[i] = new_tp;
433+
let ty = ty::mk_struct(tcx, did_a, tcx.mk_substs(new_substs));
434+
if self.fcx.infcx().try(|_| self.subtype(ty, ty_b)).is_err() {
435+
debug!("Unsized type parameter '{}', but still \
436+
could not match types {} and {}",
437+
ppaux::ty_to_string(tcx, *tp_a),
438+
ppaux::ty_to_string(tcx, ty),
439+
ppaux::ty_to_string(tcx, ty_b));
440+
// We can only unsize a single type parameter, so
441+
// if we unsize one and it doesn't give us the
442+
// type we want, then we won't succeed later.
443+
break;
444+
}
445+
446+
result = Some((ty, ty::UnsizeStruct(box k, i)));
428447
break;
429448
}
430-
431-
result = Some((ty, ty::UnsizeStruct(box k, i)));
432-
break;
449+
None => {}
433450
}
434-
None => {}
435451
}
452+
result
436453
}
437-
result
454+
_ => None
438455
}
439-
_ => None
440-
}
456+
})
441457
})
442458
}
443459

0 commit comments

Comments
 (0)