Skip to content

Fix generic Drop impls with trait bounds. #12403

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Feb 20, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 6 additions & 34 deletions src/librustc/middle/astencode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use metadata::tydecode;
use metadata::tydecode::{DefIdSource, NominalType, TypeWithId, TypeParameter,
RegionParameter};
use metadata::tyencode;
use middle::typeck::{method_origin, method_map_entry};
use middle::typeck::method_origin;
use middle::{ty, typeck, moves};
use middle;
use util::ppaux::ty_to_str;
Expand Down Expand Up @@ -573,35 +573,7 @@ impl tr for moves::CaptureVar {
}

// ______________________________________________________________________
// Encoding and decoding of method_map_entry

trait read_method_map_entry_helper {
fn read_method_map_entry(&mut self, xcx: @ExtendedDecodeContext)
-> method_map_entry;
}

fn encode_method_map_entry(ebml_w: &mut writer::Encoder, mme: method_map_entry) {
ebml_w.emit_struct("method_map_entry", 3, |ebml_w| {
ebml_w.emit_struct_field("origin", 1u, |ebml_w| {
mme.origin.encode(ebml_w);
});
})
}

impl<'a> read_method_map_entry_helper for reader::Decoder<'a> {
fn read_method_map_entry(&mut self, xcx: @ExtendedDecodeContext)
-> method_map_entry {
self.read_struct("method_map_entry", 3, |this| {
method_map_entry {
origin: this.read_struct_field("origin", 1, |this| {
let method_origin: method_origin =
Decodable::decode(this);
method_origin.tr(xcx)
})
}
})
}
}
// Encoding and decoding of method_origin

