Skip to content

Commit 7d02ce4

Browse files
committed
---
yaml --- r: 273357 b: refs/heads/beta c: ad6ca08 h: refs/heads/master i: 273355: 0497454
1 parent 4fed659 commit 7d02ce4

File tree

2 files changed

+85
-42
lines changed

2 files changed

+85
-42
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ refs/tags/0.9: 36870b185fc5f5486636d4515f0e22677493f225
2323
refs/tags/0.10: ac33f2b15782272ae348dbd7b14b8257b2148b5a
2424
refs/tags/0.11.0: e1247cb1d0d681be034adb4b558b5a0c0d5720f9
2525
refs/tags/0.12.0: f0c419429ef30723ceaf6b42f9b5a2aeb5d2e2d1
26-
refs/heads/beta: 00c942016033abb6dea1015c017bea5517af25a0
26+
refs/heads/beta: ad6ca084e7ac47b59714356c08eeb274a6e239ca
2727
refs/tags/1.0.0-alpha: e42bd6d93a1d3433c486200587f8f9e12590a4d7
2828
refs/heads/tmp: e06d2ad9fcd5027bcaac5b08fc9aa39a49d0ecd3
2929
refs/tags/1.0.0-alpha.2: 4c705f6bc559886632d3871b04f58aab093bfa2f

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

Lines changed: 84 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ use middle::ty::adjustment::{AdjustUnsafeFnPointer, AdjustMutToConstPointer};
7171
use middle::ty::{self, LvaluePreference, TypeAndMut, Ty, TyCtxt};
7272
use middle::ty::fold::TypeFoldable;
7373
use middle::ty::error::TypeError;
74-
use middle::ty::relate::{relate_substs, RelateResult, TypeRelation};
74+
use middle::ty::relate::{relate_substs, Relate, RelateResult, TypeRelation};
7575
use util::common::indent;
7676

7777
use std::cell::RefCell;
@@ -112,8 +112,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
112112
self.fcx.tcx()
113113
}
114114

115-
/// Unify two types (using sub or lub) and produce a noop coercion.
116-
fn unify_and_identity(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
115+
fn unify(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
117116
let infcx = self.fcx.infcx();
118117
infcx.commit_if_ok(|_| {
119118
let trace = TypeTrace::types(self.origin, false, a, b);
@@ -122,7 +121,12 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
122121
} else {
123122
infcx.sub(false, trace).relate(&a, &b)
124123
}
125-
}).and_then(|ty| self.identity(ty))
124+
})
125+
}
126+
127+
/// Unify two types (using sub or lub) and produce a noop coercion.
128+
fn unify_and_identity(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
129+
self.unify(&a, &b).and_then(|ty| self.identity(ty))
126130
}
127131

128132
/// Synthesize an identity adjustment.
@@ -167,7 +171,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
167171
}
168172

169173
ty::TyRef(r_b, mt_b) => {
170-
return self.coerce_borrowed_pointer(exprs, a, b, r_b, mt_b.mutbl);
174+
return self.coerce_borrowed_pointer(exprs, a, b, r_b, mt_b);
171175
}
172176

173177
_ => {}
@@ -200,7 +204,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
200204
a: Ty<'tcx>,
201205
b: Ty<'tcx>,
202206
r_b: &'tcx ty::Region,
203-
mutbl_b: hir::Mutability)
207+
mt_b: TypeAndMut<'tcx>)
204208
-> CoerceResult<'tcx>
205209
// FIXME(eddyb) use copyable iterators when that becomes ergonomic.
206210
where E: Fn() -> I,
@@ -214,68 +218,107 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
214218
// to type check, we will construct the type that `&M*expr` would
215219
// yield.
216220

