Auto merge of #23998 - nrc:impl-self, r=nikomatsakis
Closes #23909 r? @nikomatsakis (or anyone else, really)
This commit is contained in:
@@ -457,7 +457,11 @@ impl tr for def::Def {
|
|||||||
def::DefMethod(did, p) => {
|
def::DefMethod(did, p) => {
|
||||||
def::DefMethod(did.tr(dcx), p.map(|did2| did2.tr(dcx)))
|
def::DefMethod(did.tr(dcx), p.map(|did2| did2.tr(dcx)))
|
||||||
}
|
}
|
||||||
def::DefSelfTy(nid) => { def::DefSelfTy(dcx.tr_id(nid)) }
|
def::DefSelfTy(opt_did, impl_ids) => { def::DefSelfTy(opt_did.map(|did| did.tr(dcx)),
|
||||||
|
impl_ids.map(|(nid1, nid2)| {
|
||||||
|
(dcx.tr_id(nid1),
|
||||||
|
dcx.tr_id(nid2))
|
||||||
|
})) }
|
||||||
def::DefMod(did) => { def::DefMod(did.tr(dcx)) }
|
def::DefMod(did) => { def::DefMod(did.tr(dcx)) }
|
||||||
def::DefForeignMod(did) => { def::DefForeignMod(did.tr(dcx)) }
|
def::DefForeignMod(did) => { def::DefForeignMod(did.tr(dcx)) }
|
||||||
def::DefStatic(did, m) => { def::DefStatic(did.tr(dcx), m) }
|
def::DefStatic(did, m) => { def::DefStatic(did.tr(dcx), m) }
|
||||||
|
|||||||
@@ -22,7 +22,8 @@ use std::cell::RefCell;
|
|||||||
#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||||
pub enum Def {
|
pub enum Def {
|
||||||
DefFn(ast::DefId, bool /* is_ctor */),
|
DefFn(ast::DefId, bool /* is_ctor */),
|
||||||
DefSelfTy(/* trait id */ ast::NodeId),
|
DefSelfTy(Option<ast::DefId>, // trait id
|
||||||
|
Option<(ast::NodeId, ast::NodeId)>), // (impl id, self type id)
|
||||||
DefMod(ast::DefId),
|
DefMod(ast::DefId),
|
||||||
DefForeignMod(ast::DefId),
|
DefForeignMod(ast::DefId),
|
||||||
DefStatic(ast::DefId, bool /* is_mutbl */),
|
DefStatic(ast::DefId, bool /* is_mutbl */),
|
||||||
@@ -139,18 +140,19 @@ impl Def {
|
|||||||
DefFn(id, _) | DefMod(id) | DefForeignMod(id) | DefStatic(id, _) |
|
DefFn(id, _) | DefMod(id) | DefForeignMod(id) | DefStatic(id, _) |
|
||||||
DefVariant(_, id, _) | DefTy(id, _) | DefAssociatedTy(_, id) |
|
DefVariant(_, id, _) | DefTy(id, _) | DefAssociatedTy(_, id) |
|
||||||
DefTyParam(_, _, id, _) | DefUse(id) | DefStruct(id) | DefTrait(id) |
|
DefTyParam(_, _, id, _) | DefUse(id) | DefStruct(id) | DefTrait(id) |
|
||||||
DefMethod(id, _) | DefConst(id) => {
|
DefMethod(id, _) | DefConst(id) | DefSelfTy(Some(id), None)=> {
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
DefLocal(id) |
|
DefLocal(id) |
|
||||||
DefSelfTy(id) |
|
|
||||||
DefUpvar(id, _) |
|
DefUpvar(id, _) |
|
||||||
DefRegion(id) |
|
DefRegion(id) |
|
||||||
DefLabel(id) => {
|
DefLabel(id) |
|
||||||
|
DefSelfTy(_, Some((_, id))) => {
|
||||||
local_def(id)
|
local_def(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
DefPrimTy(_) => panic!("attempted .def_id() on DefPrimTy")
|
DefPrimTy(_) => panic!("attempted .def_id() on DefPrimTy"),
|
||||||
|
DefSelfTy(..) => panic!("attempted .def_id() on invalid DefSelfTy"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1178,7 +1178,7 @@ impl<'a, 'tcx> VisiblePrivateTypesVisitor<'a, 'tcx> {
|
|||||||
let did = match self.tcx.def_map.borrow().get(&path_id).map(|d| d.full_def()) {
|
let did = match self.tcx.def_map.borrow().get(&path_id).map(|d| d.full_def()) {
|
||||||
// `int` etc. (None doesn't seem to occur.)
|
// `int` etc. (None doesn't seem to occur.)
|
||||||
None | Some(def::DefPrimTy(..)) => return false,
|
None | Some(def::DefPrimTy(..)) => return false,
|
||||||
Some(def) => def.def_id()
|
Some(def) => def.def_id(),
|
||||||
};
|
};
|
||||||
// A path can only be private if:
|
// A path can only be private if:
|
||||||
// it's in this crate...
|
// it's in this crate...
|
||||||
|
|||||||
@@ -1689,7 +1689,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DefTyParam(..) | DefSelfTy(_) => {
|
DefTyParam(..) | DefSelfTy(..) => {
|
||||||
for rib in ribs {
|
for rib in ribs {
|
||||||
match rib.kind {
|
match rib.kind {
|
||||||
NormalRibKind | MethodRibKind | ClosureRibKind(..) => {
|
NormalRibKind | MethodRibKind | ClosureRibKind(..) => {
|
||||||
@@ -1797,63 +1797,57 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ItemDefaultImpl(_, ref trait_ref) => {
|
ItemDefaultImpl(_, ref trait_ref) => {
|
||||||
self.with_optional_trait_ref(Some(trait_ref), |_| {});
|
self.with_optional_trait_ref(Some(trait_ref), |_, _| {});
|
||||||
}
|
}
|
||||||
ItemImpl(_, _,
|
ItemImpl(_,
|
||||||
|
_,
|
||||||
ref generics,
|
ref generics,
|
||||||
ref implemented_traits,
|
ref opt_trait_ref,
|
||||||
ref self_type,
|
ref self_type,
|
||||||
ref impl_items) => {
|
ref impl_items) => {
|
||||||
self.resolve_implementation(generics,
|
self.resolve_implementation(generics,
|
||||||
implemented_traits,
|
opt_trait_ref,
|
||||||
&**self_type,
|
&**self_type,
|
||||||
|
item.id,
|
||||||
&impl_items[..]);
|
&impl_items[..]);
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemTrait(_, ref generics, ref bounds, ref trait_items) => {
|
ItemTrait(_, ref generics, ref bounds, ref trait_items) => {
|
||||||
self.check_if_primitive_type_name(name, item.span);
|
self.check_if_primitive_type_name(name, item.span);
|
||||||
|
|
||||||
// Create a new rib for the self type.
|
|
||||||
let mut self_type_rib = Rib::new(ItemRibKind);
|
|
||||||
|
|
||||||
// plain insert (no renaming, types are not currently hygienic....)
|
|
||||||
let name = special_names::type_self;
|
|
||||||
self_type_rib.bindings.insert(name, DlDef(DefSelfTy(item.id)));
|
|
||||||
self.type_ribs.push(self_type_rib);
|
|
||||||
|
|
||||||
// Create a new rib for the trait-wide type parameters.
|
// Create a new rib for the trait-wide type parameters.
|
||||||
self.with_type_parameter_rib(HasTypeParameters(generics,
|
self.with_type_parameter_rib(HasTypeParameters(generics,
|
||||||
TypeSpace,
|
TypeSpace,
|
||||||
NormalRibKind),
|
ItemRibKind),
|
||||||
|this| {
|
|this| {
|
||||||
this.visit_generics(generics);
|
this.with_self_rib(DefSelfTy(Some(local_def(item.id)), None), |this| {
|
||||||
visit::walk_ty_param_bounds_helper(this, bounds);
|
this.visit_generics(generics);
|
||||||
|
visit::walk_ty_param_bounds_helper(this, bounds);
|
||||||
|
|
||||||
for trait_item in trait_items {
|
for trait_item in trait_items {
|
||||||
// Create a new rib for the trait_item-specific type
|
// Create a new rib for the trait_item-specific type
|
||||||
// parameters.
|
// parameters.
|
||||||
//
|
//
|
||||||
// FIXME #4951: Do we need a node ID here?
|
// FIXME #4951: Do we need a node ID here?
|
||||||
|
|
||||||
let type_parameters = match trait_item.node {
|
let type_parameters = match trait_item.node {
|
||||||
ast::MethodTraitItem(ref sig, _) => {
|
ast::MethodTraitItem(ref sig, _) => {
|
||||||
HasTypeParameters(&sig.generics,
|
HasTypeParameters(&sig.generics,
|
||||||
FnSpace,
|
FnSpace,
|
||||||
MethodRibKind)
|
MethodRibKind)
|
||||||
}
|
}
|
||||||
ast::TypeTraitItem(..) => {
|
ast::TypeTraitItem(..) => {
|
||||||
this.check_if_primitive_type_name(trait_item.ident.name,
|
this.check_if_primitive_type_name(trait_item.ident.name,
|
||||||
trait_item.span);
|
trait_item.span);
|
||||||
NoTypeParameters
|
NoTypeParameters
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
this.with_type_parameter_rib(type_parameters, |this| {
|
this.with_type_parameter_rib(type_parameters, |this| {
|
||||||
visit::walk_trait_item(this, trait_item)
|
visit::walk_trait_item(this, trait_item)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
self.type_ribs.pop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemMod(_) | ItemForeignMod(_) => {
|
ItemMod(_) | ItemForeignMod(_) => {
|
||||||
@@ -2030,8 +2024,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
visit::walk_generics(self, generics);
|
visit::walk_generics(self, generics);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_current_self_type<T, F>(&mut self, self_type: &Ty, f: F) -> T where
|
fn with_current_self_type<T, F>(&mut self, self_type: &Ty, f: F) -> T
|
||||||
F: FnOnce(&mut Resolver) -> T,
|
where F: FnOnce(&mut Resolver) -> T
|
||||||
{
|
{
|
||||||
// Handle nested impls (inside fn bodies)
|
// Handle nested impls (inside fn bodies)
|
||||||
let previous_value = replace(&mut self.current_self_type, Some(self_type.clone()));
|
let previous_value = replace(&mut self.current_self_type, Some(self_type.clone()));
|
||||||
@@ -2044,29 +2038,44 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
opt_trait_ref: Option<&TraitRef>,
|
opt_trait_ref: Option<&TraitRef>,
|
||||||
f: F)
|
f: F)
|
||||||
-> T
|
-> T
|
||||||
where F: FnOnce(&mut Resolver) -> T,
|
where F: FnOnce(&mut Resolver, Option<DefId>) -> T
|
||||||
{
|
{
|
||||||
let mut new_val = None;
|
let mut new_val = None;
|
||||||
|
let mut new_id = None;
|
||||||
if let Some(trait_ref) = opt_trait_ref {
|
if let Some(trait_ref) = opt_trait_ref {
|
||||||
match self.resolve_trait_reference(trait_ref.ref_id, &trait_ref.path, 0) {
|
if let Ok(path_res) = self.resolve_trait_reference(trait_ref.ref_id,
|
||||||
Ok(path_res) => {
|
&trait_ref.path, 0) {
|
||||||
self.record_def(trait_ref.ref_id, path_res);
|
assert!(path_res.depth == 0);
|
||||||
new_val = Some((path_res.base_def.def_id(), trait_ref.clone()));
|
self.record_def(trait_ref.ref_id, path_res);
|
||||||
}
|
new_val = Some((path_res.base_def.def_id(), trait_ref.clone()));
|
||||||
Err(_) => { /* error was already reported */ }
|
new_id = Some(path_res.base_def.def_id());
|
||||||
}
|
}
|
||||||
visit::walk_trait_ref(self, trait_ref);
|
visit::walk_trait_ref(self, trait_ref);
|
||||||
}
|
}
|
||||||
let original_trait_ref = replace(&mut self.current_trait_ref, new_val);
|
let original_trait_ref = replace(&mut self.current_trait_ref, new_val);
|
||||||
let result = f(self);
|
let result = f(self, new_id);
|
||||||
self.current_trait_ref = original_trait_ref;
|
self.current_trait_ref = original_trait_ref;
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn with_self_rib<F>(&mut self, self_def: Def, f: F)
|
||||||
|
where F: FnOnce(&mut Resolver)
|
||||||
|
{
|
||||||
|
let mut self_type_rib = Rib::new(NormalRibKind);
|
||||||
|
|
||||||
|
// plain insert (no renaming, types are not currently hygienic....)
|
||||||
|
let name = special_names::type_self;
|
||||||
|
self_type_rib.bindings.insert(name, DlDef(self_def));
|
||||||
|
self.type_ribs.push(self_type_rib);
|
||||||
|
f(self);
|
||||||
|
self.type_ribs.pop();
|
||||||
|
}
|
||||||
|
|
||||||
fn resolve_implementation(&mut self,
|
fn resolve_implementation(&mut self,
|
||||||
generics: &Generics,
|
generics: &Generics,
|
||||||
opt_trait_reference: &Option<TraitRef>,
|
opt_trait_reference: &Option<TraitRef>,
|
||||||
self_type: &Ty,
|
self_type: &Ty,
|
||||||
|
item_id: NodeId,
|
||||||
impl_items: &[P<ImplItem>]) {
|
impl_items: &[P<ImplItem>]) {
|
||||||
// If applicable, create a rib for the type parameters.
|
// If applicable, create a rib for the type parameters.
|
||||||
self.with_type_parameter_rib(HasTypeParameters(generics,
|
self.with_type_parameter_rib(HasTypeParameters(generics,
|
||||||
@@ -2077,40 +2086,42 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
this.visit_generics(generics);
|
this.visit_generics(generics);
|
||||||
|
|
||||||
// Resolve the trait reference, if necessary.
|
// Resolve the trait reference, if necessary.
|
||||||
this.with_optional_trait_ref(opt_trait_reference.as_ref(), |this| {
|
this.with_optional_trait_ref(opt_trait_reference.as_ref(), |this, trait_id| {
|
||||||
// Resolve the self type.
|
// Resolve the self type.
|
||||||
this.visit_ty(self_type);
|
this.visit_ty(self_type);
|
||||||
|
|
||||||
this.with_current_self_type(self_type, |this| {
|
this.with_self_rib(DefSelfTy(trait_id, Some((item_id, self_type.id))), |this| {
|
||||||
for impl_item in impl_items {
|
this.with_current_self_type(self_type, |this| {
|
||||||
match impl_item.node {
|
for impl_item in impl_items {
|
||||||
MethodImplItem(ref sig, _) => {
|
match impl_item.node {
|
||||||
// If this is a trait impl, ensure the method
|
MethodImplItem(ref sig, _) => {
|
||||||
// exists in trait
|
// If this is a trait impl, ensure the method
|
||||||
this.check_trait_item(impl_item.ident.name,
|
// exists in trait
|
||||||
impl_item.span);
|
this.check_trait_item(impl_item.ident.name,
|
||||||
|
impl_item.span);
|
||||||
|
|
||||||
// We also need a new scope for the method-
|
// We also need a new scope for the method-
|
||||||
// specific type parameters.
|
// specific type parameters.
|
||||||
let type_parameters =
|
let type_parameters =
|
||||||
HasTypeParameters(&sig.generics,
|
HasTypeParameters(&sig.generics,
|
||||||
FnSpace,
|
FnSpace,
|
||||||
MethodRibKind);
|
MethodRibKind);
|
||||||
this.with_type_parameter_rib(type_parameters, |this| {
|
this.with_type_parameter_rib(type_parameters, |this| {
|
||||||
visit::walk_impl_item(this, impl_item);
|
visit::walk_impl_item(this, impl_item);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
TypeImplItem(ref ty) => {
|
TypeImplItem(ref ty) => {
|
||||||
// If this is a trait impl, ensure the method
|
// If this is a trait impl, ensure the method
|
||||||
// exists in trait
|
// exists in trait
|
||||||
this.check_trait_item(impl_item.ident.name,
|
this.check_trait_item(impl_item.ident.name,
|
||||||
impl_item.span);
|
impl_item.span);
|
||||||
|
|
||||||
this.visit_ty(ty);
|
this.visit_ty(ty);
|
||||||
|
}
|
||||||
|
ast::MacImplItem(_) => {}
|
||||||
}
|
}
|
||||||
ast::MacImplItem(_) => {}
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -248,7 +248,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
|
|||||||
|
|
||||||
def::DefFn(..) => Some(recorder::FnRef),
|
def::DefFn(..) => Some(recorder::FnRef),
|
||||||
|
|
||||||
def::DefSelfTy(_) |
|
def::DefSelfTy(..) |
|
||||||
def::DefRegion(_) |
|
def::DefRegion(_) |
|
||||||
def::DefLabel(_) |
|
def::DefLabel(_) |
|
||||||
def::DefTyParam(..) |
|
def::DefTyParam(..) |
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ use middle::privacy::{AllPublic, LastMod};
|
|||||||
use middle::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs};
|
use middle::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs};
|
||||||
use middle::traits;
|
use middle::traits;
|
||||||
use middle::ty::{self, RegionEscape, Ty};
|
use middle::ty::{self, RegionEscape, Ty};
|
||||||
use rscope::{self, UnelidableRscope, RegionScope, ElidableRscope,
|
use rscope::{self, UnelidableRscope, RegionScope, ElidableRscope, ExplicitRscope,
|
||||||
ObjectLifetimeDefaultRscope, ShiftedRscope, BindingRscope};
|
ObjectLifetimeDefaultRscope, ShiftedRscope, BindingRscope};
|
||||||
use util::common::{ErrorReported, FN_OUTPUT_NAME};
|
use util::common::{ErrorReported, FN_OUTPUT_NAME};
|
||||||
use util::ppaux::{self, Repr, UserString};
|
use util::ppaux::{self, Repr, UserString};
|
||||||
@@ -872,24 +872,11 @@ fn ast_type_binding_to_poly_projection_predicate<'tcx>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if candidates.len() > 1 {
|
let candidate = try!(one_bound_for_assoc_type(tcx,
|
||||||
span_err!(tcx.sess, binding.span, E0217,
|
candidates,
|
||||||
"ambiguous associated type: `{}` defined in multiple supertraits `{}`",
|
&trait_ref.user_string(tcx),
|
||||||
token::get_name(binding.item_name),
|
&token::get_name(binding.item_name),
|
||||||
candidates.user_string(tcx));
|
binding.span));
|
||||||
return Err(ErrorReported);
|
|
||||||
}
|
|
||||||
|
|
||||||
let candidate = match candidates.pop() {
|
|
||||||
Some(c) => c,
|
|
||||||
None => {
|
|
||||||
span_err!(tcx.sess, binding.span, E0218,
|
|
||||||
"no associated type `{}` defined in `{}`",
|
|
||||||
token::get_name(binding.item_name),
|
|
||||||
trait_ref.user_string(tcx));
|
|
||||||
return Err(ErrorReported);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(ty::Binder(ty::ProjectionPredicate { // <-------------------------+
|
Ok(ty::Binder(ty::ProjectionPredicate { // <-------------------------+
|
||||||
projection_ty: ty::ProjectionTy { // |
|
projection_ty: ty::ProjectionTy { // |
|
||||||
@@ -1042,6 +1029,81 @@ fn report_ambiguous_associated_type(tcx: &ty::ctxt,
|
|||||||
type_str, trait_str, name);
|
type_str, trait_str, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Search for a bound on a type parameter which includes the associated item
|
||||||
|
// given by assoc_name. ty_param_node_id is the node id for the type parameter
|
||||||
|
// (which might be `Self`, but only if it is the `Self` of a trait, not an
|
||||||
|
// impl). This function will fail if there are no suitable bounds or there is
|
||||||
|
// any ambiguity.
|
||||||
|
fn find_bound_for_assoc_item<'tcx>(this: &AstConv<'tcx>,
|
||||||
|
ty_param_node_id: ast::NodeId,
|
||||||
|
assoc_name: ast::Name,
|
||||||
|
span: Span)
|
||||||
|
-> Result<ty::PolyTraitRef<'tcx>, ErrorReported>
|
||||||
|
{
|
||||||
|
let tcx = this.tcx();
|
||||||
|
|
||||||
|
let bounds = match this.get_type_parameter_bounds(span, ty_param_node_id) {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(ErrorReported) => {
|
||||||
|
return Err(ErrorReported);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Ensure the super predicates and stop if we encountered an error.
|
||||||
|
if bounds.iter().any(|b| this.ensure_super_predicates(span, b.def_id()).is_err()) {
|
||||||
|
return Err(ErrorReported);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that there is exactly one way to find an associated type with the
|
||||||
|
// correct name.
|
||||||
|
let suitable_bounds: Vec<_> =
|
||||||
|
traits::transitive_bounds(tcx, &bounds)
|
||||||
|
.filter(|b| this.trait_defines_associated_type_named(b.def_id(), assoc_name))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let ty_param_name = tcx.type_parameter_def(ty_param_node_id).name;
|
||||||
|
one_bound_for_assoc_type(tcx,
|
||||||
|
suitable_bounds,
|
||||||
|
&token::get_name(ty_param_name),
|
||||||
|
&token::get_name(assoc_name),
|
||||||
|
span)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Checks that bounds contains exactly one element and reports appropriate
|
||||||
|
// errors otherwise.
|
||||||
|
fn one_bound_for_assoc_type<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||||
|
bounds: Vec<ty::PolyTraitRef<'tcx>>,
|
||||||
|
ty_param_name: &str,
|
||||||
|
assoc_name: &str,
|
||||||
|
span: Span)
|
||||||
|
-> Result<ty::PolyTraitRef<'tcx>, ErrorReported>
|
||||||
|
{
|
||||||
|
if bounds.len() == 0 {
|
||||||
|
span_err!(tcx.sess, span, E0220,
|
||||||
|
"associated type `{}` not found for `{}`",
|
||||||
|
assoc_name,
|
||||||
|
ty_param_name);
|
||||||
|
return Err(ErrorReported);
|
||||||
|
}
|
||||||
|
|
||||||
|
if bounds.len() > 1 {
|
||||||
|
span_err!(tcx.sess, span, E0221,
|
||||||
|
"ambiguous associated type `{}` in bounds of `{}`",
|
||||||
|
assoc_name,
|
||||||
|
ty_param_name);
|
||||||
|
|
||||||
|
for bound in &bounds {
|
||||||
|
span_note!(tcx.sess, span,
|
||||||
|
"associated type `{}` could derive from `{}`",
|
||||||
|
ty_param_name,
|
||||||
|
bound.user_string(tcx));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(bounds[0].clone())
|
||||||
|
}
|
||||||
|
|
||||||
// Create a type from a a path to an associated type.
|
// Create a type from a a path to an associated type.
|
||||||
// For a path A::B::C::D, ty and ty_path_def are the type and def for A::B::C
|
// For a path A::B::C::D, ty and ty_path_def are the type and def for A::B::C
|
||||||
// and item_segment is the path segment for D. We return a type and a def for
|
// and item_segment is the path segment for D. We return a type and a def for
|
||||||
@@ -1062,10 +1124,55 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
|
|||||||
|
|
||||||
check_path_args(tcx, slice::ref_slice(item_segment), NO_TPS | NO_REGIONS);
|
check_path_args(tcx, slice::ref_slice(item_segment), NO_TPS | NO_REGIONS);
|
||||||
|
|
||||||
// Check that the path prefix given by ty/ty_path_def is a type parameter/Self.
|
// Find the type of the associated item, and the trait where the associated
|
||||||
match (&ty.sty, ty_path_def) {
|
// item is declared.
|
||||||
|
let bound = match (&ty.sty, ty_path_def) {
|
||||||
|
(_, def::DefSelfTy(Some(trait_did), Some((impl_id, _)))) => {
|
||||||
|
// `Self` in an impl of a trait - we have a concrete self type and a
|
||||||
|
// trait reference.
|
||||||
|
match tcx.map.expect_item(impl_id).node {
|
||||||
|
ast::ItemImpl(_, _, _, Some(ref trait_ref), _, _) => {
|
||||||
|
if this.ensure_super_predicates(span, trait_did).is_err() {
|
||||||
|
return (tcx.types.err, ty_path_def);
|
||||||
|
}
|
||||||
|
|
||||||
|
let trait_segment = &trait_ref.path.segments.last().unwrap();
|
||||||
|
let trait_ref = ast_path_to_mono_trait_ref(this,
|
||||||
|
&ExplicitRscope,
|
||||||
|
span,
|
||||||
|
PathParamMode::Explicit,
|
||||||
|
trait_did,
|
||||||
|
Some(ty),
|
||||||
|
trait_segment);
|
||||||
|
|
||||||
|
let candidates: Vec<ty::PolyTraitRef> =
|
||||||
|
traits::supertraits(tcx, ty::Binder(trait_ref.clone()))
|
||||||
|
.filter(|r| this.trait_defines_associated_type_named(r.def_id(),
|
||||||
|
assoc_name))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
match one_bound_for_assoc_type(tcx,
|
||||||
|
candidates,
|
||||||
|
"Self",
|
||||||
|
&token::get_name(assoc_name),
|
||||||
|
span) {
|
||||||
|
Ok(bound) => bound,
|
||||||
|
Err(ErrorReported) => return (tcx.types.err, ty_path_def),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
(&ty::ty_param(_), def::DefTyParam(..)) |
|
(&ty::ty_param(_), def::DefTyParam(..)) |
|
||||||
(&ty::ty_param(_), def::DefSelfTy(_)) => {}
|
(&ty::ty_param(_), def::DefSelfTy(Some(_), None)) => {
|
||||||
|
// A type parameter or Self, we need to find the associated item from
|
||||||
|
// a bound.
|
||||||
|
let ty_param_node_id = ty_path_def.local_node_id();
|
||||||
|
match find_bound_for_assoc_item(this, ty_param_node_id, assoc_name, span) {
|
||||||
|
Ok(bound) => bound,
|
||||||
|
Err(ErrorReported) => return (tcx.types.err, ty_path_def),
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
report_ambiguous_associated_type(tcx,
|
report_ambiguous_associated_type(tcx,
|
||||||
span,
|
span,
|
||||||
@@ -1074,61 +1181,15 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
|
|||||||
&token::get_name(assoc_name));
|
&token::get_name(assoc_name));
|
||||||
return (tcx.types.err, ty_path_def);
|
return (tcx.types.err, ty_path_def);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let ty_param_node_id = ty_path_def.local_node_id();
|
|
||||||
let ty_param_name = tcx.ty_param_defs.borrow().get(&ty_param_node_id).unwrap().name;
|
|
||||||
|
|
||||||
let bounds = match this.get_type_parameter_bounds(span, ty_param_node_id) {
|
|
||||||
Ok(v) => v,
|
|
||||||
Err(ErrorReported) => {
|
|
||||||
return (tcx.types.err, ty_path_def);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Ensure the super predicates and stop if we encountered an error.
|
let trait_did = bound.0.def_id;
|
||||||
if bounds.iter().any(|b| this.ensure_super_predicates(span, b.def_id()).is_err()) {
|
let ty = this.projected_ty_from_poly_trait_ref(span, bound, assoc_name);
|
||||||
return (this.tcx().types.err, ty_path_def);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that there is exactly one way to find an associated type with the
|
|
||||||
// correct name.
|
|
||||||
let mut suitable_bounds: Vec<_> =
|
|
||||||
traits::transitive_bounds(tcx, &bounds)
|
|
||||||
.filter(|b| this.trait_defines_associated_type_named(b.def_id(), assoc_name))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
if suitable_bounds.len() == 0 {
|
|
||||||
span_err!(tcx.sess, span, E0220,
|
|
||||||
"associated type `{}` not found for type parameter `{}`",
|
|
||||||
token::get_name(assoc_name),
|
|
||||||
token::get_name(ty_param_name));
|
|
||||||
return (this.tcx().types.err, ty_path_def);
|
|
||||||
}
|
|
||||||
|
|
||||||
if suitable_bounds.len() > 1 {
|
|
||||||
span_err!(tcx.sess, span, E0221,
|
|
||||||
"ambiguous associated type `{}` in bounds of `{}`",
|
|
||||||
token::get_name(assoc_name),
|
|
||||||
token::get_name(ty_param_name));
|
|
||||||
|
|
||||||
for suitable_bound in &suitable_bounds {
|
|
||||||
span_note!(this.tcx().sess, span,
|
|
||||||
"associated type `{}` could derive from `{}`",
|
|
||||||
token::get_name(ty_param_name),
|
|
||||||
suitable_bound.user_string(this.tcx()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let suitable_bound = suitable_bounds.pop().unwrap().clone();
|
|
||||||
let trait_did = suitable_bound.0.def_id;
|
|
||||||
|
|
||||||
let ty = this.projected_ty_from_poly_trait_ref(span, suitable_bound, assoc_name);
|
|
||||||
|
|
||||||
let item_did = if trait_did.krate == ast::LOCAL_CRATE {
|
let item_did = if trait_did.krate == ast::LOCAL_CRATE {
|
||||||
// `ty::trait_items` used below requires information generated
|
// `ty::trait_items` used below requires information generated
|
||||||
// by type collection, which may be in progress at this point.
|
// by type collection, which may be in progress at this point.
|
||||||
match this.tcx().map.expect_item(trait_did.node).node {
|
match tcx.map.expect_item(trait_did.node).node {
|
||||||
ast::ItemTrait(_, _, _, ref trait_items) => {
|
ast::ItemTrait(_, _, _, ref trait_items) => {
|
||||||
let item = trait_items.iter()
|
let item = trait_items.iter()
|
||||||
.find(|i| i.ident.name == assoc_name)
|
.find(|i| i.ident.name == assoc_name)
|
||||||
@@ -1138,7 +1199,7 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
|
|||||||
_ => unreachable!()
|
_ => unreachable!()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let trait_items = ty::trait_items(this.tcx(), trait_did);
|
let trait_items = ty::trait_items(tcx, trait_did);
|
||||||
let item = trait_items.iter().find(|i| i.name() == assoc_name);
|
let item = trait_items.iter().find(|i| i.name() == assoc_name);
|
||||||
item.expect("missing associated type").def_id()
|
item.expect("missing associated type").def_id()
|
||||||
};
|
};
|
||||||
@@ -1174,14 +1235,13 @@ fn qpath_to_ty<'tcx>(this: &AstConv<'tcx>,
|
|||||||
|
|
||||||
debug!("qpath_to_ty: self_type={}", self_ty.repr(tcx));
|
debug!("qpath_to_ty: self_type={}", self_ty.repr(tcx));
|
||||||
|
|
||||||
let trait_ref =
|
let trait_ref = ast_path_to_mono_trait_ref(this,
|
||||||
ast_path_to_mono_trait_ref(this,
|
rscope,
|
||||||
rscope,
|
span,
|
||||||
span,
|
param_mode,
|
||||||
param_mode,
|
trait_def_id,
|
||||||
trait_def_id,
|
Some(self_ty),
|
||||||
Some(self_ty),
|
trait_segment);
|
||||||
trait_segment);
|
|
||||||
|
|
||||||
debug!("qpath_to_ty: trait_ref={}", trait_ref.repr(tcx));
|
debug!("qpath_to_ty: trait_ref={}", trait_ref.repr(tcx));
|
||||||
|
|
||||||
@@ -1221,20 +1281,20 @@ pub fn ast_ty_arg_to_ty<'tcx>(this: &AstConv<'tcx>,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note that both base_segments and assoc_segments may be empty, although not at
|
// Check the base def in a PathResolution and convert it to a Ty. If there are
|
||||||
// the same time.
|
// associated types in the PathResolution, these will need to be seperately
|
||||||
pub fn finish_resolving_def_to_ty<'tcx>(this: &AstConv<'tcx>,
|
// resolved.
|
||||||
rscope: &RegionScope,
|
fn base_def_to_ty<'tcx>(this: &AstConv<'tcx>,
|
||||||
span: Span,
|
rscope: &RegionScope,
|
||||||
param_mode: PathParamMode,
|
span: Span,
|
||||||
def: &def::Def,
|
param_mode: PathParamMode,
|
||||||
opt_self_ty: Option<Ty<'tcx>>,
|
def: &def::Def,
|
||||||
base_segments: &[ast::PathSegment],
|
opt_self_ty: Option<Ty<'tcx>>,
|
||||||
assoc_segments: &[ast::PathSegment])
|
base_segments: &[ast::PathSegment])
|
||||||
-> Ty<'tcx> {
|
-> Ty<'tcx> {
|
||||||
let tcx = this.tcx();
|
let tcx = this.tcx();
|
||||||
|
|
||||||
let base_ty = match *def {
|
match *def {
|
||||||
def::DefTrait(trait_def_id) => {
|
def::DefTrait(trait_def_id) => {
|
||||||
// N.B. this case overlaps somewhat with
|
// N.B. this case overlaps somewhat with
|
||||||
// TyObjectSum, see that fn for details
|
// TyObjectSum, see that fn for details
|
||||||
@@ -1258,18 +1318,28 @@ pub fn finish_resolving_def_to_ty<'tcx>(this: &AstConv<'tcx>,
|
|||||||
}
|
}
|
||||||
def::DefTy(did, _) | def::DefStruct(did) => {
|
def::DefTy(did, _) | def::DefStruct(did) => {
|
||||||
check_path_args(tcx, base_segments.init(), NO_TPS | NO_REGIONS);
|
check_path_args(tcx, base_segments.init(), NO_TPS | NO_REGIONS);
|
||||||
ast_path_to_ty(this, rscope, span,
|
ast_path_to_ty(this,
|
||||||
param_mode, did,
|
rscope,
|
||||||
|
span,
|
||||||
|
param_mode,
|
||||||
|
did,
|
||||||
base_segments.last().unwrap())
|
base_segments.last().unwrap())
|
||||||
}
|
}
|
||||||
def::DefTyParam(space, index, _, name) => {
|
def::DefTyParam(space, index, _, name) => {
|
||||||
check_path_args(tcx, base_segments, NO_TPS | NO_REGIONS);
|
check_path_args(tcx, base_segments, NO_TPS | NO_REGIONS);
|
||||||
ty::mk_param(tcx, space, index, name)
|
ty::mk_param(tcx, space, index, name)
|
||||||
}
|
}
|
||||||
def::DefSelfTy(_) => {
|
def::DefSelfTy(_, Some((_, self_ty_id))) => {
|
||||||
// N.b.: resolve guarantees that the this type only appears in a
|
// Self in impl (we know the concrete type).
|
||||||
// trait, which we rely upon in various places when creating
|
check_path_args(tcx, base_segments, NO_TPS | NO_REGIONS);
|
||||||
// substs.
|
if let Some(&ty) = tcx.ast_ty_to_ty_cache.borrow().get(&self_ty_id) {
|
||||||
|
ty
|
||||||
|
} else {
|
||||||
|
tcx.sess.span_bug(span, "self type has not been fully resolved")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
def::DefSelfTy(Some(_), None) => {
|
||||||
|
// Self in trait.
|
||||||
check_path_args(tcx, base_segments, NO_TPS | NO_REGIONS);
|
check_path_args(tcx, base_segments, NO_TPS | NO_REGIONS);
|
||||||
ty::mk_self_type(tcx)
|
ty::mk_self_type(tcx)
|
||||||
}
|
}
|
||||||
@@ -1289,6 +1359,9 @@ pub fn finish_resolving_def_to_ty<'tcx>(this: &AstConv<'tcx>,
|
|||||||
// FIXME(#22519) This part of the resolution logic should be
|
// FIXME(#22519) This part of the resolution logic should be
|
||||||
// avoided entirely for that form, once we stop needed a Def
|
// avoided entirely for that form, once we stop needed a Def
|
||||||
// for `associated_path_def_to_ty`.
|
// for `associated_path_def_to_ty`.
|
||||||
|
// Fixing this will also let use resolve <Self>::Foo the same way we
|
||||||
|
// resolve Self::Foo, at the moment we can't resolve the former because
|
||||||
|
// we don't have the trait information around, which is just sad.
|
||||||
|
|
||||||
if !base_segments.is_empty() {
|
if !base_segments.is_empty() {
|
||||||
span_err!(tcx.sess,
|
span_err!(tcx.sess,
|
||||||
@@ -1309,11 +1382,29 @@ pub fn finish_resolving_def_to_ty<'tcx>(this: &AstConv<'tcx>,
|
|||||||
"found value name used as a type: {:?}", *def);
|
"found value name used as a type: {:?}", *def);
|
||||||
return this.tcx().types.err;
|
return this.tcx().types.err;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If any associated type segments remain, attempt to resolve them.
|
// Note that both base_segments and assoc_segments may be empty, although not at
|
||||||
let mut ty = base_ty;
|
// the same time.
|
||||||
|
pub fn finish_resolving_def_to_ty<'tcx>(this: &AstConv<'tcx>,
|
||||||
|
rscope: &RegionScope,
|
||||||
|
span: Span,
|
||||||
|
param_mode: PathParamMode,
|
||||||
|
def: &def::Def,
|
||||||
|
opt_self_ty: Option<Ty<'tcx>>,
|
||||||
|
base_segments: &[ast::PathSegment],
|
||||||
|
assoc_segments: &[ast::PathSegment])
|
||||||
|
-> Ty<'tcx> {
|
||||||
|
let mut ty = base_def_to_ty(this,
|
||||||
|
rscope,
|
||||||
|
span,
|
||||||
|
param_mode,
|
||||||
|
def,
|
||||||
|
opt_self_ty,
|
||||||
|
base_segments);
|
||||||
let mut def = *def;
|
let mut def = *def;
|
||||||
|
// If any associated type segments remain, attempt to resolve them.
|
||||||
for segment in assoc_segments {
|
for segment in assoc_segments {
|
||||||
if ty.sty == ty::ty_err {
|
if ty.sty == ty::ty_err {
|
||||||
break;
|
break;
|
||||||
@@ -1997,7 +2088,7 @@ pub fn partition_bounds<'a>(tcx: &ty::ctxt,
|
|||||||
check_type_argument_count(tcx, b.trait_ref.path.span,
|
check_type_argument_count(tcx, b.trait_ref.path.span,
|
||||||
parameters.types().len(), 0, 0);
|
parameters.types().len(), 0, 0);
|
||||||
}
|
}
|
||||||
if parameters.lifetimes().len() > 0{
|
if parameters.lifetimes().len() > 0 {
|
||||||
report_lifetime_number_error(tcx, b.trait_ref.path.span,
|
report_lifetime_number_error(tcx, b.trait_ref.path.span,
|
||||||
parameters.lifetimes().len(), 0);
|
parameters.lifetimes().len(), 0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3341,11 +3341,17 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
|||||||
|
|
||||||
let def = path_res.base_def;
|
let def = path_res.base_def;
|
||||||
if path_res.depth == 0 {
|
if path_res.depth == 0 {
|
||||||
let (scheme, predicates) =
|
let (scheme, predicates) = type_scheme_and_predicates_for_def(fcx,
|
||||||
type_scheme_and_predicates_for_def(fcx, expr.span, def);
|
expr.span,
|
||||||
instantiate_path(fcx, &path.segments,
|
def);
|
||||||
scheme, &predicates,
|
instantiate_path(fcx,
|
||||||
opt_self_ty, def, expr.span, id);
|
&path.segments,
|
||||||
|
scheme,
|
||||||
|
&predicates,
|
||||||
|
opt_self_ty,
|
||||||
|
def,
|
||||||
|
expr.span,
|
||||||
|
id);
|
||||||
} else {
|
} else {
|
||||||
let ty_segments = path.segments.init();
|
let ty_segments = path.segments.init();
|
||||||
let base_ty_end = path.segments.len() - path_res.depth;
|
let base_ty_end = path.segments.len() - path_res.depth;
|
||||||
|
|||||||
@@ -547,14 +547,15 @@ fn is_param<'tcx>(tcx: &ty::ctxt<'tcx>,
|
|||||||
if let ast::TyPath(None, _) = ast_ty.node {
|
if let ast::TyPath(None, _) = ast_ty.node {
|
||||||
let path_res = *tcx.def_map.borrow().get(&ast_ty.id).unwrap();
|
let path_res = *tcx.def_map.borrow().get(&ast_ty.id).unwrap();
|
||||||
match path_res.base_def {
|
match path_res.base_def {
|
||||||
def::DefSelfTy(node_id) =>
|
def::DefSelfTy(Some(def_id), None) => {
|
||||||
path_res.depth == 0 && node_id == param_id,
|
path_res.depth == 0 && def_id.node == param_id
|
||||||
|
}
|
||||||
def::DefTyParam(_, _, def_id, _) =>
|
def::DefTyParam(_, _, def_id, _) => {
|
||||||
path_res.depth == 0 && def_id == local_def(param_id),
|
path_res.depth == 0 && def_id == local_def(param_id)
|
||||||
|
}
|
||||||
_ =>
|
_ => {
|
||||||
false,
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
@@ -1814,7 +1815,7 @@ fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
|
|||||||
ty::ty_param(p) => if p.idx > cur_idx {
|
ty::ty_param(p) => if p.idx > cur_idx {
|
||||||
span_err!(tcx.sess, path.span, E0128,
|
span_err!(tcx.sess, path.span, E0128,
|
||||||
"type parameters with a default cannot use \
|
"type parameters with a default cannot use \
|
||||||
forward declared identifiers");
|
forward declared identifiers");
|
||||||
},
|
},
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ use ast::{ItemMac, MacStmtWithSemicolon, Mrk, Stmt, StmtDecl, StmtMac};
|
|||||||
use ast::{StmtExpr, StmtSemi};
|
use ast::{StmtExpr, StmtSemi};
|
||||||
use ast::TokenTree;
|
use ast::TokenTree;
|
||||||
use ast;
|
use ast;
|
||||||
use ast_util::path_to_ident;
|
|
||||||
use ext::mtwt;
|
use ext::mtwt;
|
||||||
use ext::build::AstBuilder;
|
use ext::build::AstBuilder;
|
||||||
use attr;
|
use attr;
|
||||||
@@ -34,30 +33,6 @@ use visit;
|
|||||||
use visit::Visitor;
|
use visit::Visitor;
|
||||||
use std_inject;
|
use std_inject;
|
||||||
|
|
||||||
pub fn expand_type(t: P<ast::Ty>,
|
|
||||||
fld: &mut MacroExpander,
|
|
||||||
impl_ty: Option<P<ast::Ty>>)
|
|
||||||
-> P<ast::Ty> {
|
|
||||||
debug!("expanding type {:?} with impl_ty {:?}", t, impl_ty);
|
|
||||||
let t = match (t.node.clone(), impl_ty) {
|
|
||||||
// Expand uses of `Self` in impls to the concrete type.
|
|
||||||
(ast::Ty_::TyPath(None, ref path), Some(ref impl_ty)) => {
|
|
||||||
let path_as_ident = path_to_ident(path);
|
|
||||||
// Note unhygenic comparison here. I think this is correct, since
|
|
||||||
// even though `Self` is almost just a type parameter, the treatment
|
|
||||||
// for this expansion is as if it were a keyword.
|
|
||||||
if path_as_ident.is_some() &&
|
|
||||||
path_as_ident.unwrap().name == token::special_idents::type_self.name {
|
|
||||||
impl_ty.clone()
|
|
||||||
} else {
|
|
||||||
t
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => t
|
|
||||||
};
|
|
||||||
fold::noop_fold_ty(t, fld)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
|
pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
|
||||||
e.and_then(|ast::Expr {id, node, span}| match node {
|
e.and_then(|ast::Expr {id, node, span}| match node {
|
||||||
// expr_mac should really be expr_ext or something; it's the
|
// expr_mac should really be expr_ext or something; it's the
|
||||||
@@ -1354,13 +1329,11 @@ fn expand_and_rename_method(sig: ast::MethodSig, body: P<ast::Block>,
|
|||||||
/// A tree-folder that performs macro expansion
|
/// A tree-folder that performs macro expansion
|
||||||
pub struct MacroExpander<'a, 'b:'a> {
|
pub struct MacroExpander<'a, 'b:'a> {
|
||||||
pub cx: &'a mut ExtCtxt<'b>,
|
pub cx: &'a mut ExtCtxt<'b>,
|
||||||
// The type of the impl currently being expanded.
|
|
||||||
current_impl_type: Option<P<ast::Ty>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> MacroExpander<'a, 'b> {
|
impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||||
pub fn new(cx: &'a mut ExtCtxt<'b>) -> MacroExpander<'a, 'b> {
|
pub fn new(cx: &'a mut ExtCtxt<'b>) -> MacroExpander<'a, 'b> {
|
||||||
MacroExpander { cx: cx, current_impl_type: None }
|
MacroExpander { cx: cx }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1374,14 +1347,7 @@ impl<'a, 'b> Folder for MacroExpander<'a, 'b> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn fold_item(&mut self, item: P<ast::Item>) -> SmallVector<P<ast::Item>> {
|
fn fold_item(&mut self, item: P<ast::Item>) -> SmallVector<P<ast::Item>> {
|
||||||
let prev_type = self.current_impl_type.clone();
|
expand_item(item, self)
|
||||||
if let ast::Item_::ItemImpl(_, _, _, _, ref ty, _) = item.node {
|
|
||||||
self.current_impl_type = Some(ty.clone());
|
|
||||||
}
|
|
||||||
|
|
||||||
let result = expand_item(item, self);
|
|
||||||
self.current_impl_type = prev_type;
|
|
||||||
result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fold_item_underscore(&mut self, item: ast::Item_) -> ast::Item_ {
|
fn fold_item_underscore(&mut self, item: ast::Item_) -> ast::Item_ {
|
||||||
@@ -1410,11 +1376,6 @@ impl<'a, 'b> Folder for MacroExpander<'a, 'b> {
|
|||||||
.into_iter().map(|i| i.expect_impl_item()).collect()
|
.into_iter().map(|i| i.expect_impl_item()).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fold_ty(&mut self, t: P<ast::Ty>) -> P<ast::Ty> {
|
|
||||||
let impl_type = self.current_impl_type.clone();
|
|
||||||
expand_type(t, self, impl_type)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn new_span(&mut self, span: Span) -> Span {
|
fn new_span(&mut self, span: Span) -> Span {
|
||||||
new_span(self.cx, span)
|
new_span(self.cx, span)
|
||||||
}
|
}
|
||||||
|
|||||||
40
src/test/compile-fail/self-impl.rs
Normal file
40
src/test/compile-fail/self-impl.rs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
// Test that unsupported uses of `Self` in impls don't crash
|
||||||
|
|
||||||
|
struct Bar;
|
||||||
|
|
||||||
|
trait Foo {
|
||||||
|
type Baz;
|
||||||
|
}
|
||||||
|
|
||||||
|
trait SuperFoo {
|
||||||
|
type SuperBaz;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Foo for Bar {
|
||||||
|
type Baz = bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SuperFoo for Bar {
|
||||||
|
type SuperBaz = bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Bar {
|
||||||
|
fn f() {
|
||||||
|
let _: <Self>::Baz = true;
|
||||||
|
//~^ERROR: ambiguous associated type; specify the type using the syntax `<Bar as Trait>::Baz`
|
||||||
|
let _: Self::Baz = true;
|
||||||
|
//~^ERROR: ambiguous associated type; specify the type using the syntax `<Bar as Trait>::Baz`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
trait One<A> { fn foo(&self) -> A; }
|
trait One<A> { fn foo(&self) -> A; }
|
||||||
|
|
||||||
fn foo(_: &One()) //~ ERROR no associated type `Output` defined in `One<()>`
|
fn foo(_: &One()) //~ ERROR associated type `Output` not found for `One<()>`
|
||||||
{}
|
{}
|
||||||
|
|
||||||
fn main() { }
|
fn main() { }
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ trait Three<A,B,C> { fn dummy(&self) -> (A,B,C); }
|
|||||||
|
|
||||||
fn foo(_: &Three())
|
fn foo(_: &Three())
|
||||||
//~^ ERROR wrong number of type arguments
|
//~^ ERROR wrong number of type arguments
|
||||||
//~| ERROR no associated type `Output`
|
//~| ERROR associated type `Output` not found
|
||||||
{}
|
{}
|
||||||
|
|
||||||
fn main() { }
|
fn main() { }
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ trait Zero { fn dummy(&self); }
|
|||||||
|
|
||||||
fn foo(_: Zero())
|
fn foo(_: Zero())
|
||||||
//~^ ERROR wrong number of type arguments
|
//~^ ERROR wrong number of type arguments
|
||||||
//~| ERROR no associated type `Output` defined in `Zero`
|
//~| ERROR associated type `Output` not found for `Zero`
|
||||||
{}
|
{}
|
||||||
|
|
||||||
fn main() { }
|
fn main() { }
|
||||||
|
|||||||
@@ -14,6 +14,6 @@ trait Trait {}
|
|||||||
|
|
||||||
fn f<F:Trait(isize) -> isize>(x: F) {}
|
fn f<F:Trait(isize) -> isize>(x: F) {}
|
||||||
//~^ ERROR wrong number of type arguments: expected 0, found 1
|
//~^ ERROR wrong number of type arguments: expected 0, found 1
|
||||||
//~| ERROR no associated type `Output`
|
//~| ERROR associated type `Output` not found
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|||||||
@@ -22,6 +22,17 @@ impl Foo {
|
|||||||
fn foo(_x: Self, _y: &Self, _z: Box<Self>) -> Self {
|
fn foo(_x: Self, _y: &Self, _z: Box<Self>) -> Self {
|
||||||
Foo
|
Foo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn baz() {
|
||||||
|
// Test that Self cannot be shadowed.
|
||||||
|
type Foo = i32;
|
||||||
|
// There is no empty method on i32.
|
||||||
|
Self::empty();
|
||||||
|
|
||||||
|
let _: Self = Foo;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn empty() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test uses when implementing a trait and with a type parameter.
|
// Test uses when implementing a trait and with a type parameter.
|
||||||
@@ -29,13 +40,31 @@ pub struct Baz<X> {
|
|||||||
pub f: X,
|
pub f: X,
|
||||||
}
|
}
|
||||||
|
|
||||||
trait Bar<X> {
|
trait SuperBar {
|
||||||
fn bar(x: Self, y: &Self, z: Box<Self>) -> Self;
|
type SuperQux;
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Bar<X>: SuperBar {
|
||||||
|
type Qux;
|
||||||
|
|
||||||
|
fn bar(x: Self, y: &Self, z: Box<Self>, _: Self::SuperQux) -> Self;
|
||||||
fn dummy(&self, x: X) { }
|
fn dummy(&self, x: X) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl SuperBar for Box<Baz<isize>> {
|
||||||
|
type SuperQux = bool;
|
||||||
|
}
|
||||||
|
|
||||||
impl Bar<isize> for Box<Baz<isize>> {
|
impl Bar<isize> for Box<Baz<isize>> {
|
||||||
fn bar(_x: Self, _y: &Self, _z: Box<Self>) -> Self {
|
type Qux = i32;
|
||||||
|
|
||||||
|
fn bar(_x: Self, _y: &Self, _z: Box<Self>, _: Self::SuperQux) -> Self {
|
||||||
|
let _: Self::Qux = 42;
|
||||||
|
let _: <Self as Bar<isize>>::Qux = 42;
|
||||||
|
|
||||||
|
let _: Self::SuperQux = true;
|
||||||
|
let _: <Self as SuperBar>::SuperQux = true;
|
||||||
|
|
||||||
box Baz { f: 42 }
|
box Baz { f: 42 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -43,6 +72,7 @@ impl Bar<isize> for Box<Baz<isize>> {
|
|||||||
fn main() {
|
fn main() {
|
||||||
let _: Foo = Foo::foo(Foo, &Foo, box Foo);
|
let _: Foo = Foo::foo(Foo, &Foo, box Foo);
|
||||||
let _: Box<Baz<isize>> = Bar::bar(box Baz { f: 42 },
|
let _: Box<Baz<isize>> = Bar::bar(box Baz { f: 42 },
|
||||||
&box Baz { f: 42 },
|
&box Baz { f: 42 },
|
||||||
box box Baz { f: 42 });
|
box box Baz { f: 42 },
|
||||||
|
true);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user