impl tr for method_origin {
fn tr(&self, xcx: @ExtendedDecodeContext) -> method_origin {
Expand Down Expand Up @@ -1023,11 +995,11 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
{
let method_map = maps.method_map.borrow();
let r = method_map.get().find(&id);
for &mme in r.iter() {
for &origin in r.iter() {
ebml_w.tag(c::tag_table_method_map, |ebml_w| {
ebml_w.id(id);
ebml_w.tag(c::tag_table_val, |ebml_w| {
encode_method_map_entry(ebml_w, *mme)
origin.encode(ebml_w);
})
})
}
Expand Down Expand Up @@ -1364,9 +1336,9 @@ fn decode_side_tables(xcx: @ExtendedDecodeContext,
ty_param_defs.get().insert(id, bounds);
}
c::tag_table_method_map => {
let entry = val_dsr.read_method_map_entry(xcx);
let origin: method_origin = Decodable::decode(val_dsr);
let mut method_map = dcx.maps.method_map.borrow_mut();
method_map.get().insert(id, entry);
method_map.get().insert(id, origin.tr(xcx));
}
c::tag_table_vtable_map => {
let vtable_res =
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/dead.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ impl MarkSymbolVisitor {
span: codemap::Span) {
let method_map = self.method_map.borrow();
match method_map.get().find(id) {
Some(&typeck::method_map_entry { origin, .. }) => {
Some(&origin) => {
match origin {
typeck::method_static(def_id) => {
match ty::provided_source(self.tcx, def_id) {
Expand Down
11 changes: 9 additions & 2 deletions src/librustc/middle/kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,8 +285,15 @@ pub fn check_expr(cx: &mut Context, e: &Expr) {

// Even though the callee_id may have been the id with
// node_type_substs, e.id is correct here.
ty::method_call_type_param_defs(cx.tcx, cx.method_map, e.id).expect(
"non path/method call expr has type substs??")
match cx.method_map.borrow().get().find(&e.id) {
Some(origin) => {
ty::method_call_type_param_defs(cx.tcx, *origin)
}
None => {
cx.tcx.sess.span_bug(e.span,
"non path/method call expr has type substs??");
}
}
}
};
let type_param_defs = type_param_defs.borrow();
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/lint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1402,7 +1402,7 @@ fn check_stability(cx: &Context, e: &ast::Expr) {
ast::ExprMethodCall(..) => {
let method_map = cx.method_map.borrow();
match method_map.get().find(&e.id) {
Some(&typeck::method_map_entry { origin, .. }) => {
Some(&origin) => {
match origin {
typeck::method_static(def_id) => {
// If this implements a trait method, get def_id
Expand Down
12 changes: 6 additions & 6 deletions src/librustc/middle/privacy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -790,17 +790,17 @@ impl<'a> Visitor<()> for PrivacyVisitor<'a> {
let t = ty::type_autoderef(ty::expr_ty(self.tcx, args[0]));
match ty::get(t).sty {
ty::ty_enum(_, _) | ty::ty_struct(_, _) => {
let method_map = self.method_map.borrow();
let entry = match method_map.get().find(&expr.id) {
match self.method_map.borrow().get().find(&expr.id) {
None => {
self.tcx.sess.span_bug(expr.span,
"method call not in \
method map");
}
Some(entry) => entry
};
debug!("(privacy checking) checking impl method");
self.check_method(expr.span, &entry.origin, ident);
Some(origin) => {
debug!("(privacy checking) checking impl method");
self.check_method(expr.span, origin, ident);
}
}
}
_ => {}
}
Expand Down
8 changes: 2 additions & 6 deletions src/librustc/middle/reachable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,10 +149,7 @@ impl Visitor<()> for MarkSymbolVisitor {
ast::ExprMethodCall(..) => {
let method_map = self.method_map.borrow();
match method_map.get().find(&expr.id) {
Some(&typeck::method_map_entry {
origin: typeck::method_static(def_id),
..
}) => {
Some(&typeck::method_static(def_id)) => {
if is_local(def_id) {
if ReachableContext::
def_id_represents_local_inlined_item(
Expand All @@ -174,8 +171,7 @@ impl Visitor<()> for MarkSymbolVisitor {
Some(_) => {}
None => {
self.tcx.sess.span_bug(expr.span,
"method call expression \
not in method map?!")
"method call expression not in method map?!")
}
}
}
Expand Down
25 changes: 9 additions & 16 deletions src/librustc/middle/trans/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ use middle::trans::type_of;
use middle::trans::type_of::*;
use middle::trans::value::Value;
use middle::ty;
use middle::typeck;
use util::common::indenter;
use util::ppaux::{Repr, ty_to_str};
use util::sha2::Sha256;
Expand Down Expand Up @@ -535,22 +536,14 @@ pub fn get_res_dtor(ccx: @CrateContext,
};
if !substs.is_empty() {
assert_eq!(did.krate, ast::LOCAL_CRATE);
let tsubsts = ty::substs {regions: ty::ErasedRegions,
self_ty: None,
tps: /*bad*/ substs.to_owned() };

// FIXME: #4252: Generic destructors with type bounds are broken.
//
// Since the vtables aren't passed to `monomorphic_fn` here, generic destructors with type
// bounds are broken. Sadly, the `typeck` pass isn't outputting the necessary metadata
// because it does so based on method calls present in the AST. Destructor calls are not yet
// known about at that stage of compilation, since `trans` handles cleanups.
let (val, _) = monomorphize::monomorphic_fn(ccx,
did,
&tsubsts,
None,
None,
None);
let tsubsts = ty::substs {
regions: ty::ErasedRegions,
self_ty: None,
tps: substs.to_owned()
};

let vtables = typeck::check::vtable::trans_resolve_method(ccx.tcx, did.node, &tsubsts);
let (val, _) = monomorphize::monomorphic_fn(ccx, did, &tsubsts, vtables, None, None);

val
} else if did.krate == ast::LOCAL_CRATE {
Expand Down
9 changes: 4 additions & 5 deletions src/librustc/middle/trans/meth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,16 +95,15 @@ pub fn trans_method_callee<'a>(
bcx: &'a Block<'a>,
callee_id: ast::NodeId,
this: &ast::Expr,
mentry: typeck::method_map_entry,
origin: typeck::method_origin,
arg_cleanup_scope: cleanup::ScopeId)
-> Callee<'a> {
let _icx = push_ctxt("meth::trans_method_callee");

debug!("trans_method_callee(callee_id={:?}, mentry={})",
callee_id,
mentry.repr(bcx.tcx()));
debug!("trans_method_callee(callee_id={:?}, origin={})",
callee_id, origin.repr(bcx.tcx()));

match mentry.origin {
match origin {
typeck::method_static(did) => {
Callee {
bcx: bcx,
Expand Down
29 changes: 12 additions & 17 deletions src/librustc/middle/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3242,25 +3242,21 @@ pub fn expr_has_ty_params(cx: ctxt, expr: &ast::Expr) -> bool {
return node_id_has_type_params(cx, expr.id);
}

pub fn method_call_type_param_defs(tcx: ctxt,
method_map: typeck::method_map,
id: ast::NodeId)
-> Option<Rc<~[TypeParameterDef]>> {
let method_map = method_map.borrow();
method_map.get().find(&id).map(|method| {
match method.origin {
typeck::method_static(did) => {
pub fn method_call_type_param_defs(tcx: ctxt, origin: typeck::method_origin)
-> Rc<~[TypeParameterDef]> {
match origin {
typeck::method_static(did) => {
// n.b.: When we encode impl methods, the bounds
// that we encode include both the impl bounds
// and then the method bounds themselves...
ty::lookup_item_type(tcx, did).generics.type_param_defs
}
typeck::method_param(typeck::method_param {
trait_id: trt_id,
method_num: n_mth, ..}) |
typeck::method_object(typeck::method_object {
trait_id: trt_id,
method_num: n_mth, ..}) => {
}
typeck::method_param(typeck::method_param {
trait_id: trt_id,
method_num: n_mth, ..}) |
typeck::method_object(typeck::method_object {
trait_id: trt_id,
method_num: n_mth, ..}) => {
// ...trait methods bounds, in contrast, include only the
// method bounds, so we must preprend the tps from the
// trait itself. This ought to be harmonized.
Expand All @@ -3271,9 +3267,8 @@ pub fn method_call_type_param_defs(tcx: ctxt,
ty::trait_method(tcx,
trt_id,
n_mth).generics.type_param_defs()))
}
}
})
}
}

pub fn resolve_expr(tcx: ctxt, expr: &ast::Expr) -> ast::Def {
Expand Down
6 changes: 3 additions & 3 deletions src/librustc/middle/typeck/check/demand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,17 @@ use syntax::codemap::Span;

// Requires that the two types unify, and prints an error message if they
// don't.
pub fn suptype(fcx: @FnCtxt, sp: Span, expected: ty::t, actual: ty::t) {
pub fn suptype(fcx: &FnCtxt, sp: Span, expected: ty::t, actual: ty::t) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It'd be really nice to keep these in separate commits/PRs ;)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've already split this into 3 commits, I have to take it one step at a time :).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 @huonw

suptype_with_fn(fcx, sp, false, expected, actual,
|sp, e, a, s| { fcx.report_mismatched_types(sp, e, a, s) })
}

pub fn subtype(fcx: @FnCtxt, sp: Span, expected: ty::t, actual: ty::t) {
pub fn subtype(fcx: &FnCtxt, sp: Span, expected: ty::t, actual: ty::t) {
suptype_with_fn(fcx, sp, true, actual, expected,
|sp, a, e, s| { fcx.report_mismatched_types(sp, e, a, s) })
}

pub fn suptype_with_fn(fcx: @FnCtxt,
pub fn suptype_with_fn(fcx: &FnCtxt,
sp: Span,
b_is_expected: bool,
ty_a: ty::t,
Expand Down
28 changes: 13 additions & 15 deletions src/librustc/middle/typeck/check/method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ use middle::typeck::check::{structurally_resolved_type};
use middle::typeck::check::vtable;
use middle::typeck::check;
use middle::typeck::infer;
use middle::typeck::{method_map_entry, method_origin, method_param};
use middle::typeck::{method_origin, method_param};
use middle::typeck::{method_static, method_object};
use middle::typeck::{param_numbered, param_self, param_index};
use middle::typeck::check::regionmanip::replace_bound_regions_in_fn_sig;
Expand Down Expand Up @@ -133,7 +133,7 @@ pub fn lookup(
deref_args: check::DerefArgs, // Whether we autopointer first.
check_traits: CheckTraitsFlag, // Whether we check traits only.
autoderef_receiver: AutoderefReceiverFlag)
-> Option<method_map_entry> {
-> Option<method_origin> {
let impl_dups = @RefCell::new(HashSet::new());
let lcx = LookupContext {
fcx: fcx,
Expand Down Expand Up @@ -211,7 +211,7 @@ enum RcvrMatchCondition {
}

impl<'a> LookupContext<'a> {
fn search(&self, self_ty: ty::t) -> Option<method_map_entry> {
fn search(&self, self_ty: ty::t) -> Option<method_origin> {
let mut self_ty = self_ty;
let mut autoderefs = 0;
loop {
Expand Down Expand Up @@ -592,7 +592,7 @@ impl<'a> LookupContext<'a> {
fn search_for_autoderefd_method(&self,
self_ty: ty::t,
autoderefs: uint)
-> Option<method_map_entry> {
-> Option<method_origin> {
let (self_ty, autoadjust) =
self.consider_reborrow(self_ty, autoderefs);
match self.search_for_method(self_ty) {
Expand Down Expand Up @@ -686,9 +686,9 @@ impl<'a> LookupContext<'a> {
}

fn search_for_autosliced_method(&self,
self_ty: ty::t,
autoderefs: uint)
-> Option<method_map_entry> {
self_ty: ty::t,
autoderefs: uint)
-> Option<method_origin> {
/*!
*
* Searches for a candidate by converting things like
Expand Down Expand Up @@ -763,7 +763,7 @@ impl<'a> LookupContext<'a> {
}

fn search_for_autoptrd_method(&self, self_ty: ty::t, autoderefs: uint)
-> Option<method_map_entry> {
-> Option<method_origin> {
/*!
*
* Converts any type `T` to `&M T` where `M` is an
Expand Down Expand Up @@ -799,7 +799,7 @@ impl<'a> LookupContext<'a> {
autoderefs: uint,
mutbls: &[ast::Mutability],
mk_autoref_ty: |ast::Mutability, ty::Region| -> ty::t)
-> Option<method_map_entry> {
-> Option<method_origin> {
// This is hokey. We should have mutability inference as a
// variable. But for now, try &const, then &, then &mut:
let region =
Expand All @@ -823,7 +823,7 @@ impl<'a> LookupContext<'a> {
}

fn search_for_method(&self, rcvr_ty: ty::t)
-> Option<method_map_entry> {
-> Option<method_origin> {
debug!("search_for_method(rcvr_ty={})", self.ty_to_str(rcvr_ty));
let _indenter = indenter();

Expand Down Expand Up @@ -855,7 +855,7 @@ impl<'a> LookupContext<'a> {
fn consider_candidates(&self,
rcvr_ty: ty::t,
candidates: &mut ~[Candidate])
-> Option<method_map_entry> {
-> Option<method_origin> {
// FIXME(pcwalton): Do we need to clone here?
let relevant_candidates: ~[Candidate] =
candidates.iter().map(|c| (*c).clone()).
Expand Down Expand Up @@ -926,7 +926,7 @@ impl<'a> LookupContext<'a> {
}

fn confirm_candidate(&self, rcvr_ty: ty::t, candidate: &Candidate)
-> method_map_entry {
-> method_origin {
// This method performs two sets of substitutions, one after the other:
// 1. Substitute values for any type/lifetime parameters from the impl and
// method declaration into the method type. This is the function type
Expand Down Expand Up @@ -1037,9 +1037,7 @@ impl<'a> LookupContext<'a> {

self.fcx.write_ty(self.callee_id, fty);
self.fcx.write_substs(self.callee_id, all_substs);
method_map_entry {
origin: candidate.origin
}
candidate.origin
}

fn construct_transformed_self_ty_for_object(
Expand Down
Loading