Skip to content

Commit 0e584f2

Browse files
committed
Fix bug in auto-ref on bounded type parameters
1 parent 2f6b66e commit 0e584f2

File tree

4 files changed

+92
-14
lines changed

4 files changed

+92
-14
lines changed

src/rustc/middle/typeck/check.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -861,8 +861,7 @@ fn check_expr(fcx: @fn_ctxt, expr: @ast::expr,
861861
// variables.
862862
fn impl_self_ty(fcx: @fn_ctxt,
863863
expr: @ast::expr, // (potential) receiver for this impl
864-
did: ast::def_id,
865-
require_rp: bool) -> ty_param_substs_and_ty {
864+
did: ast::def_id) -> ty_param_substs_and_ty {
866865
let tcx = fcx.ccx.tcx;
867866

868867
let {n_tps, region_param, raw_ty} = if did.crate == ast::local_crate {
@@ -897,7 +896,7 @@ fn impl_self_ty(fcx: @fn_ctxt,
897896
raw_ty: ity.ty}
898897
};
899898

900-
let self_r = if region_param.is_some() || require_rp {
899+
let self_r = if region_param.is_some() {
901900
Some(fcx.infcx().next_region_var(expr.span, expr.id))
902901
} else {
903902
None

src/rustc/middle/typeck/check/method.rs

Lines changed: 59 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,10 @@ fn lookup(
9999
inherent_candidates: DVec(),
100100
extension_candidates: DVec()
101101
};
102-
return lcx.do_lookup(self_ty);
102+
let mme = lcx.do_lookup(self_ty);
103+
debug!("method lookup for %s yielded %?",
104+
expr_repr(fcx.tcx(), expr), mme);
105+
return move mme;
103106
}
104107

105108
struct LookupContext {
@@ -333,6 +336,10 @@ impl LookupContext {
333336
let rcvr_ty = ty::mk_param(tcx, param_ty.idx, param_ty.def_id);
334337
let rcvr_substs = {self_ty: Some(rcvr_ty), ..bound_substs};
335338

339+
let (rcvr_ty, rcvr_substs) =
340+
self.create_rcvr_ty_and_substs_for_method(
341+
method.self_ty, rcvr_ty, move rcvr_substs);
342+
336343
self.inherent_candidates.push(Candidate {
337344
rcvr_ty: rcvr_ty,
338345
rcvr_substs: rcvr_substs,
@@ -384,8 +391,12 @@ impl LookupContext {
384391
// candidate be selected if the method refers to `self`.
385392
let rcvr_substs = {self_ty: Some(self_ty), ..*substs};
386393

394+
let (rcvr_ty, rcvr_substs) =
395+
self.create_rcvr_ty_and_substs_for_method(
396+
method.self_ty, self_ty, move rcvr_substs);
397+
387398
self.inherent_candidates.push(Candidate {
388-
rcvr_ty: self_ty,
399+
rcvr_ty: rcvr_ty,
389400
rcvr_substs: move rcvr_substs,
390401
num_method_tps: method.tps.len(),
391402
self_mode: get_mode_from_self_type(method.self_ty),
@@ -424,18 +435,14 @@ impl LookupContext {
424435
let tcx = self.tcx();
425436
let method = &impl_info.methods[idx];
426437

427-
let need_rp = match method.self_type {
428-
ast::sty_region(_) => true,
429-
_ => false
430-
};
431-
432438
// determine the `self` of the impl with fresh
433439
// variables for each parameter:
434440
let {substs: impl_substs, ty: impl_ty} =
435-
impl_self_ty(self.fcx, self.self_expr, impl_info.did, need_rp);
441+
impl_self_ty(self.fcx, self.self_expr, impl_info.did);
436442

437-
let impl_ty = transform_self_type_for_method(
438-
tcx, impl_substs.self_r, impl_ty, method.self_type);
443+
let (impl_ty, impl_substs) =
444+
self.create_rcvr_ty_and_substs_for_method(
445+
method.self_type, impl_ty, move impl_substs);
439446

440447
candidates.push(Candidate {
441448
rcvr_ty: impl_ty,
@@ -446,6 +453,48 @@ impl LookupContext {
446453
});
447454
}
448455

456+
fn create_rcvr_ty_and_substs_for_method(&self,
457+
self_decl: ast::self_ty_,
458+
self_ty: ty::t,
459+
+self_substs: ty::substs)
460+
-> (ty::t, ty::substs)
461+
{
462+
// If the self type includes a region (like &self), we need to
463+
// ensure that the receiver substitutions have a self region.
464+
// If the receiver type does not itself contain borrowed
465+
// pointers, there may not be one yet.
466+
//
467+
// FIXME(#3446)--this awkward situation comes about because
468+
// the regions in the receiver are substituted before (and
469+
// differently from) those in the argument types. This
470+
// shouldn't really have to be.
471+
let rcvr_substs = {
472+
match self_decl {
473+
sty_static | sty_value | sty_by_ref |
474+
sty_box(_) | sty_uniq(_) => {
475+
move self_substs
476+
}
477+
sty_region(_) if self_substs.self_r.is_some() => {
478+
move self_substs
479+
}
480+
sty_region(_) => {
481+
{self_r:
482+
Some(self.infcx().next_region_var(
483+
self.expr.span,
484+
self.expr.id)),
485+
..self_substs}
486+
}
487+
}
488+
};
489+
490+
let rcvr_ty =
491+
transform_self_type_for_method(
492+
self.tcx(), rcvr_substs.self_r,
493+
self_ty, self_decl);
494+
495+
(rcvr_ty, rcvr_substs)
496+
}
497+
449498
// ______________________________________________________________________
450499
// Candidate selection (see comment at start of file)
451500

src/rustc/middle/typeck/check/vtable.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ fn lookup_vtable(fcx: @fn_ctxt,
239239
// to some_trait. If not, then we try the next
240240
// impl.
241241
let {substs: substs, ty: for_ty} =
242-
impl_self_ty(fcx, expr, im.did, false);
242+
impl_self_ty(fcx, expr, im.did);
243243
let im_bs = ty::lookup_item_type(tcx,
244244
im.did).bounds;
245245
match fcx.mk_subty(false, expr.span, ty, for_ty) {
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
use to_str::ToStr;
2+
3+
trait Foo {
4+
fn f(&self);
5+
}
6+
7+
struct Bar {
8+
x: int
9+
}
10+
11+
trait Baz {
12+
fn g(&self);
13+
}
14+
15+
impl<T:Baz> T : Foo {
16+
fn f(&self) {
17+
self.g();
18+
}
19+
}
20+
21+
impl Bar : Baz {
22+
fn g(&self) {
23+
io::println(self.x.to_str());
24+
}
25+
}
26+
27+
fn main() {
28+
let y = Bar { x: 42 };
29+
y.f();
30+
}

0 commit comments

Comments
 (0)