rustc_resolve: don't handle impl items as if they were modules.
This commit is contained in:
parent
6700166442
commit
06f362aeb3
24 changed files with 157 additions and 385 deletions
|
@ -51,6 +51,7 @@ use middle::dependency_format;
|
||||||
use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem};
|
use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem};
|
||||||
use middle::lang_items::{FnOnceTraitLangItem, TyDescStructLangItem};
|
use middle::lang_items::{FnOnceTraitLangItem, TyDescStructLangItem};
|
||||||
use middle::mem_categorization as mc;
|
use middle::mem_categorization as mc;
|
||||||
|
use middle::privacy::LastPrivateMap;
|
||||||
use middle::region;
|
use middle::region;
|
||||||
use middle::resolve_lifetime;
|
use middle::resolve_lifetime;
|
||||||
use middle::infer;
|
use middle::infer;
|
||||||
|
@ -683,6 +684,7 @@ pub struct ctxt<'tcx> {
|
||||||
pub sess: Session,
|
pub sess: Session,
|
||||||
pub def_map: DefMap,
|
pub def_map: DefMap,
|
||||||
pub partial_def_map: PartialDefMap,
|
pub partial_def_map: PartialDefMap,
|
||||||
|
pub last_private_map: RefCell<LastPrivateMap>,
|
||||||
|
|
||||||
pub named_region_map: resolve_lifetime::NamedRegionMap,
|
pub named_region_map: resolve_lifetime::NamedRegionMap,
|
||||||
|
|
||||||
|
@ -2426,6 +2428,7 @@ pub fn mk_ctxt<'tcx>(s: Session,
|
||||||
arenas: &'tcx CtxtArenas<'tcx>,
|
arenas: &'tcx CtxtArenas<'tcx>,
|
||||||
def_map: DefMap,
|
def_map: DefMap,
|
||||||
partial_def_map: PartialDefMap,
|
partial_def_map: PartialDefMap,
|
||||||
|
last_private_map: LastPrivateMap,
|
||||||
named_region_map: resolve_lifetime::NamedRegionMap,
|
named_region_map: resolve_lifetime::NamedRegionMap,
|
||||||
map: ast_map::Map<'tcx>,
|
map: ast_map::Map<'tcx>,
|
||||||
freevars: RefCell<FreevarMap>,
|
freevars: RefCell<FreevarMap>,
|
||||||
|
@ -2449,6 +2452,7 @@ pub fn mk_ctxt<'tcx>(s: Session,
|
||||||
sess: s,
|
sess: s,
|
||||||
def_map: def_map,
|
def_map: def_map,
|
||||||
partial_def_map: partial_def_map,
|
partial_def_map: partial_def_map,
|
||||||
|
last_private_map: RefCell::new(last_private_map),
|
||||||
region_maps: region_maps,
|
region_maps: region_maps,
|
||||||
node_types: RefCell::new(FnvHashMap()),
|
node_types: RefCell::new(FnvHashMap()),
|
||||||
item_substs: RefCell::new(NodeMap()),
|
item_substs: RefCell::new(NodeMap()),
|
||||||
|
|
|
@ -609,6 +609,7 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
|
||||||
arenas,
|
arenas,
|
||||||
def_map,
|
def_map,
|
||||||
partial_def_map,
|
partial_def_map,
|
||||||
|
last_private_map,
|
||||||
named_region_map,
|
named_region_map,
|
||||||
ast_map,
|
ast_map,
|
||||||
freevars,
|
freevars,
|
||||||
|
@ -622,10 +623,9 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
|
||||||
time(time_passes, "const checking", (), |_|
|
time(time_passes, "const checking", (), |_|
|
||||||
middle::check_const::check_crate(&ty_cx));
|
middle::check_const::check_crate(&ty_cx));
|
||||||
|
|
||||||
let maps = (external_exports, last_private_map);
|
|
||||||
let (exported_items, public_items) =
|
let (exported_items, public_items) =
|
||||||
time(time_passes, "privacy checking", maps, |(a, b)|
|
time(time_passes, "privacy checking", (), |_|
|
||||||
rustc_privacy::check_crate(&ty_cx, &export_map, a, b));
|
rustc_privacy::check_crate(&ty_cx, &export_map, external_exports));
|
||||||
|
|
||||||
// Do not move this check past lint
|
// Do not move this check past lint
|
||||||
time(time_passes, "stability index", (), |_|
|
time(time_passes, "stability index", (), |_|
|
||||||
|
|
|
@ -38,8 +38,7 @@ use rustc::middle::def;
|
||||||
use rustc::middle::privacy::ImportUse::*;
|
use rustc::middle::privacy::ImportUse::*;
|
||||||
use rustc::middle::privacy::LastPrivate::*;
|
use rustc::middle::privacy::LastPrivate::*;
|
||||||
use rustc::middle::privacy::PrivateDep::*;
|
use rustc::middle::privacy::PrivateDep::*;
|
||||||
use rustc::middle::privacy::{ExportedItems, PublicItems, LastPrivateMap};
|
use rustc::middle::privacy::{ExternalExports, ExportedItems, PublicItems};
|
||||||
use rustc::middle::privacy::{ExternalExports};
|
|
||||||
use rustc::middle::ty::{MethodTypeParam, MethodStatic};
|
use rustc::middle::ty::{MethodTypeParam, MethodStatic};
|
||||||
use rustc::middle::ty::{MethodCall, MethodMap, MethodOrigin, MethodParam};
|
use rustc::middle::ty::{MethodCall, MethodMap, MethodOrigin, MethodParam};
|
||||||
use rustc::middle::ty::{MethodStaticClosure, MethodObject};
|
use rustc::middle::ty::{MethodStaticClosure, MethodObject};
|
||||||
|
@ -379,7 +378,6 @@ struct PrivacyVisitor<'a, 'tcx: 'a> {
|
||||||
in_foreign: bool,
|
in_foreign: bool,
|
||||||
parents: NodeMap<ast::NodeId>,
|
parents: NodeMap<ast::NodeId>,
|
||||||
external_exports: ExternalExports,
|
external_exports: ExternalExports,
|
||||||
last_private_map: LastPrivateMap,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum PrivacyResult {
|
enum PrivacyResult {
|
||||||
|
@ -730,7 +728,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
|
||||||
&format!("{} `{}`", tyname, name))
|
&format!("{} `{}`", tyname, name))
|
||||||
};
|
};
|
||||||
|
|
||||||
match self.last_private_map[path_id] {
|
match self.tcx.last_private_map.borrow()[path_id] {
|
||||||
LastMod(AllPublic) => {},
|
LastMod(AllPublic) => {},
|
||||||
LastMod(DependsOn(def)) => {
|
LastMod(DependsOn(def)) => {
|
||||||
self.report_error(ck_public(def));
|
self.report_error(ck_public(def));
|
||||||
|
@ -1500,8 +1498,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
|
||||||
|
|
||||||
pub fn check_crate(tcx: &ty::ctxt,
|
pub fn check_crate(tcx: &ty::ctxt,
|
||||||
export_map: &def::ExportMap,
|
export_map: &def::ExportMap,
|
||||||
external_exports: ExternalExports,
|
external_exports: ExternalExports)
|
||||||
last_private_map: LastPrivateMap)
|
|
||||||
-> (ExportedItems, PublicItems) {
|
-> (ExportedItems, PublicItems) {
|
||||||
let krate = tcx.map.krate();
|
let krate = tcx.map.krate();
|
||||||
|
|
||||||
|
@ -1519,7 +1516,6 @@ pub fn check_crate(tcx: &ty::ctxt,
|
||||||
tcx: tcx,
|
tcx: tcx,
|
||||||
parents: visitor.parents,
|
parents: visitor.parents,
|
||||||
external_exports: external_exports,
|
external_exports: external_exports,
|
||||||
last_private_map: last_private_map,
|
|
||||||
};
|
};
|
||||||
visit::walk_crate(&mut visitor, krate);
|
visit::walk_crate(&mut visitor, krate);
|
||||||
|
|
||||||
|
|
|
@ -39,18 +39,16 @@ use syntax::ast::{ForeignItem, ForeignItemFn, ForeignItemStatic};
|
||||||
use syntax::ast::{Item, ItemConst, ItemEnum, ItemExternCrate, ItemFn};
|
use syntax::ast::{Item, ItemConst, ItemEnum, ItemExternCrate, ItemFn};
|
||||||
use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, ItemDefaultImpl};
|
use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, ItemDefaultImpl};
|
||||||
use syntax::ast::{ItemStruct, ItemTrait, ItemTy, ItemUse};
|
use syntax::ast::{ItemStruct, ItemTrait, ItemTy, ItemUse};
|
||||||
use syntax::ast::{MethodImplItem, Name, NamedField, NodeId};
|
use syntax::ast::{Name, NamedField, NodeId};
|
||||||
use syntax::ast::{PathListIdent, PathListMod, Public};
|
use syntax::ast::{PathListIdent, PathListMod, Public};
|
||||||
use syntax::ast::StmtDecl;
|
use syntax::ast::StmtDecl;
|
||||||
use syntax::ast::StructVariantKind;
|
use syntax::ast::StructVariantKind;
|
||||||
use syntax::ast::TupleVariantKind;
|
use syntax::ast::TupleVariantKind;
|
||||||
use syntax::ast::TyObjectSum;
|
use syntax::ast::UnnamedField;
|
||||||
use syntax::ast::{TypeImplItem, UnnamedField};
|
|
||||||
use syntax::ast::{Variant, ViewPathGlob, ViewPathList, ViewPathSimple};
|
use syntax::ast::{Variant, ViewPathGlob, ViewPathList, ViewPathSimple};
|
||||||
use syntax::ast::{Visibility};
|
use syntax::ast::{Visibility};
|
||||||
use syntax::ast::TyPath;
|
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use syntax::ast_util::{self, PostExpansionMethod, local_def};
|
use syntax::ast_util::{self, local_def};
|
||||||
use syntax::attr::AttrMetaMethods;
|
use syntax::attr::AttrMetaMethods;
|
||||||
use syntax::parse::token::{self, special_idents};
|
use syntax::parse::token::{self, special_idents};
|
||||||
use syntax::codemap::{Span, DUMMY_SP};
|
use syntax::codemap::{Span, DUMMY_SP};
|
||||||
|
@ -177,12 +175,8 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
|
||||||
Some(TypeNS)
|
Some(TypeNS)
|
||||||
}
|
}
|
||||||
ForbidDuplicateTypesAndModules => {
|
ForbidDuplicateTypesAndModules => {
|
||||||
match child.def_for_namespace(TypeNS) {
|
if child.defined_in_namespace(TypeNS) {
|
||||||
None => {}
|
duplicate_type = TypeError;
|
||||||
Some(_) if child.get_module_if_available()
|
|
||||||
.map(|m| m.kind.get()) ==
|
|
||||||
Some(ImplModuleKind) => {}
|
|
||||||
Some(_) => duplicate_type = TypeError
|
|
||||||
}
|
}
|
||||||
Some(TypeNS)
|
Some(TypeNS)
|
||||||
}
|
}
|
||||||
|
@ -461,9 +455,6 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
|
||||||
name_bindings.define_type(DefTy(local_def(item.id), true), sp, modifiers);
|
name_bindings.define_type(DefTy(local_def(item.id), true), sp, modifiers);
|
||||||
|
|
||||||
let parent_link = self.get_parent_link(parent, name);
|
let parent_link = self.get_parent_link(parent, name);
|
||||||
// We want to make sure the module type is EnumModuleKind
|
|
||||||
// even if there's already an ImplModuleKind module defined,
|
|
||||||
// since that's how we prevent duplicate enum definitions
|
|
||||||
name_bindings.set_module_kind(parent_link,
|
name_bindings.set_module_kind(parent_link,
|
||||||
Some(local_def(item.id)),
|
Some(local_def(item.id)),
|
||||||
EnumModuleKind,
|
EnumModuleKind,
|
||||||
|
@ -513,133 +504,8 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
|
||||||
parent.clone()
|
parent.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemImpl(_, _, _, None, ref ty, ref impl_items) => {
|
ItemImpl(..) => parent.clone(),
|
||||||
// If this implements an anonymous trait, then add all the
|
|
||||||
// methods within to a new module, if the type was defined
|
|
||||||
// within this module.
|
|
||||||
|
|
||||||
let mod_name = match ty.node {
|
|
||||||
TyPath(ref path) if path.segments.len() == 1 => {
|
|
||||||
// FIXME(18446) we should distinguish between the name of
|
|
||||||
// a trait and the name of an impl of that trait.
|
|
||||||
Some(path.segments.last().unwrap().identifier.name)
|
|
||||||
}
|
|
||||||
TyObjectSum(ref lhs_ty, _) => {
|
|
||||||
match lhs_ty.node {
|
|
||||||
TyPath(ref path) if path.segments.len() == 1 => {
|
|
||||||
Some(path.segments.last().unwrap().identifier.name)
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let mod_name = match mod_name {
|
|
||||||
Some(mod_name) => mod_name,
|
|
||||||
None => {
|
|
||||||
self.resolve_error(ty.span,
|
|
||||||
"inherent implementations may \
|
|
||||||
only be implemented in the same \
|
|
||||||
module as the type they are \
|
|
||||||
implemented for");
|
|
||||||
return parent.clone();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// Create the module and add all methods.
|
|
||||||
let child_opt = parent.children.borrow().get(&mod_name)
|
|
||||||
.and_then(|m| m.get_module_if_available());
|
|
||||||
let new_parent = match child_opt {
|
|
||||||
// It already exists
|
|
||||||
Some(ref child) if (child.kind.get() == ImplModuleKind ||
|
|
||||||
child.kind.get() == TraitModuleKind) => {
|
|
||||||
child.clone()
|
|
||||||
}
|
|
||||||
Some(ref child) if child.kind.get() == EnumModuleKind ||
|
|
||||||
child.kind.get() == TypeModuleKind => {
|
|
||||||
child.clone()
|
|
||||||
}
|
|
||||||
// Create the module
|
|
||||||
_ => {
|
|
||||||
let name_bindings =
|
|
||||||
self.add_child(mod_name, parent, ForbidDuplicateModules, sp);
|
|
||||||
|
|
||||||
let parent_link = self.get_parent_link(parent, name);
|
|
||||||
let def_id = local_def(item.id);
|
|
||||||
let ns = TypeNS;
|
|
||||||
let is_public =
|
|
||||||
!name_bindings.defined_in_namespace(ns) ||
|
|
||||||
name_bindings.defined_in_public_namespace(ns);
|
|
||||||
|
|
||||||
name_bindings.define_module(parent_link,
|
|
||||||
Some(def_id),
|
|
||||||
ImplModuleKind,
|
|
||||||
false,
|
|
||||||
is_public,
|
|
||||||
sp);
|
|
||||||
|
|
||||||
name_bindings.get_module()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// For each implementation item...
|
|
||||||
for impl_item in impl_items {
|
|
||||||
match *impl_item {
|
|
||||||
MethodImplItem(ref method) => {
|
|
||||||
// Add the method to the module.
|
|
||||||
let name = method.pe_ident().name;
|
|
||||||
let method_name_bindings =
|
|
||||||
self.add_child(name,
|
|
||||||
&new_parent,
|
|
||||||
ForbidDuplicateValues,
|
|
||||||
method.span);
|
|
||||||
let def = DefMethod(local_def(method.id),
|
|
||||||
FromImpl(local_def(item.id)));
|
|
||||||
|
|
||||||
// NB: not IMPORTABLE
|
|
||||||
let modifiers = if method.pe_vis() == ast::Public {
|
|
||||||
PUBLIC
|
|
||||||
} else {
|
|
||||||
DefModifiers::empty()
|
|
||||||
};
|
|
||||||
method_name_bindings.define_value(
|
|
||||||
def,
|
|
||||||
method.span,
|
|
||||||
modifiers);
|
|
||||||
}
|
|
||||||
TypeImplItem(ref typedef) => {
|
|
||||||
// Add the typedef to the module.
|
|
||||||
let name = typedef.ident.name;
|
|
||||||
let typedef_name_bindings =
|
|
||||||
self.add_child(
|
|
||||||
name,
|
|
||||||
&new_parent,
|
|
||||||
ForbidDuplicateTypesAndModules,
|
|
||||||
typedef.span);
|
|
||||||
let def = DefAssociatedTy(local_def(item.id),
|
|
||||||
local_def(typedef.id));
|
|
||||||
// NB: not IMPORTABLE
|
|
||||||
let modifiers = if typedef.vis == ast::Public {
|
|
||||||
PUBLIC
|
|
||||||
} else {
|
|
||||||
DefModifiers::empty()
|
|
||||||
};
|
|
||||||
typedef_name_bindings.define_type(
|
|
||||||
def,
|
|
||||||
typedef.span,
|
|
||||||
modifiers);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
parent.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
ItemDefaultImpl(_, _) |
|
ItemDefaultImpl(_, _) |
|
||||||
ItemImpl(_, _, _, Some(_), _, _) => parent.clone(),
|
|
||||||
|
|
||||||
ItemTrait(_, _, _, ref items) => {
|
ItemTrait(_, _, _, ref items) => {
|
||||||
let name_bindings =
|
let name_bindings =
|
||||||
|
@ -805,8 +671,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
|
||||||
|
|
||||||
let kind = match def {
|
let kind = match def {
|
||||||
DefTy(_, true) => EnumModuleKind,
|
DefTy(_, true) => EnumModuleKind,
|
||||||
DefTy(_, false) => TypeModuleKind,
|
DefTy(_, false) | DefStruct(..) => TypeModuleKind,
|
||||||
DefStruct(..) => ImplModuleKind,
|
|
||||||
_ => NormalModuleKind
|
_ => NormalModuleKind
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -980,92 +845,9 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DlImpl(def) => {
|
DlImpl(_) => {
|
||||||
match csearch::get_type_name_if_impl(&self.session.cstore, def) {
|
debug!("(building reduced graph for external crate) \
|
||||||
None => {}
|
ignoring impl");
|
||||||
Some(final_name) => {
|
|
||||||
let methods_opt =
|
|
||||||
csearch::get_methods_if_impl(&self.session.cstore, def);
|
|
||||||
match methods_opt {
|
|
||||||
Some(ref methods) if
|
|
||||||
methods.len() >= 1 => {
|
|
||||||
debug!("(building reduced graph for \
|
|
||||||
external crate) processing \
|
|
||||||
static methods for type name {}",
|
|
||||||
token::get_name(final_name));
|
|
||||||
|
|
||||||
let child_name_bindings =
|
|
||||||
self.add_child(
|
|
||||||
final_name,
|
|
||||||
root,
|
|
||||||
OverwriteDuplicates,
|
|
||||||
DUMMY_SP);
|
|
||||||
|
|
||||||
// Process the static methods. First,
|
|
||||||
// create the module.
|
|
||||||
let type_module;
|
|
||||||
let type_def = child_name_bindings.type_def.borrow().clone();
|
|
||||||
match type_def {
|
|
||||||
Some(TypeNsDef {
|
|
||||||
module_def: Some(module_def),
|
|
||||||
..
|
|
||||||
}) => {
|
|
||||||
// We already have a module. This
|
|
||||||
// is OK.
|
|
||||||
type_module = module_def;
|
|
||||||
|
|
||||||
// Mark it as an impl module if
|
|
||||||
// necessary.
|
|
||||||
type_module.kind.set(ImplModuleKind);
|
|
||||||
}
|
|
||||||
Some(_) | None => {
|
|
||||||
let parent_link =
|
|
||||||
self.get_parent_link(root, final_name);
|
|
||||||
child_name_bindings.define_module(
|
|
||||||
parent_link,
|
|
||||||
Some(def),
|
|
||||||
ImplModuleKind,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
DUMMY_SP);
|
|
||||||
type_module =
|
|
||||||
child_name_bindings.
|
|
||||||
get_module();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add each static method to the module.
|
|
||||||
let new_parent = type_module;
|
|
||||||
for method_info in methods {
|
|
||||||
let name = method_info.name;
|
|
||||||
debug!("(building reduced graph for \
|
|
||||||
external crate) creating \
|
|
||||||
static method '{}'",
|
|
||||||
token::get_name(name));
|
|
||||||
|
|
||||||
let method_name_bindings =
|
|
||||||
self.add_child(name,
|
|
||||||
&new_parent,
|
|
||||||
OverwriteDuplicates,
|
|
||||||
DUMMY_SP);
|
|
||||||
let def = DefFn(method_info.def_id, false);
|
|
||||||
|
|
||||||
// NB: not IMPORTABLE
|
|
||||||
let modifiers = if method_info.vis == ast::Public {
|
|
||||||
PUBLIC
|
|
||||||
} else {
|
|
||||||
DefModifiers::empty()
|
|
||||||
};
|
|
||||||
method_name_bindings.define_value(
|
|
||||||
def, DUMMY_SP, modifiers);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, do nothing.
|
|
||||||
Some(_) | None => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
DlField => {
|
DlField => {
|
||||||
debug!("(building reduced graph for external crate) \
|
debug!("(building reduced graph for external crate) \
|
||||||
|
|
|
@ -514,7 +514,6 @@ enum ParentLink {
|
||||||
enum ModuleKind {
|
enum ModuleKind {
|
||||||
NormalModuleKind,
|
NormalModuleKind,
|
||||||
TraitModuleKind,
|
TraitModuleKind,
|
||||||
ImplModuleKind,
|
|
||||||
EnumModuleKind,
|
EnumModuleKind,
|
||||||
TypeModuleKind,
|
TypeModuleKind,
|
||||||
AnonymousModuleKind,
|
AnonymousModuleKind,
|
||||||
|
@ -1863,13 +1862,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||||
match import_resolution.value_target {
|
match import_resolution.value_target {
|
||||||
Some(ref target) if target.shadowable != Shadowable::Always => {
|
Some(ref target) if target.shadowable != Shadowable::Always => {
|
||||||
if let Some(ref value) = *name_bindings.value_def.borrow() {
|
if let Some(ref value) = *name_bindings.value_def.borrow() {
|
||||||
let msg = format!("import `{}` conflicts with value \
|
span_err!(self.session, import_span, E0255,
|
||||||
in this module",
|
"import `{}` conflicts with value in this module",
|
||||||
&token::get_name(name));
|
&token::get_name(name));
|
||||||
span_err!(self.session, import_span, E0255, "{}", &msg[..]);
|
|
||||||
if let Some(span) = value.value_span {
|
if let Some(span) = value.value_span {
|
||||||
self.session.span_note(span,
|
self.session.span_note(span, "conflicting value here");
|
||||||
"conflicting value here");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1879,41 +1876,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||||
match import_resolution.type_target {
|
match import_resolution.type_target {
|
||||||
Some(ref target) if target.shadowable != Shadowable::Always => {
|
Some(ref target) if target.shadowable != Shadowable::Always => {
|
||||||
if let Some(ref ty) = *name_bindings.type_def.borrow() {
|
if let Some(ref ty) = *name_bindings.type_def.borrow() {
|
||||||
match ty.module_def {
|
let (what, note) = if ty.module_def.is_some() {
|
||||||
None => {
|
("existing submodule", "note conflicting module here")
|
||||||
let msg = format!("import `{}` conflicts with type in \
|
} else {
|
||||||
this module",
|
("type in this module", "note conflicting type here")
|
||||||
&token::get_name(name));
|
};
|
||||||
span_err!(self.session, import_span, E0256, "{}", &msg[..]);
|
span_err!(self.session, import_span, E0256,
|
||||||
|
"import `{}` conflicts with {}",
|
||||||
|
&token::get_name(name), what);
|
||||||
if let Some(span) = ty.type_span {
|
if let Some(span) = ty.type_span {
|
||||||
self.session.span_note(span,
|
self.session.span_note(span, note);
|
||||||
"note conflicting type here")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some(ref module_def) => {
|
|
||||||
match module_def.kind.get() {
|
|
||||||
ImplModuleKind => {
|
|
||||||
if let Some(span) = ty.type_span {
|
|
||||||
let msg = format!("inherent implementations \
|
|
||||||
are only allowed on types \
|
|
||||||
defined in the current module");
|
|
||||||
span_err!(self.session, span, E0257, "{}", &msg[..]);
|
|
||||||
self.session.span_note(import_span,
|
|
||||||
"import from other module here")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
let msg = format!("import `{}` conflicts with existing \
|
|
||||||
submodule",
|
|
||||||
&token::get_name(name));
|
|
||||||
span_err!(self.session, import_span, E0258, "{}", &msg[..]);
|
|
||||||
if let Some(span) = ty.type_span {
|
|
||||||
self.session.span_note(span,
|
|
||||||
"note conflicting module here")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2267,7 +2239,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||||
return Failed(None);
|
return Failed(None);
|
||||||
}
|
}
|
||||||
TraitModuleKind |
|
TraitModuleKind |
|
||||||
ImplModuleKind |
|
|
||||||
EnumModuleKind |
|
EnumModuleKind |
|
||||||
TypeModuleKind |
|
TypeModuleKind |
|
||||||
AnonymousModuleKind => {
|
AnonymousModuleKind => {
|
||||||
|
@ -2365,7 +2336,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||||
match new_module.kind.get() {
|
match new_module.kind.get() {
|
||||||
NormalModuleKind => return Some(new_module),
|
NormalModuleKind => return Some(new_module),
|
||||||
TraitModuleKind |
|
TraitModuleKind |
|
||||||
ImplModuleKind |
|
|
||||||
EnumModuleKind |
|
EnumModuleKind |
|
||||||
TypeModuleKind |
|
TypeModuleKind |
|
||||||
AnonymousModuleKind => module_ = new_module,
|
AnonymousModuleKind => module_ = new_module,
|
||||||
|
@ -2382,7 +2352,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||||
match module_.kind.get() {
|
match module_.kind.get() {
|
||||||
NormalModuleKind => return module_,
|
NormalModuleKind => return module_,
|
||||||
TraitModuleKind |
|
TraitModuleKind |
|
||||||
ImplModuleKind |
|
|
||||||
EnumModuleKind |
|
EnumModuleKind |
|
||||||
TypeModuleKind |
|
TypeModuleKind |
|
||||||
AnonymousModuleKind => {
|
AnonymousModuleKind => {
|
||||||
|
|
|
@ -15,6 +15,7 @@ use check::{FnCtxt};
|
||||||
use check::vtable;
|
use check::vtable;
|
||||||
use check::vtable::select_new_fcx_obligations;
|
use check::vtable::select_new_fcx_obligations;
|
||||||
use middle::def;
|
use middle::def;
|
||||||
|
use middle::privacy::{AllPublic, DependsOn, LastPrivate, LastMod};
|
||||||
use middle::subst;
|
use middle::subst;
|
||||||
use middle::traits;
|
use middle::traits;
|
||||||
use middle::ty::*;
|
use middle::ty::*;
|
||||||
|
@ -309,16 +310,22 @@ pub fn resolve_ufcs<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||||
method_name: ast::Name,
|
method_name: ast::Name,
|
||||||
self_ty: Ty<'tcx>,
|
self_ty: Ty<'tcx>,
|
||||||
expr_id: ast::NodeId)
|
expr_id: ast::NodeId)
|
||||||
-> Result<def::Def, MethodError>
|
-> Result<(def::Def, LastPrivate), MethodError>
|
||||||
{
|
{
|
||||||
let mode = probe::Mode::Path;
|
let mode = probe::Mode::Path;
|
||||||
let pick = try!(probe::probe(fcx, span, mode, method_name, self_ty, expr_id));
|
let pick = try!(probe::probe(fcx, span, mode, method_name, self_ty, expr_id));
|
||||||
let def_id = pick.method_ty.def_id;
|
let def_id = pick.method_ty.def_id;
|
||||||
|
let mut lp = LastMod(AllPublic);
|
||||||
let provenance = match pick.kind {
|
let provenance = match pick.kind {
|
||||||
probe::InherentImplPick(impl_def_id) => def::FromImpl(impl_def_id),
|
probe::InherentImplPick(impl_def_id) => {
|
||||||
|
if pick.method_ty.vis != ast::Public {
|
||||||
|
lp = LastMod(DependsOn(def_id));
|
||||||
|
}
|
||||||
|
def::FromImpl(impl_def_id)
|
||||||
|
}
|
||||||
_ => def::FromTrait(pick.method_ty.container.id())
|
_ => def::FromTrait(pick.method_ty.container.id())
|
||||||
};
|
};
|
||||||
Ok(def::DefMethod(def_id, provenance))
|
Ok((def::DefMethod(def_id, provenance), lp))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -281,6 +281,11 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
|
||||||
ty::ty_closure(did, _, _) => {
|
ty::ty_closure(did, _, _) => {
|
||||||
self.assemble_inherent_impl_candidates_for_type(did);
|
self.assemble_inherent_impl_candidates_for_type(did);
|
||||||
}
|
}
|
||||||
|
ty::ty_uniq(_) => {
|
||||||
|
if let Some(box_did) = self.tcx().lang_items.owned_box() {
|
||||||
|
self.assemble_inherent_impl_candidates_for_type(box_did);
|
||||||
|
}
|
||||||
|
}
|
||||||
ty::ty_param(p) => {
|
ty::ty_param(p) => {
|
||||||
self.assemble_inherent_candidates_from_param(self_ty, p);
|
self.assemble_inherent_candidates_from_param(self_ty, p);
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||||
span: Span,
|
span: Span,
|
||||||
rcvr_ty: Ty<'tcx>,
|
rcvr_ty: Ty<'tcx>,
|
||||||
method_name: ast::Name,
|
method_name: ast::Name,
|
||||||
callee_expr: &ast::Expr,
|
rcvr_expr: Option<&ast::Expr>,
|
||||||
error: MethodError)
|
error: MethodError)
|
||||||
{
|
{
|
||||||
// avoid suggestions when we don't know what's going on.
|
// avoid suggestions when we don't know what's going on.
|
||||||
|
@ -46,16 +46,6 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||||
let cx = fcx.tcx();
|
let cx = fcx.tcx();
|
||||||
let method_ustring = method_name.user_string(cx);
|
let method_ustring = method_name.user_string(cx);
|
||||||
|
|
||||||
// True if the type is a struct and contains a field with
|
|
||||||
// the same name as the not-found method
|
|
||||||
let is_field = match rcvr_ty.sty {
|
|
||||||
ty::ty_struct(did, _) =>
|
|
||||||
ty::lookup_struct_fields(cx, did)
|
|
||||||
.iter()
|
|
||||||
.any(|f| f.name.user_string(cx) == method_ustring),
|
|
||||||
_ => false
|
|
||||||
};
|
|
||||||
|
|
||||||
fcx.type_error_message(
|
fcx.type_error_message(
|
||||||
span,
|
span,
|
||||||
|actual| {
|
|actual| {
|
||||||
|
@ -68,11 +58,14 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||||
None);
|
None);
|
||||||
|
|
||||||
// If the method has the name of a field, give a help note
|
// If the method has the name of a field, give a help note
|
||||||
if is_field {
|
if let (&ty::ty_struct(did, _), Some(_)) = (&rcvr_ty.sty, rcvr_expr) {
|
||||||
|
let fields = ty::lookup_struct_fields(cx, did);
|
||||||
|
if fields.iter().any(|f| f.name == method_name) {
|
||||||
cx.sess.span_note(span,
|
cx.sess.span_note(span,
|
||||||
&format!("use `(s.{0})(...)` if you meant to call the \
|
&format!("use `(s.{0})(...)` if you meant to call the \
|
||||||
function stored in the `{0}` field", method_ustring));
|
function stored in the `{0}` field", method_ustring));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if static_sources.len() > 0 {
|
if static_sources.len() > 0 {
|
||||||
fcx.tcx().sess.fileline_note(
|
fcx.tcx().sess.fileline_note(
|
||||||
|
@ -82,7 +75,8 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||||
report_candidates(fcx, span, method_name, static_sources);
|
report_candidates(fcx, span, method_name, static_sources);
|
||||||
}
|
}
|
||||||
|
|
||||||
suggest_traits_to_import(fcx, span, rcvr_ty, method_name, out_of_scope_traits)
|
suggest_traits_to_import(fcx, span, rcvr_ty, method_name,
|
||||||
|
rcvr_expr, out_of_scope_traits)
|
||||||
}
|
}
|
||||||
|
|
||||||
MethodError::Ambiguity(sources) => {
|
MethodError::Ambiguity(sources) => {
|
||||||
|
@ -93,15 +87,18 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
MethodError::ClosureAmbiguity(trait_def_id) => {
|
MethodError::ClosureAmbiguity(trait_def_id) => {
|
||||||
fcx.sess().span_err(
|
let msg = format!("the `{}` method from the `{}` trait cannot be explicitly \
|
||||||
span,
|
|
||||||
&*format!("the `{}` method from the `{}` trait cannot be explicitly \
|
|
||||||
invoked on this closure as we have not yet inferred what \
|
invoked on this closure as we have not yet inferred what \
|
||||||
kind of closure it is; use overloaded call notation instead \
|
kind of closure it is",
|
||||||
(e.g., `{}()`)",
|
|
||||||
method_name.user_string(fcx.tcx()),
|
method_name.user_string(fcx.tcx()),
|
||||||
ty::item_path_str(fcx.tcx(), trait_def_id),
|
ty::item_path_str(fcx.tcx(), trait_def_id));
|
||||||
pprust::expr_to_string(callee_expr)));
|
let msg = if let Some(callee) = rcvr_expr {
|
||||||
|
format!("{}; use overloaded call notation instead (e.g., `{}()`)",
|
||||||
|
msg, pprust::expr_to_string(callee))
|
||||||
|
} else {
|
||||||
|
msg
|
||||||
|
};
|
||||||
|
fcx.sess().span_err(span, &msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,6 +153,7 @@ fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||||
span: Span,
|
span: Span,
|
||||||
rcvr_ty: Ty<'tcx>,
|
rcvr_ty: Ty<'tcx>,
|
||||||
method_name: ast::Name,
|
method_name: ast::Name,
|
||||||
|
rcvr_expr: Option<&ast::Expr>,
|
||||||
valid_out_of_scope_traits: Vec<ast::DefId>)
|
valid_out_of_scope_traits: Vec<ast::DefId>)
|
||||||
{
|
{
|
||||||
let tcx = fcx.tcx();
|
let tcx = fcx.tcx();
|
||||||
|
@ -184,7 +182,7 @@ fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let type_is_local = type_derefs_to_local(fcx, span, rcvr_ty);
|
let type_is_local = type_derefs_to_local(fcx, span, rcvr_ty, rcvr_expr);
|
||||||
|
|
||||||
// there's no implemented traits, so lets suggest some traits to
|
// there's no implemented traits, so lets suggest some traits to
|
||||||
// implement, by finding ones that have the method name, and are
|
// implement, by finding ones that have the method name, and are
|
||||||
|
@ -233,33 +231,39 @@ fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||||
/// autoderefs of `rcvr_ty`.
|
/// autoderefs of `rcvr_ty`.
|
||||||
fn type_derefs_to_local<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
fn type_derefs_to_local<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||||
span: Span,
|
span: Span,
|
||||||
rcvr_ty: Ty<'tcx>) -> bool {
|
rcvr_ty: Ty<'tcx>,
|
||||||
check::autoderef(fcx, span, rcvr_ty, None,
|
rcvr_expr: Option<&ast::Expr>) -> bool {
|
||||||
check::UnresolvedTypeAction::Ignore, check::NoPreference,
|
fn is_local(ty: Ty) -> bool {
|
||||||
|&: ty, _| {
|
match ty.sty {
|
||||||
let is_local = match ty.sty {
|
|
||||||
ty::ty_enum(did, _) | ty::ty_struct(did, _) => ast_util::is_local(did),
|
ty::ty_enum(did, _) | ty::ty_struct(did, _) => ast_util::is_local(did),
|
||||||
|
|
||||||
ty::ty_trait(ref tr) => ast_util::is_local(tr.principal_def_id()),
|
ty::ty_trait(ref tr) => ast_util::is_local(tr.principal_def_id()),
|
||||||
|
|
||||||
ty::ty_param(_) => true,
|
ty::ty_param(_) => true,
|
||||||
|
|
||||||
// the user cannot implement traits for unboxed closures, so
|
|
||||||
// there's no point suggesting anything at all, local or not.
|
|
||||||
ty::ty_closure(..) => return Some(false),
|
|
||||||
|
|
||||||
// everything else (primitive types etc.) is effectively
|
// everything else (primitive types etc.) is effectively
|
||||||
// non-local (there are "edge" cases, e.g. (LocalType,), but
|
// non-local (there are "edge" cases, e.g. (LocalType,), but
|
||||||
// the noise from these sort of types is usually just really
|
// the noise from these sort of types is usually just really
|
||||||
// annoying, rather than any sort of help).
|
// annoying, rather than any sort of help).
|
||||||
_ => false
|
_ => false
|
||||||
};
|
}
|
||||||
if is_local {
|
}
|
||||||
Some(true)
|
|
||||||
|
// This occurs for UFCS desugaring of `T::method`, where there is no
|
||||||
|
// receiver expression for the method call, and thus no autoderef.
|
||||||
|
if rcvr_expr.is_none() {
|
||||||
|
return is_local(fcx.resolve_type_vars_if_possible(rcvr_ty));
|
||||||
|
}
|
||||||
|
|
||||||
|
check::autoderef(fcx, span, rcvr_ty, None,
|
||||||
|
check::UnresolvedTypeAction::Ignore, check::NoPreference,
|
||||||
|
|ty, _| {
|
||||||
|
if is_local(ty) {
|
||||||
|
Some(())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}).2.unwrap_or(false)
|
}).2.is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy)]
|
#[derive(Copy)]
|
||||||
|
|
|
@ -91,6 +91,7 @@ use middle::infer;
|
||||||
use middle::mem_categorization as mc;
|
use middle::mem_categorization as mc;
|
||||||
use middle::mem_categorization::McResult;
|
use middle::mem_categorization::McResult;
|
||||||
use middle::pat_util::{self, pat_id_map};
|
use middle::pat_util::{self, pat_id_map};
|
||||||
|
use middle::privacy::{AllPublic, LastMod};
|
||||||
use middle::region::{self, CodeExtent};
|
use middle::region::{self, CodeExtent};
|
||||||
use middle::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace, TypeSpace};
|
use middle::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace, TypeSpace};
|
||||||
use middle::traits;
|
use middle::traits;
|
||||||
|
@ -2687,7 +2688,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
||||||
}
|
}
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
method::report_error(fcx, method_name.span, expr_t,
|
method::report_error(fcx, method_name.span, expr_t,
|
||||||
method_name.node.name, rcvr, error);
|
method_name.node.name, Some(rcvr), error);
|
||||||
fcx.write_error(expr.id);
|
fcx.write_error(expr.id);
|
||||||
fcx.tcx().types.err
|
fcx.tcx().types.err
|
||||||
}
|
}
|
||||||
|
@ -3598,8 +3599,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Helpers to avoid keeping the RefCell borrow for too long.
|
// Helpers to avoid keeping the RefCell borrow for too long.
|
||||||
let get_def = |&:| tcx.def_map.borrow().get(&id).cloned();
|
let get_def = || tcx.def_map.borrow().get(&id).cloned();
|
||||||
let get_partial_def = |&:| tcx.partial_def_map.borrow().get(&id).cloned();
|
let get_partial_def = || tcx.partial_def_map.borrow().get(&id).cloned();
|
||||||
|
|
||||||
if let Some(def) = get_def() {
|
if let Some(def) = get_def() {
|
||||||
let (scheme, predicates) =
|
let (scheme, predicates) =
|
||||||
|
@ -3621,10 +3622,16 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
||||||
let method_segment = path.segments.last().unwrap();
|
let method_segment = path.segments.last().unwrap();
|
||||||
let method_name = method_segment.identifier.name;
|
let method_name = method_segment.identifier.name;
|
||||||
match method::resolve_ufcs(fcx, expr.span, method_name, ty, id) {
|
match method::resolve_ufcs(fcx, expr.span, method_name, ty, id) {
|
||||||
Ok(def) => {
|
Ok((def, lp)) => {
|
||||||
// Write back the new resolution.
|
// Write back the new resolution.
|
||||||
tcx.def_map.borrow_mut().insert(id, def);
|
tcx.def_map.borrow_mut().insert(id, def);
|
||||||
|
|
||||||
|
if let LastMod(AllPublic) = lp {
|
||||||
|
// Public method, don't change the last private entry.
|
||||||
|
} else {
|
||||||
|
tcx.last_private_map.borrow_mut().insert(id, lp);
|
||||||
|
}
|
||||||
|
|
||||||
let (scheme, predicates) =
|
let (scheme, predicates) =
|
||||||
type_scheme_and_predicates_for_def(fcx, expr.span, def);
|
type_scheme_and_predicates_for_def(fcx, expr.span, def);
|
||||||
instantiate_path(fcx, slice::ref_slice(method_segment),
|
instantiate_path(fcx, slice::ref_slice(method_segment),
|
||||||
|
@ -3633,7 +3640,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
||||||
}
|
}
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
method::report_error(fcx, expr.span, ty,
|
method::report_error(fcx, expr.span, ty,
|
||||||
method_name, expr, error);
|
method_name, None, error);
|
||||||
fcx.write_error(id);
|
fcx.write_error(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4842,10 +4849,10 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(self_ty) = opt_self_ty {
|
if let Some(self_ty) = opt_self_ty {
|
||||||
// `<T as Trait>::foo` shouldn't have resolved to a `Self`-less item.
|
if type_defs.len(subst::SelfSpace) == 1 {
|
||||||
assert_eq!(type_defs.len(subst::SelfSpace), 1);
|
|
||||||
substs.types.push(subst::SelfSpace, self_ty);
|
substs.types.push(subst::SelfSpace, self_ty);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Now we have to compare the types that the user *actually*
|
// Now we have to compare the types that the user *actually*
|
||||||
// provided against the types that were *expected*. If the user
|
// provided against the types that were *expected*. If the user
|
||||||
|
|
|
@ -15,8 +15,8 @@ use middle::traits;
|
||||||
use middle::ty;
|
use middle::ty;
|
||||||
use syntax::ast::{Item, ItemImpl};
|
use syntax::ast::{Item, ItemImpl};
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
|
use syntax::ast_map;
|
||||||
use syntax::ast_util;
|
use syntax::ast_util;
|
||||||
use syntax::codemap::Span;
|
|
||||||
use syntax::visit;
|
use syntax::visit;
|
||||||
use util::ppaux::{Repr, UserString};
|
use util::ppaux::{Repr, UserString};
|
||||||
|
|
||||||
|
@ -30,9 +30,9 @@ struct OrphanChecker<'cx, 'tcx:'cx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
|
impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
|
||||||
fn check_def_id(&self, span: Span, def_id: ast::DefId) {
|
fn check_def_id(&self, item: &ast::Item, def_id: ast::DefId) {
|
||||||
if def_id.krate != ast::LOCAL_CRATE {
|
if def_id.krate != ast::LOCAL_CRATE {
|
||||||
span_err!(self.tcx.sess, span, E0116,
|
span_err!(self.tcx.sess, item.span, E0116,
|
||||||
"cannot associate methods with a type outside the \
|
"cannot associate methods with a type outside the \
|
||||||
crate the type is defined in; define and implement \
|
crate the type is defined in; define and implement \
|
||||||
a trait or new type instead");
|
a trait or new type instead");
|
||||||
|
@ -41,7 +41,7 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> {
|
impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> {
|
||||||
fn visit_item(&mut self, item: &'v ast::Item) {
|
fn visit_item(&mut self, item: &ast::Item) {
|
||||||
let def_id = ast_util::local_def(item.id);
|
let def_id = ast_util::local_def(item.id);
|
||||||
match item.node {
|
match item.node {
|
||||||
ast::ItemImpl(_, _, _, None, _, _) => {
|
ast::ItemImpl(_, _, _, None, _, _) => {
|
||||||
|
@ -52,15 +52,13 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> {
|
||||||
match self_ty.sty {
|
match self_ty.sty {
|
||||||
ty::ty_enum(def_id, _) |
|
ty::ty_enum(def_id, _) |
|
||||||
ty::ty_struct(def_id, _) => {
|
ty::ty_struct(def_id, _) => {
|
||||||
self.check_def_id(item.span, def_id);
|
self.check_def_id(item, def_id);
|
||||||
}
|
}
|
||||||
ty::ty_trait(ref data) => {
|
ty::ty_trait(ref data) => {
|
||||||
self.check_def_id(item.span, data.principal_def_id());
|
self.check_def_id(item, data.principal_def_id());
|
||||||
}
|
}
|
||||||
ty::ty_uniq(..) => {
|
ty::ty_uniq(..) => {
|
||||||
self.check_def_id(item.span,
|
self.check_def_id(item, self.tcx.lang_items.owned_box().unwrap());
|
||||||
self.tcx.lang_items.owned_box()
|
|
||||||
.unwrap());
|
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
span_err!(self.tcx.sess, item.span, E0118,
|
span_err!(self.tcx.sess, item.span, E0118,
|
||||||
|
|
|
@ -80,6 +80,7 @@ register_diagnostics! {
|
||||||
E0120,
|
E0120,
|
||||||
E0121,
|
E0121,
|
||||||
E0122,
|
E0122,
|
||||||
|
E0123,
|
||||||
E0124,
|
E0124,
|
||||||
E0127,
|
E0127,
|
||||||
E0128,
|
E0128,
|
||||||
|
|
|
@ -43,7 +43,7 @@ fn foo<'a>() {
|
||||||
//~^ ERROR too many type parameters provided
|
//~^ ERROR too many type parameters provided
|
||||||
|
|
||||||
let _ = S::<'a,isize>::new::<f64>(1, 1.0);
|
let _ = S::<'a,isize>::new::<f64>(1, 1.0);
|
||||||
//~^ ERROR too many lifetime parameters provided
|
//~^ ERROR wrong number of lifetime parameters
|
||||||
|
|
||||||
let _: S2 = Trait::new::<isize,f64>(1, 1.0);
|
let _: S2 = Trait::new::<isize,f64>(1, 1.0);
|
||||||
//~^ ERROR too many type parameters provided
|
//~^ ERROR too many type parameters provided
|
||||||
|
|
|
@ -19,5 +19,5 @@ impl<A, B, C = (A, B)> Foo<A, B, C> {
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
Foo::<isize>::new();
|
Foo::<isize>::new();
|
||||||
//~^ ERROR too few type parameters provided
|
//~^ ERROR wrong number of type arguments
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,5 +21,5 @@ impl<T, A = Heap> Vec<T, A> {
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
Vec::<isize, Heap, bool>::new();
|
Vec::<isize, Heap, bool>::new();
|
||||||
//~^ ERROR too many type parameters provided
|
//~^ ERROR wrong number of type arguments
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
struct Foo;
|
struct Foo;
|
||||||
impl Foo {
|
impl Foo {
|
||||||
fn orange(&self){}
|
fn orange(&self){}
|
||||||
fn orange(&self){} //~ ERROR error: duplicate definition of value `orange`
|
fn orange(&self){} //~ ERROR error: duplicate method in trait impl
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -29,7 +29,7 @@ impl Foo for *const BarTy {
|
||||||
baz();
|
baz();
|
||||||
//~^ ERROR: unresolved name `baz`. Did you mean to call `self.baz`?
|
//~^ ERROR: unresolved name `baz`. Did you mean to call `self.baz`?
|
||||||
a;
|
a;
|
||||||
//~^ ERROR: unresolved name `a`. Did you mean to call `BarTy::a`?
|
//~^ ERROR: unresolved name `a`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,11 +42,11 @@ impl<'a> Foo for &'a BarTy {
|
||||||
y;
|
y;
|
||||||
//~^ ERROR: unresolved name `y`. Did you mean `self.y`?
|
//~^ ERROR: unresolved name `y`. Did you mean `self.y`?
|
||||||
a;
|
a;
|
||||||
//~^ ERROR: unresolved name `a`. Did you mean to call `BarTy::a`?
|
//~^ ERROR: unresolved name `a`
|
||||||
bah;
|
bah;
|
||||||
//~^ ERROR: unresolved name `bah`. Did you mean to call `Foo::bah`?
|
//~^ ERROR: unresolved name `bah`. Did you mean to call `Foo::bah`?
|
||||||
b;
|
b;
|
||||||
//~^ ERROR: unresolved name `b`. Did you mean to call `self.b`?
|
//~^ ERROR: unresolved name `b`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,11 +59,11 @@ impl<'a> Foo for &'a mut BarTy {
|
||||||
y;
|
y;
|
||||||
//~^ ERROR: unresolved name `y`. Did you mean `self.y`?
|
//~^ ERROR: unresolved name `y`. Did you mean `self.y`?
|
||||||
a;
|
a;
|
||||||
//~^ ERROR: unresolved name `a`. Did you mean to call `BarTy::a`?
|
//~^ ERROR: unresolved name `a`
|
||||||
bah;
|
bah;
|
||||||
//~^ ERROR: unresolved name `bah`. Did you mean to call `Foo::bah`?
|
//~^ ERROR: unresolved name `bah`. Did you mean to call `Foo::bah`?
|
||||||
b;
|
b;
|
||||||
//~^ ERROR: unresolved name `b`. Did you mean to call `self.b`?
|
//~^ ERROR: unresolved name `b`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ mod B {
|
||||||
use crate1::A::Foo;
|
use crate1::A::Foo;
|
||||||
fn bar(f: Foo) {
|
fn bar(f: Foo) {
|
||||||
Foo::foo(&f);
|
Foo::foo(&f);
|
||||||
//~^ ERROR: function `foo` is private
|
//~^ ERROR: method `foo` is private
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ impl Groom for cat {
|
||||||
shave(4);
|
shave(4);
|
||||||
//~^ ERROR: unresolved name `shave`. Did you mean to call `Groom::shave`?
|
//~^ ERROR: unresolved name `shave`. Did you mean to call `Groom::shave`?
|
||||||
purr();
|
purr();
|
||||||
//~^ ERROR: unresolved name `purr`. Did you mean to call `self.purr`?
|
//~^ ERROR: unresolved name `purr`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,13 +45,13 @@ impl cat {
|
||||||
|
|
||||||
fn purr_louder() {
|
fn purr_louder() {
|
||||||
static_method();
|
static_method();
|
||||||
//~^ ERROR: unresolved name `static_method`. Did you mean to call `cat::static_method`
|
//~^ ERROR: unresolved name `static_method`
|
||||||
purr();
|
purr();
|
||||||
//~^ ERROR: unresolved name `purr`. Did you mean to call `self.purr`?
|
//~^ ERROR: unresolved name `purr`
|
||||||
purr();
|
purr();
|
||||||
//~^ ERROR: unresolved name `purr`. Did you mean to call `self.purr`?
|
//~^ ERROR: unresolved name `purr`
|
||||||
purr();
|
purr();
|
||||||
//~^ ERROR: unresolved name `purr`. Did you mean to call `self.purr`?
|
//~^ ERROR: unresolved name `purr`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ impl cat {
|
||||||
|
|
||||||
fn purr(&self) {
|
fn purr(&self) {
|
||||||
grow_older();
|
grow_older();
|
||||||
//~^ ERROR: unresolved name `grow_older`. Did you mean to call `cat::grow_older`
|
//~^ ERROR: unresolved name `grow_older`
|
||||||
shave();
|
shave();
|
||||||
//~^ ERROR: unresolved name `shave`
|
//~^ ERROR: unresolved name `shave`
|
||||||
}
|
}
|
||||||
|
@ -79,7 +79,7 @@ impl cat {
|
||||||
whiskers = 4;
|
whiskers = 4;
|
||||||
//~^ ERROR: unresolved name `whiskers`. Did you mean `self.whiskers`?
|
//~^ ERROR: unresolved name `whiskers`. Did you mean `self.whiskers`?
|
||||||
purr_louder();
|
purr_louder();
|
||||||
//~^ ERROR: unresolved name `purr_louder`. Did you mean to call `cat::purr_louder`
|
//~^ ERROR: unresolved name `purr_louder`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ impl Foo {
|
||||||
Foo { baz: 0 }.bar();
|
Foo { baz: 0 }.bar();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bar() { //~ ERROR duplicate definition of value `bar`
|
fn bar() { //~ ERROR duplicate method in trait impl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ impl S {
|
||||||
|
|
||||||
// Cause an error. It shouldn't have any macro backtrace frames.
|
// Cause an error. It shouldn't have any macro backtrace frames.
|
||||||
fn bar(&self) { }
|
fn bar(&self) { }
|
||||||
fn bar(&self) { } //~ ERROR duplicate definition
|
fn bar(&self) { } //~ ERROR duplicate method
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() { }
|
fn main() { }
|
||||||
|
|
|
@ -8,8 +8,8 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
// FIXME(eddyb/UFCS) This should have a nicer error, but that's not possible just yet.
|
impl<T> Option<T> {
|
||||||
impl<T> Option<T> { //~ ERROR use of undeclared type name `Option`
|
//~^ ERROR cannot associate methods with a type outside the crate the type is defined in
|
||||||
pub fn foo(&self) { }
|
pub fn foo(&self) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
use Trait::foo;
|
use Trait::foo;
|
||||||
//~^ ERROR `foo` is not directly importable
|
//~^ ERROR `foo` is not directly importable
|
||||||
use Foo::new;
|
use Foo::new;
|
||||||
//~^ ERROR `new` is not directly importable
|
//~^ ERROR unresolved import `Foo::new`. Not a module `Foo`
|
||||||
|
|
||||||
pub trait Trait {
|
pub trait Trait {
|
||||||
fn foo();
|
fn foo();
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||||
// file at the top-level directory of this distribution and at
|
// file at the top-level directory of this distribution and at
|
||||||
// http://rust-lang.org/COPYRIGHT.
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
//
|
//
|
||||||
|
@ -8,17 +8,17 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
// Test calling methods on an impl for a bare trait. This test checks trait impls
|
mod foo {
|
||||||
// must be in the same module as the trait.
|
pub struct Point {
|
||||||
|
pub x: i32,
|
||||||
mod Foo {
|
pub y: i32,
|
||||||
trait T {}
|
|
||||||
}
|
|
||||||
|
|
||||||
mod Bar {
|
|
||||||
impl<'a> ::Foo::T+'a { //~ERROR: inherent implementations may only be implemented in the same
|
|
||||||
fn foo(&self) {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
impl foo::Point {
|
||||||
|
fn x(&self) -> i32 { self.x }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
assert_eq!((foo::Point { x: 1, y: 3}).x(), 1);
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||||
// file at the top-level directory of this distribution and at
|
// file at the top-level directory of this distribution and at
|
||||||
// http://rust-lang.org/COPYRIGHT.
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
//
|
//
|
||||||
|
@ -8,17 +8,16 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
mod foo {
|
mod Foo {
|
||||||
pub struct Foo {
|
trait Trait {
|
||||||
x: isize,
|
fn foo(&self);
|
||||||
y: isize,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl foo::Foo {
|
mod Bar {
|
||||||
//~^ ERROR implementations may only be implemented in the same module
|
impl<'a> ::Foo::Trait+'a {
|
||||||
fn bar() {}
|
fn bar(&self) { self.foo() }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue