rustc_resolve: don't handle impl items as if they were modules.

This commit is contained in:
Eduard Burtescu 2015-02-20 08:17:05 +02:00
parent 6700166442
commit 06f362aeb3
24 changed files with 157 additions and 385 deletions

View File

@ -51,6 +51,7 @@ use middle::dependency_format;
use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem};
use middle::lang_items::{FnOnceTraitLangItem, TyDescStructLangItem};
use middle::mem_categorization as mc;
use middle::privacy::LastPrivateMap;
use middle::region;
use middle::resolve_lifetime;
use middle::infer;
@ -683,6 +684,7 @@ pub struct ctxt<'tcx> {
pub sess: Session,
pub def_map: DefMap,
pub partial_def_map: PartialDefMap,
pub last_private_map: RefCell<LastPrivateMap>,
pub named_region_map: resolve_lifetime::NamedRegionMap,
@ -2426,6 +2428,7 @@ pub fn mk_ctxt<'tcx>(s: Session,
arenas: &'tcx CtxtArenas<'tcx>,
def_map: DefMap,
partial_def_map: PartialDefMap,
last_private_map: LastPrivateMap,
named_region_map: resolve_lifetime::NamedRegionMap,
map: ast_map::Map<'tcx>,
freevars: RefCell<FreevarMap>,
@ -2449,6 +2452,7 @@ pub fn mk_ctxt<'tcx>(s: Session,
sess: s,
def_map: def_map,
partial_def_map: partial_def_map,
last_private_map: RefCell::new(last_private_map),
region_maps: region_maps,
node_types: RefCell::new(FnvHashMap()),
item_substs: RefCell::new(NodeMap()),

View File

