mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-19 18:34:08 +00:00
librustc: Implement (and require) explicit self for derivable traits. r=nmatsakis
This commit is contained in:
parent
29e10c91fe
commit
adc4bed773
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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),
|
||||
|
@ -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;
|
||||
|
@ -1,6 +1,6 @@
|
||||
trait MyEq {
|
||||
#[derivable]
|
||||
pure fn eq(other: &self) -> bool;
|
||||
pure fn eq(&self, other: &self) -> bool;
|
||||
}
|
||||
|
||||
struct A {
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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() {
|
||||
|
@ -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() {
|
||||
|
@ -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";
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user