librustc: Implement (and require) explicit self for derivable traits. r=nmatsakis

This commit is contained in:
Patrick Walton 2012-11-14 16:32:37 -08:00
parent 29e10c91fe
commit adc4bed773
13 changed files with 89 additions and 46 deletions

View File

@ -4,6 +4,7 @@
use lib::llvm::llvm::{LLVMCountParams, LLVMGetParam};
use middle::trans::base::{GEP_enum, finish_fn, get_insn_ctxt, get_item_val};
use middle::trans::base::{new_fn_ctxt, sub_block, top_scope_block};
use middle::trans::base;
use middle::trans::build::{AddCase, Br, CondBr, GEPi, Load, PointerCast};
use middle::trans::build::{Store, Switch, Unreachable, ValueRef};
use middle::trans::callee;
@ -14,7 +15,8 @@ use middle::trans::common::{C_bool, C_int, T_ptr, block, crate_ctxt};
use middle::trans::common::{fn_ctxt};
use middle::trans::expr::SaveIn;
use middle::trans::type_of::type_of;
use middle::ty::DerivedFieldInfo;
use middle::ty::{DerivedFieldInfo, re_static};
use middle::typeck::check::method;
use middle::typeck::method_static;
use syntax::ast;
use syntax::ast::{def_id, ident, node_id, ty_param};
@ -78,14 +80,33 @@ pub fn trans_deriving_impl(ccx: @crate_ctxt,
for method_dids.each |method_did| {
let kind = DerivingKind::of_item(ccx, *method_did);
let llfn = get_item_val(ccx, method_did.node);
// Transform the self type as appropriate.
let derived_method_info =
ccx.tcx.automatically_derived_methods.get(*method_did);
let transformed_self_ty =
method::transform_self_type_for_method(
ccx.tcx,
Some(re_static),
self_ty.ty,
derived_method_info.method_info.self_type);
match ty::get(self_ty.ty).sty {
ty::ty_class(*) => {
trans_deriving_struct_method(ccx, llfn, impl_def_id,
self_ty.ty, kind);
trans_deriving_struct_method(ccx,
llfn,
impl_def_id,
self_ty.ty,
transformed_self_ty,
kind);
}
ty::ty_enum(*) => {
trans_deriving_enum_method(ccx, llfn, impl_def_id,
self_ty.ty, kind);
trans_deriving_enum_method(ccx,
llfn,
impl_def_id,
self_ty.ty,
transformed_self_ty,
kind);
}
_ => {
ccx.tcx.sess.bug(~"translation of non-struct \
@ -119,6 +140,7 @@ fn trans_deriving_struct_method(ccx: @crate_ctxt,
llfn: ValueRef,
impl_did: def_id,
self_ty: ty::t,
transformed_self_ty: ty::t,
kind: DerivingKind) {
let _icx = ccx.insn_ctxt("trans_deriving_struct_method");
let fcx = new_fn_ctxt(ccx, ~[], llfn, None);
@ -128,8 +150,10 @@ fn trans_deriving_struct_method(ccx: @crate_ctxt,
let llextraparams = get_extra_params(llfn, kind);
let llselfty = type_of(ccx, self_ty);
let llselfval = PointerCast(bcx, fcx.llenv, T_ptr(llselfty));
let lltransformedselfty = type_of(ccx, transformed_self_ty);
let lltransformedselfval =
PointerCast(bcx, fcx.llenv, T_ptr(lltransformedselfty));
let llselfval = Load(bcx, lltransformedselfval);
// If there is an "other" value, then get it. The "other" value is the
// value we're comparing against in the case of Eq and Ord.
@ -155,6 +179,9 @@ fn trans_deriving_struct_method(ccx: @crate_ctxt,
for ccx.tcx.deriving_struct_methods.get(impl_did).eachi
|i, derived_method_info| {
let llselfval = GEPi(bcx, llselfval, [0, 0, i]);
let llselfallocaty = common::val_ty(llselfval);
let llselfalloca = base::alloca(bcx, llselfallocaty);
Store(bcx, llselfval, llselfalloca);
let llotherval_opt = llotherval_opt.map(
|llotherval| GEPi(bcx, *llotherval, [0, 0, i]));
@ -163,7 +190,7 @@ fn trans_deriving_struct_method(ccx: @crate_ctxt,
bcx = call_substructure_method(bcx,
derived_method_info,
self_ty,
llselfval,
llselfalloca,
llotherval_opt,
llextraparams);
@ -197,6 +224,7 @@ fn trans_deriving_enum_method(ccx: @crate_ctxt,
llfn: ValueRef,
impl_did: def_id,
self_ty: ty::t,
transformed_self_ty: ty::t,
kind: DerivingKind) {
let _icx = ccx.insn_ctxt("trans_deriving_enum_method");
let fcx = new_fn_ctxt(ccx, ~[], llfn, None);
@ -206,8 +234,10 @@ fn trans_deriving_enum_method(ccx: @crate_ctxt,
let llextraparams = get_extra_params(llfn, kind);
let llselfty = type_of(ccx, self_ty);
let llselfval = PointerCast(bcx, fcx.llenv, T_ptr(llselfty));
let lltransformedselfty = type_of(ccx, transformed_self_ty);
let lltransformedselfval =
PointerCast(bcx, fcx.llenv, T_ptr(lltransformedselfty));
let llselfval = Load(bcx, lltransformedselfval);
let llotherval_opt;
match kind {
@ -280,6 +310,9 @@ fn trans_deriving_enum_method(ccx: @crate_ctxt,
enum_variant_infos[self_variant_index].id;
let llselfval = GEP_enum(match_bcx, llselfpayload, enum_id,
variant_def_id, enum_substs.tps, i);
let llselfallocaty = common::val_ty(llselfval);
let llselfalloca = base::alloca(match_bcx, llselfallocaty);
Store(match_bcx, llselfval, llselfalloca);
let llotherval_opt = llotherpayload_opt.map(|llotherpayload|
GEP_enum(match_bcx, *llotherpayload, enum_id,
@ -289,7 +322,7 @@ fn trans_deriving_enum_method(ccx: @crate_ctxt,
match_bcx = call_substructure_method(match_bcx,
derived_method_info,
self_ty,
llselfval,
llselfalloca,
llotherval_opt,
llextraparams);

View File

@ -63,6 +63,7 @@ use std::list;
use list::{List, Nil, Cons};
use dvec::DVec;
export check;
export check_crate;
export infer;
export method_map;

View File

@ -17,8 +17,8 @@ use syntax::print::pprust;
use syntax::visit::{default_simple_visitor, mk_simple_visitor, visit_crate};
use middle::resolve::{Impl, MethodInfo};
use middle::ty;
use middle::ty::{DerivedFieldInfo, substs, ty_class, ty_enum};
use middle::ty::{ty_param_bounds_and_ty};
use middle::ty::{DerivedFieldInfo, ReVar, re_infer, re_static, substs};
use middle::ty::{ty_class, ty_enum, ty_param_bounds_and_ty};
use /*middle::typeck::*/check::method;
use /*middle::typeck::*/check::vtable;
use /*middle::typeck::*/infer::infer_ctxt;
@ -56,10 +56,12 @@ impl DerivingChecker {
let tcx = self.crate_context.tcx;
let impl_self_tpbt = ty::lookup_item_type(tcx, impl_info.did);
let transformed_type = method::transform_self_type_for_method(
tcx, None, impl_self_tpbt.ty, method_info.self_type);
let inference_context = infer::new_infer_ctxt(self.crate_context.tcx);
let region = inference_context.next_region_var_nb(span);
let transformed_type = method::transform_self_type_for_method(
tcx, Some(region), impl_self_tpbt.ty, method_info.self_type);
let substs = {
self_r: None,
self_ty: None,
@ -68,6 +70,13 @@ impl DerivingChecker {
let transformed_type = ty::subst(
self.crate_context.tcx, &substs, transformed_type);
// Automatically reference the substructure type.
let region = inference_context.next_region_var_nb(span);
let substructure_type = ty::mk_rptr(
self.crate_context.tcx,
region,
{ ty: substructure_type, mutbl: ast::m_imm });
debug!("(matching impl method) substructure type %s, transformed \
type %s, subst tps %u",
ppaux::ty_to_str(self.crate_context.tcx, substructure_type),

View File

@ -95,10 +95,10 @@ mod middle {
mod ty;
#[legacy_exports]
mod resolve;
mod typeck {
pub mod typeck {
#[legacy_exports];
mod check {
#[legacy_exports];
#[legacy_exports]
pub mod check {
#[legacy_exports]
mod alt;
#[legacy_exports]
@ -112,7 +112,7 @@ mod middle {
#[legacy_exports]
mod demand;
#[legacy_exports]
mod method;
pub mod method;
}
#[legacy_exports]
mod rscope;

View File

@ -1,6 +1,6 @@
trait MyEq {
#[derivable]
pure fn eq(other: &self) -> bool;
pure fn eq(&self, other: &self) -> bool;
}
struct A {

View File

@ -1,5 +1,5 @@
trait MyEq {
pure fn eq(other: &self) -> bool;
pure fn eq(&self, other: &self) -> bool;
}
struct A {
@ -7,7 +7,7 @@ struct A {
}
impl int : MyEq {
pure fn eq(other: &int) -> bool { self == *other }
pure fn eq(&self, other: &int) -> bool { *self == *other }
}
impl A : MyEq; //~ ERROR missing method

View File

@ -1,20 +1,20 @@
trait MyEq {
#[derivable]
pure fn eq(other: &self) -> bool;
pure fn eq(&self, other: &self) -> bool;
}
impl int : MyEq {
pure fn eq(other: &int) -> bool {
self == *other
pure fn eq(&self, other: &int) -> bool {
*self == *other
}
}
impl<T:MyEq> @T : MyEq {
pure fn eq(other: &@T) -> bool {
pure fn eq(&self, other: &@T) -> bool {
unsafe {
io::println("@T");
}
(*self).eq(&**other)
(**self).eq(&**other)
}
}

View File

@ -1,7 +1,7 @@
trait MyEq {
#[derivable]
pure fn eq(other: &self) -> bool;
pure fn ne(other: &self) -> bool;
pure fn eq(&self, other: &self) -> bool;
pure fn ne(&self, other: &self) -> bool;
}
struct A {
@ -9,12 +9,12 @@ struct A {
}
impl int : MyEq {
pure fn eq(other: &int) -> bool { self == *other }
pure fn ne(other: &int) -> bool { self != *other }
pure fn eq(&self, other: &int) -> bool { *self == *other }
pure fn ne(&self, other: &int) -> bool { *self != *other }
}
impl A : MyEq {
pure fn ne(other: &A) -> bool { !self.eq(other) }
pure fn ne(&self, other: &A) -> bool { !self.eq(other) }
}
fn main() {

View File

@ -1,8 +1,8 @@
trait MyEq {
#[derivable]
pure fn eq(other: &self) -> bool;
pure fn eq(&self, other: &self) -> bool;
#[derivable]
pure fn ne(other: &self) -> bool;
pure fn ne(&self, other: &self) -> bool;
}
struct A {
@ -10,12 +10,12 @@ struct A {
}
impl int : MyEq {
pure fn eq(other: &int) -> bool { self == *other }
pure fn ne(other: &int) -> bool { self != *other }
pure fn eq(&self, other: &int) -> bool { *self == *other }
pure fn ne(&self, other: &int) -> bool { *self != *other }
}
impl A : MyEq {
pure fn ne(other: &A) -> bool { !self.eq(other) }
pure fn ne(&self, other: &A) -> bool { !self.eq(other) }
}
fn main() {

View File

@ -1,17 +1,17 @@
trait Trait {
#[derivable]
fn f(x: int, y: &str);
fn f(&self, x: int, y: &str);
}
impl int : Trait {
fn f(x: int, y: &str) {
fn f(&self, x: int, y: &str) {
assert x == 42;
assert y == "hello";
}
}
impl float : Trait {
fn f(x: int, y: &str) {
fn f(&self, x: int, y: &str) {
assert x == 42;
assert y == "hello";
}

View File

@ -1,10 +1,10 @@
trait Show {
#[derivable]
fn show();
fn show(&self);
}
impl int : Show {
fn show() {
fn show(&self) {
io::println(self.to_str());
}
}

View File

@ -1,6 +1,6 @@
trait MyEq {
#[derivable]
pure fn eq(other: &self) -> bool;
pure fn eq(&self, other: &self) -> bool;
}
struct A {
@ -14,7 +14,7 @@ struct B {
}
impl A : MyEq {
pure fn eq(other: &A) -> bool {
pure fn eq(&self, other: &A) -> bool {
unsafe { io::println(fmt!("eq %d %d", self.x, other.x)); }
self.x == other.x
}

View File

@ -1,6 +1,6 @@
trait MyEq {
#[derivable]
pure fn eq(other: &self) -> bool;
pure fn eq(&self, other: &self) -> bool;
}
struct A {
@ -14,7 +14,7 @@ enum B {
}
impl A : MyEq {
pure fn eq(other: &A) -> bool {
pure fn eq(&self, other: &A) -> bool {
unsafe { io::println("in eq"); }
self.x == other.x
}