let mut llself;
debug!("(translating trait callee) loading second index from pair");
let llbox = Load(bcx, GEPi(bcx, llpair, [0u, 1u]));
- match vstore {
- ty::vstore_box | ty::vstore_uniq => {
- llself = GEPi(bcx, llbox, [0u, abi::box_field_body]);
- }
- ty::vstore_slice(_) => {
- llself = llbox;
- }
- ty::vstore_fixed(*) => {
- bcx.tcx().sess.bug(~"vstore_fixed trait");
- }
- }
// Munge `llself` appropriately for the type of `self` in the method.
+ let self_mode;
match explicit_self {
ast::sty_static => {
bcx.tcx().sess.bug(~"shouldn't see static method here");
}
- ast::sty_by_ref => {} // Nothing to do.
+ ast::sty_by_ref => {
+ // We need to pass a pointer to a pointer to the payload.
+ match vstore {
+ ty::vstore_box | ty::vstore_uniq => {
+ llself = GEPi(bcx, llbox, [0u, abi::box_field_body]);
+ }
+ ty::vstore_slice(_) => {
+ llself = llbox;
+ }
+ ty::vstore_fixed(*) => {
+ bcx.tcx().sess.bug(~"vstore_fixed trait");
+ }
+ }
+
+ self_mode = ast::by_ref;
+ }
ast::sty_value => {
bcx.tcx().sess.bug(~"methods with by-value self should not be \
called on objects");
}
ast::sty_region(_) => {
+ // As before, we need to pass a pointer to a pointer to the
+ // payload.
+ match vstore {
+ ty::vstore_box | ty::vstore_uniq => {
+ llself = GEPi(bcx, llbox, [0u, abi::box_field_body]);
+ }
+ ty::vstore_slice(_) => {
+ llself = llbox;
+ }
+ ty::vstore_fixed(*) => {
+ bcx.tcx().sess.bug(~"vstore_fixed trait");
+ }
+ }
+
let llscratch = alloca(bcx, val_ty(llself));
Store(bcx, llself, llscratch);
llself = llscratch;
+
+ self_mode = ast::by_ref;
}
ast::sty_box(_) => {
// Bump the reference count on the box.
debug!("(translating trait callee) callee type is `%s`",
bcx.ty_to_str(callee_ty));
- bcx = glue::take_ty(bcx, llself, callee_ty);
+ bcx = glue::take_ty(bcx, llbox, callee_ty);
+
+ // Pass a pointer to the box.
+ match vstore {
+ ty::vstore_box => llself = llbox,
+ _ => bcx.tcx().sess.bug(~"@self receiver with non-@Trait")
+ }
+
+ let llscratch = alloca(bcx, val_ty(llself));
+ Store(bcx, llself, llscratch);
+ llself = llscratch;
+
+ self_mode = ast::by_ref;
+ }
+ ast::sty_uniq(_) => {
+ // Pass the unique pointer.
+ match vstore {
+ ty::vstore_uniq => llself = llbox,
+ _ => bcx.tcx().sess.bug(~"~self receiver with non-~Trait")
+ }
+
+ let llscratch = alloca(bcx, val_ty(llself));
+ Store(bcx, llself, llscratch);
+ llself = llscratch;
+
+ self_mode = ast::by_ref;
}
- ast::sty_uniq(_) => {} // Nothing to do here.
}
// Load the function from the vtable and cast it to the expected type.
llfn: mptr,
llself: llself,
self_ty: ty::mk_opaque_box(bcx.tcx()),
- self_mode: ast::by_ref, // XXX: is this bogosity?
+ self_mode: self_mode,
/* XXX: Some(llbox) */
})
};
origin: method_origin,
}
+/**
+ * Whether the self type should be transformed according to the form of
+ * explicit self provided by the method.
+ */
+enum TransformTypeFlag {
+ DontTransformType,
+ TransformType
+}
+
impl LookupContext {
fn do_lookup(&self, self_ty: ty::t) -> Option<method_map_entry> {
debug!("do_lookup(self_ty=%s, expr=%s, self_expr=%s)",
let (rcvr_ty, rcvr_substs) =
self.create_rcvr_ty_and_substs_for_method(
- method.self_ty, rcvr_ty, move init_substs);
+ method.self_ty,
+ rcvr_ty,
+ move init_substs,
+ TransformType);
let cand = Candidate {
rcvr_ty: rcvr_ty,
let rcvr_substs = {self_ty: Some(self_ty), ..*substs};
let (rcvr_ty, rcvr_substs) =
- self.create_rcvr_ty_and_substs_for_method(
- method.self_ty, self_ty, move rcvr_substs);
+ self.create_rcvr_ty_and_substs_for_method(method.self_ty,
+ self_ty,
+ move rcvr_substs,
+ DontTransformType);
self.inherent_candidates.push(Candidate {
rcvr_ty: rcvr_ty,
let rcvr_substs = { self_ty: Some(self_ty), ..*substs };
let (rcvr_ty, rcvr_substs) =
self.create_rcvr_ty_and_substs_for_method(
- method.self_ty, self_ty, move rcvr_substs);
+ method.self_ty,
+ self_ty,
+ move rcvr_substs,
+ TransformType);
self.inherent_candidates.push(Candidate {
rcvr_ty: rcvr_ty,
let (impl_ty, impl_substs) =
self.create_rcvr_ty_and_substs_for_method(
- method.self_type, impl_ty, move impl_substs);
+ method.self_type,
+ impl_ty,
+ move impl_substs,
+ TransformType);
candidates.push(Candidate {
rcvr_ty: impl_ty,
self.create_rcvr_ty_and_substs_for_method(
provided_method_info.method_info.self_type,
self_ty,
- dummy_substs);
+ dummy_substs,
+ TransformType);
candidates.push(Candidate {
rcvr_ty: impl_ty,
fn create_rcvr_ty_and_substs_for_method(&self,
self_decl: ast::self_ty_,
self_ty: ty::t,
- +self_substs: ty::substs)
- -> (ty::t, ty::substs) {
+ +self_substs: ty::substs,
+ transform_type: TransformTypeFlag)
+ -> (ty::t, ty::substs) {
// If the self type includes a region (like &self), we need to
// ensure that the receiver substitutions have a self region.
// If the receiver type does not itself contain borrowed
}
};
- let rcvr_ty =
- transform_self_type_for_method(
- self.tcx(), rcvr_substs.self_r,
- self_ty, self_decl);
+ let rcvr_ty;
+ match transform_type {
+ TransformType => {
+ rcvr_ty = transform_self_type_for_method(self.tcx(),
+ rcvr_substs.self_r,
+ self_ty,
+ self_decl);
+ }
+ DontTransformType => {
+ rcvr_ty = self_ty;
+ }
+ }
(rcvr_ty, rcvr_substs)
}