diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index c8695ef4ff0..7dcdeaf16d2 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -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, 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, @@ -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()), diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index b5933ca11ba..aafa4dec0de 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -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", (), |_| diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 439e4331e35..1452c44ca71 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -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, 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); diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index abfb226994a..e4612d6c8b9 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -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) \ diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 0c5236101cf..6b05a648746 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -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 => { diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 488d9d53dbe..7ef2db2c28d 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -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 + -> 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)) } diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 938b7edeef2..f24da78bc7d 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -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); } diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index f5a03f0721a..9832fe1cb6e 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -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) { 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)] diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 7a4fab5e56c..068e03dab12 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -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 { - // `::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* diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs index d34a16a924f..34fadc70af8 100644 --- a/src/librustc_typeck/coherence/orphan.rs +++ b/src/librustc_typeck/coherence/orphan.rs @@ -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, diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 6f363faef60..7b43a9fef06 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -80,6 +80,7 @@ register_diagnostics! { E0120, E0121, E0122, + E0123, E0124, E0127, E0128, diff --git a/src/test/compile-fail/bad-mid-path-type-params.rs b/src/test/compile-fail/bad-mid-path-type-params.rs index 3e02a11c378..7a7406115d3 100644 --- a/src/test/compile-fail/bad-mid-path-type-params.rs +++ b/src/test/compile-fail/bad-mid-path-type-params.rs @@ -43,7 +43,7 @@ fn foo<'a>() { //~^ ERROR too many type parameters provided let _ = S::<'a,isize>::new::(1, 1.0); - //~^ ERROR too many lifetime parameters provided + //~^ ERROR wrong number of lifetime parameters let _: S2 = Trait::new::(1, 1.0); //~^ ERROR too many type parameters provided diff --git a/src/test/compile-fail/generic-impl-less-params-with-defaults.rs b/src/test/compile-fail/generic-impl-less-params-with-defaults.rs index 9fea5e609d1..5fa429445a3 100644 --- a/src/test/compile-fail/generic-impl-less-params-with-defaults.rs +++ b/src/test/compile-fail/generic-impl-less-params-with-defaults.rs @@ -19,5 +19,5 @@ impl Foo { fn main() { Foo::::new(); - //~^ ERROR too few type parameters provided + //~^ ERROR wrong number of type arguments } diff --git a/src/test/compile-fail/generic-impl-more-params-with-defaults.rs b/src/test/compile-fail/generic-impl-more-params-with-defaults.rs index 73c19aa012d..d3babb8982d 100644 --- a/src/test/compile-fail/generic-impl-more-params-with-defaults.rs +++ b/src/test/compile-fail/generic-impl-more-params-with-defaults.rs @@ -21,5 +21,5 @@ impl Vec { fn main() { Vec::::new(); - //~^ ERROR too many type parameters provided + //~^ ERROR wrong number of type arguments } diff --git a/src/test/compile-fail/impl-duplicate-methods.rs b/src/test/compile-fail/impl-duplicate-methods.rs index c6ce4d04e10..c0c951dd8b1 100644 --- a/src/test/compile-fail/impl-duplicate-methods.rs +++ b/src/test/compile-fail/impl-duplicate-methods.rs @@ -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() {} diff --git a/src/test/compile-fail/issue-14254.rs b/src/test/compile-fail/issue-14254.rs index 74eea0c57a0..ce5fa1f1fe1 100644 --- a/src/test/compile-fail/issue-14254.rs +++ b/src/test/compile-fail/issue-14254.rs @@ -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` } } diff --git a/src/test/compile-fail/issue-21202.rs b/src/test/compile-fail/issue-21202.rs index 5c1de6dfc55..05485008e51 100644 --- a/src/test/compile-fail/issue-21202.rs +++ b/src/test/compile-fail/issue-21202.rs @@ -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 } } diff --git a/src/test/compile-fail/issue-2356.rs b/src/test/compile-fail/issue-2356.rs index f0ae0eb59f5..48cc27e2289 100644 --- a/src/test/compile-fail/issue-2356.rs +++ b/src/test/compile-fail/issue-2356.rs @@ -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` } } diff --git a/src/test/compile-fail/issue-4265.rs b/src/test/compile-fail/issue-4265.rs index b4bc7ecdc5f..ab18e0bcddc 100644 --- a/src/test/compile-fail/issue-4265.rs +++ b/src/test/compile-fail/issue-4265.rs @@ -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 } } diff --git a/src/test/compile-fail/method-macro-backtrace.rs b/src/test/compile-fail/method-macro-backtrace.rs index f4740492651..c9ef2df8e13 100644 --- a/src/test/compile-fail/method-macro-backtrace.rs +++ b/src/test/compile-fail/method-macro-backtrace.rs @@ -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() { } diff --git a/src/test/compile-fail/trait-or-new-type-instead.rs b/src/test/compile-fail/trait-or-new-type-instead.rs index 047e4e50c82..3aec23a55b8 100644 --- a/src/test/compile-fail/trait-or-new-type-instead.rs +++ b/src/test/compile-fail/trait-or-new-type-instead.rs @@ -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 Option { //~ ERROR use of undeclared type name `Option` +impl Option { +//~^ ERROR cannot associate methods with a type outside the crate the type is defined in pub fn foo(&self) { } } diff --git a/src/test/compile-fail/use-from-trait.rs b/src/test/compile-fail/use-from-trait.rs index 2a97155dd2e..49d8622976b 100644 --- a/src/test/compile-fail/use-from-trait.rs +++ b/src/test/compile-fail/use-from-trait.rs @@ -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(); diff --git a/src/test/compile-fail/trait-impl-2.rs b/src/test/run-pass/impl-not-adjacent-to-type.rs similarity index 53% rename from src/test/compile-fail/trait-impl-2.rs rename to src/test/run-pass/impl-not-adjacent-to-type.rs index 303e3d93744..c1dc68b2456 100644 --- a/src/test/compile-fail/trait-impl-2.rs +++ b/src/test/run-pass/impl-not-adjacent-to-type.rs @@ -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); +} diff --git a/src/test/compile-fail/impl-not-adjacent-to-type.rs b/src/test/run-pass/trait-impl-2.rs similarity index 64% rename from src/test/compile-fail/impl-not-adjacent-to-type.rs rename to src/test/run-pass/trait-impl-2.rs index 7a7673d871d..727c33d6ce5 100644 --- a/src/test/compile-fail/impl-not-adjacent-to-type.rs +++ b/src/test/run-pass/trait-impl-2.rs @@ -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() {} -