@ -609,6 +609,7 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
arenas,
def_map,
partial_def_map,
last_private_map,
named_region_map,
ast_map,
freevars,
@ -622,10 +623,9 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
time(time_passes, "const checking", (), |_|
middle::check_const::check_crate(&ty_cx));
let maps = (external_exports, last_private_map);
let (exported_items, public_items) =
time(time_passes, "privacy checking", maps, |(a, b)|
rustc_privacy::check_crate(&ty_cx, &export_map, a, b));
time(time_passes, "privacy checking", (), |_|
rustc_privacy::check_crate(&ty_cx, &export_map, external_exports));
// Do not move this check past lint
time(time_passes, "stability index", (), |_|

View File

@ -38,8 +38,7 @@ use rustc::middle::def;
use rustc::middle::privacy::ImportUse::*;
use rustc::middle::privacy::LastPrivate::*;
use rustc::middle::privacy::PrivateDep::*;
use rustc::middle::privacy::{ExportedItems, PublicItems, LastPrivateMap};
use rustc::middle::privacy::{ExternalExports};
use rustc::middle::privacy::{ExternalExports, ExportedItems, PublicItems};
use rustc::middle::ty::{MethodTypeParam, MethodStatic};
use rustc::middle::ty::{MethodCall, MethodMap, MethodOrigin, MethodParam};
use rustc::middle::ty::{MethodStaticClosure, MethodObject};
@ -379,7 +378,6 @@ struct PrivacyVisitor<'a, 'tcx: 'a> {
in_foreign: bool,
parents: NodeMap<ast::NodeId>,
external_exports: ExternalExports,
last_private_map: LastPrivateMap,
}
enum PrivacyResult {
@ -730,7 +728,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
&format!("{} `{}`", tyname, name))
};
match self.last_private_map[path_id] {
match self.tcx.last_private_map.borrow()[path_id] {
LastMod(AllPublic) => {},
LastMod(DependsOn(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,
export_map: &def::ExportMap,
external_exports: ExternalExports,
last_private_map: LastPrivateMap)
external_exports: ExternalExports)
-> (ExportedItems, PublicItems) {
let krate = tcx.map.krate();
@ -1519,7 +1516,6 @@ pub fn check_crate(tcx: &ty::ctxt,
tcx: tcx,
parents: visitor.parents,
external_exports: external_exports,
last_private_map: last_private_map,
};
visit::walk_crate(&mut visitor, krate);

View File

@ -39,18 +39,16 @@ use syntax::ast::{ForeignItem, ForeignItemFn, ForeignItemStatic};
use syntax::ast::{Item, ItemConst, ItemEnum, ItemExternCrate, ItemFn};
use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, ItemDefaultImpl};
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::StmtDecl;
use syntax::ast::StructVariantKind;
use syntax::ast::TupleVariantKind;
use syntax::ast::TyObjectSum;
use syntax::ast::{TypeImplItem, UnnamedField};
use syntax::ast::UnnamedField;
use syntax::ast::{Variant, ViewPathGlob, ViewPathList, ViewPathSimple};
use syntax::ast::{Visibility};
use syntax::ast::TyPath;
use syntax::ast;
use syntax::ast_util::{self, PostExpansionMethod, local_def};
use syntax::ast_util::{self, local_def};
use syntax::attr::AttrMetaMethods;
use syntax::parse::token::{self, special_idents};
use syntax::codemap::{Span, DUMMY_SP};
@ -177,12 +175,8 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
Some(TypeNS)
}
ForbidDuplicateTypesAndModules => {
match child.def_for_namespace(TypeNS) {
None => {}
Some(_) if child.get_module_if_available()
.map(|m| m.kind.get()) ==
Some(ImplModuleKind) => {}
Some(_) => duplicate_type = TypeError
if child.defined_in_namespace(TypeNS) {
duplicate_type = TypeError;
}
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);
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,
Some(local_def(item.id)),
EnumModuleKind,
@ -513,133 +504,8 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
parent.clone()
}
ItemImpl(_, _, _, None, ref ty, ref impl_items) => {
// 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()
}
ItemImpl(..) => parent.clone(),
ItemDefaultImpl(_, _) |
ItemImpl(_, _, _, Some(_), _, _) => parent.clone(),
ItemTrait(_, _, _, ref items) => {
let name_bindings =
@ -805,8 +671,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
let kind = match def {
DefTy(_, true) => EnumModuleKind,
DefTy(_, false) => TypeModuleKind,
DefStruct(..) => ImplModuleKind,
DefTy(_, false) | DefStruct(..) => TypeModuleKind,
_ => NormalModuleKind
};
@ -980,92 +845,9 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
}
}
}
DlImpl(def) => {
match csearch::get_type_name_if_impl(&self.session.cstore, def) {
None => {}
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 => {}
}
}
}
DlImpl(_) => {
debug!("(building reduced graph for external crate) \
ignoring impl");
}
DlField => {
debug!("(building reduced graph for external crate) \

View File

@ -514,7 +514,6 @@ enum ParentLink {
enum ModuleKind {
NormalModuleKind,
TraitModuleKind,
ImplModuleKind,
EnumModuleKind,
TypeModuleKind,
AnonymousModuleKind,
@ -1863,13 +1862,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
match import_resolution.value_target {
Some(ref target) if target.shadowable != Shadowable::Always => {
if let Some(ref value) = *name_bindings.value_def.borrow() {
let msg = format!("import `{}` conflicts with value \
in this module",
&token::get_name(name));
span_err!(self.session, import_span, E0255, "{}", &msg[..]);
span_err!(self.session, import_span, E0255,
"import `{}` conflicts with value in this module",
&token::get_name(name));
if let Some(span) = value.value_span {
self.session.span_note(span,
"conflicting value here");
self.session.span_note(span, "conflicting value here");
}
}
}
@ -1879,41 +1876,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
match import_resolution.type_target {
Some(ref target) if target.shadowable != Shadowable::Always => {
if let Some(ref ty) = *name_bindings.type_def.borrow() {
match ty.module_def {
None => {
let msg = format!("import `{}` conflicts with type in \
this module",
&token::get_name(name));
span_err!(self.session, import_span, E0256, "{}", &msg[..]);
if let Some(span) = ty.type_span {
self.session.span_note(span,
"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")
}
}
}
}
let (what, note) = if ty.module_def.is_some() {
("existing submodule", "note conflicting module here")
} else {
("type in this module", "note conflicting type here")
};
span_err!(self.session, import_span, E0256,
"import `{}` conflicts with {}",
&token::get_name(name), what);
if let Some(span) = ty.type_span {
self.session.span_note(span, note);
}
}
}
@ -2267,7 +2239,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
return Failed(None);
}
TraitModuleKind |
ImplModuleKind |
EnumModuleKind |
TypeModuleKind |
AnonymousModuleKind => {
@ -2365,7 +2336,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
match new_module.kind.get() {
NormalModuleKind => return Some(new_module),
TraitModuleKind |
ImplModuleKind |
EnumModuleKind |
TypeModuleKind |
AnonymousModuleKind => module_ = new_module,
@ -2382,7 +2352,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
match module_.kind.get() {
NormalModuleKind => return module_,
TraitModuleKind |
ImplModuleKind |
EnumModuleKind |
TypeModuleKind |
AnonymousModuleKind => {

View File

@ -15,6 +15,7 @@ use check::{FnCtxt};
use check::vtable;
use check::vtable::select_new_fcx_obligations;
use middle::def;
use middle::privacy::{AllPublic, DependsOn, LastPrivate, LastMod};
use middle::subst;
use middle::traits;
use middle::ty::*;
@ -309,16 +310,22 @@ pub fn resolve_ufcs<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
method_name: ast::Name,
self_ty: Ty<'tcx>,
expr_id: ast::NodeId)
-> Result<def::Def, MethodError>
-> Result<(def::Def, LastPrivate), MethodError>
{
let mode = probe::Mode::Path;
let pick = try!(probe::probe(fcx, span, mode, method_name, self_ty, expr_id));
let def_id = pick.method_ty.def_id;
let mut lp = LastMod(AllPublic);
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())
};
Ok(def::DefMethod(def_id, provenance))
Ok((def::DefMethod(def_id, provenance), lp))
}

View File

@ -281,6 +281,11 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
ty::ty_closure(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) => {
self.assemble_inherent_candidates_from_param(self_ty, p);
}

View File

@ -33,7 +33,7 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
span: Span,
rcvr_ty: Ty<'tcx>,
method_name: ast::Name,
callee_expr: &ast::Expr,
rcvr_expr: Option<&ast::Expr>,
error: MethodError)
{
// 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 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(
span,
|actual| {
@ -68,10 +58,13 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
None);
// If the method has the name of a field, give a help note
if is_field {
cx.sess.span_note(span,
&format!("use `(s.{0})(...)` if you meant to call the \
function stored in the `{0}` field", method_ustring));
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,
&format!("use `(s.{0})(...)` if you meant to call the \
function stored in the `{0}` field", method_ustring));
}
}
if static_sources.len() > 0 {
@ -82,7 +75,8 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
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) => {
@ -93,15 +87,18 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
}
MethodError::ClosureAmbiguity(trait_def_id) => {
fcx.sess().span_err(
span,
&*format!("the `{}` method from the `{}` trait cannot be explicitly \
invoked on this closure as we have not yet inferred what \
kind of closure it is; use overloaded call notation instead \
(e.g., `{}()`)",
method_name.user_string(fcx.tcx()),
ty::item_path_str(fcx.tcx(), trait_def_id),
pprust::expr_to_string(callee_expr)));
let msg = format!("the `{}` method from the `{}` trait cannot be explicitly \
invoked on this closure as we have not yet inferred what \
kind of closure it is",
method_name.user_string(fcx.tcx()),
ty::item_path_str(fcx.tcx(), trait_def_id));
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,
rcvr_ty: Ty<'tcx>,
method_name: ast::Name,
rcvr_expr: Option<&ast::Expr>,
valid_out_of_scope_traits: Vec<ast::DefId>)
{
let tcx = fcx.tcx();
@ -184,7 +182,7 @@ fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
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
// 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`.
fn type_derefs_to_local<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
span: Span,
rcvr_ty: Ty<'tcx>) -> bool {
check::autoderef(fcx, span, rcvr_ty, None,
check::UnresolvedTypeAction::Ignore, check::NoPreference,
|&: ty, _| {
let is_local = match ty.sty {
rcvr_ty: Ty<'tcx>,
rcvr_expr: Option<&ast::Expr>) -> bool {
fn is_local(ty: Ty) -> bool {
match ty.sty {
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_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
// non-local (there are "edge" cases, e.g. (LocalType,), but
// the noise from these sort of types is usually just really
// annoying, rather than any sort of help).
_ => 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 {
None
}
}).2.unwrap_or(false)
}).2.is_some()
}
#[derive(Copy)]

View File

@ -91,6 +91,7 @@ use middle::infer;
use middle::mem_categorization as mc;
use middle::mem_categorization::McResult;
use middle::pat_util::{self, pat_id_map};
use middle::privacy::{AllPublic, LastMod};
use middle::region::{self, CodeExtent};
use middle::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace, TypeSpace};
use middle::traits;
@ -2687,7 +2688,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
}
Err(error) => {
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.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.
let get_def = |&:| tcx.def_map.borrow().get(&id).cloned();
let get_partial_def = |&:| tcx.partial_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();
if let Some(def) = get_def() {
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_name = method_segment.identifier.name;
match method::resolve_ufcs(fcx, expr.span, method_name, ty, id) {
Ok(def) => {
Ok((def, lp)) => {
// Write back the new resolution.
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) =
type_scheme_and_predicates_for_def(fcx, expr.span, def);
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) => {
method::report_error(fcx, expr.span, ty,
method_name, expr, error);
method_name, None, error);
fcx.write_error(id);
}
}
@ -4842,9 +4849,9 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
}
}
if let Some(self_ty) = opt_self_ty {
// `<T as Trait>::foo` shouldn't have resolved to a `Self`-less item.
assert_eq!(type_defs.len(subst::SelfSpace), 1);
substs.types.push(subst::SelfSpace, self_ty);
if type_defs.len(subst::SelfSpace) == 1 {
substs.types.push(subst::SelfSpace, self_ty);
}
}
// Now we have to compare the types that the user *actually*

View File

@ -15,8 +15,8 @@ use middle::traits;
use middle::ty;
use syntax::ast::{Item, ItemImpl};
use syntax::ast;
use syntax::ast_map;
use syntax::ast_util;
use syntax::codemap::Span;
use syntax::visit;
use util::ppaux::{Repr, UserString};
@ -30,9 +30,9 @@ struct OrphanChecker<'cx, 'tcx:'cx> {
}
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 {
span_err!(self.tcx.sess, span, E0116,
span_err!(self.tcx.sess, item.span, E0116,
"cannot associate methods with a type outside the \
crate the type is defined in; define and implement \
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> {
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);
match item.node {
ast::ItemImpl(_, _, _, None, _, _) => {
@ -52,15 +52,13 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> {
match self_ty.sty {
ty::ty_enum(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) => {
self.check_def_id(item.span, data.principal_def_id());
self.check_def_id(item, data.principal_def_id());
}
ty::ty_uniq(..) => {
self.check_def_id(item.span,
self.tcx.lang_items.owned_box()
.unwrap());
self.check_def_id(item, self.tcx.lang_items.owned_box().unwrap());
}
_ => {
span_err!(self.tcx.sess, item.span, E0118,

View File

@ -80,6 +80,7 @@ register_diagnostics! {
E0120,
E0121,
E0122,
E0123,
E0124,
E0127,
E0128,

View File

@ -43,7 +43,7 @@ fn foo<'a>() {
//~^ ERROR too many type parameters provided
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);
//~^ ERROR too many type parameters provided

View File

@ -19,5 +19,5 @@ impl<A, B, C = (A, B)> Foo<A, B, C> {
fn main() {
Foo::<isize>::new();
//~^ ERROR too few type parameters provided
//~^ ERROR wrong number of type arguments
}

View File

@ -21,5 +21,5 @@ impl<T, A = Heap> Vec<T, A> {
fn main() {
Vec::<isize, Heap, bool>::new();
//~^ ERROR too many type parameters provided
//~^ ERROR wrong number of type arguments
}

View File

@ -11,7 +11,7 @@
struct Foo;
impl Foo {
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() {}

View File

@ -29,7 +29,7 @@ impl Foo for *const BarTy {
baz();
//~^ ERROR: unresolved name `baz`. Did you mean to call `self.baz`?
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;
//~^ ERROR: unresolved name `y`. Did you mean `self.y`?
a;
//~^ ERROR: unresolved name `a`. Did you mean to call `BarTy::a`?
//~^ ERROR: unresolved name `a`
bah;
//~^ ERROR: unresolved name `bah`. Did you mean to call `Foo::bah`?
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;
//~^ ERROR: unresolved name `y`. Did you mean `self.y`?
a;
//~^ ERROR: unresolved name `a`. Did you mean to call `BarTy::a`?
//~^ ERROR: unresolved name `a`
bah;
//~^ ERROR: unresolved name `bah`. Did you mean to call `Foo::bah`?
b;
//~^ ERROR: unresolved name `b`. Did you mean to call `self.b`?
//~^ ERROR: unresolved name `b`
}
}

View File

@ -18,7 +18,7 @@ mod B {
use crate1::A::Foo;
fn bar(f: Foo) {
Foo::foo(&f);
//~^ ERROR: function `foo` is private
//~^ ERROR: method `foo` is private
}
}

View File

@ -36,7 +36,7 @@ impl Groom for cat {
shave(4);
//~^ ERROR: unresolved name `shave`. Did you mean to call `Groom::shave`?
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() {
static_method();
//~^ ERROR: unresolved name `static_method`. Did you mean to call `cat::static_method`
//~^ ERROR: unresolved name `static_method`
purr();
//~^ ERROR: unresolved name `purr`. Did you mean to call `self.purr`?
//~^ ERROR: unresolved name `purr`
purr();
//~^ ERROR: unresolved name `purr`. Did you mean to call `self.purr`?
//~^ ERROR: unresolved name `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) {
grow_older();
//~^ ERROR: unresolved name `grow_older`. Did you mean to call `cat::grow_older`
//~^ ERROR: unresolved name `grow_older`
shave();
//~^ ERROR: unresolved name `shave`
}
@ -79,7 +79,7 @@ impl cat {
whiskers = 4;
//~^ ERROR: unresolved name `whiskers`. Did you mean `self.whiskers`?
purr_louder();
//~^ ERROR: unresolved name `purr_louder`. Did you mean to call `cat::purr_louder`
//~^ ERROR: unresolved name `purr_louder`
}
}

View File

@ -17,7 +17,7 @@ impl Foo {
Foo { baz: 0 }.bar();
}
fn bar() { //~ ERROR duplicate definition of value `bar`
fn bar() { //~ ERROR duplicate method in trait impl
}
}

View File

@ -29,7 +29,7 @@ impl S {
// Cause an error. It shouldn't have any macro backtrace frames.
fn bar(&self) { }
fn bar(&self) { } //~ ERROR duplicate definition
fn bar(&self) { } //~ ERROR duplicate method
}
fn main() { }

View File

@ -8,8 +8,8 @@
// option. This file may not be copied, modified, or distributed
// 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> { //~ ERROR use of undeclared type name `Option`
impl<T> Option<T> {
//~^ ERROR cannot associate methods with a type outside the crate the type is defined in
pub fn foo(&self) { }
}

View File

@ -11,7 +11,7 @@
use Trait::foo;
//~^ ERROR `foo` is not directly importable
use Foo::new;
//~^ ERROR `new` is not directly importable
//~^ ERROR unresolved import `Foo::new`. Not a module `Foo`
pub trait Trait {
fn foo();

View File

@ -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
// http://rust-lang.org/COPYRIGHT.
//
@ -8,17 +8,17 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Test calling methods on an impl for a bare trait. This test checks trait impls
// must be in the same module as the trait.
mod Foo {
trait T {}
}
mod Bar {
impl<'a> ::Foo::T+'a { //~ERROR: inherent implementations may only be implemented in the same
fn foo(&self) {}
mod foo {
pub struct Point {
pub x: i32,
pub y: i32,
}
}
fn main() {}
impl foo::Point {
fn x(&self) -> i32 { self.x }
}
fn main() {
assert_eq!((foo::Point { x: 1, y: 3}).x(), 1);
}

View File

@ -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
// http://rust-lang.org/COPYRIGHT.
//
@ -8,17 +8,16 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
mod foo {
pub struct Foo {
x: isize,
y: isize,
mod Foo {
trait Trait {
fn foo(&self);
}
}
impl foo::Foo {
//~^ ERROR implementations may only be implemented in the same module
fn bar() {}
mod Bar {
impl<'a> ::Foo::Trait+'a {
fn bar(&self) { self.foo() }
}
}
fn main() {}