pub const tag_misc_info: usize = 0x108; // top-level only
pub const tag_misc_info_crate_items: usize = 0x7c;
-pub const tag_item_method_provided_source: usize = 0x7d;
+// GAP 0x7d
pub const tag_item_impl_vtables: usize = 0x7e;
pub const tag_impls: usize = 0x109; // top-level only
translated_def_id(cdata, reader::get_doc(d, tag_def_id))
}
-fn get_provided_source(d: rbml::Doc, cdata: Cmd) -> Option<DefId> {
- reader::maybe_get_doc(d, tag_item_method_provided_source).map(|doc| {
- translated_def_id(cdata, doc)
- })
-}
-
fn reexports<'a>(d: rbml::Doc<'a>) -> reader::TaggedDocsIterator<'a> {
reader::tagged_docs(d, tag_items_data_item_reexport)
}
match fam {
Constant => {
// Check whether we have an associated const item.
- if item_sort(item) == Some('C') {
- DlDef(def::DefAssociatedConst(did))
- } else {
- // Regular const item.
- DlDef(def::DefConst(did))
+ match item_sort(item) {
+ Some('C') | Some('c') => {
+ DlDef(def::DefAssociatedConst(did))
+ }
+ _ => {
+ // Regular const item.
+ DlDef(def::DefConst(did))
+ }
}
}
ImmStatic => DlDef(def::DefStatic(did, false)),
reader::tagged_docs(cdata.lookup_item(impl_id), tag_item_impl_item).map(|doc| {
let def_id = item_def_id(doc, cdata);
match item_sort(doc) {
- Some('C') => ty::ConstTraitItemId(def_id),
+ Some('C') | Some('c') => ty::ConstTraitItemId(def_id),
Some('r') | Some('p') => ty::MethodTraitItemId(def_id),
Some('t') => ty::TypeTraitItemId(def_id),
_ => panic!("unknown impl item sort"),
let vis = item_visibility(item_doc);
match item_sort(item_doc) {
- Some('C') => {
+ sort @ Some('C') | sort @ Some('c') => {
let ty = doc_type(item_doc, tcx, cdata);
- let default = get_provided_source(item_doc, cdata);
ty::ConstTraitItem(Rc::new(ty::AssociatedConst {
name: name,
ty: ty,
vis: vis,
def_id: def_id,
container: container,
- default: default,
+ has_value: sort == Some('C')
}))
}
Some('r') | Some('p') => {
let predicates = doc_predicates(item_doc, tcx, cdata, tag_method_ty_generics);
let fty = doc_method_fty(item_doc, tcx, cdata);
let explicit_self = get_explicit_self(item_doc);
- let provided_source = get_provided_source(item_doc, cdata);
ty::MethodTraitItem(Rc::new(ty::Method::new(name,
generics,
explicit_self,
vis,
def_id,
- container,
- provided_source)))
+ container)))
}
Some('t') => {
let ty = maybe_doc_type(item_doc, tcx, cdata);
reader::tagged_docs(item, tag_item_trait_item).map(|mth| {
let def_id = item_def_id(mth, cdata);
match item_sort(mth) {
- Some('C') => ty::ConstTraitItemId(def_id),
+ Some('C') | Some('c') => ty::ConstTraitItemId(def_id),
Some('r') | Some('p') => ty::MethodTraitItemId(def_id),
Some('t') => ty::TypeTraitItemId(def_id),
_ => panic!("unknown trait item sort"),
let did = item_def_id(ac_id, cdata);
let ac_doc = cdata.lookup_item(did.node);
- if item_sort(ac_doc) == Some('C') {
- let trait_item = get_impl_or_trait_item(intr.clone(),
- cdata,
- did.node,
- tcx);
- if let ty::ConstTraitItem(ref ac) = trait_item {
- Some((*ac).clone())
- } else {
- None
+ match item_sort(ac_doc) {
+ Some('C') | Some('c') => {
+ let trait_item = get_impl_or_trait_item(intr.clone(),
+ cdata,
+ did.node,
+ tcx);
+ if let ty::ConstTraitItem(ref ac) = trait_item {
+ Some((*ac).clone())
+ } else {
+ None
+ }
}
- } else {
- None
+ _ => None
}
})
}).collect()
rbml_w.wr_tagged_u8(tag_item_trait_parent_sort, sort as u8);
}
-fn encode_provided_source(rbml_w: &mut Encoder,
- source_opt: Option<DefId>) {
- if let Some(source) = source_opt {
- rbml_w.wr_tagged_u64(tag_item_method_provided_source, def_to_u64(source));
- }
-}
-
fn encode_field<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
rbml_w: &mut Encoder,
field: ty::FieldDef<'tcx>,
}
_ => encode_family(rbml_w, METHOD_FAMILY)
}
- encode_provided_source(rbml_w, method_ty.provided_source);
}
fn encode_info_for_associated_const(ecx: &EncodeContext,
encode_name(rbml_w, associated_const.name);
encode_visibility(rbml_w, associated_const.vis);
encode_family(rbml_w, 'C');
- encode_provided_source(rbml_w, associated_const.default);
encode_parent_item(rbml_w, DefId::local(parent_id));
encode_item_sort(rbml_w, 'C');
encode_def_id(rbml_w, associated_const.def_id);
encode_visibility(rbml_w, associated_const.vis);
- encode_provided_source(rbml_w, associated_const.default);
-
let elem = ast_map::PathName(associated_const.name);
encode_path(rbml_w,
path.clone().chain(Some(elem)));
- encode_item_sort(rbml_w, 'C');
encode_family(rbml_w, 'C');
encode_bounds_and_type_for_item(rbml_w, ecx,
let trait_item = &*ms[i];
encode_attributes(rbml_w, &trait_item.attrs);
match trait_item.node {
- hir::ConstTraitItem(_, _) => {
+ hir::ConstTraitItem(_, ref default) => {
+ if default.is_some() {
+ encode_item_sort(rbml_w, 'C');
+ } else {
+ encode_item_sort(rbml_w, 'c');
+ }
+
encode_inlined_item(ecx, rbml_w,
InlinedItemRef::TraitItem(def_id, trait_item));
}
pub ty_param_defs: RefCell<NodeMap<ty::TypeParameterDef<'tcx>>>,
pub normalized_cache: RefCell<FnvHashMap<Ty<'tcx>, Ty<'tcx>>>,
pub lang_items: middle::lang_items::LanguageItems,
- /// A mapping of fake provided method def_ids to the default implementation
- pub provided_method_sources: RefCell<DefIdMap<DefId>>,
/// Maps from def-id of a type or region parameter to its
/// (inferred) variance.
ty_param_defs: RefCell::new(NodeMap()),
normalized_cache: RefCell::new(FnvHashMap()),
lang_items: lang_items,
- provided_method_sources: RefCell::new(DefIdMap()),
inherent_impls: RefCell::new(DefIdMap()),
impl_items: RefCell::new(DefIdMap()),
used_unsafe: RefCell::new(NodeSet()),
pub vis: hir::Visibility,
pub def_id: DefId,
pub container: ImplOrTraitItemContainer,
-
- // If this method is provided, we need to know where it came from
- pub provided_source: Option<DefId>
}
impl<'tcx> Method<'tcx> {
explicit_self: ExplicitSelfCategory,
vis: hir::Visibility,
def_id: DefId,
- container: ImplOrTraitItemContainer,
- provided_source: Option<DefId>)
+ container: ImplOrTraitItemContainer)
-> Method<'tcx> {
Method {
name: name,
vis: vis,
def_id: def_id,
container: container,
- provided_source: provided_source
}
}
pub vis: hir::Visibility,
pub def_id: DefId,
pub container: ImplOrTraitItemContainer,
- pub default: Option<DefId>,
+ pub has_value: bool
}
#[derive(Clone, Copy, Debug)]
}
}
- pub fn provided_source(&self, id: DefId) -> Option<DefId> {
- self.provided_method_sources.borrow().get(&id).cloned()
- }
-
pub fn provided_trait_methods(&self, id: DefId) -> Vec<Rc<Method<'tcx>>> {
if id.is_local() {
if let ItemTrait(_, _, _, ref ms) = self.map.expect_item(id.node).node {
// the map. This is a bit unfortunate.
for impl_item_def_id in &impl_items {
let method_def_id = impl_item_def_id.def_id();
- match self.impl_or_trait_item(method_def_id) {
- MethodTraitItem(method) => {
- if let Some(source) = method.provided_source {
- self.provided_method_sources
- .borrow_mut()
- .insert(method_def_id, source);
- }
- }
- _ => {}
- }
+ // load impl items eagerly for convenience
+ // FIXME: we may want to load these lazily
+ self.impl_or_trait_item(method_def_id);
}
// Store the implementation info.
use middle::const_eval::{self, ConstVal, ErrKind};
use middle::const_eval::EvalHint::UncheckedExprHint;
use middle::def_id::DefId;
-use middle::subst;
+use middle::subst::{self, Subst, Substs};
use middle::infer;
use middle::pat_util;
use middle::traits;
use std::cmp;
use std::hash::{Hash, SipHasher, Hasher};
+use std::rc::Rc;
use syntax::ast::{self, Name};
use syntax::attr::{self, AttrMetaMethods, SignedInt, UnsignedInt};
use syntax::codemap::Span;
}
}
+#[derive(Debug)]
+pub struct ImplMethod<'tcx> {
+ pub method: Rc<ty::Method<'tcx>>,
+ pub substs: Substs<'tcx>,
+ pub is_provided: bool
+}
+
+impl<'tcx> ty::ctxt<'tcx> {
+ #[inline(never)] // is this perfy enough?
+ pub fn get_impl_method(&self,
+ impl_def_id: DefId,
+ substs: Substs<'tcx>,
+ name: Name)
+ -> ImplMethod<'tcx>
+ {
+ // there don't seem to be nicer accessors to these:
+ let impl_or_trait_items_map = self.impl_or_trait_items.borrow();
+
+ for impl_item in &self.impl_items.borrow()[&impl_def_id] {
+ if let ty::MethodTraitItem(ref meth) =
+ impl_or_trait_items_map[&impl_item.def_id()] {
+ if meth.name == name {
+ return ImplMethod {
+ method: meth.clone(),
+ substs: substs,
+ is_provided: false
+ }
+ }
+ }
+ }
+
+ // It is not in the impl - get the default from the trait.
+ let trait_ref = self.impl_trait_ref(impl_def_id).unwrap();
+ for trait_item in self.trait_items(trait_ref.def_id).iter() {
+ if let &ty::MethodTraitItem(ref meth) = trait_item {
+ if meth.name == name {
+ let impl_to_trait_substs = self
+ .make_substs_for_receiver_types(&trait_ref, meth);
+ return ImplMethod {
+ method: meth.clone(),
+ substs: impl_to_trait_substs.subst(self, &substs),
+ is_provided: true
+ }
+ }
+ }
+ }
+
+ self.sess.bug(&format!("method {:?} not found in {:?}",
+ name, impl_def_id))
+ }
+}
+
impl<'tcx> ty::TyS<'tcx> {
fn impls_bound<'a>(&'tcx self, param_env: &ParameterEnvironment<'a,'tcx>,
bound: ty::BuiltinBound,
span: Span,
method_id: DefId,
name: ast::Name) {
- // If the method is a default method, we need to use the def_id of
- // the default implementation.
- let method_id = match self.tcx.impl_or_trait_item(method_id) {
- ty::MethodTraitItem(method_type) => {
- method_type.provided_source.unwrap_or(method_id)
- }
- _ => {
- self.tcx.sess
- .span_bug(span,
- "got non-method item in check_static_method")
- }
- };
-
self.report_error(self.ensure_public(span,
method_id,
None,
use middle::def_id::{DefId, LOCAL_CRATE};
use middle::infer::normalize_associated_type;
use middle::subst;
-use middle::subst::{Subst, Substs};
+use middle::subst::{Substs};
use rustc::front::map as hir_map;
use trans::adt;
use trans::base;
assert!(!substs.types.has_escaping_regions());
let substs = substs.erase_regions();
- // Load the info for the appropriate trait if necessary.
- match tcx.trait_of_item(def_id) {
- None => {}
- Some(trait_id) => {
- tcx.populate_implementations_for_trait_if_necessary(trait_id)
- }
- }
-
- // We need to do a bunch of special handling for default methods.
- // We need to modify the def_id and our substs in order to monomorphize
- // the function.
- let (is_default, def_id, substs) = match tcx.provided_source(def_id) {
- None => {
- (false, def_id, tcx.mk_substs(substs))
- }
- Some(source_id) => {
- // There are two relevant substitutions when compiling
- // default methods. First, there is the substitution for
- // the type parameters of the impl we are using and the
- // method we are calling. This substitution is the substs
- // argument we already have.
- // In order to compile a default method, though, we need
- // to consider another substitution: the substitution for
- // the type parameters on trait; the impl we are using
- // implements the trait at some particular type
- // parameters, and we need to substitute for those first.
- // So, what we need to do is find this substitution and
- // compose it with the one we already have.
-
- let impl_id = tcx.impl_or_trait_item(def_id).container()
- .id();
- let impl_or_trait_item = tcx.impl_or_trait_item(source_id);
- match impl_or_trait_item {
- ty::MethodTraitItem(method) => {
- let trait_ref = tcx.impl_trait_ref(impl_id).unwrap();
-
- // Compute the first substitution
- let first_subst =
- tcx.make_substs_for_receiver_types(&trait_ref, &*method)
- .erase_regions();
-
- // And compose them
- let new_substs = tcx.mk_substs(first_subst.subst(tcx, &substs));
-
- debug!("trans_fn_with_vtables - default method: \
- substs = {:?}, trait_subst = {:?}, \
- first_subst = {:?}, new_subst = {:?}",
- substs, trait_ref.substs,
- first_subst, new_substs);
-
- (true, source_id, new_substs)
- }
- _ => {
- tcx.sess.bug("trans_fn_ref_with_vtables() tried \
- to translate a non-method?!")
- }
- }
- }
- };
-
// Check whether this fn has an inlined copy and, if so, redirect
// def_id to the local id of the inlined copy.
let def_id = inline::maybe_instantiate_inline(ccx, def_id);
- // We must monomorphise if the fn has type parameters, is a default method,
- // or is a named tuple constructor.
- let must_monomorphise = if !substs.types.is_empty() || is_default {
- true
- } else if def_id.is_local() {
+ fn is_named_tuple_constructor(tcx: &ty::ctxt, def_id: DefId) -> bool {
+ if !def_id.is_local() { return false; }
let map_node = session::expect(
- ccx.sess(),
+ &tcx.sess,
tcx.map.find(def_id.node),
|| "local item should be in ast map".to_string());
hir_map::NodeStructCtor(_) => true,
_ => false
}
- } else {
- false
- };
+ }
+ let must_monomorphise =
+ !substs.types.is_empty() || is_named_tuple_constructor(tcx, def_id);
debug!("trans_fn_ref_with_substs({:?}) must_monomorphise: {}",
def_id, must_monomorphise);
MethodCallKey(_) => None,
};
+ let substs = tcx.mk_substs(substs);
let (val, fn_ty, must_cast) =
monomorphize::monomorphic_fn(ccx, def_id, substs, opt_ref_id);
if must_cast && node != ExprId(0) {
let llty = type_of::type_of_fn_from_ty(ccx, fn_type);
let llptrty = llty.ptr_to();
if common::val_ty(val) != llptrty {
- debug!("trans_fn_ref_with_vtables(): casting pointer!");
+ debug!("trans_fn_ref_with_substs(): casting pointer!");
val = consts::ptrcast(val, llptrty);
} else {
- debug!("trans_fn_ref_with_vtables(): not casting pointer!");
+ debug!("trans_fn_ref_with_substs(): not casting pointer!");
}
Datum::new(val, fn_type, Rvalue::new(ByValue))
impl_self,
rcvr_method));
- let mth_id = method_with_name(ccx, impl_did, mname);
- trans_fn_ref_with_substs(ccx, mth_id, ExprId(expr_id),
+ let mth = tcx.get_impl_method(impl_did, callee_substs, mname);
+ trans_fn_ref_with_substs(ccx, mth.method.def_id, ExprId(expr_id),
param_substs,
- callee_substs)
+ mth.substs)
}
traits::VtableObject(ref data) => {
let idx = traits::get_vtable_index_of_object_method(tcx, data, method_id);
}
}
-fn method_with_name(ccx: &CrateContext, impl_id: DefId, name: ast::Name)
- -> DefId {
- match ccx.impl_method_cache().borrow().get(&(impl_id, name)).cloned() {
- Some(m) => return m,
- None => {}
- }
-
- let impl_items = ccx.tcx().impl_items.borrow();
- let impl_items =
- impl_items.get(&impl_id)
- .expect("could not find impl while translating");
- let meth_did = impl_items.iter()
- .find(|&did| {
- ccx.tcx().impl_or_trait_item(did.def_id()).name() == name
- }).expect("could not find method while \
- translating");
-
- ccx.impl_method_cache().borrow_mut().insert((impl_id, name),
- meth_did.def_id());
- meth_did.def_id()
-}
-
fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
method_call: MethodCall,
self_expr: Option<&hir::Expr>,
item")
}
};
- let mth_id = method_with_name(bcx.ccx(), impl_did, mname);
-
// create a concatenated set of substitutions which includes
// those from the impl and those from the method:
let callee_substs =
combine_impl_and_methods_tps(
bcx, MethodCallKey(method_call), vtable_impl.substs);
+ let mth = bcx.tcx().get_impl_method(impl_did, callee_substs, mname);
// translate the function
let datum = trans_fn_ref_with_substs(bcx.ccx(),
- mth_id,
+ mth.method.def_id,
MethodCallKey(method_call),
bcx.fcx.param_substs,
- callee_substs);
+ mth.substs);
Callee { bcx: bcx, data: Fn(datum.val), ty: datum.ty }
}
// The substitutions we have are on the impl, so we grab
// the method type from the impl to substitute into.
- let impl_method_def_id = method_with_name(ccx, impl_id, name);
- let impl_method_type = match tcx.impl_or_trait_item(impl_method_def_id) {
- ty::MethodTraitItem(m) => m,
- _ => ccx.sess().bug("should be a method, not other assoc item"),
- };
+ let mth = tcx.get_impl_method(impl_id, substs.clone(), name);
- debug!("emit_vtable_methods: impl_method_type={:?}",
- impl_method_type);
+ debug!("emit_vtable_methods: mth={:?}", mth);
// If this is a default method, it's possible that it
// relies on where clauses that do not hold for this
// particular set of type parameters. Note that this
// method could then never be called, so we do not want to
// try and trans it, in that case. Issue #23435.
- if tcx.provided_source(impl_method_def_id).is_some() {
- let predicates = impl_method_type.predicates.predicates.subst(tcx, &substs);
+ if mth.is_provided {
+ let predicates = mth.method.predicates.predicates.subst(tcx, &mth.substs);
if !normalize_and_test_predicates(ccx, predicates.into_vec()) {
debug!("emit_vtable_methods: predicates do not hold");
return nullptr;
}
trans_fn_ref_with_substs(ccx,
- impl_method_def_id,
+ mth.method.def_id,
ExprId(0),
param_substs,
- substs.clone()).val
+ mth.substs).val
})
.collect()
}
CandidateSource::ImplSource(impl_did) => {
// Provide the best span we can. Use the item, if local to crate, else
// the impl, if local to crate (item may be defaulted), else the call site.
- let item = impl_item(fcx.tcx(), impl_did, item_name).unwrap();
+ let item = impl_item(fcx.tcx(), impl_did, item_name)
+ .or_else(|| {
+ trait_item(
+ fcx.tcx(),
+ fcx.tcx().impl_trait_ref(impl_did).unwrap().def_id,
+ item_name
+ )
+ }).unwrap();
let impl_span = fcx.tcx().map.def_id_span(impl_did, span);
let item_span = fcx.tcx().map.def_id_span(item.def_id(), impl_span);
// Check for missing items from trait
let provided_methods = tcx.provided_trait_methods(impl_trait_ref.def_id);
- let associated_consts = tcx.associated_consts(impl_trait_ref.def_id);
let mut missing_items = Vec::new();
let mut invalidated_items = Vec::new();
let associated_type_overridden = overridden_associated_type.is_some();
_ => false,
}
});
- let is_provided =
- associated_consts.iter().any(|ac| ac.default.is_some() &&
- ac.name == associated_const.name);
+ let is_provided = associated_const.has_value;
+
if !is_implemented {
if !is_provided {
missing_items.push(associated_const.name);
use middle::traits;
use middle::ty;
use middle::ty::RegionEscape;
-use middle::ty::{ImplContainer, ImplOrTraitItemId, ConstTraitItemId};
+use middle::ty::{ImplOrTraitItemId, ConstTraitItemId};
use middle::ty::{MethodTraitItemId, TypeTraitItemId, ParameterEnvironment};
use middle::ty::{Ty, TyBool, TyChar, TyEnum, TyError};
-use middle::ty::{TyParam, TypeScheme, TyRawPtr};
+use middle::ty::{TyParam, TyRawPtr};
use middle::ty::{TyRef, TyStruct, TyTrait, TyTuple};
use middle::ty::{TyStr, TyArray, TySlice, TyFloat, TyInfer, TyInt};
use middle::ty::{TyUint, TyClosure, TyBox, TyBareFn};
tcx.impl_items.borrow_mut().insert(impl_did, impl_items);
}
- // Creates default method IDs and performs type substitutions for an impl
- // and trait pair. Then, for each provided method in the trait, inserts a
- // `ProvidedMethodInfo` instance into the `provided_method_sources` map.
- fn instantiate_default_methods(
- &self,
- impl_id: DefId,
- trait_ref: &ty::TraitRef<'tcx>,
- all_impl_items: &mut Vec<ImplOrTraitItemId>) {
- let tcx = self.crate_context.tcx;
- debug!("instantiate_default_methods(impl_id={:?}, trait_ref={:?})",
- impl_id, trait_ref);
-
- let impl_type_scheme = tcx.lookup_item_type(impl_id);
-
- let prov = tcx.provided_trait_methods(trait_ref.def_id);
- for trait_method in &prov {
- // Synthesize an ID.
- let new_id = tcx.sess.next_node_id();
- let new_did = DefId::local(new_id);
-
- debug!("new_did={:?} trait_method={:?}", new_did, trait_method);
-
- // Create substitutions for the various trait parameters.
- let new_method_ty =
- Rc::new(subst_receiver_types_in_method_ty(
- tcx,
- impl_id,
- &impl_type_scheme,
- trait_ref,
- new_did,
- &**trait_method,
- Some(trait_method.def_id)));
-
- debug!("new_method_ty={:?}", new_method_ty);
- all_impl_items.push(MethodTraitItemId(new_did));
-
- // construct the polytype for the method based on the
- // method_ty. it will have all the generics from the
- // impl, plus its own.
- let new_polytype = ty::TypeScheme {
- generics: new_method_ty.generics.clone(),
- ty: tcx.mk_fn(Some(new_did),
- tcx.mk_bare_fn(new_method_ty.fty.clone()))
- };
- debug!("new_polytype={:?}", new_polytype);
-
- tcx.register_item_type(new_did, new_polytype);
- tcx.predicates.borrow_mut().insert(new_did, new_method_ty.predicates.clone());
- tcx.impl_or_trait_items
- .borrow_mut()
- .insert(new_did, ty::MethodTraitItem(new_method_ty));
-
- // Pair the new synthesized ID up with the
- // ID of the method.
- self.crate_context.tcx.provided_method_sources.borrow_mut()
- .insert(new_did, trait_method.def_id);
- }
- }
-
fn add_inherent_impl(&self, base_def_id: DefId, impl_def_id: DefId) {
match self.inherent_impls.borrow().get(&base_def_id) {
Some(implementation_list) => {
fn create_impl_from_item(&self, item: &Item) -> Vec<ImplOrTraitItemId> {
match item.node {
ItemImpl(_, _, _, _, _, ref impl_items) => {
- let mut items: Vec<ImplOrTraitItemId> =
- impl_items.iter().map(|impl_item| {
+ impl_items.iter().map(|impl_item| {
match impl_item.node {
hir::ConstImplItem(..) => {
ConstTraitItemId(DefId::local(impl_item.id))
TypeTraitItemId(DefId::local(impl_item.id))
}
}
- }).collect();
-
- let def_id = DefId::local(item.id);
- if let Some(trait_ref) = self.crate_context.tcx.impl_trait_ref(def_id) {
- self.instantiate_default_methods(def_id, &trait_ref, &mut items);
- }
-
- items
+ }).collect()
}
_ => {
self.crate_context.tcx.sess.span_bug(item.span,
"add `#![feature(unboxed_closures)]` to the crate attributes to enable");
}
-fn subst_receiver_types_in_method_ty<'tcx>(tcx: &ty::ctxt<'tcx>,
- impl_id: DefId,
- impl_type_scheme: &ty::TypeScheme<'tcx>,
- trait_ref: &ty::TraitRef<'tcx>,
- new_def_id: DefId,
- method: &ty::Method<'tcx>,
- provided_source: Option<DefId>)
- -> ty::Method<'tcx>
-{
- let combined_substs = tcx.make_substs_for_receiver_types(trait_ref, method);
-
- debug!("subst_receiver_types_in_method_ty: combined_substs={:?}",
- combined_substs);
-
- let method_predicates = method.predicates.subst(tcx, &combined_substs);
- let mut method_generics = method.generics.subst(tcx, &combined_substs);
-
- // replace the type parameters declared on the trait with those
- // from the impl
- for &space in &[subst::TypeSpace, subst::SelfSpace] {
- method_generics.types.replace(
- space,
- impl_type_scheme.generics.types.get_slice(space).to_vec());
- method_generics.regions.replace(
- space,
- impl_type_scheme.generics.regions.get_slice(space).to_vec());
- }
-
- debug!("subst_receiver_types_in_method_ty: method_generics={:?}",
- method_generics);
-
- let method_fty = method.fty.subst(tcx, &combined_substs);
-
- debug!("subst_receiver_types_in_method_ty: method_ty={:?}",
- method.fty);
-
- ty::Method::new(
- method.name,
- method_generics,
- method_predicates,
- method_fty,
- method.explicit_self,
- method.vis,
- new_def_id,
- ImplContainer(impl_id),
- provided_source
- )
-}
-
pub fn check_coherence(crate_context: &CrateCtxt) {
CoherenceChecker {
crate_context: crate_context,
explicit_self_category,
vis,
def_id,
- container,
- None);
+ container);
let fty = ccx.tcx.mk_fn(Some(def_id),
ccx.tcx.mk_bare_fn(ty_method.fty.clone()));
id: ast::NodeId,
vis: hir::Visibility,
ty: ty::Ty<'tcx>,
- default: Option<&hir::Expr>)
+ has_value: bool)
{
ccx.tcx.predicates.borrow_mut().insert(DefId::local(id),
ty::GenericPredicates::empty());
write_ty_to_tcx(ccx.tcx, id, ty);
- let default_id = default.map(|expr| DefId::local(expr.id));
let associated_const = Rc::new(ty::AssociatedConst {
name: name,
def_id: DefId::local(id),
container: container,
ty: ty,
- default: default_id,
+ has_value: has_value
});
ccx.tcx.impl_or_trait_items.borrow_mut()
.insert(DefId::local(id), ty::ConstTraitItem(associated_const));
span_err!(tcx.sess, impl_item.span, E0201, "duplicate {}", desc);
}
- if let hir::ConstImplItem(ref ty, ref expr) = impl_item.node {
+ if let hir::ConstImplItem(ref ty, _) = impl_item.node {
let ty = ccx.icx(&ty_predicates)
.to_ty(&ExplicitRscope, &*ty);
tcx.register_item_type(DefId::local(impl_item.id),
convert_associated_const(ccx, ImplContainer(DefId::local(it.id)),
impl_item.name, impl_item.id,
impl_item.vis.inherit_from(parent_visibility),
- ty, Some(&*expr));
+ ty, true /* has_value */);
}
}
});
convert_associated_const(ccx, TraitContainer(DefId::local(it.id)),
trait_item.name, trait_item.id,
- hir::Public, ty, default.as_ref().map(|d| &**d));
+ hir::Public, ty, default.is_some());
}
_ => {}
}
ty::ConstTraitItem(ref assoc_const) => {
let did = assoc_const.def_id;
let type_scheme = tcx.lookup_item_type(did);
- let default = match assoc_const.default {
- Some(_) => Some(const_eval::lookup_const_by_id(tcx, did, None)
- .unwrap().span.to_src(cx)),
- None => None,
+ let default = if assoc_const.has_value {
+ Some(const_eval::lookup_const_by_id(tcx, did, None)
+ .unwrap().span.to_src(cx))
+ } else {
+ None
};
Some(clean::Item {
name: Some(assoc_const.name.clean(cx)),
if method.vis != hir::Public && associated_trait.is_none() {
return None
}
- if method.provided_source.is_some() {
- return None
- }
let mut item = method.clean(cx);
item.inner = match item.inner.clone() {
clean::TyMethodItem(clean::TyMethod {