217-
let (_r_a, _mutbl_a) = match a.sty {
221+
let r_a = match a.sty {
218222
ty::TyRef(r_a, mt_a) => {
219-
try!(coerce_mutbls(mt_a.mutbl, mutbl_b));
220-
(r_a, mt_a.mutbl)
223+
try!(coerce_mutbls(mt_a.mutbl, mt_b.mutbl));
224+
r_a
221225
}
222226
_ => return self.unify_and_identity(a, b)
223227
};
224228

225229
let span = self.origin.span();
226-
let coercion = Coercion(span);
227-
let r_borrow = {
228-
// If are coercing from `&'a T` to `&'b U`, then we want to
229-
// reborrow the contents of `'a` for the lifetime `'b`
230-
// (which ought to be a sublifetime of `'a`).
231-
if !self.use_lub {
232-
r_b
233-
} else {
234-
// With LUB, we need more flexibility.
235-
let r_borrow = self.fcx.infcx().next_region_var(coercion);
236-
self.tcx().mk_region(r_borrow)
237-
}
238-
};
239-
let autoref = Some(AutoPtr(r_borrow, mutbl_b));
240230

241-
let lvalue_pref = LvaluePreference::from_mutbl(mutbl_b);
231+
let lvalue_pref = LvaluePreference::from_mutbl(mt_b.mutbl);
242232
let mut first_error = None;
243233
let (_, autoderefs, success) = autoderef(self.fcx, span, a, exprs,
244234
UnresolvedTypeAction::Ignore,
245235
lvalue_pref,
246-
|inner_ty, autoderef| {
236+
|referent_ty, autoderef|
237+
{
247238
if autoderef == 0 {
248239
// Don't let this pass, otherwise it would cause
249240
// &T to autoref to &&T.
250241
return None;
251242
}
252-
let ty = self.tcx().mk_ref(r_borrow,
253-
TypeAndMut {ty: inner_ty, mutbl: mutbl_b});
254-
match self.unify_and_identity(ty, b) {
243+
244+
// At this point, we have deref'd `a` to `referent_ty`. So
245+
// imagine we are coercing from `&'a mut Vec<T>` to `&'b mut [T]`.
246+
// In the autoderef loop for `&'a mut Vec<T>`, we would get
247+
// three callbacks:
248+
//
249+
// - `&'a mut Vec<T>` -- 0 derefs, just ignore it
250+
// - `Vec<T>` -- 1 deref
251+
// - `[T]` -- 2 deref
252+
//
253+
// At each point after the first callback, we want to
254+
// check to see whether this would match out target type
255+
// (`&'b mut [T]`) if we autoref'd it. We can't just
256+
// compare the referent types, though, because we still
257+
// have to consider the mutability. E.g., in the case
258+
// we've been considering, we have an `&mut` reference, so
259+
// the `T` in `[T]` needs to be unified with equality.
260+
//
261+
// Therefore, we construct reference types reflecting what
262+
// the types will be after we do the final auto-ref and
263+
// compare those. Note that this means we use the target
264+
// mutability [1], since it may be that we are coercing
265+
// from `&mut T` to `&U`.
266+
//
267+
// One fine point concerns the region that we use [2]. We
268+
// choose the region such that the region of the final
269+
// type that results from `unify` will be the region we
270+
// want for the autoref:
271+
//
272+
// - if in lub mode, that means we want to unify `&'a mut [T]`
273+
// (from source) and `&'b mut [T]` (target).
274+
// - if in sub mode, that means we want to use `'b` for
275+
// both pointers. This is because sub mode (somewhat
276+
// arbitrarily) returns the subtype region. In the case
277+
// where we are coercing to a target type, we know we
278+
// want to use that target type region (`'b`) because --
279+
// for the program to type-check -- it must be the
280+
// smaller of the two.
281+
let r = if self.use_lub {r_a} else {r_b}; // [2] above
282+
let derefd_ty_a = self.tcx().mk_ref(r, TypeAndMut {
283+
ty: referent_ty,
284+
mutbl: mt_b.mutbl // [1] above
285+
});
286+
match self.unify(derefd_ty_a, b) {
287+
Ok(ty) => Some(ty),
255288
Err(err) => {
256289
if first_error.is_none() {
257290
first_error = Some(err);
258291
}
259292
None
260293
}
261-
Ok((ty, _)) => Some(ty)
262294
}
263295
});
264296

265-
match success {
266-
Some(ty) => {
267-
Ok((ty, AdjustDerefRef(AutoDerefRef {
268-
autoderefs: autoderefs,
269-
autoref: autoref,
270-
unsize: None
271-
})))
272-
}
297+
// Extract type or return an error. We return the first error
298+
// we got, which should be from relating the "base" type
299+
// (e.g., in example above, the failure from relating `Vec<T>`
300+
// to the target type), since that should be the least
301+
// confusing.
302+
let ty = match success {
303+
Some(ty) => ty,
273304
None => {
274-
// Return original error as if overloaded deref was never
275-
// attempted, to avoid irrelevant/confusing error messages.
276-
Err(first_error.expect("coerce_borrowed_pointer failed with no error?"))
305+
return Err(first_error.expect("coerce_borrowed_pointer had no error"));
277306
}
278-
}
307+
};
308+
309+
// Now apply the autoref. We have to extract the region out of
310+
// the final ref type we got.
311+
let r_borrow = match ty.sty {
312+
ty::TyRef(r, _) => r,
313+
_ => self.tcx().sess.span_bug(span,
314+
&format!("expected a ref type, got {:?}", ty))
315+
};
316+
let autoref = Some(AutoPtr(r_borrow, mt_b.mutbl));
317+
Ok((ty, AdjustDerefRef(AutoDerefRef {
318+
autoderefs: autoderefs,
319+
autoref: autoref,
320+
unsize: None
321+
})))
279322
}
280323

281324

0 commit comments

Comments
 (0)