From a817c69297dc2bfac4029410cc055d32022cea95 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Thu, 29 Jan 2015 21:18:17 +0200 Subject: syntax: don't store a secondary NodeId for TyPath. --- src/libsyntax/ext/build.rs | 2 +- src/libsyntax/ext/expand.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/libsyntax/ext') diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 656d507ed69..baa2fab044f 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -398,7 +398,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { } fn ty_path(&self, path: ast::Path) -> P { - self.ty(path.span, ast::TyPath(path, ast::DUMMY_NODE_ID)) + self.ty(path.span, ast::TyPath(path)) } fn ty_sum(&self, path: ast::Path, bounds: OwnedSlice) -> P { diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index bc239d0c7c2..f7014d6cc3c 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -41,7 +41,7 @@ pub fn expand_type(t: P, debug!("expanding type {:?} with impl_ty {:?}", t, impl_ty); let t = match (t.node.clone(), impl_ty) { // Expand uses of `Self` in impls to the concrete type. - (ast::Ty_::TyPath(ref path, _), Some(ref impl_ty)) => { + (ast::Ty_::TyPath(ref path), Some(ref impl_ty)) => { let path_as_ident = path_to_ident(path); // Note unhygenic comparison here. I think this is correct, since // even though `Self` is almost just a type parameter, the treatment -- cgit 1.4.1-3-g733a5 From ffb8092ccf8dd186a9a03e6808d04a7276206793 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Sat, 31 Jan 2015 21:20:24 +0200 Subject: syntax: use a single Path for Trait::Item in QPath. --- src/librustc/lint/context.rs | 5 -- src/librustc/lint/mod.rs | 1 - src/librustc/middle/dead.rs | 5 -- src/librustc_back/svh.rs | 5 -- src/librustc_privacy/lib.rs | 5 -- src/librustc_resolve/lib.rs | 158 ++++++++++++++++++--------------------- src/librustc_trans/save/mod.rs | 12 +-- src/librustc_typeck/astconv.rs | 42 ++++------- src/librustc_typeck/check/mod.rs | 4 +- src/librustc_typeck/collect.rs | 3 +- src/librustdoc/clean/mod.rs | 6 +- src/libsyntax/ast.rs | 11 ++- src/libsyntax/ext/build.rs | 44 +++++------ src/libsyntax/fold.rs | 27 ++----- src/libsyntax/parse/parser.rs | 32 ++++---- src/libsyntax/print/pprust.rs | 53 +++++++------ src/libsyntax/visit.rs | 15 +--- 17 files changed, 177 insertions(+), 251 deletions(-) (limited to 'src/libsyntax/ext') diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 81fb1c8e913..d344ee8c881 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -717,11 +717,6 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> { visit::walk_path(self, p); } - fn visit_qpath(&mut self, p: &ast::QPath, id: ast::NodeId) { - run_lints!(self, check_qpath, p, id); - visit::walk_qpath(self, p); - } - fn visit_attribute(&mut self, attr: &ast::Attribute) { run_lints!(self, check_attribute, attr); } diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 1e2ddb7db0b..021827b0101 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -157,7 +157,6 @@ pub trait LintPass { fn check_explicit_self(&mut self, _: &Context, _: &ast::ExplicitSelf) { } fn check_mac(&mut self, _: &Context, _: &ast::Mac) { } fn check_path(&mut self, _: &Context, _: &ast::Path, _: ast::NodeId) { } - fn check_qpath(&mut self, _: &Context, _: &ast::QPath, _: ast::NodeId) { } fn check_attribute(&mut self, _: &Context, _: &ast::Attribute) { } /// Called when entering a syntax node that can have lint attributes such diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 4f9b900a5f8..ff78deb8d12 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -306,11 +306,6 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MarkSymbolVisitor<'a, 'tcx> { visit::walk_path(self, path); } - fn visit_qpath(&mut self, qpath: &ast::QPath, id: ast::NodeId) { - self.lookup_and_handle_definition(&id); - visit::walk_qpath(self, qpath); - } - fn visit_item(&mut self, _: &ast::Item) { // Do not recurse into items. These items will be added to the // worklist and recursed into manually if necessary. diff --git a/src/librustc_back/svh.rs b/src/librustc_back/svh.rs index af886ed25ab..2fc43ab26b5 100644 --- a/src/librustc_back/svh.rs +++ b/src/librustc_back/svh.rs @@ -194,7 +194,6 @@ mod svh_visitor { SawVariant, SawExplicitSelf, SawPath, - SawQPath, SawOptLifetimeRef, SawBlock, SawPat, @@ -486,10 +485,6 @@ mod svh_visitor { SawPath.hash(self.st); visit::walk_path(self, path) } - fn visit_qpath(&mut self, qpath: &QPath, _: ast::NodeId) { - SawQPath.hash(self.st); visit::walk_qpath(self, qpath) - } - fn visit_block(&mut self, b: &Block) { SawBlock.hash(self.st); visit::walk_block(self, b) } diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 1f8ae3fbbcb..838ba9c658c 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -1021,11 +1021,6 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> { self.check_path(path.span, id, path.segments.last().unwrap().identifier); visit::walk_path(self, path); } - - fn visit_qpath(&mut self, qpath: &ast::QPath, id: ast::NodeId) { - self.check_path(qpath.trait_path.span, id, qpath.item_path.identifier); - visit::walk_qpath(self, qpath); - } } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 914663e7581..6584e3cc19d 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1096,8 +1096,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { result } - fn path_names_to_string(&self, path: &Path) -> String { - let names: Vec = path.segments + fn path_names_to_string(&self, path: &Path, depth: usize) -> String { + let names: Vec = path.segments[..path.segments.len()-depth] .iter() .map(|seg| seg.identifier.name) .collect(); @@ -3162,7 +3162,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { match *type_parameter_bound { TraitTyParamBound(ref tref, _) => { self.resolve_trait_reference(tref.trait_ref.ref_id, - &tref.trait_ref.path, + &tref.trait_ref.path, 0, reference_type) } RegionTyParamBound(..) => {} @@ -3172,10 +3172,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn resolve_trait_reference(&mut self, id: NodeId, trait_path: &Path, + path_depth: usize, reference_type: TraitReferenceType) { - match self.resolve_path(id, trait_path, TypeNS, true) { + match self.resolve_path(id, trait_path, path_depth, TypeNS, true) { None => { - let path_str = self.path_names_to_string(trait_path); + let path_str = self.path_names_to_string(trait_path, path_depth); let usage_str = match reference_type { TraitBoundingTypeParameter => "bound type parameter with", TraitImplementation => "implement", @@ -3196,7 +3197,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { (def, _) => { self.resolve_error(trait_path.span, &format!("`{}` is not a trait", - self.path_names_to_string(trait_path))); + self.path_names_to_string(trait_path, path_depth))); // If it's a typedef, give a note if let DefTy(..) = def { @@ -3221,7 +3222,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } &ast::WherePredicate::RegionPredicate(_) => {} &ast::WherePredicate::EqPredicate(ref eq_pred) => { - match self.resolve_path(eq_pred.id, &eq_pred.path, TypeNS, true) { + match self.resolve_path(eq_pred.id, &eq_pred.path, 0, TypeNS, true) { Some((def @ DefTyParam(..), last_private)) => { self.record_def(eq_pred.id, (def, last_private)); } @@ -3297,7 +3298,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let new_val = match *opt_trait_ref { Some(ref trait_ref) => { self.resolve_trait_reference(trait_ref.ref_id, - &trait_ref.path, + &trait_ref.path, 0, TraitImplementation); match self.def_map.borrow().get(&trait_ref.ref_id) { @@ -3395,7 +3396,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // If there is a TraitRef in scope for an impl, then the method must be in the trait. if let Some((did, ref trait_ref)) = self.current_trait_ref { if self.trait_item_map.get(&(name, did)).is_none() { - let path_str = self.path_names_to_string(&trait_ref.path); + let path_str = self.path_names_to_string(&trait_ref.path, 0); self.resolve_error(span, &format!("method `{}` is not a member of trait `{}`", token::get_name(name), @@ -3563,23 +3564,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { match ty.node { // Like path expressions, the interpretation of path types depends // on whether the path has multiple elements in it or not. - TyPath(_) | TyQPath(_) => { - let mut path_from_qpath; - let path = match ty.node { - TyPath(ref path) => path, - TyQPath(ref qpath) => { - self.resolve_type(&*qpath.self_type); - - // Just make sure the trait is valid, don't record a def. - self.resolve_trait_reference(ty.id, &qpath.trait_path, TraitQPath); - self.def_map.borrow_mut().remove(&ty.id); - - path_from_qpath = qpath.trait_path.clone(); - path_from_qpath.segments.push(qpath.item_path.clone()); - &path_from_qpath - } - _ => unreachable!() - }; + + TyPath(ref path) | TyQPath(ast::QPath { ref path, .. }) => { + if let TyQPath(ref qpath) = ty.node { + self.resolve_type(&*qpath.self_type); + + // Just make sure the trait is valid, don't record a def. + self.resolve_trait_reference(ty.id, path, 1, TraitQPath); + self.def_map.borrow_mut().remove(&ty.id); + } // This is a path in the type namespace. Walk through scopes // looking for it. @@ -3612,7 +3605,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } if let None = result_def { - result_def = self.resolve_path(ty.id, path, TypeNS, true); + result_def = self.resolve_path(ty.id, path, 0, TypeNS, true); } match result_def { @@ -3620,7 +3613,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Write the result into the def map. debug!("(resolving type) writing resolution for `{}` \ (id {}) = {:?}", - self.path_names_to_string(path), + self.path_names_to_string(path, 0), ty.id, def); self.record_def(ty.id, def); } @@ -3630,7 +3623,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { _ => "type name" }; let msg = format!("use of undeclared {} `{}`", kind, - self.path_names_to_string(path)); + self.path_names_to_string(path, 0)); self.resolve_error(ty.span, &msg[..]); } } @@ -3765,7 +3758,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { PatEnum(ref path, _) => { // This must be an enum variant, struct or const. - match self.resolve_path(pat_id, path, ValueNS, false) { + match self.resolve_path(pat_id, path, 0, ValueNS, false) { Some(def @ (DefVariant(..), _)) | Some(def @ (DefStruct(..), _)) | Some(def @ (DefConst(..), _)) => { @@ -3808,7 +3801,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } PatStruct(ref path, _, _) => { - match self.resolve_path(pat_id, path, TypeNS, false) { + match self.resolve_path(pat_id, path, 0, TypeNS, false) { Some(definition) => { self.record_def(pattern.id, definition); } @@ -3816,7 +3809,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { debug!("(resolving pattern) didn't find struct \ def: {:?}", result); let msg = format!("`{}` does not name a structure", - self.path_names_to_string(path)); + self.path_names_to_string(path, 0)); self.resolve_error(path.span, &msg[..]); } } @@ -3896,34 +3889,38 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn resolve_path(&mut self, id: NodeId, path: &Path, + path_depth: usize, namespace: Namespace, check_ribs: bool) -> Option<(Def, LastPrivate)> { + let span = path.span; + let segments = &path.segments[..path.segments.len()-path_depth]; + // First, resolve the types and associated type bindings. - for ty in path.segments.iter().flat_map(|s| s.parameters.types().into_iter()) { + for ty in segments.iter().flat_map(|s| s.parameters.types().into_iter()) { self.resolve_type(&**ty); } - for binding in path.segments.iter().flat_map(|s| s.parameters.bindings().into_iter()) { + for binding in segments.iter().flat_map(|s| s.parameters.bindings().into_iter()) { self.resolve_type(&*binding.ty); } // A special case for sugared associated type paths `T::A` where `T` is // a type parameter and `A` is an associated type on some bound of `T`. - if namespace == TypeNS && path.segments.len() == 2 { - match self.resolve_identifier(path.segments[0].identifier, + if namespace == TypeNS && segments.len() == 2 { + match self.resolve_identifier(segments[0].identifier, TypeNS, true, - path.span) { + span) { Some((def, last_private)) => { match def { DefTyParam(_, _, did, _) => { let def = DefAssociatedPath(TyParamProvenance::FromParam(did), - path.segments.last() + segments.last() .unwrap().identifier); return Some((def, last_private)); } DefSelfTy(nid) => { let def = DefAssociatedPath(TyParamProvenance::FromSelf(local_def(nid)), - path.segments.last() + segments.last() .unwrap().identifier); return Some((def, last_private)); } @@ -3935,24 +3932,23 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } if path.global { - return self.resolve_crate_relative_path(path, namespace); + return self.resolve_crate_relative_path(span, segments, namespace); } // Try to find a path to an item in a module. let unqualified_def = - self.resolve_identifier(path.segments.last().unwrap().identifier, + self.resolve_identifier(segments.last().unwrap().identifier, namespace, check_ribs, - path.span); + span); - if path.segments.len() > 1 { - let def = self.resolve_module_relative_path(path, namespace); + if segments.len() > 1 { + let def = self.resolve_module_relative_path(span, segments, namespace); match (def, unqualified_def) { (Some((ref d, _)), Some((ref ud, _))) if *d == *ud => { self.session .add_lint(lint::builtin::UNUSED_QUALIFICATIONS, - id, - path.span, + id, span, "unnecessary qualification".to_string()); } _ => () @@ -4063,12 +4059,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // resolve a "module-relative" path, e.g. a::b::c fn resolve_module_relative_path(&mut self, - path: &Path, + span: Span, + segments: &[ast::PathSegment], namespace: Namespace) -> Option<(Def, LastPrivate)> { - let module_path = path.segments.init().iter() - .map(|ps| ps.identifier.name) - .collect::>(); + let module_path = segments.init().iter() + .map(|ps| ps.identifier.name) + .collect::>(); let containing_module; let last_private; @@ -4076,7 +4073,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { match self.resolve_module_path(module, &module_path[..], UseLexicalScope, - path.span, + span, PathSearch) { Failed(err) => { let (span, msg) = match err { @@ -4084,7 +4081,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { None => { let msg = format!("Use of undeclared type or module `{}`", self.names_to_string(&module_path)); - (path.span, msg) + (span, msg) } }; @@ -4099,7 +4096,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - let name = path.segments.last().unwrap().identifier.name; + let name = segments.last().unwrap().identifier.name; let def = match self.resolve_definition_of_name_in_module(containing_module.clone(), name, namespace) { @@ -4120,12 +4117,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { /// Invariant: This must be called only during main resolution, not during /// import resolution. fn resolve_crate_relative_path(&mut self, - path: &Path, + span: Span, + segments: &[ast::PathSegment], namespace: Namespace) -> Option<(Def, LastPrivate)> { - let module_path = path.segments.init().iter() - .map(|ps| ps.identifier.name) - .collect::>(); + let module_path = segments.init().iter() + .map(|ps| ps.identifier.name) + .collect::>(); let root_module = self.graph_root.get_module(); @@ -4134,7 +4132,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { match self.resolve_module_path_from_root(root_module, &module_path[..], 0, - path.span, + span, PathSearch, LastMod(AllPublic)) { Failed(err) => { @@ -4143,7 +4141,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { None => { let msg = format!("Use of undeclared module `::{}`", self.names_to_string(&module_path[..])); - (path.span, msg) + (span, msg) } }; @@ -4162,7 +4160,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - let name = path.segments.last().unwrap().identifier.name; + let name = segments.last().unwrap().identifier.name; match self.resolve_definition_of_name_in_module(containing_module, name, namespace) { @@ -4342,7 +4340,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { match get_module(self, path.span, &name_path[..]) { Some(module) => match module.children.borrow().get(&name) { Some(binding) => { - let p_str = self.path_names_to_string(&path); + let p_str = self.path_names_to_string(&path, 0); match binding.def_for_namespace(ValueNS) { Some(DefStaticMethod(_, provenance)) => { match provenance { @@ -4363,7 +4361,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Look for a method in the current trait. match self.current_trait_ref { Some((did, ref trait_ref)) => { - let path_str = self.path_names_to_string(&trait_ref.path); + let path_str = self.path_names_to_string(&trait_ref.path, 0); match self.trait_item_map.get(&(name, did)) { Some(&StaticMethodTraitItemKind) => { @@ -4426,29 +4424,21 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // The interpretation of paths depends on whether the path has // multiple elements in it or not. - ExprPath(_) | ExprQPath(_) => { - let mut path_from_qpath; - let path = match expr.node { - ExprPath(ref path) => path, - ExprQPath(ref qpath) => { - self.resolve_type(&*qpath.self_type); + ExprPath(ref path) | ExprQPath(ast::QPath { ref path, .. }) => { + if let ExprQPath(ref qpath) = expr.node { + self.resolve_type(&*qpath.self_type); - // Just make sure the trait is valid, don't record a def. - self.resolve_trait_reference(expr.id, &qpath.trait_path, TraitQPath); - self.def_map.borrow_mut().remove(&expr.id); + // Just make sure the trait is valid, don't record a def. + self.resolve_trait_reference(expr.id, path, 1, TraitQPath); + self.def_map.borrow_mut().remove(&expr.id); + } - path_from_qpath = qpath.trait_path.clone(); - path_from_qpath.segments.push(qpath.item_path.clone()); - &path_from_qpath - } - _ => unreachable!() - }; // This is a local path in the value namespace. Walk through // scopes looking for it. - match self.resolve_path(expr.id, path, ValueNS, true) { + match self.resolve_path(expr.id, path, 0, ValueNS, true) { // Check if struct variant Some((DefVariant(_, _, true), _)) => { - let path_name = self.path_names_to_string(path); + let path_name = self.path_names_to_string(path, 0); self.resolve_error(expr.span, &format!("`{}` is a struct variant name, but \ this expression \ @@ -4463,7 +4453,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Some(def) => { // Write the result into the def map. debug!("(resolving expr) resolved `{}`", - self.path_names_to_string(path)); + self.path_names_to_string(path, 0)); self.record_def(expr.id, def); } @@ -4472,9 +4462,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // (The pattern matching def_tys where the id is in self.structs // matches on regular structs while excluding tuple- and enum-like // structs, which wouldn't result in this error.) - let path_name = self.path_names_to_string(path); + let path_name = self.path_names_to_string(path, 0); match self.with_no_errors(|this| - this.resolve_path(expr.id, path, TypeNS, false)) { + this.resolve_path(expr.id, path, 0, TypeNS, false)) { Some((DefTy(struct_id, _), _)) if self.structs.contains_key(&struct_id) => { self.resolve_error(expr.span, @@ -4557,13 +4547,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Resolve the path to the structure it goes to. We don't // check to ensure that the path is actually a structure; that // is checked later during typeck. - match self.resolve_path(expr.id, path, TypeNS, false) { + match self.resolve_path(expr.id, path, 0, TypeNS, false) { Some(definition) => self.record_def(expr.id, definition), result => { debug!("(resolving expression) didn't find struct \ def: {:?}", result); let msg = format!("`{}` does not name a structure", - self.path_names_to_string(path)); + self.path_names_to_string(path, 0)); self.resolve_error(path.span, &msg[..]); } } diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs index c9288665128..6a20938da2e 100644 --- a/src/librustc_trans/save/mod.rs +++ b/src/librustc_trans/save/mod.rs @@ -1334,16 +1334,10 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> { // Don't need to do anything for function calls, // because just walking the callee path does what we want. visit::walk_expr(self, ex); - }, - ast::ExprPath(ref path) => { - self.process_path(ex.id, path.span, path, None); - visit::walk_path(self, path); } - ast::ExprQPath(ref qpath) => { - let mut path = qpath.trait_path.clone(); - path.segments.push(qpath.item_path.clone()); - self.process_path(ex.id, ex.span, &path, None); - visit::walk_qpath(self, &**qpath); + ast::ExprPath(ref path) | ast::ExprQPath(ast::QPath { ref path, .. }) => { + self.process_path(ex.id, path.span, path, None); + visit::walk_expr(self, ex); } ast::ExprStruct(ref path, ref fields, ref base) => self.process_struct_lit(ex, path, fields, base), diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index cf567f709f5..8eb75ece4a1 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -575,8 +575,7 @@ pub fn instantiate_poly_trait_ref<'tcx>( let shifted_rscope = ShiftedRscope::new(rscope); let trait_ref = instantiate_trait_ref(this, &shifted_rscope, - &ast_trait_ref.trait_ref.path, - ast_trait_ref.trait_ref.ref_id, + &ast_trait_ref.trait_ref, None, self_ty, Some(&mut projections)); for projection in projections { @@ -595,14 +594,14 @@ pub fn instantiate_poly_trait_ref<'tcx>( pub fn instantiate_trait_ref<'tcx>( this: &AstConv<'tcx>, rscope: &RegionScope, - path: &ast::Path, - path_id: ast::NodeId, + trait_ref: &ast::TraitRef, impl_id: Option, self_ty: Option>, projections: Option<&mut Vec>>) -> Rc> { - match ::lookup_def_tcx(this.tcx(), path.span, path_id) { + let path = &trait_ref.path; + match ::lookup_def_tcx(this.tcx(), path.span, trait_ref.ref_id) { def::DefTrait(trait_def_id) => { let trait_ref = ast_path_to_trait_ref(this, rscope, @@ -1201,11 +1200,7 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>, ast::TyPolyTraitRef(ref bounds) => { conv_ty_poly_trait_ref(this, rscope, ast_ty.span, &bounds[..]) } - ast::TyPath(_) | ast::TyQPath(_) => { - let simple_path = |&:| match ast_ty.node { - ast::TyPath(ref path) => path, - _ => tcx.sess.span_bug(ast_ty.span, "expected non-qualified path") - }; + ast::TyPath(ref path) | ast::TyQPath(ast::QPath { ref path, .. }) => { let a_def = match tcx.def_map.borrow().get(&ast_ty.id) { None => { tcx.sess @@ -1224,24 +1219,24 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>, let trait_ref = object_path_to_poly_trait_ref(this, rscope, trait_def_id, - simple_path(), + path, &mut projection_bounds); trait_ref_to_object_type(this, rscope, ast_ty.span, trait_ref, projection_bounds, &[]) } def::DefTy(did, _) | def::DefStruct(did) => { - ast_path_to_ty(this, rscope, did, simple_path()).ty + ast_path_to_ty(this, rscope, did, path).ty } def::DefTyParam(space, index, _, name) => { - check_path_args(tcx, simple_path(), NO_TPS | NO_REGIONS); + check_path_args(tcx, path, NO_TPS | NO_REGIONS); ty::mk_param(tcx, space, index, name) } def::DefSelfTy(_) => { // n.b.: resolve guarantees that the this type only appears in a // trait, which we rely upon in various places when creating // substs - check_path_args(tcx, simple_path(), NO_TPS | NO_REGIONS); + check_path_args(tcx, path, NO_TPS | NO_REGIONS); ty::mk_self_type(tcx) } def::DefMod(id) => { @@ -1253,19 +1248,14 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>, panic!("DefPrimTy arm missed in previous ast_ty_to_prim_ty call"); } def::DefAssociatedTy(trait_did, _) => { - let (opt_self_ty, trait_segment, item_segment) = match ast_ty.node { - ast::TyQPath(ref qpath) => { - (Some(&*qpath.self_type), qpath.trait_path.segments.last().unwrap(), - &qpath.item_path) - } - ast::TyPath(ref path) => { - (None, &path.segments[path.segments.len()-2], - path.segments.last().unwrap()) - } - _ => unreachable!() + let opt_self_ty = if let ast::TyQPath(ref qpath) = ast_ty.node { + Some(&*qpath.self_type) + } else { + None }; - qpath_to_ty(this, rscope, ast_ty.span, opt_self_ty, - trait_did, trait_segment, item_segment) + qpath_to_ty(this, rscope, ast_ty.span, opt_self_ty, trait_did, + &path.segments[path.segments.len()-2], + path.segments.last().unwrap()) } def::DefAssociatedPath(provenance, assoc_ident) => { associated_path_def_to_ty(this, ast_ty, provenance, assoc_ident.name) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index b6003071f8c..5b3090be593 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3614,9 +3614,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, let self_ty = fcx.to_ty(&*qpath.self_type); let defn = lookup_def(fcx, expr.span, id); let (scheme, predicates) = type_scheme_and_predicates_for_def(fcx, expr.span, defn); - let mut path = qpath.trait_path.clone(); - path.segments.push(qpath.item_path.clone()); - instantiate_path(fcx, &path, scheme, &predicates, Some(self_ty), + instantiate_path(fcx, &qpath.path, scheme, &predicates, Some(self_ty), defn, expr.span, expr.id); // We always require that the type provided as the value for diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 65c1d7adf48..46e1f6f076a 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -740,8 +740,7 @@ fn convert_item(ccx: &CollectCtxt, it: &ast::Item) { if let Some(ref trait_ref) = *opt_trait_ref { astconv::instantiate_trait_ref(ccx, &ExplicitRscope, - &trait_ref.path, - trait_ref.ref_id, + trait_ref, Some(it.id), Some(selfty), None); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index aff15761ae7..2af81076223 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1500,10 +1500,12 @@ impl Clean for ast::Ty { resolve_type(cx, p.clean(cx), self.id) } TyQPath(ref qp) => { + let mut trait_path = qp.path.clone(); + trait_path.segments.pop(); Type::QPath { - name: qp.item_path.identifier.clean(cx), + name: qp.path.segments.last().unwrap().identifier.clean(cx), self_type: box qp.self_type.clean(cx), - trait_: box resolve_type(cx, qp.trait_path.clean(cx), self.id) + trait_: box resolve_type(cx, trait_path.clean(cx), self.id) } } TyObjectSum(ref lhs, ref bounds) => { diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 5f9776425c3..80a5527cb94 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -757,7 +757,7 @@ pub enum Expr_ { /// type parameters, e.g. foo::bar:: ExprPath(Path), /// A "qualified path", e.g. ` as SomeTrait>::SomeType` - ExprQPath(P), + ExprQPath(QPath), ExprAddrOf(Mutability, P), ExprBreak(Option), @@ -781,13 +781,12 @@ pub enum Expr_ { /// A "qualified path": /// /// as SomeTrait>::SomeAssociatedItem -/// ^~~~~ ^~~~~~~~~ ^~~~~~~~~~~~~~~~~~ -/// self_type trait_path item_path +/// ^~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +/// self_type path #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct QPath { pub self_type: P, - pub trait_path: Path, - pub item_path: PathSegment, + pub path: Path, } #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] @@ -1259,7 +1258,7 @@ pub enum Ty_ { /// Type parameters are stored in the Path itself TyPath(Path), /// A "qualified path", e.g. ` as SomeTrait>::SomeType` - TyQPath(P), + TyQPath(QPath), /// Something like `A+B`. Note that `B` must always be a path. TyObjectSum(P, TyParamBounds), /// A type like `for<'a> Foo<&'a Bar>` diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index baa2fab044f..90842bbab47 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -41,16 +41,16 @@ pub trait AstBuilder { -> ast::Path; fn qpath(&self, self_type: P, - trait_ref: P, - ident: ast::Ident ) - -> P; + trait_path: ast::Path, + ident: ast::Ident) + -> ast::QPath; fn qpath_all(&self, self_type: P, - trait_ref: P, + trait_path: ast::Path, ident: ast::Ident, lifetimes: Vec, types: Vec>, - bindings: Vec> ) - -> P; + bindings: Vec>) + -> ast::QPath; // types fn ty_mt(&self, ty: P, mutbl: ast::Mutability) -> ast::MutTy; @@ -114,7 +114,7 @@ pub trait AstBuilder { // expressions fn expr(&self, span: Span, node: ast::Expr_) -> P; fn expr_path(&self, path: ast::Path) -> P; - fn expr_qpath(&self, span: Span, qpath: P) -> P; + fn expr_qpath(&self, span: Span, qpath: ast::QPath) -> P; fn expr_ident(&self, span: Span, id: ast::Ident) -> P; fn expr_self(&self, span: Span) -> P; @@ -346,40 +346,40 @@ impl<'a> AstBuilder for ExtCtxt<'a> { /// Constructs a qualified path. /// - /// Constructs a path like `::ident`. + /// Constructs a path like `::ident`. fn qpath(&self, self_type: P, - trait_ref: P, + trait_path: ast::Path, ident: ast::Ident) - -> P { - self.qpath_all(self_type, trait_ref, ident, Vec::new(), Vec::new(), Vec::new()) + -> ast::QPath { + self.qpath_all(self_type, trait_path, ident, vec![], vec![], vec![]) } /// Constructs a qualified path. /// - /// Constructs a path like `::ident`. + /// Constructs a path like `::ident<'a, T, A=Bar>`. fn qpath_all(&self, self_type: P, - trait_ref: P, + trait_path: ast::Path, ident: ast::Ident, lifetimes: Vec, types: Vec>, - bindings: Vec> ) - -> P { - let segment = ast::PathSegment { + bindings: Vec>) + -> ast::QPath { + let mut path = trait_path; + path.segments.push(ast::PathSegment { identifier: ident, parameters: ast::AngleBracketedParameters(ast::AngleBracketedParameterData { lifetimes: lifetimes, types: OwnedSlice::from_vec(types), bindings: OwnedSlice::from_vec(bindings), }) - }; + }); - P(ast::QPath { + ast::QPath { self_type: self_type, - trait_ref: trait_ref, - item_path: segment, - }) + path: path + } } fn ty_mt(&self, ty: P, mutbl: ast::Mutability) -> ast::MutTy { @@ -607,7 +607,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { } /// Constructs a QPath expression. - fn expr_qpath(&self, span: Span, qpath: P) -> P { + fn expr_qpath(&self, span: Span, qpath: ast::QPath) -> P { self.expr(span, ast::ExprQPath(qpath)) } diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index c0421fb6f1c..c706ce9065d 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -146,10 +146,6 @@ pub trait Folder : Sized { noop_fold_ty(t, self) } - fn fold_qpath(&mut self, t: P) -> P { - noop_fold_qpath(t, self) - } - fn fold_ty_binding(&mut self, t: P) -> P { noop_fold_ty_binding(t, self) } @@ -430,7 +426,10 @@ pub fn noop_fold_ty(t: P, fld: &mut T) -> P { TyParen(ty) => TyParen(fld.fold_ty(ty)), TyPath(path) => TyPath(fld.fold_path(path)), TyQPath(qpath) => { - TyQPath(fld.fold_qpath(qpath)) + TyQPath(QPath { + self_type: fld.fold_ty(qpath.self_type), + path: fld.fold_path(qpath.path) + }) } TyObjectSum(ty, bounds) => { TyObjectSum(fld.fold_ty(ty), @@ -450,19 +449,6 @@ pub fn noop_fold_ty(t: P, fld: &mut T) -> P { }) } -pub fn noop_fold_qpath(qpath: P, fld: &mut T) -> P { - qpath.map(|qpath| { - QPath { - self_type: fld.fold_ty(qpath.self_type), - trait_path: fld.fold_path(qpath.trait_path), - item_path: PathSegment { - identifier: fld.fold_ident(qpath.item_path.identifier), - parameters: fld.fold_path_parameters(qpath.item_path.parameters), - } - } - }) -} - pub fn noop_fold_foreign_mod(ForeignMod {abi, items}: ForeignMod, fld: &mut T) -> ForeignMod { ForeignMod { @@ -1362,7 +1348,10 @@ pub fn noop_fold_expr(Expr {id, node, span}: Expr, folder: &mut T) -> e2.map(|x| folder.fold_expr(x))) } ExprPath(pth) => ExprPath(folder.fold_path(pth)), - ExprQPath(qpath) => ExprQPath(folder.fold_qpath(qpath)), + ExprQPath(qpath) => ExprQPath(QPath { + self_type: folder.fold_ty(qpath.self_type), + path: folder.fold_path(qpath.path) + }), ExprBreak(opt_ident) => ExprBreak(opt_ident.map(|x| folder.fold_ident(x))), ExprAgain(opt_ident) => ExprAgain(opt_ident.map(|x| folder.fold_ident(x))), ExprRet(e) => ExprRet(e.map(|x| folder.fold_expr(x))), diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index b2f59725855..ad290da7d0a 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1525,18 +1525,14 @@ impl<'a> Parser<'a> { // QUALIFIED PATH `::item` let self_type = self.parse_ty_sum(); self.expect_keyword(keywords::As); - let trait_path = self.parse_path(LifetimeAndTypesWithoutColons); + let mut path = self.parse_path(LifetimeAndTypesWithoutColons); self.expect(&token::Gt); self.expect(&token::ModSep); - let item_name = self.parse_ident(); - TyQPath(P(QPath { - self_type: self_type, - trait_path: trait_path, - item_path: ast::PathSegment { - identifier: item_name, - parameters: ast::PathParameters::none() - } - })) + path.segments.push(ast::PathSegment { + identifier: self.parse_ident(), + parameters: ast::PathParameters::none() + }); + TyQPath(QPath { self_type: self_type, path: path }) } else if self.check(&token::ModSep) || self.token.is_ident() || self.token.is_path() { @@ -2220,7 +2216,7 @@ impl<'a> Parser<'a> { // QUALIFIED PATH `::item::<'a, T>` let self_type = self.parse_ty_sum(); self.expect_keyword(keywords::As); - let trait_path = self.parse_path(LifetimeAndTypesWithoutColons); + let mut path = self.parse_path(LifetimeAndTypesWithoutColons); self.expect(&token::Gt); self.expect(&token::ModSep); let item_name = self.parse_ident(); @@ -2237,15 +2233,13 @@ impl<'a> Parser<'a> { } else { ast::PathParameters::none() }; + path.segments.push(ast::PathSegment { + identifier: item_name, + parameters: parameters + }); let hi = self.span.hi; - return self.mk_expr(lo, hi, ExprQPath(P(QPath { - self_type: self_type, - trait_path: trait_path, - item_path: ast::PathSegment { - identifier: item_name, - parameters: parameters - } - }))); + return self.mk_expr(lo, hi, + ExprQPath(QPath { self_type: self_type, path: path })); } if self.eat_keyword(keywords::Move) { return self.parse_lambda_expr(CaptureByValue); diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 3cfb90a3e68..11502c29ebb 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -373,7 +373,7 @@ pub fn fn_block_to_string(p: &ast::FnDecl) -> String { } pub fn path_to_string(p: &ast::Path) -> String { - $to_string(|s| s.print_path(p, false)) + $to_string(|s| s.print_path(p, false, 0)) } pub fn ident_to_string(id: &ast::Ident) -> String { @@ -730,7 +730,10 @@ impl<'a> State<'a> { None)); } ast::TyPath(ref path) => { - try!(self.print_path(path, false)); + try!(self.print_path(path, false, 0)); + } + ast::TyQPath(ref qpath) => { + try!(self.print_qpath(qpath, false)) } ast::TyObjectSum(ref ty, ref bounds) => { try!(self.print_type(&**ty)); @@ -739,9 +742,6 @@ impl<'a> State<'a> { ast::TyPolyTraitRef(ref bounds) => { try!(self.print_bounds("", &bounds[..])); } - ast::TyQPath(ref qpath) => { - try!(self.print_qpath(&**qpath, false)) - } ast::TyFixedLengthVec(ref ty, ref v) => { try!(word(&mut self.s, "[")); try!(self.print_type(&**ty)); @@ -1018,7 +1018,7 @@ impl<'a> State<'a> { ast::ItemMac(codemap::Spanned { node: ast::MacInvocTT(ref pth, ref tts, _), ..}) => { try!(self.print_visibility(item.vis)); - try!(self.print_path(pth, false)); + try!(self.print_path(pth, false, 0)); try!(word(&mut self.s, "! ")); try!(self.print_ident(item.ident)); try!(self.cbox(indent_unit)); @@ -1033,7 +1033,7 @@ impl<'a> State<'a> { } fn print_trait_ref(&mut self, t: &ast::TraitRef) -> IoResult<()> { - self.print_path(&t.path, false) + self.print_path(&t.path, false, 0) } fn print_formal_lifetime_list(&mut self, lifetimes: &[ast::LifetimeDef]) -> IoResult<()> { @@ -1297,7 +1297,7 @@ impl<'a> State<'a> { ast::MethMac(codemap::Spanned { node: ast::MacInvocTT(ref pth, ref tts, _), ..}) => { // code copied from ItemMac: - try!(self.print_path(pth, false)); + try!(self.print_path(pth, false, 0)); try!(word(&mut self.s, "! ")); try!(self.cbox(indent_unit)); try!(self.popen()); @@ -1514,7 +1514,7 @@ impl<'a> State<'a> { match m.node { // I think it's reasonable to hide the ctxt here: ast::MacInvocTT(ref pth, ref tts, _) => { - try!(self.print_path(pth, false)); + try!(self.print_path(pth, false, 0)); try!(word(&mut self.s, "!")); match delim { token::Paren => try!(self.popen()), @@ -1584,7 +1584,7 @@ impl<'a> State<'a> { path: &ast::Path, fields: &[ast::Field], wth: &Option>) -> IoResult<()> { - try!(self.print_path(path, true)); + try!(self.print_path(path, true, 0)); if !(fields.is_empty() && wth.is_none()) { try!(word(&mut self.s, "{")); try!(self.commasep_cmnt( @@ -1852,8 +1852,8 @@ impl<'a> State<'a> { try!(self.print_expr(&**e)); } } - ast::ExprPath(ref path) => try!(self.print_path(path, true)), - ast::ExprQPath(ref qpath) => try!(self.print_qpath(&**qpath, true)), + ast::ExprPath(ref path) => try!(self.print_path(path, true, 0)), + ast::ExprQPath(ref qpath) => try!(self.print_qpath(qpath, true)), ast::ExprBreak(opt_ident) => { try!(word(&mut self.s, "break")); try!(space(&mut self.s)); @@ -2014,16 +2014,14 @@ impl<'a> State<'a> { fn print_path(&mut self, path: &ast::Path, - colons_before_params: bool) + colons_before_params: bool, + depth: usize) -> IoResult<()> { try!(self.maybe_print_comment(path.span.lo)); - if path.global { - try!(word(&mut self.s, "::")); - } - let mut first = true; - for segment in &path.segments { + let mut first = !path.global; + for segment in &path.segments[..path.segments.len()-depth] { if first { first = false } else { @@ -2047,11 +2045,12 @@ impl<'a> State<'a> { try!(self.print_type(&*qpath.self_type)); try!(space(&mut self.s)); try!(self.word_space("as")); - try!(self.print_path(&qpath.trait_path, false)); + try!(self.print_path(&qpath.path, false, 1)); try!(word(&mut self.s, ">")); try!(word(&mut self.s, "::")); - try!(self.print_ident(qpath.item_path.identifier)); - self.print_path_parameters(&qpath.item_path.parameters, colons_before_params) + let item_segment = qpath.path.segments.last().unwrap(); + try!(self.print_ident(item_segment.identifier)); + self.print_path_parameters(&item_segment.parameters, colons_before_params) } fn print_path_parameters(&mut self, @@ -2156,7 +2155,7 @@ impl<'a> State<'a> { } } ast::PatEnum(ref path, ref args_) => { - try!(self.print_path(path, true)); + try!(self.print_path(path, true, 0)); match *args_ { None => try!(word(&mut self.s, "(..)")), Some(ref args) => { @@ -2170,7 +2169,7 @@ impl<'a> State<'a> { } } ast::PatStruct(ref path, ref fields, etc) => { - try!(self.print_path(path, true)); + try!(self.print_path(path, true, 0)); try!(self.nbsp()); try!(self.word_space("{")); try!(self.commasep_cmnt( @@ -2555,7 +2554,7 @@ impl<'a> State<'a> { } } &ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ref path, ref ty, ..}) => { - try!(self.print_path(path, false)); + try!(self.print_path(path, false, 0)); try!(space(&mut self.s)); try!(self.word_space("=")); try!(self.print_type(&**ty)); @@ -2592,7 +2591,7 @@ impl<'a> State<'a> { pub fn print_view_path(&mut self, vp: &ast::ViewPath) -> IoResult<()> { match vp.node { ast::ViewPathSimple(ident, ref path) => { - try!(self.print_path(path, false)); + try!(self.print_path(path, false, 0)); // FIXME(#6993) can't compare identifiers directly here if path.segments.last().unwrap().identifier.name != @@ -2606,7 +2605,7 @@ impl<'a> State<'a> { } ast::ViewPathGlob(ref path) => { - try!(self.print_path(path, false)); + try!(self.print_path(path, false, 0)); word(&mut self.s, "::*") } @@ -2614,7 +2613,7 @@ impl<'a> State<'a> { if path.segments.is_empty() { try!(word(&mut self.s, "{")); } else { - try!(self.print_path(path, false)); + try!(self.print_path(path, false, 0)); try!(word(&mut self.s, "::{")); } try!(self.commasep(Inconsistent, &idents[..], |s, w| { diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 4e90adea90c..55372585062 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -125,9 +125,6 @@ pub trait Visitor<'v> : Sized { fn visit_path(&mut self, path: &'v Path, _id: ast::NodeId) { walk_path(self, path) } - fn visit_qpath(&mut self, qpath: &'v QPath, _id: ast::NodeId) { - walk_qpath(self, qpath) - } fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v PathSegment) { walk_path_segment(self, path_span, path_segment) } @@ -403,7 +400,8 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) { visitor.visit_path(path, typ.id); } TyQPath(ref qpath) => { - visitor.visit_qpath(&**qpath, typ.id); + visitor.visit_ty(&*qpath.self_type); + visitor.visit_path(&qpath.path, typ.id); } TyObjectSum(ref ty, ref bounds) => { visitor.visit_ty(&**ty); @@ -436,12 +434,6 @@ pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path) { } } -pub fn walk_qpath<'v, V: Visitor<'v>>(visitor: &mut V, qpath: &'v QPath) { - visitor.visit_ty(&*qpath.self_type); - walk_path(visitor, &qpath.trait_path); - visitor.visit_path_segment(qpath.trait_path.span, &qpath.item_path); -} - pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V, path_span: Span, segment: &'v PathSegment) { @@ -871,7 +863,8 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { visitor.visit_path(path, expression.id) } ExprQPath(ref qpath) => { - visitor.visit_qpath(&**qpath, expression.id) + visitor.visit_ty(&*qpath.self_type); + visitor.visit_path(&qpath.path, expression.id); } ExprBreak(_) | ExprAgain(_) => {} ExprRet(ref optional_expression) => { -- cgit 1.4.1-3-g733a5 From 5809f8ae746dbde96e0924b8e422b9e0d092375b Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Thu, 5 Feb 2015 09:19:07 +0200 Subject: rustc_resolve: use the visitor model more, remove redundant repeated lookups. --- src/librustc/middle/astconv_util.rs | 63 +- src/librustc/middle/astencode.rs | 3 - src/librustc/middle/def.rs | 2 - src/librustc/middle/mem_categorization.rs | 2 +- src/librustc_resolve/build_reduced_graph.rs | 47 +- src/librustc_resolve/lib.rs | 844 ++++++--------------- src/librustc_trans/save/mod.rs | 1 - src/librustc_trans/trans/callee.rs | 5 +- src/librustc_typeck/check/mod.rs | 1 - src/librustdoc/clean/mod.rs | 3 - src/librustdoc/html/format.rs | 3 - src/libsyntax/ext/deriving/cmp/eq.rs | 2 +- src/libsyntax/ext/deriving/cmp/ord.rs | 2 +- src/libsyntax/ext/deriving/mod.rs | 6 + src/libsyntax/ext/deriving/primitive.rs | 4 +- src/test/compile-fail/extern-with-type-bounds.rs | 2 +- src/test/compile-fail/glob-resolve1.rs | 3 - .../compile-fail/inner-static-type-parameter.rs | 3 +- src/test/compile-fail/issue-3521-2.rs | 4 +- src/test/compile-fail/issue-3521.rs | 4 +- src/test/compile-fail/issue-3668-2.rs | 4 +- src/test/compile-fail/issue-3668.rs | 1 + .../compile-fail/no-implicit-prelude-nested.rs | 30 +- src/test/compile-fail/no-implicit-prelude.rs | 10 +- src/test/compile-fail/resolve-unknown-trait.rs | 6 +- .../unboxed-closure-sugar-nonexistent-trait.rs | 2 +- 26 files changed, 335 insertions(+), 722 deletions(-) (limited to 'src/libsyntax/ext') diff --git a/src/librustc/middle/astconv_util.rs b/src/librustc/middle/astconv_util.rs index d4680844838..d45c18efee7 100644 --- a/src/librustc/middle/astconv_util.rs +++ b/src/librustc/middle/astconv_util.rs @@ -35,55 +35,36 @@ pub fn check_path_args(tcx: &ty::ctxt, if (flags & NO_REGIONS) != 0 { if path.segments.iter().any(|s| s.parameters.has_lifetimes()) { span_err!(tcx.sess, path.span, E0110, - "region parameters are not allowed on this type"); + "lifetime parameters are not allowed on this type"); } } } pub fn ast_ty_to_prim_ty<'tcx>(tcx: &ty::ctxt<'tcx>, ast_ty: &ast::Ty) -> Option> { - match ast_ty.node { - ast::TyPath(ref path) => { - let a_def = match tcx.def_map.borrow().get(&ast_ty.id) { - None => { - tcx.sess.span_bug(ast_ty.span, - &format!("unbound path {}", - path.repr(tcx))) - } - Some(&d) => d - }; - match a_def { - def::DefPrimTy(nty) => { - match nty { - ast::TyBool => { - check_path_args(tcx, path, NO_TPS | NO_REGIONS); - Some(tcx.types.bool) - } - ast::TyChar => { - check_path_args(tcx, path, NO_TPS | NO_REGIONS); - Some(tcx.types.char) - } - ast::TyInt(it) => { - check_path_args(tcx, path, NO_TPS | NO_REGIONS); - Some(ty::mk_mach_int(tcx, it)) - } - ast::TyUint(uit) => { - check_path_args(tcx, path, NO_TPS | NO_REGIONS); - Some(ty::mk_mach_uint(tcx, uit)) - } - ast::TyFloat(ft) => { - check_path_args(tcx, path, NO_TPS | NO_REGIONS); - Some(ty::mk_mach_float(tcx, ft)) - } - ast::TyStr => { - Some(ty::mk_str(tcx)) - } - } - } - _ => None + if let ast::TyPath(ref path) = ast_ty.node { + let def = match tcx.def_map.borrow().get(&ast_ty.id) { + None => { + tcx.sess.span_bug(ast_ty.span, + &format!("unbound path {}", path.repr(tcx))) } + Some(&d) => d + }; + if let def::DefPrimTy(nty) = def { + check_path_args(tcx, path, NO_TPS | NO_REGIONS); + Some(match nty { + ast::TyBool => tcx.types.bool, + ast::TyChar => tcx.types.char, + ast::TyInt(it) => ty::mk_mach_int(tcx, it), + ast::TyUint(uit) => ty::mk_mach_uint(tcx, uit), + ast::TyFloat(ft) => ty::mk_mach_float(tcx, ft), + ast::TyStr => ty::mk_str(tcx) + }) + } else { + None } - _ => None + } else { + None } } diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index c4b874f7930..37586b08b36 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -456,9 +456,6 @@ impl tr for def::Def { } def::DefStruct(did) => def::DefStruct(did.tr(dcx)), def::DefRegion(nid) => def::DefRegion(dcx.tr_id(nid)), - def::DefTyParamBinder(nid) => { - def::DefTyParamBinder(dcx.tr_id(nid)) - } def::DefLabel(nid) => def::DefLabel(dcx.tr_id(nid)) } } diff --git a/src/librustc/middle/def.rs b/src/librustc/middle/def.rs index a341b55333f..191672775f2 100644 --- a/src/librustc/middle/def.rs +++ b/src/librustc/middle/def.rs @@ -54,7 +54,6 @@ pub enum Def { /// - If it's an ExprPath referring to some tuple struct, then DefMap maps /// it to a def whose id is the StructDef.ctor_id. DefStruct(ast::DefId), - DefTyParamBinder(ast::NodeId), /* struct, impl or trait with ty params */ DefRegion(ast::NodeId), DefLabel(ast::NodeId), DefMethod(ast::DefId /* method */, Option /* trait */, MethodProvenance), @@ -145,7 +144,6 @@ impl Def { DefSelfTy(id) | DefUpvar(id, _) | DefRegion(id) | - DefTyParamBinder(id) | DefLabel(id) => { local_def(id) } diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index d1fba421bbe..59e090a6037 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -580,7 +580,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { } def::DefMod(_) | def::DefForeignMod(_) | def::DefUse(_) | def::DefTrait(_) | def::DefTy(..) | def::DefPrimTy(_) | - def::DefTyParam(..) | def::DefTyParamBinder(..) | def::DefRegion(_) | + def::DefTyParam(..) | def::DefRegion(_) | def::DefLabel(_) | def::DefSelfTy(..) | def::DefAssociatedTy(..) | def::DefAssociatedPath(..)=> { Ok(Rc::new(cmt_ { diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 7c6e537f0be..cc47090198b 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -23,10 +23,8 @@ use Namespace::{TypeNS, ValueNS}; use NameBindings; use ParentLink::{self, ModuleParentLink, BlockParentLink}; use Resolver; -use RibKind::*; use Shadowable; use TypeNsDef; -use TypeParameters::HasTypeParameters; use self::DuplicateCheckingMode::*; use self::NamespaceError::*; @@ -34,7 +32,6 @@ use self::NamespaceError::*; use rustc::metadata::csearch; use rustc::metadata::decoder::{DefLike, DlDef, DlField, DlImpl}; use rustc::middle::def::*; -use rustc::middle::subst::FnSpace; use syntax::ast::{Block, Crate}; use syntax::ast::{DeclItem, DefId}; @@ -773,12 +770,9 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { } /// Constructs the reduced graph for one foreign item. - fn build_reduced_graph_for_foreign_item(&mut self, - foreign_item: &ForeignItem, - parent: &Rc, - f: F) where - F: FnOnce(&mut Resolver), - { + fn build_reduced_graph_for_foreign_item(&mut self, + foreign_item: &ForeignItem, + parent: &Rc) { let name = foreign_item.ident.name; let is_public = foreign_item.vis == ast::Public; let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE; @@ -786,25 +780,15 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { self.add_child(name, parent, ForbidDuplicateValues, foreign_item.span); - match foreign_item.node { - ForeignItemFn(_, ref generics) => { - let def = DefFn(local_def(foreign_item.id), false); - name_bindings.define_value(def, foreign_item.span, modifiers); - - self.with_type_parameter_rib( - HasTypeParameters(generics, - FnSpace, - foreign_item.id, - NormalRibKind), - f); + let def = match foreign_item.node { + ForeignItemFn(..) => { + DefFn(local_def(foreign_item.id), false) } ForeignItemStatic(_, m) => { - let def = DefStatic(local_def(foreign_item.id), m); - name_bindings.define_value(def, foreign_item.span, modifiers); - - f(self.resolver) + DefStatic(local_def(foreign_item.id), m) } - } + }; + name_bindings.define_value(def, foreign_item.span, modifiers); } fn build_reduced_graph_for_block(&mut self, block: &Block, parent: &Rc) -> Rc { @@ -980,7 +964,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { } DefLocal(..) | DefPrimTy(..) | DefTyParam(..) | DefUse(..) | DefUpvar(..) | DefRegion(..) | - DefTyParamBinder(..) | DefLabel(..) | DefSelfTy(..) => { + DefLabel(..) | DefSelfTy(..) => { panic!("didn't expect `{:?}`", def); } } @@ -1241,16 +1225,7 @@ impl<'a, 'b, 'v, 'tcx> Visitor<'v> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { } fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) { - let parent = &self.parent; - self.builder.build_reduced_graph_for_foreign_item(foreign_item, - parent, - |r| { - let mut v = BuildReducedGraphVisitor { - builder: GraphBuilder { resolver: r }, - parent: parent.clone() - }; - visit::walk_foreign_item(&mut v, foreign_item); - }) + self.builder.build_reduced_graph_for_foreign_item(foreign_item, &self.parent); } fn visit_block(&mut self, block: &Block) { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 6584e3cc19d..b211681992b 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -41,14 +41,12 @@ use self::ResolveResult::*; use self::FallbackSuggestion::*; use self::TypeParameters::*; use self::RibKind::*; -use self::MethodSort::*; use self::UseLexicalScopeFlag::*; use self::ModulePrefixResult::*; use self::NameSearchType::*; use self::BareIdentifierPatternResolution::*; use self::ParentLink::*; use self::ModuleKind::*; -use self::TraitReferenceType::*; use self::FallbackChecks::*; use rustc::session::Session; @@ -66,21 +64,18 @@ use rustc::util::lev_distance::lev_distance; use syntax::ast::{Arm, BindByRef, BindByValue, BindingMode, Block, Crate, CrateNum}; use syntax::ast::{DefId, Expr, ExprAgain, ExprBreak, ExprField}; -use syntax::ast::{ExprClosure, ExprLoop, ExprWhile, ExprMethodCall}; +use syntax::ast::{ExprLoop, ExprWhile, ExprMethodCall}; use syntax::ast::{ExprPath, ExprQPath, ExprStruct, FnDecl}; use syntax::ast::{ForeignItemFn, ForeignItemStatic, Generics}; use syntax::ast::{Ident, ImplItem, Item, ItemConst, ItemEnum, ItemExternCrate}; use syntax::ast::{ItemFn, ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, ItemDefaultImpl}; use syntax::ast::{ItemStruct, ItemTrait, ItemTy, ItemUse}; -use syntax::ast::{Local, MethodImplItem, Mod, Name, NodeId}; +use syntax::ast::{Local, MethodImplItem, Name, NodeId}; use syntax::ast::{Pat, PatEnum, PatIdent, PatLit}; -use syntax::ast::{PatRange, PatStruct, Path}; -use syntax::ast::{PolyTraitRef, PrimTy, SelfExplicit}; -use syntax::ast::{RegionTyParamBound, StructField}; -use syntax::ast::{TraitRef, TraitTyParamBound}; -use syntax::ast::{Ty, TyBool, TyChar, TyF32}; -use syntax::ast::{TyF64, TyFloat, TyIs, TyI8, TyI16, TyI32, TyI64, TyInt, TyObjectSum}; -use syntax::ast::{TyParam, TyParamBound, TyPath, TyPtr, TyPolyTraitRef, TyQPath}; +use syntax::ast::{PatRange, PatStruct, Path, PrimTy}; +use syntax::ast::{TraitRef, Ty, TyBool, TyChar, TyF32}; +use syntax::ast::{TyF64, TyFloat, TyIs, TyI8, TyI16, TyI32, TyI64, TyInt}; +use syntax::ast::{TyPath, TyPtr, TyQPath}; use syntax::ast::{TyRptr, TyStr, TyUs, TyU8, TyU16, TyU32, TyU64, TyUint}; use syntax::ast::{TypeImplItem}; use syntax::ast; @@ -89,8 +84,7 @@ use syntax::ast_util::{PostExpansionMethod, local_def, walk_pat}; use syntax::attr::AttrMetaMethods; use syntax::ext::mtwt; use syntax::parse::token::{self, special_names, special_idents}; -use syntax::codemap::{Span, Pos}; -use syntax::owned_slice::OwnedSlice; +use syntax::codemap::{self, Span, Pos}; use syntax::visit::{self, Visitor}; use std::collections::{HashMap, HashSet}; @@ -188,6 +182,72 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> { fn visit_ty(&mut self, ty: &Ty) { self.resolve_type(ty); } + fn visit_generics(&mut self, generics: &Generics) { + self.resolve_generics(generics); + } + fn visit_poly_trait_ref(&mut self, + tref: &ast::PolyTraitRef, + m: &ast::TraitBoundModifier) { + match self.resolve_trait_reference(tref.trait_ref.ref_id, &tref.trait_ref.path, 0) { + Ok(def) => self.record_def(tref.trait_ref.ref_id, def), + Err(_) => { /* error already reported */ } + } + visit::walk_poly_trait_ref(self, tref, m); + } + fn visit_variant(&mut self, variant: &ast::Variant, generics: &Generics) { + if let Some(ref dis_expr) = variant.node.disr_expr { + // resolve the discriminator expr as a constant + self.with_constant_rib(|this| { + this.visit_expr(&**dis_expr); + }); + } + + // `visit::walk_variant` without the discriminant expression. + match variant.node.kind { + ast::TupleVariantKind(ref variant_arguments) => { + for variant_argument in variant_arguments.iter() { + self.visit_ty(&*variant_argument.ty); + } + } + ast::StructVariantKind(ref struct_definition) => { + self.visit_struct_def(&**struct_definition, + variant.node.name, + generics, + variant.node.id); + } + } + } + fn visit_foreign_item(&mut self, foreign_item: &ast::ForeignItem) { + let type_parameters = match foreign_item.node { + ForeignItemFn(_, ref generics) => { + HasTypeParameters(generics, FnSpace, ItemRibKind) + } + ForeignItemStatic(..) => NoTypeParameters + }; + self.with_type_parameter_rib(type_parameters, |this| { + visit::walk_foreign_item(this, foreign_item); + }); + } + fn visit_fn(&mut self, + function_kind: visit::FnKind<'v>, + declaration: &'v FnDecl, + block: &'v Block, + _: Span, + node_id: NodeId) { + let rib_kind = match function_kind { + visit::FkItemFn(_, generics, _, _) => { + self.visit_generics(generics); + ItemRibKind + } + visit::FkMethod(_, generics, method) => { + self.visit_generics(generics); + self.visit_explicit_self(method.pe_explicit_self()); + MethodRibKind + } + visit::FkFnBlock(..) => ClosureRibKind(node_id) + }; + self.resolve_function(rib_kind, declaration, block); + } } /// Contains data for specific types of import directives. @@ -231,9 +291,6 @@ enum TypeParameters<'a> { // were declared on (type, fn, etc) ParamSpace, - // ID of the enclosing item. - NodeId, - // The kind of the rib used for type parameters. RibKind) } @@ -253,8 +310,7 @@ enum RibKind { // methods. Allow references to ty params that impl or trait // binds. Disallow any other upvars (including other ty params that are // upvars). - // parent; method itself - MethodRibKind(NodeId, MethodSort), + MethodRibKind, // We passed through an item scope. Disallow upvars. ItemRibKind, @@ -263,13 +319,6 @@ enum RibKind { ConstantItemRibKind } -// Methods can be required or provided. RequiredMethod methods only occur in traits. -#[derive(Copy, Debug)] -enum MethodSort { - RequiredMethod, - ProvidedMethod(NodeId) -} - #[derive(Copy)] enum UseLexicalScopeFlag { DontUseLexicalScope, @@ -586,16 +635,6 @@ struct NameBindings { value_def: RefCell>, //< Meaning in value namespace. } -/// Ways in which a trait can be referenced -#[derive(Copy)] -enum TraitReferenceType { - TraitImplementation, // impl SomeTrait for T { ... } - TraitDerivation, // trait T : SomeTrait { ... } - TraitBoundingTypeParameter, // fn f() { ... } - TraitObject, // Box SomeTrait> - TraitQPath, // :: -} - impl NameBindings { fn new() -> NameBindings { NameBindings { @@ -2600,14 +2639,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { def_like: DefLike, span: Span) -> Option { - match def_like { - DlDef(d @ DefUpvar(..)) => { + let mut def = match def_like { + DlDef(def) => def, + _ => return Some(def_like) + }; + match def { + DefUpvar(..) => { self.session.span_bug(span, - &format!("unexpected {:?} in bindings", d)) + &format!("unexpected {:?} in bindings", def)) } - DlDef(d @ DefLocal(_)) => { - let node_id = d.def_id().node; - let mut def = d; + DefLocal(node_id) => { for rib in ribs { match rib.kind { NormalRibKind => { @@ -2631,39 +2672,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { }.push(Freevar { def: prev_def, span: span }); seen.insert(node_id); } - MethodRibKind(item_id, _) => { - // If the def is a ty param, and came from the parent - // item, it's ok - match def { - DefTyParam(_, _, did, _) if { - self.def_map.borrow().get(&did.node).cloned() - == Some(DefTyParamBinder(item_id)) - } => {} // ok - DefSelfTy(did) if did == item_id => {} // ok - _ => { - // This was an attempt to access an upvar inside a - // named function item. This is not allowed, so we - // report an error. - - self.resolve_error( - span, - "can't capture dynamic environment in a fn item; \ - use the || { ... } closure form instead"); - - return None; - } - } - } - ItemRibKind => { + ItemRibKind | MethodRibKind => { // This was an attempt to access an upvar inside a // named function item. This is not allowed, so we // report an error. - self.resolve_error( - span, + self.resolve_error(span, "can't capture dynamic environment in a fn item; \ - use the || { ... } closure form instead"); - + use the || { ... } closure form instead"); return None; } ConstantItemRibKind => { @@ -2671,42 +2687,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.resolve_error(span, "attempt to use a non-constant \ value in a constant"); - + return None; } } } - Some(DlDef(def)) } - DlDef(def @ DefTyParam(..)) | - DlDef(def @ DefSelfTy(..)) => { + DefTyParam(..) | DefSelfTy(_) => { for rib in ribs { match rib.kind { - NormalRibKind | ClosureRibKind(..) => { + NormalRibKind | MethodRibKind | ClosureRibKind(..) => { // Nothing to do. Continue. } - MethodRibKind(item_id, _) => { - // If the def is a ty param, and came from the parent - // item, it's ok - match def { - DefTyParam(_, _, did, _) if { - self.def_map.borrow().get(&did.node).cloned() - == Some(DefTyParamBinder(item_id)) - } => {} // ok - DefSelfTy(did) if did == item_id => {} // ok - - _ => { - // This was an attempt to use a type parameter outside - // its scope. - - self.resolve_error(span, - "can't use type parameters from \ - outer function; try using a local \ - type parameter instead"); - - return None; - } - } - } ItemRibKind => { // This was an attempt to use a type parameter outside // its scope. @@ -2715,7 +2706,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { "can't use type parameters from \ outer function; try using a local \ type parameter instead"); - return None; } ConstantItemRibKind => { @@ -2723,14 +2713,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.resolve_error(span, "cannot use an outer type \ parameter in this context"); - + return None; } } } - Some(DlDef(def)) } - _ => Some(def_like) + _ => {} } + Some(DlDef(def)) } /// Searches the current set of local scopes and @@ -2743,13 +2733,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // FIXME #4950: Try caching? for (i, rib) in ribs.iter().enumerate().rev() { - match rib.bindings.get(&name).cloned() { - Some(def_like) => { - return self.upvarify(&ribs[i + 1..], def_like, span); - } - None => { - // Continue. - } + if let Some(def_like) = rib.bindings.get(&name).cloned() { + return self.upvarify(&ribs[i + 1..], def_like, span); } } @@ -2797,47 +2782,21 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { token::get_name(name)); match item.node { - - // enum item: resolve all the variants' discrs, - // then resolve the ty params - ItemEnum(ref enum_def, ref generics) => { + ItemEnum(_, ref generics) | + ItemTy(_, ref generics) | + ItemStruct(_, ref generics) => { self.check_if_primitive_type_name(name, item.span); - for variant in &(*enum_def).variants { - if let Some(ref dis_expr) = variant.node.disr_expr { - // resolve the discriminator expr - // as a constant - self.with_constant_rib(|this| { - this.resolve_expr(&**dis_expr); - }); - } - } - - // n.b. the discr expr gets visited twice. - // but maybe it's okay since the first time will signal an - // error if there is one? -- tjc self.with_type_parameter_rib(HasTypeParameters(generics, TypeSpace, - item.id, ItemRibKind), - |this| { - this.resolve_type_parameters(&generics.ty_params); - this.resolve_where_clause(&generics.where_clause); - visit::walk_item(this, item); - }); + |this| visit::walk_item(this, item)); } - - ItemTy(_, ref generics) => { - self.check_if_primitive_type_name(name, item.span); - + ItemFn(_, _, _, ref generics, _) => { self.with_type_parameter_rib(HasTypeParameters(generics, - TypeSpace, - item.id, + FnSpace, ItemRibKind), - |this| { - this.resolve_type_parameters(&generics.ty_params); - visit::walk_item(this, item); - }); + |this| visit::walk_item(this, item)); } ItemDefaultImpl(_, ref trait_ref) => { @@ -2848,8 +2807,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ref implemented_traits, ref self_type, ref impl_items) => { - self.resolve_implementation(item.id, - generics, + self.resolve_implementation(generics, implemented_traits, &**self_type, &impl_items[..]); @@ -2869,13 +2827,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Create a new rib for the trait-wide type parameters. self.with_type_parameter_rib(HasTypeParameters(generics, TypeSpace, - item.id, NormalRibKind), |this| { - this.resolve_type_parameters(&generics.ty_params); - this.resolve_where_clause(&generics.where_clause); - - this.resolve_type_parameter_bounds(bounds, TraitDerivation); + this.visit_generics(generics); + visit::walk_ty_param_bounds_helper(this, bounds); for trait_item in &(*trait_items) { // Create a new rib for the trait_item-specific type @@ -2883,101 +2838,34 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // // FIXME #4951: Do we need a node ID here? - match *trait_item { - ast::RequiredMethod(ref ty_m) => { - this.with_type_parameter_rib - (HasTypeParameters(&ty_m.generics, - FnSpace, - item.id, - MethodRibKind(item.id, RequiredMethod)), - |this| { - - // Resolve the method-specific type - // parameters. - this.resolve_type_parameters( - &ty_m.generics.ty_params); - this.resolve_where_clause(&ty_m.generics - .where_clause); - - for argument in &ty_m.decl.inputs { - this.resolve_type(&*argument.ty); - } - - if let SelfExplicit(ref typ, _) = ty_m.explicit_self.node { - this.resolve_type(&**typ) - } - - if let ast::Return(ref ret_ty) = ty_m.decl.output { - this.resolve_type(&**ret_ty); - } - }); - } - ast::ProvidedMethod(ref m) => { - this.resolve_method(MethodRibKind(item.id, - ProvidedMethod(m.id)), - &**m) - } - ast::TypeTraitItem(ref data) => { - this.resolve_type_parameter(&data.ty_param); - visit::walk_trait_item(this, trait_item); - } - } + let type_parameters = match *trait_item { + ast::RequiredMethod(ref ty_m) => { + HasTypeParameters(&ty_m.generics, + FnSpace, + MethodRibKind) + } + ast::ProvidedMethod(ref m) => { + HasTypeParameters(m.pe_generics(), + FnSpace, + MethodRibKind) + } + ast::TypeTraitItem(_) => NoTypeParameters, + }; + this.with_type_parameter_rib(type_parameters, |this| { + visit::walk_trait_item(this, trait_item) + }); } }); self.type_ribs.pop(); } - ItemStruct(ref struct_def, ref generics) => { - self.check_if_primitive_type_name(name, item.span); - - self.resolve_struct(item.id, - generics, - &struct_def.fields); - } - - ItemMod(ref module_) => { + ItemMod(_) | ItemForeignMod(_) => { self.with_scope(Some(name), |this| { - this.resolve_module(module_, item.span, name, - item.id); - }); - } - - ItemForeignMod(ref foreign_module) => { - self.with_scope(Some(name), |this| { - for foreign_item in &foreign_module.items { - match foreign_item.node { - ForeignItemFn(_, ref generics) => { - this.with_type_parameter_rib( - HasTypeParameters( - generics, FnSpace, foreign_item.id, - ItemRibKind), - |this| { - this.resolve_type_parameters(&generics.ty_params); - this.resolve_where_clause(&generics.where_clause); - visit::walk_foreign_item(this, &**foreign_item) - }); - } - ForeignItemStatic(..) => { - visit::walk_foreign_item(this, - &**foreign_item); - } - } - } + visit::walk_item(this, item); }); } - ItemFn(ref fn_decl, _, _, ref generics, ref block) => { - self.resolve_function(ItemRibKind, - Some(&**fn_decl), - HasTypeParameters - (generics, - FnSpace, - item.id, - ItemRibKind), - &**block); - } - ItemConst(..) | ItemStatic(..) => { self.with_constant_rib(|this| { visit::walk_item(this, item); @@ -3006,35 +2894,29 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { F: FnOnce(&mut Resolver), { match type_parameters { - HasTypeParameters(generics, space, node_id, rib_kind) => { + HasTypeParameters(generics, space, rib_kind) => { let mut function_type_rib = Rib::new(rib_kind); let mut seen_bindings = HashSet::new(); for (index, type_parameter) in generics.ty_params.iter().enumerate() { let name = type_parameter.ident.name; - debug!("with_type_parameter_rib: {} {}", node_id, - type_parameter.id); + debug!("with_type_parameter_rib: {}", type_parameter.id); if seen_bindings.contains(&name) { self.resolve_error(type_parameter.span, &format!("the name `{}` is already \ - used for a type \ - parameter in this type \ - parameter list", - token::get_name( - name))) + used for a type \ + parameter in this type \ + parameter list", + token::get_name(name))) } seen_bindings.insert(name); - let def_like = DlDef(DefTyParam(space, - index as u32, - local_def(type_parameter.id), - name)); - // Associate this type parameter with - // the item that bound it - self.record_def(type_parameter.id, - (DefTyParamBinder(node_id), LastMod(AllPublic))); // plain insert (no renaming) - function_type_rib.bindings.insert(name, def_like); + function_type_rib.bindings.insert(name, + DlDef(DefTyParam(space, + index as u32, + local_def(type_parameter.id), + name))); } self.type_ribs.push(function_type_rib); } @@ -3072,154 +2954,74 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn resolve_function(&mut self, rib_kind: RibKind, - optional_declaration: Option<&FnDecl>, - type_parameters: TypeParameters, + declaration: &FnDecl, block: &Block) { // Create a value rib for the function. - let function_value_rib = Rib::new(rib_kind); - self.value_ribs.push(function_value_rib); + self.value_ribs.push(Rib::new(rib_kind)); // Create a label rib for the function. - let function_label_rib = Rib::new(rib_kind); - self.label_ribs.push(function_label_rib); - - // If this function has type parameters, add them now. - self.with_type_parameter_rib(type_parameters, |this| { - // Resolve the type parameters. - match type_parameters { - NoTypeParameters => { - // Continue. - } - HasTypeParameters(ref generics, _, _, _) => { - this.resolve_type_parameters(&generics.ty_params); - this.resolve_where_clause(&generics.where_clause); - } - } + self.label_ribs.push(Rib::new(rib_kind)); - // Add each argument to the rib. - match optional_declaration { - None => { - // Nothing to do. - } - Some(declaration) => { - let mut bindings_list = HashMap::new(); - for argument in &declaration.inputs { - this.resolve_pattern(&*argument.pat, - ArgumentIrrefutableMode, - &mut bindings_list); - - this.resolve_type(&*argument.ty); + // Add each argument to the rib. + let mut bindings_list = HashMap::new(); + for argument in &declaration.inputs { + self.resolve_pattern(&*argument.pat, + ArgumentIrrefutableMode, + &mut bindings_list); - debug!("(resolving function) recorded argument"); - } + self.visit_ty(&*argument.ty); - if let ast::Return(ref ret_ty) = declaration.output { - this.resolve_type(&**ret_ty); - } - } - } + debug!("(resolving function) recorded argument"); + } + visit::walk_fn_ret_ty(self, &declaration.output); - // Resolve the function body. - this.resolve_block(&*block); + // Resolve the function body. + self.visit_block(&*block); - debug!("(resolving function) leaving function"); - }); + debug!("(resolving function) leaving function"); self.label_ribs.pop(); self.value_ribs.pop(); } - fn resolve_type_parameters(&mut self, - type_parameters: &OwnedSlice) { - for type_parameter in &**type_parameters { - self.resolve_type_parameter(type_parameter); - } - } - - fn resolve_type_parameter(&mut self, - type_parameter: &TyParam) { - self.check_if_primitive_type_name(type_parameter.ident.name, type_parameter.span); - for bound in &*type_parameter.bounds { - self.resolve_type_parameter_bound(bound, TraitBoundingTypeParameter); - } - match type_parameter.default { - Some(ref ty) => self.resolve_type(&**ty), - None => {} - } - } - - fn resolve_type_parameter_bounds(&mut self, - type_parameter_bounds: &OwnedSlice, - reference_type: TraitReferenceType) { - for type_parameter_bound in &**type_parameter_bounds { - self.resolve_type_parameter_bound(type_parameter_bound, reference_type); - } - } - - fn resolve_type_parameter_bound(&mut self, - type_parameter_bound: &TyParamBound, - reference_type: TraitReferenceType) { - match *type_parameter_bound { - TraitTyParamBound(ref tref, _) => { - self.resolve_trait_reference(tref.trait_ref.ref_id, - &tref.trait_ref.path, 0, - reference_type) - } - RegionTyParamBound(..) => {} - } - } - fn resolve_trait_reference(&mut self, id: NodeId, trait_path: &Path, - path_depth: usize, - reference_type: TraitReferenceType) { + path_depth: usize) + -> Result<(Def, LastPrivate), ()> { match self.resolve_path(id, trait_path, path_depth, TypeNS, true) { - None => { - let path_str = self.path_names_to_string(trait_path, path_depth); - let usage_str = match reference_type { - TraitBoundingTypeParameter => "bound type parameter with", - TraitImplementation => "implement", - TraitDerivation => "derive", - TraitObject => "reference", - TraitQPath => "extract an associated item from", - }; - - let msg = format!("attempt to {} a nonexistent trait `{}`", usage_str, path_str); - self.resolve_error(trait_path.span, &msg[..]); - } - Some(def) => { - match def { - (DefTrait(_), _) => { - debug!("(resolving trait) found trait def: {:?}", def); - self.record_def(id, def); - } - (def, _) => { - self.resolve_error(trait_path.span, - &format!("`{}` is not a trait", - self.path_names_to_string(trait_path, path_depth))); - - // If it's a typedef, give a note - if let DefTy(..) = def { - self.session.span_note(trait_path.span, - &format!("`type` aliases cannot be used for traits")); - } - } + Some(def @ (DefTrait(_), _)) => { + debug!("(resolving trait) found trait def: {:?}", def); + Ok(def) + } + Some((def, _)) => { + self.resolve_error(trait_path.span, + &format!("`{}` is not a trait", + self.path_names_to_string(trait_path, path_depth))); + + // If it's a typedef, give a note + if let DefTy(..) = def { + self.session.span_note(trait_path.span, + "`type` aliases cannot be used for traits"); } + Err(()) + } + None => { + let msg = format!("use of undeclared trait name `{}`", + self.path_names_to_string(trait_path, path_depth)); + self.resolve_error(trait_path.span, &msg[]); + Err(()) } } } - fn resolve_where_clause(&mut self, where_clause: &ast::WhereClause) { - for predicate in &where_clause.predicates { + fn resolve_generics(&mut self, generics: &Generics) { + for type_parameter in &generics.ty_params { + self.check_if_primitive_type_name(type_parameter.ident.name, type_parameter.span); + } + for predicate in &generics.where_clause.predicates { match predicate { - &ast::WherePredicate::BoundPredicate(ref bound_pred) => { - self.resolve_type(&*bound_pred.bounded_ty); - - for bound in &*bound_pred.bounds { - self.resolve_type_parameter_bound(bound, TraitBoundingTypeParameter); - } - } + &ast::WherePredicate::BoundPredicate(_) | &ast::WherePredicate::RegionPredicate(_) => {} &ast::WherePredicate::EqPredicate(ref eq_pred) => { match self.resolve_path(eq_pred.id, &eq_pred.path, 0, TypeNS, true) { @@ -3231,53 +3033,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { "undeclared associated type"); } } - - self.resolve_type(&*eq_pred.ty); } } } - } - - fn resolve_struct(&mut self, - id: NodeId, - generics: &Generics, - fields: &[StructField]) { - // If applicable, create a rib for the type parameters. - self.with_type_parameter_rib(HasTypeParameters(generics, - TypeSpace, - id, - ItemRibKind), - |this| { - // Resolve the type parameters. - this.resolve_type_parameters(&generics.ty_params); - this.resolve_where_clause(&generics.where_clause); - - // Resolve fields. - for field in fields { - this.resolve_type(&*field.node.ty); - } - }); - } - - // Does this really need to take a RibKind or is it always going - // to be NormalRibKind? - fn resolve_method(&mut self, - rib_kind: RibKind, - method: &ast::Method) { - let method_generics = method.pe_generics(); - let type_parameters = HasTypeParameters(method_generics, - FnSpace, - method.id, - rib_kind); - - if let SelfExplicit(ref typ, _) = method.pe_explicit_self().node { - self.resolve_type(&**typ); - } - - self.resolve_function(rib_kind, - Some(method.pe_fn_decl()), - type_parameters, - method.pe_body()); + visit::walk_generics(self, generics); } fn with_current_self_type(&mut self, self_type: &Ty, f: F) -> T where @@ -3295,22 +3054,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { f: F) -> T where F: FnOnce(&mut Resolver) -> T, { - let new_val = match *opt_trait_ref { - Some(ref trait_ref) => { - self.resolve_trait_reference(trait_ref.ref_id, - &trait_ref.path, 0, - TraitImplementation); - - match self.def_map.borrow().get(&trait_ref.ref_id) { - Some(def) => { - let did = def.def_id(); - Some((did, trait_ref.clone())) - } - None => None + let mut new_val = None; + if let Some(ref trait_ref) = *opt_trait_ref { + match self.resolve_trait_reference(trait_ref.ref_id, &trait_ref.path, 0) { + Ok(def) => { + self.record_def(trait_ref.ref_id, def); + new_val = Some((def.0.def_id(), trait_ref.clone())); } + Err(_) => { /* error was already reported */ } } - None => None - }; + visit::walk_trait_ref(self, trait_ref); + } let original_trait_ref = replace(&mut self.current_trait_ref, new_val); let result = f(self); self.current_trait_ref = original_trait_ref; @@ -3318,7 +3072,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } fn resolve_implementation(&mut self, - id: NodeId, generics: &Generics, opt_trait_reference: &Option, self_type: &Ty, @@ -3326,17 +3079,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // If applicable, create a rib for the type parameters. self.with_type_parameter_rib(HasTypeParameters(generics, TypeSpace, - id, - NormalRibKind), + ItemRibKind), |this| { // Resolve the type parameters. - this.resolve_type_parameters(&generics.ty_params); - this.resolve_where_clause(&generics.where_clause); + this.visit_generics(generics); // Resolve the trait reference, if necessary. this.with_optional_trait_ref(opt_trait_reference, |this| { // Resolve the self type. - this.resolve_type(self_type); + this.visit_ty(self_type); this.with_current_self_type(self_type, |this| { for impl_item in impl_items { @@ -3349,9 +3100,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // We also need a new scope for the method- // specific type parameters. - this.resolve_method( - MethodRibKind(id, ProvidedMethod(method.id)), - &**method); + let type_parameters = + HasTypeParameters(method.pe_generics(), + FnSpace, + MethodRibKind); + this.with_type_parameter_rib(type_parameters, |this| { + visit::walk_method_helper(this, &**method); + }); } TypeImplItem(ref typedef) => { // If this is a trait impl, ensure the method @@ -3359,7 +3114,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { this.check_trait_item(typedef.ident.name, typedef.span); - this.resolve_type(&*typedef.typ); + this.visit_ty(&*typedef.typ); } } } @@ -3405,34 +3160,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - fn resolve_module(&mut self, module: &Mod, _span: Span, - _name: Name, id: NodeId) { - // Write the implementations in scope into the module metadata. - debug!("(resolving module) resolving module ID {}", id); - visit::walk_mod(self, module); - } - fn resolve_local(&mut self, local: &Local) { // Resolve the type. - if let Some(ref ty) = local.ty { - self.resolve_type(&**ty); - } + visit::walk_ty_opt(self, &local.ty); - // Resolve the initializer, if necessary. - match local.init { - None => { - // Nothing to do. - } - Some(ref initializer) => { - self.resolve_expr(&**initializer); - } - } + // Resolve the initializer. + visit::walk_expr_opt(self, &local.init); // Resolve the pattern. - let mut bindings_list = HashMap::new(); self.resolve_pattern(&*local.pat, LocalIrrefutableMode, - &mut bindings_list); + &mut HashMap::new()); } // build a map from pattern identifiers to binding-info's. @@ -3510,7 +3248,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.check_consistent_bindings(arm); visit::walk_expr_opt(self, &arm.guard); - self.resolve_expr(&*arm.body); + self.visit_expr(&*arm.body); self.value_ribs.pop(); } @@ -3566,49 +3304,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // on whether the path has multiple elements in it or not. TyPath(ref path) | TyQPath(ast::QPath { ref path, .. }) => { - if let TyQPath(ref qpath) = ty.node { - self.resolve_type(&*qpath.self_type); - - // Just make sure the trait is valid, don't record a def. - self.resolve_trait_reference(ty.id, path, 1, TraitQPath); - self.def_map.borrow_mut().remove(&ty.id); + if let TyQPath(_) = ty.node { + // Make sure the trait is valid. + self.resolve_trait_reference(ty.id, path, 1); } // This is a path in the type namespace. Walk through scopes // looking for it. - let mut result_def = None; - - // First, check to see whether the name is a primitive type. - if path.segments.len() == 1 { - let id = path.segments.last().unwrap().identifier; - - match self.primitive_type_table - .primitive_types - .get(&id.name) { - - Some(&primitive_type) => { - result_def = - Some((DefPrimTy(primitive_type), LastMod(AllPublic))); - - if path.segments[0].parameters.has_lifetimes() { - span_err!(self.session, path.span, E0157, - "lifetime parameters are not allowed on this type"); - } else if !path.segments[0].parameters.is_empty() { - span_err!(self.session, path.span, E0153, - "type parameters are not allowed on this type"); - } - } - None => { - // Continue. - } - } - } - - if let None = result_def { - result_def = self.resolve_path(ty.id, path, 0, TypeNS, true); - } - - match result_def { + match self.resolve_path(ty.id, path, 0, TypeNS, true) { Some(def) => { // Write the result into the def map. debug!("(resolving type) writing resolution for `{}` \ @@ -3628,21 +3331,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } } - - TyObjectSum(ref ty, ref bound_vec) => { - self.resolve_type(&**ty); - self.resolve_type_parameter_bounds(bound_vec, TraitBoundingTypeParameter); - } - - TyPolyTraitRef(ref bounds) => { - self.resolve_type_parameter_bounds(bounds, TraitObject); - visit::walk_ty(self, ty); - } - _ => { - // Just resolve embedded types. - visit::walk_ty(self, ty); - } + _ => {} } + // Resolve embedded types. + visit::walk_ty(self, ty); } fn resolve_pattern(&mut self, @@ -3669,7 +3361,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let renamed = mtwt::resolve(ident); match self.resolve_bare_identifier_pattern(ident.name, pattern.span) { - FoundStructOrEnumVariant(ref def, lp) + FoundStructOrEnumVariant(def, lp) if mode == RefutableMode => { debug!("(resolving pattern) resolving `{}` to \ struct or enum variant", @@ -3679,7 +3371,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { pattern, binding_mode, "an enum variant"); - self.record_def(pattern.id, (def.clone(), lp)); + self.record_def(pattern.id, (def, lp)); } FoundStructOrEnumVariant(..) => { self.resolve_error( @@ -3689,7 +3381,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { scope", token::get_name(renamed))); } - FoundConst(ref def, lp) if mode == RefutableMode => { + FoundConst(def, lp) if mode == RefutableMode => { debug!("(resolving pattern) resolving `{}` to \ constant", token::get_name(renamed)); @@ -3698,7 +3390,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { pattern, binding_mode, "a constant"); - self.record_def(pattern.id, (def.clone(), lp)); + self.record_def(pattern.id, (def, lp)); } FoundConst(..) => { self.resolve_error(pattern.span, @@ -3782,22 +3474,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { token::get_ident(path.segments.last().unwrap().identifier))); } } - - // Check the types in the path pattern. - for ty in path.segments - .iter() - .flat_map(|s| s.parameters.types().into_iter()) { - self.resolve_type(&**ty); - } - } - - PatLit(ref expr) => { - self.resolve_expr(&**expr); - } - - PatRange(ref first_expr, ref last_expr) => { - self.resolve_expr(&**first_expr); - self.resolve_expr(&**last_expr); + visit::walk_path(self, path); } PatStruct(ref path, _, _) => { @@ -3813,6 +3490,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.resolve_error(path.span, &msg[..]); } } + visit::walk_path(self, path); + } + + PatLit(_) | PatRange(..) => { + visit::walk_pat(self, pattern); } _ => { @@ -3895,14 +3577,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let span = path.span; let segments = &path.segments[..path.segments.len()-path_depth]; - // First, resolve the types and associated type bindings. - for ty in segments.iter().flat_map(|s| s.parameters.types().into_iter()) { - self.resolve_type(&**ty); - } - for binding in segments.iter().flat_map(|s| s.parameters.bindings().into_iter()) { - self.resolve_type(&*binding.ty); - } - // A special case for sugared associated type paths `T::A` where `T` is // a type parameter and `A` is an associated type on some bound of `T`. if namespace == TypeNS && segments.len() == 2 { @@ -3957,7 +3631,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { return def; } - return unqualified_def; + unqualified_def } // resolve a single identifier (used as a varref) @@ -3967,20 +3641,24 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { check_ribs: bool, span: Span) -> Option<(Def, LastPrivate)> { + // First, check to see whether the name is a primitive type. + if namespace == TypeNS { + if let Some(&prim_ty) = self.primitive_type_table + .primitive_types + .get(&identifier.name) { + return Some((DefPrimTy(prim_ty), LastMod(AllPublic))); + } + } + if check_ribs { - match self.resolve_identifier_in_local_ribs(identifier, - namespace, - span) { - Some(def) => { - return Some((def, LastMod(AllPublic))); - } - None => { - // Continue. - } + if let Some(def) = self.resolve_identifier_in_local_ribs(identifier, + namespace, + span) { + return Some((def, LastMod(AllPublic))); } } - return self.resolve_item_by_name_in_lexical_scope(identifier.name, namespace); + self.resolve_item_by_name_in_lexical_scope(identifier.name, namespace) } // FIXME #4952: Merge me with resolve_name_in_module? @@ -4197,10 +3875,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { local: {:?}", token::get_ident(ident), def); - return Some(def); + Some(def) } Some(DlField) | Some(DlImpl(_)) | None => { - return None; + None } } } @@ -4425,12 +4103,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // multiple elements in it or not. ExprPath(ref path) | ExprQPath(ast::QPath { ref path, .. }) => { - if let ExprQPath(ref qpath) = expr.node { - self.resolve_type(&*qpath.self_type); - - // Just make sure the trait is valid, don't record a def. - self.resolve_trait_reference(expr.id, path, 1, TraitQPath); - self.def_map.borrow_mut().remove(&expr.id); + if let ExprQPath(_) = expr.node { + // Make sure the trait is valid. + self.resolve_trait_reference(expr.id, path, 1); } // This is a local path in the value namespace. Walk through @@ -4482,13 +4157,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { _ => { let mut method_scope = false; self.value_ribs.iter().rev().all(|rib| { - let res = match *rib { - Rib { bindings: _, kind: MethodRibKind(_, _) } => true, - Rib { bindings: _, kind: ItemRibKind } => false, + method_scope = match rib.kind { + MethodRibKind => true, + ItemRibKind | ConstantItemRibKind => false, _ => return true, // Keep advancing }; - - method_scope = res; false // Stop advancing }); @@ -4537,21 +4210,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { visit::walk_expr(self, expr); } - ExprClosure(_, ref fn_decl, ref block) => { - self.resolve_function(ClosureRibKind(expr.id), - Some(&**fn_decl), NoTypeParameters, - &**block); - } - ExprStruct(ref path, _, _) => { // Resolve the path to the structure it goes to. We don't // check to ensure that the path is actually a structure; that // is checked later during typeck. match self.resolve_path(expr.id, path, 0, TypeNS, false) { Some(definition) => self.record_def(expr.id, definition), - result => { - debug!("(resolving expression) didn't find struct \ - def: {:?}", result); + None => { + debug!("(resolving expression) didn't find struct def",); let msg = format!("`{}` does not name a structure", self.path_names_to_string(path, 0)); self.resolve_error(path.span, &msg[..]); @@ -4704,26 +4370,20 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { found_traits } - fn record_def(&mut self, node_id: NodeId, (def, lp): (Def, LastPrivate)) { + fn record_def(&mut self, + node_id: NodeId, + (def, lp): (Def, LastPrivate)) { debug!("(recording def) recording {:?} for {}, last private {:?}", def, node_id, lp); assert!(match lp {LastImport{..} => false, _ => true}, "Import should only be used for `use` directives"); self.last_private.insert(node_id, lp); - match self.def_map.borrow_mut().entry(node_id) { - // Resolve appears to "resolve" the same ID multiple - // times, so here is a sanity check it at least comes to - // the same conclusion! - nmatsakis - Occupied(entry) => if def != *entry.get() { - self.session - .bug(&format!("node_id {} resolved first to {:?} and \ - then {:?}", - node_id, - *entry.get(), - def)); - }, - Vacant(entry) => { entry.insert(def); }, + if let Some(prev_def) = self.def_map.borrow_mut().insert(node_id, def) { + let span = self.ast_map.opt_span(node_id).unwrap_or(codemap::DUMMY_SP); + self.session.span_bug(span, &format!("path resolved multiple times \ + ({:?} before, {:?} now)", + prev_def, def)); } } diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs index 6a20938da2e..531700b9563 100644 --- a/src/librustc_trans/save/mod.rs +++ b/src/librustc_trans/save/mod.rs @@ -250,7 +250,6 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { def::DefSelfTy(_) | def::DefRegion(_) | - def::DefTyParamBinder(_) | def::DefLabel(_) | def::DefStaticMethod(..) | def::DefTyParam(..) | diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs index 25568db8148..9dbcbc8b1a2 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -209,9 +209,8 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr) } def::DefMod(..) | def::DefForeignMod(..) | def::DefTrait(..) | def::DefTy(..) | def::DefPrimTy(..) | def::DefAssociatedTy(..) | - def::DefUse(..) | def::DefTyParamBinder(..) | - def::DefRegion(..) | def::DefLabel(..) | def::DefTyParam(..) | - def::DefSelfTy(..) | def::DefAssociatedPath(..) => { + def::DefUse(..) | def::DefRegion(..) | def::DefLabel(..) | + def::DefTyParam(..) | def::DefSelfTy(..) | def::DefAssociatedPath(..) => { bcx.tcx().sess.span_bug( ref_expr.span, &format!("cannot translate def {:?} \ diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 5b3090be593..9d303f492eb 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4729,7 +4729,6 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, def::DefSelfTy(..) | def::DefStruct(..) | def::DefVariant(..) | - def::DefTyParamBinder(..) | def::DefTy(..) | def::DefAssociatedTy(..) | def::DefAssociatedPath(..) | diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 2af81076223..7a27159bc47 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1344,8 +1344,6 @@ pub enum Type { typarams: Option>, did: ast::DefId, }, - // I have no idea how to usefully use this. - TyParamBinder(ast::NodeId), /// For parameterized types, so the consumer of the JSON don't go /// looking for types which don't exist anywhere. Generic(String), @@ -2416,7 +2414,6 @@ fn resolve_type(cx: &DocContext, ast::TyFloat(ast::TyF64) => return Primitive(F64), }, def::DefTyParam(_, _, _, n) => return Generic(token::get_name(n).to_string()), - def::DefTyParamBinder(i) => return TyParamBinder(i), _ => {} }; let did = register_def(&*cx, def); diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 11d9ecac14d..03a2d708ee4 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -454,9 +454,6 @@ fn tybounds(w: &mut fmt::Formatter, impl fmt::Display for clean::Type { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - clean::TyParamBinder(id) => { - f.write_str(&cache().typarams[ast_util::local_def(id)]) - } clean::Generic(ref name) => { f.write_str(name) } diff --git a/src/libsyntax/ext/deriving/cmp/eq.rs b/src/libsyntax/ext/deriving/cmp/eq.rs index 91212a86958..80ef882745f 100644 --- a/src/libsyntax/ext/deriving/cmp/eq.rs +++ b/src/libsyntax/ext/deriving/cmp/eq.rs @@ -70,7 +70,7 @@ pub fn expand_deriving_eq(cx: &mut ExtCtxt, generics: LifetimeBounds::empty(), explicit_self: borrowed_explicit_self(), args: vec!(borrowed_self()), - ret_ty: Literal(path!(bool)), + ret_ty: Literal(path_local!(bool)), attributes: attrs, combine_substructure: combine_substructure(box |a, b, c| { $f(a, b, c) diff --git a/src/libsyntax/ext/deriving/cmp/ord.rs b/src/libsyntax/ext/deriving/cmp/ord.rs index b109850a6bd..be4a33002aa 100644 --- a/src/libsyntax/ext/deriving/cmp/ord.rs +++ b/src/libsyntax/ext/deriving/cmp/ord.rs @@ -36,7 +36,7 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt, generics: LifetimeBounds::empty(), explicit_self: borrowed_explicit_self(), args: vec!(borrowed_self()), - ret_ty: Literal(path!(bool)), + ret_ty: Literal(path_local!(bool)), attributes: attrs, combine_substructure: combine_substructure(box |cx, span, substr| { cs_op($op, $equal, cx, span, substr) diff --git a/src/libsyntax/ext/deriving/mod.rs b/src/libsyntax/ext/deriving/mod.rs index eee780f457c..973c8f5fa1e 100644 --- a/src/libsyntax/ext/deriving/mod.rs +++ b/src/libsyntax/ext/deriving/mod.rs @@ -30,6 +30,12 @@ macro_rules! path { ) } +macro_rules! path_local { + ($x:ident) => ( + ::ext::deriving::generic::ty::Path::new_local(stringify!($x)) + ) +} + macro_rules! pathvec_std { ($cx:expr, $first:ident :: $($rest:ident)::+) => ( if $cx.use_std { diff --git a/src/libsyntax/ext/deriving/primitive.rs b/src/libsyntax/ext/deriving/primitive.rs index 22c87d978c9..3b96292323a 100644 --- a/src/libsyntax/ext/deriving/primitive.rs +++ b/src/libsyntax/ext/deriving/primitive.rs @@ -38,7 +38,7 @@ pub fn expand_deriving_from_primitive(cx: &mut ExtCtxt, name: "from_i64", generics: LifetimeBounds::empty(), explicit_self: None, - args: vec!(Literal(path!(i64))), + args: vec!(Literal(path_local!(i64))), ret_ty: Literal(Path::new_(pathvec_std!(cx, core::option::Option), None, vec!(box Self_), @@ -53,7 +53,7 @@ pub fn expand_deriving_from_primitive(cx: &mut ExtCtxt, name: "from_u64", generics: LifetimeBounds::empty(), explicit_self: None, - args: vec!(Literal(path!(u64))), + args: vec!(Literal(path_local!(u64))), ret_ty: Literal(Path::new_(pathvec_std!(cx, core::option::Option), None, vec!(box Self_), diff --git a/src/test/compile-fail/extern-with-type-bounds.rs b/src/test/compile-fail/extern-with-type-bounds.rs index ade8b397e00..21334e1d513 100644 --- a/src/test/compile-fail/extern-with-type-bounds.rs +++ b/src/test/compile-fail/extern-with-type-bounds.rs @@ -24,7 +24,7 @@ extern "rust-intrinsic" { // Unresolved bounds should still error. fn align_of() -> usize; - //~^ ERROR attempt to bound type parameter with a nonexistent trait `NoSuchTrait` + //~^ ERROR use of undeclared trait name `NoSuchTrait` } fn main() {} diff --git a/src/test/compile-fail/glob-resolve1.rs b/src/test/compile-fail/glob-resolve1.rs index fce8a07d727..181503db818 100644 --- a/src/test/compile-fail/glob-resolve1.rs +++ b/src/test/compile-fail/glob-resolve1.rs @@ -36,9 +36,6 @@ fn main() { import(); //~ ERROR: unresolved foo::(); //~ ERROR: undeclared - //~^ ERROR: undeclared foo::(); //~ ERROR: undeclared - //~^ ERROR: undeclared foo::(); //~ ERROR: undeclared - //~^ ERROR: undeclared } diff --git a/src/test/compile-fail/inner-static-type-parameter.rs b/src/test/compile-fail/inner-static-type-parameter.rs index abd7efe0e8e..cf2a70deee5 100644 --- a/src/test/compile-fail/inner-static-type-parameter.rs +++ b/src/test/compile-fail/inner-static-type-parameter.rs @@ -14,7 +14,8 @@ enum Bar { What } fn foo() { static a: Bar = Bar::What; - //~^ ERROR: cannot use an outer type parameter in this context + //~^ ERROR cannot use an outer type parameter in this context + //~| ERROR use of undeclared type name `T` } fn main() { diff --git a/src/test/compile-fail/issue-3521-2.rs b/src/test/compile-fail/issue-3521-2.rs index 678618d7216..ad5bc4e445c 100644 --- a/src/test/compile-fail/issue-3521-2.rs +++ b/src/test/compile-fail/issue-3521-2.rs @@ -11,7 +11,9 @@ fn main() { let foo = 100; - static y: isize = foo + 1; //~ ERROR: attempt to use a non-constant value in a constant + static y: isize = foo + 1; + //~^ ERROR attempt to use a non-constant value in a constant + //~| ERROR unresolved name `foo` println!("{}", y); } diff --git a/src/test/compile-fail/issue-3521.rs b/src/test/compile-fail/issue-3521.rs index c49959c16a6..f06aa45ac38 100644 --- a/src/test/compile-fail/issue-3521.rs +++ b/src/test/compile-fail/issue-3521.rs @@ -13,7 +13,9 @@ fn main() { #[derive(Debug)] enum Stuff { - Bar = foo //~ ERROR attempt to use a non-constant value in a constant + Bar = foo + //~^ ERROR attempt to use a non-constant value in a constant + //~| ERROR unresolved name `foo` } println!("{}", Stuff::Bar); diff --git a/src/test/compile-fail/issue-3668-2.rs b/src/test/compile-fail/issue-3668-2.rs index 0577b152723..a09c8090de0 100644 --- a/src/test/compile-fail/issue-3668-2.rs +++ b/src/test/compile-fail/issue-3668-2.rs @@ -9,7 +9,9 @@ // except according to those terms. fn f(x:isize) { - static child: isize = x + 1; //~ ERROR attempt to use a non-constant value in a constant + static child: isize = x + 1; + //~^ ERROR attempt to use a non-constant value in a constant + //~| ERROR unresolved name `x` } fn main() {} diff --git a/src/test/compile-fail/issue-3668.rs b/src/test/compile-fail/issue-3668.rs index 9c31dc1e38e..9b7476244f0 100644 --- a/src/test/compile-fail/issue-3668.rs +++ b/src/test/compile-fail/issue-3668.rs @@ -17,6 +17,7 @@ impl PTrait for P { fn getChildOption(&self) -> Option> { static childVal: Box

= self.child.get(); //~^ ERROR attempt to use a non-constant value in a constant + //~| ERROR unresolved name `self` panic!(); } } diff --git a/src/test/compile-fail/no-implicit-prelude-nested.rs b/src/test/compile-fail/no-implicit-prelude-nested.rs index 2fb097f111d..526750257d2 100644 --- a/src/test/compile-fail/no-implicit-prelude-nested.rs +++ b/src/test/compile-fail/no-implicit-prelude-nested.rs @@ -18,11 +18,11 @@ mod foo { mod baz { struct Test; - impl Add for Test {} //~ ERROR: attempt to implement a nonexistent trait - impl Clone for Test {} //~ ERROR: attempt to implement a nonexistent trait - impl Iterator for Test {} //~ ERROR: attempt to implement a nonexistent trait - impl ToString for Test {} //~ ERROR: attempt to implement a nonexistent trait - impl Writer for Test {} //~ ERROR: attempt to implement a nonexistent trait + impl Add for Test {} //~ ERROR: use of undeclared trait + impl Clone for Test {} //~ ERROR: use of undeclared trait + impl Iterator for Test {} //~ ERROR: use of undeclared trait + impl ToString for Test {} //~ ERROR: use of undeclared trait + impl Writer for Test {} //~ ERROR: use of undeclared trait fn foo() { drop(2) //~ ERROR: unresolved name @@ -30,11 +30,11 @@ mod foo { } struct Test; - impl Add for Test {} //~ ERROR: attempt to implement a nonexistent trait - impl Clone for Test {} //~ ERROR: attempt to implement a nonexistent trait - impl Iterator for Test {} //~ ERROR: attempt to implement a nonexistent trait - impl ToString for Test {} //~ ERROR: attempt to implement a nonexistent trait - impl Writer for Test {} //~ ERROR: attempt to implement a nonexistent trait + impl Add for Test {} //~ ERROR: use of undeclared trait + impl Clone for Test {} //~ ERROR: use of undeclared trait + impl Iterator for Test {} //~ ERROR: use of undeclared trait + impl ToString for Test {} //~ ERROR: use of undeclared trait + impl Writer for Test {} //~ ERROR: use of undeclared trait fn foo() { drop(2) //~ ERROR: unresolved name @@ -45,11 +45,11 @@ fn qux() { #[no_implicit_prelude] mod qux_inner { struct Test; - impl Add for Test {} //~ ERROR: attempt to implement a nonexistent trait - impl Clone for Test {} //~ ERROR: attempt to implement a nonexistent trait - impl Iterator for Test {} //~ ERROR: attempt to implement a nonexistent trait - impl ToString for Test {} //~ ERROR: attempt to implement a nonexistent trait - impl Writer for Test {} //~ ERROR: attempt to implement a nonexistent trait + impl Add for Test {} //~ ERROR: use of undeclared trait + impl Clone for Test {} //~ ERROR: use of undeclared trait + impl Iterator for Test {} //~ ERROR: use of undeclared trait + impl ToString for Test {} //~ ERROR: use of undeclared trait + impl Writer for Test {} //~ ERROR: use of undeclared trait fn foo() { drop(2) //~ ERROR: unresolved name diff --git a/src/test/compile-fail/no-implicit-prelude.rs b/src/test/compile-fail/no-implicit-prelude.rs index c0f7bea25b5..c4bcd33b93b 100644 --- a/src/test/compile-fail/no-implicit-prelude.rs +++ b/src/test/compile-fail/no-implicit-prelude.rs @@ -17,11 +17,11 @@ // fail with the same error message). struct Test; -impl Add for Test {} //~ ERROR: attempt to implement a nonexistent trait -impl Clone for Test {} //~ ERROR: attempt to implement a nonexistent trait -impl Iterator for Test {} //~ ERROR: attempt to implement a nonexistent trait -impl ToString for Test {} //~ ERROR: attempt to implement a nonexistent trait -impl Writer for Test {} //~ ERROR: attempt to implement a nonexistent trait +impl Add for Test {} //~ ERROR: use of undeclared trait +impl Clone for Test {} //~ ERROR: use of undeclared trait +impl Iterator for Test {} //~ ERROR: use of undeclared trait +impl ToString for Test {} //~ ERROR: use of undeclared trait +impl Writer for Test {} //~ ERROR: use of undeclared trait fn main() { drop(2) //~ ERROR: unresolved name diff --git a/src/test/compile-fail/resolve-unknown-trait.rs b/src/test/compile-fail/resolve-unknown-trait.rs index 0d0dc0a05d1..3983a84f6ad 100644 --- a/src/test/compile-fail/resolve-unknown-trait.rs +++ b/src/test/compile-fail/resolve-unknown-trait.rs @@ -10,11 +10,11 @@ trait NewTrait : SomeNonExistentTrait {} -//~^ ERROR attempt to derive a nonexistent trait `SomeNonExistentTrait` +//~^ ERROR use of undeclared trait name `SomeNonExistentTrait` impl SomeNonExistentTrait for isize {} -//~^ ERROR attempt to implement a nonexistent trait `SomeNonExistentTrait` +//~^ ERROR use of undeclared trait name `SomeNonExistentTrait` fn f() {} -//~^ ERROR attempt to bound type parameter with a nonexistent trait `SomeNonExistentTrait` +//~^ ERROR use of undeclared trait name `SomeNonExistentTrait` diff --git a/src/test/compile-fail/unboxed-closure-sugar-nonexistent-trait.rs b/src/test/compile-fail/unboxed-closure-sugar-nonexistent-trait.rs index 12f62d805e1..f28bf7acadd 100644 --- a/src/test/compile-fail/unboxed-closure-sugar-nonexistent-trait.rs +++ b/src/test/compile-fail/unboxed-closure-sugar-nonexistent-trait.rs @@ -10,7 +10,7 @@ #![feature(unboxed_closures)] -fn f isize>(x: F) {} //~ ERROR nonexistent trait `Nonexist` +fn f isize>(x: F) {} //~ ERROR undeclared trait name `Nonexist` type Typedef = isize; -- cgit 1.4.1-3-g733a5 From d31b9ebef5c39de3fff9da02eea880d1838a8a3b Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Tue, 17 Feb 2015 19:29:13 +0200 Subject: Implement `::method` UFCS expression syntax. --- src/librustc/lint/builtin.rs | 6 +-- src/librustc/metadata/encoder.rs | 2 +- src/librustc/middle/astconv_util.rs | 2 +- src/librustc/middle/cfg/construct.rs | 3 +- src/librustc/middle/check_const.rs | 2 +- src/librustc/middle/check_static_recursion.rs | 4 +- src/librustc/middle/const_eval.rs | 11 +---- src/librustc/middle/effect.rs | 2 +- src/librustc/middle/expr_use_visitor.rs | 2 +- src/librustc/middle/infer/error_reporting.rs | 11 ++++- src/librustc/middle/liveness.rs | 12 ++--- src/librustc/middle/mem_categorization.rs | 2 +- src/librustc/middle/reachable.rs | 2 +- src/librustc/middle/resolve_lifetime.rs | 2 +- src/librustc/middle/ty.rs | 4 +- src/librustc_back/svh.rs | 6 +-- src/librustc_privacy/lib.rs | 12 ++--- src/librustc_resolve/lib.rs | 46 +++++++++++------- src/librustc_trans/save/mod.rs | 6 +-- src/librustc_trans/trans/_match.rs | 2 +- src/librustc_trans/trans/callee.rs | 2 +- src/librustc_trans/trans/consts.rs | 4 +- src/librustc_trans/trans/debuginfo.rs | 3 +- src/librustc_trans/trans/expr.rs | 6 +-- src/librustc_typeck/astconv.rs | 39 ++++++++++----- src/librustc_typeck/check/mod.rs | 22 ++++++--- src/librustc_typeck/collect.rs | 19 +++----- src/librustdoc/clean/mod.rs | 10 ++-- src/libsyntax/ast.rs | 37 ++++++++------ src/libsyntax/ast_util.rs | 2 +- src/libsyntax/ext/build.rs | 26 +++++----- src/libsyntax/ext/concat_idents.rs | 2 +- src/libsyntax/ext/expand.rs | 11 ++--- src/libsyntax/feature_gate.rs | 2 +- src/libsyntax/fold.rs | 28 ++++++----- src/libsyntax/parse/mod.rs | 12 ++--- src/libsyntax/parse/parser.rs | 70 +++++++++++++++++++++------ src/libsyntax/print/pprust.rs | 23 +++++---- src/libsyntax/visit.rs | 18 +++---- src/test/run-pass/ufcs-polymorphic-paths.rs | 11 +++++ 40 files changed, 286 insertions(+), 200 deletions(-) (limited to 'src/libsyntax/ext') diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 28baeb5dc9e..3c0d9e93ccb 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -437,7 +437,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { impl<'a, 'tcx, 'v> Visitor<'v> for ImproperCTypesVisitor<'a, 'tcx> { fn visit_ty(&mut self, ty: &ast::Ty) { - if let ast::TyPath(_) = ty.node { + if let ast::TyPath(..) = ty.node { self.check_def(ty.span, ty.id); } visit::walk_ty(self, ty); @@ -682,8 +682,8 @@ impl LintPass for PathStatements { match s.node { ast::StmtSemi(ref expr, _) => { match expr.node { - ast::ExprPath(_) => cx.span_lint(PATH_STATEMENTS, s.span, - "path statement with no effect"), + ast::ExprPath(..) => cx.span_lint(PATH_STATEMENTS, s.span, + "path statement with no effect"), _ => () } } diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 4aea73cfb0e..a01b17ac194 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -1221,7 +1221,7 @@ fn encode_info_for_item(ecx: &EncodeContext, encode_unsafety(rbml_w, unsafety); encode_polarity(rbml_w, polarity); match ty.node { - ast::TyPath(ref path) if path.segments.len() == 1 => { + ast::TyPath(None, ref path) if path.segments.len() == 1 => { let ident = path.segments.last().unwrap().identifier; encode_impl_type_basename(rbml_w, ident); } diff --git a/src/librustc/middle/astconv_util.rs b/src/librustc/middle/astconv_util.rs index c9196f0cb2a..17fd80ceaea 100644 --- a/src/librustc/middle/astconv_util.rs +++ b/src/librustc/middle/astconv_util.rs @@ -59,7 +59,7 @@ pub fn prim_ty_to_ty<'tcx>(tcx: &ty::ctxt<'tcx>, pub fn ast_ty_to_prim_ty<'tcx>(tcx: &ty::ctxt<'tcx>, ast_ty: &ast::Ty) -> Option> { - if let ast::TyPath(ref path) = ast_ty.node { + if let ast::TyPath(None, ref path) = ast_ty.node { let def = match tcx.def_map.borrow().get(&ast_ty.id) { None => { tcx.sess.span_bug(ast_ty.span, diff --git a/src/librustc/middle/cfg/construct.rs b/src/librustc/middle/cfg/construct.rs index ca9455ac421..24c54b53590 100644 --- a/src/librustc/middle/cfg/construct.rs +++ b/src/librustc/middle/cfg/construct.rs @@ -398,8 +398,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { ast::ExprMac(..) | ast::ExprClosure(..) | ast::ExprLit(..) | - ast::ExprPath(..) | - ast::ExprQPath(..) => { + ast::ExprPath(..) => { self.straightline(expr, pred, None::.iter()) } } diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs index 57e4d3d2f02..8401d25024d 100644 --- a/src/librustc/middle/check_const.rs +++ b/src/librustc/middle/check_const.rs @@ -439,7 +439,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, } } } - ast::ExprPath(_) | ast::ExprQPath(_) => { + ast::ExprPath(..) => { let def = v.tcx.def_map.borrow().get(&e.id).map(|d| d.full_def()); match def { Some(def::DefVariant(_, _, _)) => { diff --git a/src/librustc/middle/check_static_recursion.rs b/src/librustc/middle/check_static_recursion.rs index a4393f4648b..b97978fc03f 100644 --- a/src/librustc/middle/check_static_recursion.rs +++ b/src/librustc/middle/check_static_recursion.rs @@ -93,8 +93,8 @@ impl<'a, 'ast, 'v> Visitor<'v> for CheckItemRecursionVisitor<'a, 'ast> { fn visit_expr(&mut self, e: &ast::Expr) { match e.node { - ast::ExprPath(_) | ast::ExprQPath(_) => { - match self.def_map.borrow().get(&e.id).map(|d| d.full_def()) { + ast::ExprPath(..) => { + match self.def_map.borrow().get(&e.id).map(|d| d.base_def) { Some(DefStatic(def_id, _)) | Some(DefConst(def_id)) if ast_util::is_local(def_id) => { diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index d3c6a585fa3..f793d3ce2fb 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -178,7 +178,7 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr, span: Span) -> P ast::PatVec(pats, None, vec![]) } - ast::ExprPath(ref path) => { + ast::ExprPath(_, ref path) => { let opt_def = tcx.def_map.borrow().get(&expr.id).map(|d| d.full_def()); match opt_def { Some(def::DefStruct(..)) => @@ -194,13 +194,6 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr, span: Span) -> P } } - ast::ExprQPath(_) => { - match lookup_const(tcx, expr) { - Some(actual) => return const_expr_to_pat(tcx, actual, span), - _ => unreachable!() - } - } - _ => ast::PatLit(P(expr.clone())) }; P(ast::Pat { id: expr.id, node: pat, span: span }) @@ -388,7 +381,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>, let val = try!(eval_const_expr_partial(tcx, &**base, Some(base_hint))); cast_const(val, ety) } - ast::ExprPath(_) | ast::ExprQPath(_) => { + ast::ExprPath(..) => { let opt_def = tcx.def_map.borrow().get(&e.id).map(|d| d.full_def()); let (const_expr, const_ty) = match opt_def { Some(def::DefConst(def_id)) => { diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs index ba81b2f3899..9c85b7748ab 100644 --- a/src/librustc/middle/effect.rs +++ b/src/librustc/middle/effect.rs @@ -175,7 +175,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> { ast::ExprInlineAsm(..) => { self.require_unsafe(expr.span, "use of inline assembly"); } - ast::ExprPath(_) | ast::ExprQPath(_) => { + ast::ExprPath(..) => { if let def::DefStatic(_, true) = ty::resolve_expr(self.tcx, expr) { self.require_unsafe(expr.span, "use of mutable static"); } diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index f7c723c6874..a1e38a1c8bd 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -422,7 +422,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { self.walk_expr(&**subexpr) } - ast::ExprPath(_) | ast::ExprQPath(_) => { } + ast::ExprPath(..) => { } ast::ExprUnary(ast::UnDeref, ref base) => { // *base if !self.walk_overloaded_operator(expr, &**base, Vec::new(), PassArgs::ByRef) { diff --git a/src/librustc/middle/infer/error_reporting.rs b/src/librustc/middle/infer/error_reporting.rs index 60b7e1169b4..da4df813030 100644 --- a/src/librustc/middle/infer/error_reporting.rs +++ b/src/librustc/middle/infer/error_reporting.rs @@ -1233,7 +1233,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> { } ty_queue.push(&*mut_ty.ty); } - ast::TyPath(ref path) => { + ast::TyPath(ref maybe_qself, ref path) => { let a_def = match self.tcx.def_map.borrow().get(&cur_ty.id) { None => { self.tcx @@ -1277,9 +1277,16 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> { region_names: region_names }; let new_path = self.rebuild_path(rebuild_info, lifetime); + let qself = maybe_qself.as_ref().map(|qself| { + ast::QSelf { + ty: self.rebuild_arg_ty_or_output(&qself.ty, lifetime, + anon_nums, region_names), + position: qself.position + } + }); let to = ast::Ty { id: cur_ty.id, - node: ast::TyPath(new_path), + node: ast::TyPath(qself, new_path), span: cur_ty.span }; new_ty = self.rebuild_ty(new_ty, P(to)); diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 4685a05f416..2ac019aa964 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -445,7 +445,7 @@ fn visit_arm(ir: &mut IrMaps, arm: &ast::Arm) { fn visit_expr(ir: &mut IrMaps, expr: &Expr) { match expr.node { // live nodes required for uses or definitions of variables: - ast::ExprPath(_) | ast::ExprQPath(_) => { + ast::ExprPath(..) => { let def = ir.tcx.def_map.borrow()[expr.id].full_def(); debug!("expr {}: path that leads to {:?}", expr.id, def); if let DefLocal(..) = def { @@ -947,7 +947,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { match expr.node { // Interesting cases with control flow or which gen/kill - ast::ExprPath(_) | ast::ExprQPath(_) => { + ast::ExprPath(..) => { self.access_path(expr, succ, ACC_READ | ACC_USE) } @@ -1275,7 +1275,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { // just ignore such cases and treat them as reads. match expr.node { - ast::ExprPath(_) | ast::ExprQPath(_) => succ, + ast::ExprPath(..) => succ, ast::ExprField(ref e, _) => self.propagate_through_expr(&**e, succ), ast::ExprTupField(ref e, _) => self.propagate_through_expr(&**e, succ), _ => self.propagate_through_expr(expr, succ) @@ -1286,7 +1286,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { fn write_lvalue(&mut self, expr: &Expr, succ: LiveNode, acc: uint) -> LiveNode { match expr.node { - ast::ExprPath(_) | ast::ExprQPath(_) => { + ast::ExprPath(..) => { self.access_path(expr, succ, acc) } @@ -1468,7 +1468,7 @@ fn check_expr(this: &mut Liveness, expr: &Expr) { ast::ExprBlock(..) | ast::ExprMac(..) | ast::ExprAddrOf(..) | ast::ExprStruct(..) | ast::ExprRepeat(..) | ast::ExprParen(..) | ast::ExprClosure(..) | ast::ExprPath(..) | ast::ExprBox(..) | - ast::ExprRange(..) | ast::ExprQPath(..) => { + ast::ExprRange(..) => { visit::walk_expr(this, expr); } ast::ExprIfLet(..) => { @@ -1561,7 +1561,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { fn check_lvalue(&mut self, expr: &Expr) { match expr.node { - ast::ExprPath(_) | ast::ExprQPath(_) => { + ast::ExprPath(..) => { if let DefLocal(nid) = self.ir.tcx.def_map.borrow()[expr.id].full_def() { // Assignment to an immutable variable or argument: only legal // if there is no later assignment. If this local is actually diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 44ab3cf60aa..c4446b87855 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -529,7 +529,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { } } - ast::ExprPath(_) | ast::ExprQPath(_) => { + ast::ExprPath(..) => { let def = self.tcx().def_map.borrow()[expr.id].full_def(); self.cat_def(expr.id, expr.span, expr_ty, def) } diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index a140c766758..45d565ec693 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -94,7 +94,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ReachableContext<'a, 'tcx> { fn visit_expr(&mut self, expr: &ast::Expr) { match expr.node { - ast::ExprPath(_) | ast::ExprQPath(_) => { + ast::ExprPath(..) => { let def = match self.tcx.def_map.borrow().get(&expr.id) { Some(d) => d.full_def(), None => { diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 9bcda68eb3a..a8a2887644a 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -165,7 +165,7 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> { visit::walk_ty(this, ty); }); } - ast::TyPath(ref path) => { + ast::TyPath(None, ref path) => { // if this path references a trait, then this will resolve to // a trait ref, which introduces a binding scope. match self.def_map.borrow().get(&ty.id).map(|d| (d.base_def, d.depth)) { diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 7cd04727902..7b05e510852 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -4550,7 +4550,7 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind { } match expr.node { - ast::ExprPath(_) | ast::ExprQPath(_) => { + ast::ExprPath(..) => { match resolve_expr(tcx, expr) { def::DefVariant(tid, vid, _) => { let variant_info = enum_variant_with_id(tcx, tid, vid); @@ -5838,7 +5838,7 @@ pub fn eval_repeat_count(tcx: &ctxt, count_expr: &ast::Expr) -> uint { } Err(_) => { let found = match count_expr.node { - ast::ExprPath(ast::Path { + ast::ExprPath(None, ast::Path { global: false, ref segments, .. diff --git a/src/librustc_back/svh.rs b/src/librustc_back/svh.rs index 2fc43ab26b5..e16df61c25c 100644 --- a/src/librustc_back/svh.rs +++ b/src/librustc_back/svh.rs @@ -244,8 +244,7 @@ mod svh_visitor { SawExprAssignOp(ast::BinOp_), SawExprIndex, SawExprRange, - SawExprPath, - SawExprQPath, + SawExprPath(Option), SawExprAddrOf(ast::Mutability), SawExprRet, SawExprInlineAsm(&'a ast::InlineAsm), @@ -277,8 +276,7 @@ mod svh_visitor { ExprTupField(_, id) => SawExprTupField(id.node), ExprIndex(..) => SawExprIndex, ExprRange(..) => SawExprRange, - ExprPath(..) => SawExprPath, - ExprQPath(..) => SawExprQPath, + ExprPath(ref qself, _) => SawExprPath(qself.as_ref().map(|q| q.position)), ExprAddrOf(m, _) => SawExprAddrOf(m), ExprBreak(id) => SawExprBreak(id.map(content)), ExprAgain(id) => SawExprAgain(id.map(content)), diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index f325a6abede..29448c68c80 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -258,7 +258,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> { // * Private trait impls for private types can be completely ignored ast::ItemImpl(_, _, _, _, ref ty, ref impl_items) => { let public_ty = match ty.node { - ast::TyPath(_) => { + ast::TyPath(..) => { match self.tcx.def_map.borrow()[ty.id].full_def() { def::DefPrimTy(..) => true, def => { @@ -325,7 +325,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> { } ast::ItemTy(ref ty, _) if public_first => { - if let ast::TyPath(_) = ty.node { + if let ast::TyPath(..) = ty.node { match self.tcx.def_map.borrow()[ty.id].full_def() { def::DefPrimTy(..) | def::DefTyParam(..) => {}, def => { @@ -627,7 +627,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> { // was private. ast::ItemImpl(_, _, _, _, ref ty, _) => { match ty.node { - ast::TyPath(_) => {} + ast::TyPath(..) => {} _ => return Some((err_span, err_msg, None)), }; let def = self.tcx.def_map.borrow()[ty.id].full_def(); @@ -908,7 +908,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> { struct type?!"), } } - ast::ExprPath(_) | ast::ExprQPath(_) => { + ast::ExprPath(..) => { let guard = |did: ast::DefId| { let fields = ty::lookup_struct_fields(self.tcx, did); let any_priv = fields.iter().any(|f| { @@ -1254,7 +1254,7 @@ impl<'a, 'tcx> VisiblePrivateTypesVisitor<'a, 'tcx> { impl<'a, 'b, 'tcx, 'v> Visitor<'v> for CheckTypeForPrivatenessVisitor<'a, 'b, 'tcx> { fn visit_ty(&mut self, ty: &ast::Ty) { - if let ast::TyPath(_) = ty.node { + if let ast::TyPath(..) = ty.node { if self.inner.path_is_private_type(ty.id) { self.contains_private = true; // found what we're looking for so let's stop @@ -1460,7 +1460,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> { } fn visit_ty(&mut self, t: &ast::Ty) { - if let ast::TyPath(ref p) = t.node { + if let ast::TyPath(_, ref p) = t.node { if !self.tcx.sess.features.borrow().visible_private_types && self.path_is_private_type(t.id) { self.tcx.sess.span_err(p.span, diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 265f398d25c..cb7224f7cbf 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -65,7 +65,7 @@ use rustc::util::lev_distance::lev_distance; use syntax::ast::{Arm, BindByRef, BindByValue, BindingMode, Block, Crate, CrateNum}; use syntax::ast::{DefId, Expr, ExprAgain, ExprBreak, ExprField}; use syntax::ast::{ExprLoop, ExprWhile, ExprMethodCall}; -use syntax::ast::{ExprPath, ExprQPath, ExprStruct, FnDecl}; +use syntax::ast::{ExprPath, ExprStruct, FnDecl}; use syntax::ast::{ForeignItemFn, ForeignItemStatic, Generics}; use syntax::ast::{Ident, ImplItem, Item, ItemConst, ItemEnum, ItemExternCrate}; use syntax::ast::{ItemFn, ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, ItemDefaultImpl}; @@ -75,7 +75,7 @@ use syntax::ast::{Pat, PatEnum, PatIdent, PatLit}; use syntax::ast::{PatRange, PatStruct, Path, PrimTy}; use syntax::ast::{TraitRef, Ty, TyBool, TyChar, TyF32}; use syntax::ast::{TyF64, TyFloat, TyIs, TyI8, TyI16, TyI32, TyI64, TyInt}; -use syntax::ast::{TyPath, TyPtr, TyQPath}; +use syntax::ast::{TyPath, TyPtr}; use syntax::ast::{TyRptr, TyStr, TyUs, TyU8, TyU16, TyU32, TyU64, TyUint}; use syntax::ast::{TypeImplItem}; use syntax::ast; @@ -2821,7 +2821,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { FnSpace, MethodRibKind) } - ast::TypeTraitItem(_) => NoTypeParameters, + ast::TypeTraitItem(ref assoc_ty) => { + let ty_param = &assoc_ty.ty_param; + this.check_if_primitive_type_name(ty_param.ident.name, + ty_param.span); + NoTypeParameters + } }; this.with_type_parameter_rib(type_parameters, |this| { visit::walk_trait_item(this, trait_item) @@ -3243,14 +3248,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn resolve_type(&mut self, ty: &Ty) { match ty.node { - // Like path expressions, the interpretation of path types depends - // on whether the path has multiple elements in it or not. + // `::a::b::c` is resolved by typeck alone. + TyPath(Some(ast::QSelf { position: 0, .. }), _) => {} - TyPath(ref path) | TyQPath(ast::QPath { ref path, .. }) => { - let max_assoc_types = if let TyQPath(_) = ty.node { + TyPath(ref maybe_qself, ref path) => { + let max_assoc_types = if let Some(ref qself) = *maybe_qself { // Make sure the trait is valid. let _ = self.resolve_trait_reference(ty.id, path, 1); - 1 + path.segments.len() - qself.position } else { path.segments.len() }; @@ -3284,10 +3289,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Keep reporting some errors even if they're ignored above. self.resolve_path(ty.id, path, 0, TypeNS, true); - let kind = match ty.node { - TyQPath(_) => "associated type", - _ => "type name" + let kind = if maybe_qself.is_some() { + "associated type" + } else { + "type name" }; + let msg = format!("use of undeclared {} `{}`", kind, self.path_names_to_string(path, 0)); self.resolve_error(ty.span, &msg[..]); @@ -3905,7 +3912,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn extract_path_and_node_id(t: &Ty, allow: FallbackChecks) -> Option<(Path, NodeId, FallbackChecks)> { match t.node { - TyPath(ref path) => Some((path.clone(), t.id, allow)), + TyPath(None, ref path) => Some((path.clone(), t.id, allow)), TyPtr(ref mut_ty) => extract_path_and_node_id(&*mut_ty.ty, OnlyTraitAndStatics), TyRptr(_, ref mut_ty) => extract_path_and_node_id(&*mut_ty.ty, allow), // This doesn't handle the remaining `Ty` variants as they are not @@ -4063,14 +4070,19 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Next, resolve the node. match expr.node { - // The interpretation of paths depends on whether the path has - // multiple elements in it or not. + // `::a::b::c` is resolved by typeck alone. + ExprPath(Some(ast::QSelf { position: 0, .. }), ref path) => { + let method_name = path.segments.last().unwrap().identifier.name; + let traits = self.search_for_traits_containing_method(method_name); + self.trait_map.insert(expr.id, traits); + visit::walk_expr(self, expr); + } - ExprPath(ref path) | ExprQPath(ast::QPath { ref path, .. }) => { - let max_assoc_types = if let ExprQPath(_) = expr.node { + ExprPath(ref maybe_qself, ref path) => { + let max_assoc_types = if let Some(ref qself) = *maybe_qself { // Make sure the trait is valid. let _ = self.resolve_trait_reference(expr.id, path, 1); - 1 + path.segments.len() - qself.position } else { path.segments.len() }; diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs index ea346798679..ab7f3916728 100644 --- a/src/librustc_trans/save/mod.rs +++ b/src/librustc_trans/save/mod.rs @@ -659,7 +659,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { let trait_id = trait_ref.as_ref().and_then(|tr| self.lookup_type_ref(tr.ref_id)); match typ.node { // Common case impl for a struct or something basic. - ast::TyPath(ref path) => { + ast::TyPath(None, ref path) => { let sub_span = self.span.sub_span_for_type_name(path.span); let self_id = self.lookup_type_ref(typ.id).map(|id| { self.fmt.ref_str(recorder::TypeRef, @@ -1306,7 +1306,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> { } match t.node { - ast::TyPath(ref path) => { + ast::TyPath(_, ref path) => { match self.lookup_type_ref(t.id) { Some(id) => { let sub_span = self.span.sub_span_for_type_name(t.span); @@ -1338,7 +1338,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> { // because just walking the callee path does what we want. visit::walk_expr(self, ex); } - ast::ExprPath(ref path) | ast::ExprQPath(ast::QPath { ref path, .. }) => { + ast::ExprPath(_, ref path) => { self.process_path(ex.id, path.span, path, None); visit::walk_expr(self, ex); } diff --git a/src/librustc_trans/trans/_match.rs b/src/librustc_trans/trans/_match.rs index 3e741640117..9a121a8830b 100644 --- a/src/librustc_trans/trans/_match.rs +++ b/src/librustc_trans/trans/_match.rs @@ -1277,7 +1277,7 @@ pub fn trans_match<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, /// Checks whether the binding in `discr` is assigned to anywhere in the expression `body` fn is_discr_reassigned(bcx: Block, discr: &ast::Expr, body: &ast::Expr) -> bool { let (vid, field) = match discr.node { - ast::ExprPath(_) | ast::ExprQPath(_) => match bcx.def(discr.id) { + ast::ExprPath(..) => match bcx.def(discr.id) { def::DefLocal(vid) | def::DefUpvar(vid, _) => (vid, None), _ => return false }, diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs index 41e3d4b5bab..59fcd5492eb 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -93,7 +93,7 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr) // pick out special kinds of expressions that can be called: match expr.node { - ast::ExprPath(_) | ast::ExprQPath(_) => { + ast::ExprPath(..) => { return trans_def(bcx, bcx.def(expr.id), expr); } _ => {} diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs index 6e1d2da02c1..93ab4a96e6f 100644 --- a/src/librustc_trans/trans/consts.rs +++ b/src/librustc_trans/trans/consts.rs @@ -193,7 +193,7 @@ pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, -> ValueRef { // Special-case constants to cache a common global for all uses. match expr.node { - ast::ExprPath(_) => { + ast::ExprPath(..) => { let def = ccx.tcx().def_map.borrow()[expr.id].full_def(); match def { def::DefConst(def_id) => { @@ -663,7 +663,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, C_array(llunitty, &vs[..]) } } - ast::ExprPath(_) | ast::ExprQPath(_) => { + ast::ExprPath(..) => { let def = cx.tcx().def_map.borrow()[e.id].full_def(); match def { def::DefFn(..) | def::DefMethod(..) => { diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs index 162881f58c7..d70a904b811 100644 --- a/src/librustc_trans/trans/debuginfo.rs +++ b/src/librustc_trans/trans/debuginfo.rs @@ -3487,8 +3487,7 @@ fn create_scope_map(cx: &CrateContext, ast::ExprLit(_) | ast::ExprBreak(_) | ast::ExprAgain(_) | - ast::ExprPath(_) | - ast::ExprQPath(_) => {} + ast::ExprPath(..) => {} ast::ExprCast(ref sub_exp, _) | ast::ExprAddrOf(_, ref sub_exp) | diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs index 80fe2ed8f3a..5cc1baf66c6 100644 --- a/src/librustc_trans/trans/expr.rs +++ b/src/librustc_trans/trans/expr.rs @@ -143,7 +143,7 @@ pub fn trans_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, // it prefers in-place instantiation, likely because it contains // `[x; N]` somewhere within. match expr.node { - ast::ExprPath(_) | ast::ExprQPath(_) => { + ast::ExprPath(..) => { match bcx.def(expr.id) { def::DefConst(did) => { let expr = consts::get_const_expr(bcx.ccx(), did, expr); @@ -629,7 +629,7 @@ fn trans_datum_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ast::ExprParen(ref e) => { trans(bcx, &**e) } - ast::ExprPath(_) | ast::ExprQPath(_) => { + ast::ExprPath(..) => { trans_def(bcx, expr, bcx.def(expr.id)) } ast::ExprField(ref base, ident) => { @@ -1033,7 +1033,7 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ast::ExprParen(ref e) => { trans_into(bcx, &**e, dest) } - ast::ExprPath(_) | ast::ExprQPath(_) => { + ast::ExprPath(..) => { trans_def_dps_unadjusted(bcx, expr, bcx.def(expr.id), dest) } ast::ExprIf(ref cond, ref thn, ref els) => { diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 982cc1e3792..602f041222f 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -52,6 +52,7 @@ use middle::astconv_util::{prim_ty_to_ty, check_path_args, NO_TPS, NO_REGIONS}; use middle::const_eval; use middle::def; use middle::resolve_lifetime as rl; +use middle::privacy::{AllPublic, LastMod}; use middle::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs}; use middle::traits; use middle::ty::{self, RegionEscape, ToPolyTraitRef, Ty}; @@ -897,7 +898,7 @@ fn ast_ty_to_trait_ref<'tcx>(this: &AstConv<'tcx>, */ match ty.node { - ast::TyPath(ref path) => { + ast::TyPath(None, ref path) => { let def = this.tcx().def_map.borrow().get(&ty.id).map(|d| d.full_def()); match def { Some(def::DefTrait(trait_def_id)) => { @@ -981,7 +982,13 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>, check_path_args(tcx, slice::ref_slice(item_segment), NO_TPS | NO_REGIONS); let assoc_name = item_segment.identifier.name; - let ty_param_node_id = if let ty::ty_param(_) = ty.sty { + let is_param = match (&ty.sty, ty_path_def) { + (&ty::ty_param(_), def::DefTyParam(..)) | + (&ty::ty_param(_), def::DefSelfTy(_)) => true, + _ => false + }; + + let ty_param_node_id = if is_param { ty_path_def.local_node_id() } else { span_err!(tcx.sess, span, E0223, @@ -1195,9 +1202,14 @@ pub fn finish_resolving_def_to_ty<'tcx>(this: &AstConv<'tcx>, segments.last().unwrap()) } def::DefMod(id) => { - tcx.sess.span_bug(span, - &format!("found module name used as a type: {}", - tcx.map.node_to_string(id.node))); + // Used as sentinel by callers to indicate the `::a::b::c` form. + if segments.is_empty() { + opt_self_ty.expect("missing T in ::a::b::c") + } else { + tcx.sess.span_bug(span, + &format!("found module name used as a type: {}", + tcx.map.node_to_string(id.node))); + } } def::DefPrimTy(prim_ty) => { prim_ty_to_ty(tcx, segments, prim_ty) @@ -1302,20 +1314,25 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>, ast::TyPolyTraitRef(ref bounds) => { conv_ty_poly_trait_ref(this, rscope, ast_ty.span, bounds) } - ast::TyPath(ref path) | ast::TyQPath(ast::QPath { ref path, .. }) => { + ast::TyPath(ref maybe_qself, ref path) => { let path_res = if let Some(&d) = tcx.def_map.borrow().get(&ast_ty.id) { d + } else if let Some(ast::QSelf { position: 0, .. }) = *maybe_qself { + // Create some fake resolution that can't possibly be a type. + def::PathResolution { + base_def: def::DefMod(ast_util::local_def(ast::CRATE_NODE_ID)), + last_private: LastMod(AllPublic), + depth: path.segments.len() + } } else { tcx.sess.span_bug(ast_ty.span, &format!("unbound path {}", ast_ty.repr(tcx))) }; let mut def = path_res.base_def; let base_ty_end = path.segments.len() - path_res.depth; - let opt_self_ty = if let ast::TyQPath(ref qpath) = ast_ty.node { - Some(ast_ty_to_ty(this, rscope, &*qpath.self_type)) - } else { - None - }; + let opt_self_ty = maybe_qself.as_ref().map(|qself| { + ast_ty_to_ty(this, rscope, &qself.ty) + }); let ty = finish_resolving_def_to_ty(this, rscope, ast_ty.span, PathParamMode::Explicit, &mut def, opt_self_ty, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index f99e4e4b2ed..f5d6d5baf93 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; @@ -3397,7 +3398,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, let mut checked = false; opt_place.as_ref().map(|place| match place.node { - ast::ExprPath(ref path) => { + ast::ExprPath(None, ref path) => { // FIXME(pcwalton): For now we hardcode the two permissible // places: the exchange heap and the managed heap. let definition = lookup_def(fcx, path.span, place.id); @@ -3590,16 +3591,21 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, }; fcx.write_ty(id, oprnd_t); } - ast::ExprPath(ref path) | ast::ExprQPath(ast::QPath { ref path, .. }) => { - let opt_self_ty = if let ast::ExprQPath(ref qpath) = expr.node { - Some(fcx.to_ty(&*qpath.self_type)) - } else { - None - }; + ast::ExprPath(ref maybe_qself, ref path) => { + let opt_self_ty = maybe_qself.as_ref().map(|qself| { + fcx.to_ty(&qself.ty) + }); let path_res = if let Some(&d) = tcx.def_map.borrow().get(&id) { d - } else { + } else if let Some(ast::QSelf { position: 0, .. }) = *maybe_qself { + // Create some fake resolution that can't possibly be a type. + def::PathResolution { + base_def: def::DefMod(local_def(ast::CRATE_NODE_ID)), + last_private: LastMod(AllPublic), + depth: path.segments.len() + } + } else { tcx.sess.span_bug(expr.span, &format!("unbound path {}", expr.repr(tcx))[]) }; diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 976c794735f..7ed372d1b4b 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1683,20 +1683,15 @@ fn compute_object_lifetime_default<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>, index: u32) -> bool { - match ast_ty.node { - ast::TyPath(_) => { - match ccx.tcx.def_map.borrow()[ast_ty.id] { - def::DefTyParam(s, i, _, _) => { - space == s && index == i - } - _ => { - false - } - } - } - _ => { + if let ast::TyPath(None, _) = ast_ty.node { + let path_res = ccx.tcx.def_map.borrow()[ast_ty.id]; + if let def::DefTyParam(s, i, _, _) = path_res.base_def { + path_res.depth == 0 && space == s && index == i + } else { false } + } else { + false } } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 0aa1a23ad7e..b88620d577f 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1494,15 +1494,15 @@ impl Clean for ast::Ty { TyFixedLengthVec(ref ty, ref e) => FixedVector(box ty.clean(cx), e.span.to_src(cx)), TyTup(ref tys) => Tuple(tys.clean(cx)), - TyPath(ref p) => { + TyPath(None, ref p) => { resolve_type(cx, p.clean(cx), self.id) } - TyQPath(ref qp) => { - let mut trait_path = qp.path.clone(); + TyPath(Some(ref qself), ref p) => { + let mut trait_path = p.clone(); trait_path.segments.pop(); Type::QPath { - name: qp.path.segments.last().unwrap().identifier.clean(cx), - self_type: box qp.self_type.clean(cx), + name: p.segments.last().unwrap().identifier.clean(cx), + self_type: box qself.ty.clean(cx), trait_: box resolve_type(cx, trait_path.clean(cx), self.id) } } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 80a5527cb94..6d6fdffa950 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -753,11 +753,10 @@ pub enum Expr_ { ExprIndex(P, P), ExprRange(Option>, Option>), - /// Variable reference, possibly containing `::` and/or - /// type parameters, e.g. foo::bar:: - ExprPath(Path), - /// A "qualified path", e.g. ` as SomeTrait>::SomeType` - ExprQPath(QPath), + /// Variable reference, possibly containing `::` and/or type + /// parameters, e.g. foo::bar::. Optionally "qualified", + /// e.g. ` as SomeTrait>::SomeType`. + ExprPath(Option, Path), ExprAddrOf(Mutability, P), ExprBreak(Option), @@ -778,15 +777,22 @@ pub enum Expr_ { ExprParen(P) } -/// A "qualified path": +/// The explicit Self type in a "qualified path". The actual +/// path, including the trait and the associated item, is stored +/// sepparately. `position` represents the index of the associated +/// item qualified with this Self type. /// -/// as SomeTrait>::SomeAssociatedItem -/// ^~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -/// self_type path +/// as a::b::Trait>::AssociatedItem +/// ^~~~~ ~~~~~~~~~~~~~~^ +/// ty position = 3 +/// +/// >::AssociatedItem +/// ^~~~~ ^ +/// ty position = 0 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct QPath { - pub self_type: P, - pub path: Path, +pub struct QSelf { + pub ty: P, + pub position: usize } #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] @@ -1253,12 +1259,11 @@ pub enum Ty_ { TyBareFn(P), /// A tuple (`(A, B, C, D,...)`) TyTup(Vec> ), - /// A path (`module::module::...::Type`) or primitive + /// A path (`module::module::...::Type`), optionally + /// "qualified", e.g. ` as SomeTrait>::SomeType`. /// /// Type parameters are stored in the Path itself - TyPath(Path), - /// A "qualified path", e.g. ` as SomeTrait>::SomeType` - TyQPath(QPath), + TyPath(Option, Path), /// Something like `A+B`. Note that `B` must always be a path. TyObjectSum(P, TyParamBounds), /// A type like `for<'a> Foo<&'a Bar>` diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index f207efc5b6c..79f0433761d 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -134,7 +134,7 @@ pub fn unop_to_string(op: UnOp) -> &'static str { } pub fn is_path(e: P) -> bool { - return match e.node { ExprPath(_) => true, _ => false }; + match e.node { ExprPath(..) => true, _ => false } } /// Get a string representation of a signed int type, with its value. diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 90842bbab47..d916651b056 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -43,14 +43,14 @@ pub trait AstBuilder { fn qpath(&self, self_type: P, trait_path: ast::Path, ident: ast::Ident) - -> ast::QPath; + -> (ast::QSelf, ast::Path); fn qpath_all(&self, self_type: P, trait_path: ast::Path, ident: ast::Ident, lifetimes: Vec, types: Vec>, bindings: Vec>) - -> ast::QPath; + -> (ast::QSelf, ast::Path); // types fn ty_mt(&self, ty: P, mutbl: ast::Mutability) -> ast::MutTy; @@ -114,7 +114,7 @@ pub trait AstBuilder { // expressions fn expr(&self, span: Span, node: ast::Expr_) -> P; fn expr_path(&self, path: ast::Path) -> P; - fn expr_qpath(&self, span: Span, qpath: ast::QPath) -> P; + fn expr_qpath(&self, span: Span, qself: ast::QSelf, path: ast::Path) -> P; fn expr_ident(&self, span: Span, id: ast::Ident) -> P; fn expr_self(&self, span: Span) -> P; @@ -351,7 +351,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { self_type: P, trait_path: ast::Path, ident: ast::Ident) - -> ast::QPath { + -> (ast::QSelf, ast::Path) { self.qpath_all(self_type, trait_path, ident, vec![], vec![], vec![]) } @@ -365,7 +365,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { lifetimes: Vec, types: Vec>, bindings: Vec>) - -> ast::QPath { + -> (ast::QSelf, ast::Path) { let mut path = trait_path; path.segments.push(ast::PathSegment { identifier: ident, @@ -376,10 +376,10 @@ impl<'a> AstBuilder for ExtCtxt<'a> { }) }); - ast::QPath { - self_type: self_type, - path: path - } + (ast::QSelf { + ty: self_type, + position: path.segments.len() - 1 + }, path) } fn ty_mt(&self, ty: P, mutbl: ast::Mutability) -> ast::MutTy { @@ -398,7 +398,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { } fn ty_path(&self, path: ast::Path) -> P { - self.ty(path.span, ast::TyPath(path)) + self.ty(path.span, ast::TyPath(None, path)) } fn ty_sum(&self, path: ast::Path, bounds: OwnedSlice) -> P { @@ -603,12 +603,12 @@ impl<'a> AstBuilder for ExtCtxt<'a> { } fn expr_path(&self, path: ast::Path) -> P { - self.expr(path.span, ast::ExprPath(path)) + self.expr(path.span, ast::ExprPath(None, path)) } /// Constructs a QPath expression. - fn expr_qpath(&self, span: Span, qpath: ast::QPath) -> P { - self.expr(span, ast::ExprQPath(qpath)) + fn expr_qpath(&self, span: Span, qself: ast::QSelf, path: ast::Path) -> P { + self.expr(span, ast::ExprPath(Some(qself), path)) } fn expr_ident(&self, span: Span, id: ast::Ident) -> P { diff --git a/src/libsyntax/ext/concat_idents.rs b/src/libsyntax/ext/concat_idents.rs index 9410a51e7a5..2303eb9645b 100644 --- a/src/libsyntax/ext/concat_idents.rs +++ b/src/libsyntax/ext/concat_idents.rs @@ -53,7 +53,7 @@ pub fn expand_syntax_ext<'cx>(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree] let e = P(ast::Expr { id: ast::DUMMY_NODE_ID, - node: ast::ExprPath( + node: ast::ExprPath(None, ast::Path { span: sp, global: false, diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index f7014d6cc3c..b6e7b309f35 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -41,7 +41,7 @@ pub fn expand_type(t: P, debug!("expanding type {:?} with impl_ty {:?}", t, impl_ty); let t = match (t.node.clone(), impl_ty) { // Expand uses of `Self` in impls to the concrete type. - (ast::Ty_::TyPath(ref path), Some(ref impl_ty)) => { + (ast::Ty_::TyPath(None, ref path), Some(ref impl_ty)) => { let path_as_ident = path_to_ident(path); // Note unhygenic comparison here. I think this is correct, since // even though `Self` is almost just a type parameter, the treatment @@ -1594,13 +1594,10 @@ mod test { impl<'v> Visitor<'v> for PathExprFinderContext { fn visit_expr(&mut self, expr: &ast::Expr) { - match expr.node { - ast::ExprPath(ref p) => { - self.path_accumulator.push(p.clone()); - // not calling visit_path, but it should be fine. - } - _ => visit::walk_expr(self, expr) + if let ast::ExprPath(None, ref p) = expr.node { + self.path_accumulator.push(p.clone()); } + visit::walk_expr(self, expr); } } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 4efae84fea5..32fd5b49f9a 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -549,7 +549,7 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { fn visit_ty(&mut self, t: &ast::Ty) { match t.node { - ast::TyPath(ref p) => { + ast::TyPath(None, ref p) => { match &*p.segments { [ast::PathSegment { identifier, .. }] => { diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index c706ce9065d..a556b2dfd2a 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -424,12 +424,14 @@ pub fn noop_fold_ty(t: P, fld: &mut T) -> P { } TyTup(tys) => TyTup(tys.move_map(|ty| fld.fold_ty(ty))), TyParen(ty) => TyParen(fld.fold_ty(ty)), - TyPath(path) => TyPath(fld.fold_path(path)), - TyQPath(qpath) => { - TyQPath(QPath { - self_type: fld.fold_ty(qpath.self_type), - path: fld.fold_path(qpath.path) - }) + TyPath(qself, path) => { + let qself = qself.map(|QSelf { ty, position }| { + QSelf { + ty: fld.fold_ty(ty), + position: position + } + }); + TyPath(qself, fld.fold_path(path)) } TyObjectSum(ty, bounds) => { TyObjectSum(fld.fold_ty(ty), @@ -1347,11 +1349,15 @@ pub fn noop_fold_expr(Expr {id, node, span}: Expr, folder: &mut T) -> ExprRange(e1.map(|x| folder.fold_expr(x)), e2.map(|x| folder.fold_expr(x))) } - ExprPath(pth) => ExprPath(folder.fold_path(pth)), - ExprQPath(qpath) => ExprQPath(QPath { - self_type: folder.fold_ty(qpath.self_type), - path: folder.fold_path(qpath.path) - }), + ExprPath(qself, path) => { + let qself = qself.map(|QSelf { ty, position }| { + QSelf { + ty: folder.fold_ty(ty), + position: position + } + }); + ExprPath(qself, folder.fold_path(path)) + } ExprBreak(opt_ident) => ExprBreak(opt_ident.map(|x| folder.fold_ident(x))), ExprAgain(opt_ident) => ExprAgain(opt_ident.map(|x| folder.fold_ident(x))), ExprRet(e) => ExprRet(e.map(|x| folder.fold_expr(x))), diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index d4c66529e77..4d099529cb4 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -774,7 +774,7 @@ mod test { assert!(string_to_expr("a".to_string()) == P(ast::Expr{ id: ast::DUMMY_NODE_ID, - node: ast::ExprPath(ast::Path { + node: ast::ExprPath(None, ast::Path { span: sp(0, 1), global: false, segments: vec!( @@ -792,7 +792,7 @@ mod test { assert!(string_to_expr("::a::b".to_string()) == P(ast::Expr { id: ast::DUMMY_NODE_ID, - node: ast::ExprPath(ast::Path { + node: ast::ExprPath(None, ast::Path { span: sp(0, 6), global: true, segments: vec!( @@ -974,7 +974,7 @@ mod test { id: ast::DUMMY_NODE_ID, node:ast::ExprRet(Some(P(ast::Expr{ id: ast::DUMMY_NODE_ID, - node:ast::ExprPath(ast::Path{ + node:ast::ExprPath(None, ast::Path{ span: sp(7, 8), global: false, segments: vec!( @@ -995,7 +995,7 @@ mod test { P(Spanned{ node: ast::StmtExpr(P(ast::Expr { id: ast::DUMMY_NODE_ID, - node: ast::ExprPath(ast::Path { + node: ast::ExprPath(None, ast::Path { span:sp(0,1), global:false, segments: vec!( @@ -1041,7 +1041,7 @@ mod test { node: ast::ItemFn(P(ast::FnDecl { inputs: vec!(ast::Arg{ ty: P(ast::Ty{id: ast::DUMMY_NODE_ID, - node: ast::TyPath(ast::Path{ + node: ast::TyPath(None, ast::Path{ span:sp(10,13), global:false, segments: vec!( @@ -1084,7 +1084,7 @@ mod test { stmts: vec!(P(Spanned{ node: ast::StmtSemi(P(ast::Expr{ id: ast::DUMMY_NODE_ID, - node: ast::ExprPath( + node: ast::ExprPath(None, ast::Path{ span:sp(17,18), global:false, diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index ad290da7d0a..f171e8279f4 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -25,7 +25,7 @@ use ast::{ExprAssign, ExprAssignOp, ExprBinary, ExprBlock, ExprBox}; use ast::{ExprBreak, ExprCall, ExprCast}; use ast::{ExprField, ExprTupField, ExprClosure, ExprIf, ExprIfLet, ExprIndex}; use ast::{ExprLit, ExprLoop, ExprMac, ExprRange}; -use ast::{ExprMethodCall, ExprParen, ExprPath, ExprQPath}; +use ast::{ExprMethodCall, ExprParen, ExprPath}; use ast::{ExprRepeat, ExprRet, ExprStruct, ExprTup, ExprUnary}; use ast::{ExprVec, ExprWhile, ExprWhileLet, ExprForLoop, Field, FnDecl}; use ast::{ForeignItem, ForeignItemStatic, ForeignItemFn, ForeignMod, FunctionRetTy}; @@ -43,7 +43,7 @@ use ast::{MethodImplItem, NamedField, UnNeg, NoReturn, NodeId, UnNot}; use ast::{Pat, PatEnum, PatIdent, PatLit, PatRange, PatRegion, PatStruct}; use ast::{PatTup, PatBox, PatWild, PatWildMulti, PatWildSingle}; use ast::{PolyTraitRef}; -use ast::{QPath, RequiredMethod}; +use ast::{QSelf, RequiredMethod}; use ast::{Return, BiShl, BiShr, Stmt, StmtDecl}; use ast::{StmtExpr, StmtSemi, StmtMac, StructDef, StructField}; use ast::{StructVariantKind, BiSub, StrStyle}; @@ -53,7 +53,7 @@ use ast::{TtDelimited, TtSequence, TtToken}; use ast::{TupleVariantKind, Ty, Ty_, TypeBinding}; use ast::{TyFixedLengthVec, TyBareFn}; use ast::{TyTypeof, TyInfer, TypeMethod}; -use ast::{TyParam, TyParamBound, TyParen, TyPath, TyPolyTraitRef, TyPtr, TyQPath}; +use ast::{TyParam, TyParamBound, TyParen, TyPath, TyPolyTraitRef, TyPtr}; use ast::{TyRptr, TyTup, TyU32, TyVec, UnUniq}; use ast::{TypeImplItem, TypeTraitItem, Typedef,}; use ast::{UnnamedField, UnsafeBlock}; @@ -143,7 +143,7 @@ macro_rules! maybe_whole_expr { _ => unreachable!() }; let span = $p.span; - Some($p.mk_expr(span.lo, span.hi, ExprPath(pt))) + Some($p.mk_expr(span.lo, span.hi, ExprPath(None, pt))) } token::Interpolated(token::NtBlock(_)) => { // FIXME: The following avoids an issue with lexical borrowck scopes, @@ -1076,7 +1076,7 @@ impl<'a> Parser<'a> { } pub fn parse_ty_path(&mut self) -> Ty_ { - TyPath(self.parse_path(LifetimeAndTypesWithoutColons)) + TyPath(None, self.parse_path(LifetimeAndTypesWithoutColons)) } /// parse a TyBareFn type: @@ -1524,15 +1524,36 @@ impl<'a> Parser<'a> { } else if self.eat_lt() { // QUALIFIED PATH `::item` let self_type = self.parse_ty_sum(); - self.expect_keyword(keywords::As); - let mut path = self.parse_path(LifetimeAndTypesWithoutColons); + + let mut path = if self.eat_keyword(keywords::As) { + self.parse_path(LifetimeAndTypesWithoutColons) + } else { + ast::Path { + span: self.span, + global: false, + segments: vec![] + } + }; + + let qself = QSelf { + ty: self_type, + position: path.segments.len() + }; + self.expect(&token::Gt); self.expect(&token::ModSep); + path.segments.push(ast::PathSegment { identifier: self.parse_ident(), parameters: ast::PathParameters::none() }); - TyQPath(QPath { self_type: self_type, path: path }) + + if path.segments.len() == 1 { + path.span.lo = self.last_span.lo; + } + path.span.hi = self.last_span.hi; + + TyPath(Some(qself), path) } else if self.check(&token::ModSep) || self.token.is_ident() || self.token.is_path() { @@ -2173,7 +2194,7 @@ impl<'a> Parser<'a> { }, token::Plain) => { self.bump(); let path = ast_util::ident_to_path(mk_sp(lo, hi), id); - ex = ExprPath(path); + ex = ExprPath(None, path); hi = self.last_span.hi; } token::OpenDelim(token::Bracket) => { @@ -2215,10 +2236,22 @@ impl<'a> Parser<'a> { if self.eat_lt() { // QUALIFIED PATH `::item::<'a, T>` let self_type = self.parse_ty_sum(); - self.expect_keyword(keywords::As); - let mut path = self.parse_path(LifetimeAndTypesWithoutColons); + let mut path = if self.eat_keyword(keywords::As) { + self.parse_path(LifetimeAndTypesWithoutColons) + } else { + ast::Path { + span: self.span, + global: false, + segments: vec![] + } + }; + let qself = QSelf { + ty: self_type, + position: path.segments.len() + }; self.expect(&token::Gt); self.expect(&token::ModSep); + let item_name = self.parse_ident(); let parameters = if self.eat(&token::ModSep) { self.expect_lt(); @@ -2237,9 +2270,14 @@ impl<'a> Parser<'a> { identifier: item_name, parameters: parameters }); + + if path.segments.len() == 1 { + path.span.lo = self.last_span.lo; + } + path.span.hi = self.last_span.hi; + let hi = self.span.hi; - return self.mk_expr(lo, hi, - ExprQPath(QPath { self_type: self_type, path: path })); + return self.mk_expr(lo, hi, ExprPath(Some(qself), path)); } if self.eat_keyword(keywords::Move) { return self.parse_lambda_expr(CaptureByValue); @@ -2379,7 +2417,7 @@ impl<'a> Parser<'a> { } hi = pth.span.hi; - ex = ExprPath(pth); + ex = ExprPath(None, pth); } else { // other literal expression let lit = self.parse_lit(); @@ -3421,7 +3459,7 @@ impl<'a> Parser<'a> { let end = if self.token.is_ident() || self.token.is_path() { let path = self.parse_path(LifetimeAndTypesWithColons); let hi = self.span.hi; - self.mk_expr(lo, hi, ExprPath(path)) + self.mk_expr(lo, hi, ExprPath(None, path)) } else { self.parse_literal_maybe_minus() }; @@ -4808,7 +4846,7 @@ impl<'a> Parser<'a> { let opt_trait = if could_be_trait && self.eat_keyword(keywords::For) { // New-style trait. Reinterpret the type as a trait. match ty.node { - TyPath(ref path) => { + TyPath(None, ref path) => { Some(TraitRef { path: (*path).clone(), ref_id: ty.id, diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 11502c29ebb..78b9487d1c9 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -729,11 +729,11 @@ impl<'a> State<'a> { &generics, None)); } - ast::TyPath(ref path) => { + ast::TyPath(None, ref path) => { try!(self.print_path(path, false, 0)); } - ast::TyQPath(ref qpath) => { - try!(self.print_qpath(qpath, false)) + ast::TyPath(Some(ref qself), ref path) => { + try!(self.print_qpath(path, qself, false)) } ast::TyObjectSum(ref ty, ref bounds) => { try!(self.print_type(&**ty)); @@ -1852,8 +1852,12 @@ impl<'a> State<'a> { try!(self.print_expr(&**e)); } } - ast::ExprPath(ref path) => try!(self.print_path(path, true, 0)), - ast::ExprQPath(ref qpath) => try!(self.print_qpath(qpath, true)), + ast::ExprPath(None, ref path) => { + try!(self.print_path(path, true, 0)) + } + ast::ExprPath(Some(ref qself), ref path) => { + try!(self.print_qpath(path, qself, true)) + } ast::ExprBreak(opt_ident) => { try!(word(&mut self.s, "break")); try!(space(&mut self.s)); @@ -2037,18 +2041,19 @@ impl<'a> State<'a> { } fn print_qpath(&mut self, - qpath: &ast::QPath, + path: &ast::Path, + qself: &ast::QSelf, colons_before_params: bool) -> IoResult<()> { try!(word(&mut self.s, "<")); - try!(self.print_type(&*qpath.self_type)); + try!(self.print_type(&qself.ty)); try!(space(&mut self.s)); try!(self.word_space("as")); - try!(self.print_path(&qpath.path, false, 1)); + try!(self.print_path(&path, false, 1)); try!(word(&mut self.s, ">")); try!(word(&mut self.s, "::")); - let item_segment = qpath.path.segments.last().unwrap(); + let item_segment = path.segments.last().unwrap(); try!(self.print_ident(item_segment.identifier)); self.print_path_parameters(&item_segment.parameters, colons_before_params) } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 55372585062..33d8d56b4b1 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -396,13 +396,12 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) { walk_fn_ret_ty(visitor, &function_declaration.decl.output); walk_lifetime_decls_helper(visitor, &function_declaration.lifetimes); } - TyPath(ref path) => { + TyPath(ref maybe_qself, ref path) => { + if let Some(ref qself) = *maybe_qself { + visitor.visit_ty(&qself.ty); + } visitor.visit_path(path, typ.id); } - TyQPath(ref qpath) => { - visitor.visit_ty(&*qpath.self_type); - visitor.visit_path(&qpath.path, typ.id); - } TyObjectSum(ref ty, ref bounds) => { visitor.visit_ty(&**ty); walk_ty_param_bounds_helper(visitor, bounds); @@ -859,13 +858,12 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { walk_expr_opt(visitor, start); walk_expr_opt(visitor, end) } - ExprPath(ref path) => { + ExprPath(ref maybe_qself, ref path) => { + if let Some(ref qself) = *maybe_qself { + visitor.visit_ty(&qself.ty); + } visitor.visit_path(path, expression.id) } - ExprQPath(ref qpath) => { - visitor.visit_ty(&*qpath.self_type); - visitor.visit_path(&qpath.path, expression.id); - } ExprBreak(_) | ExprAgain(_) => {} ExprRet(ref optional_expression) => { walk_expr_opt(visitor, optional_expression) diff --git a/src/test/run-pass/ufcs-polymorphic-paths.rs b/src/test/run-pass/ufcs-polymorphic-paths.rs index 277aaf086f4..29b1c8f81d3 100644 --- a/src/test/run-pass/ufcs-polymorphic-paths.rs +++ b/src/test/run-pass/ufcs-polymorphic-paths.rs @@ -61,8 +61,10 @@ tests! { // Inherent static methods. Vec::new, fn() -> Vec<()>, (); Vec::<()>::new, fn() -> Vec<()>, (); + >::new, fn() -> Vec<()>, (); Vec::with_capacity, fn(usize) -> Vec<()>, (5); Vec::<()>::with_capacity, fn(usize) -> Vec<()>, (5); + >::with_capacity, fn(usize) -> Vec<()>, (5); BitVec::from_fn, fn(usize, fn(usize) -> bool) -> BitVec, (5, odd); BitVec::from_fn:: bool>, fn(usize, fn(usize) -> bool) -> BitVec, (5, odd); @@ -78,26 +80,32 @@ tests! { // Trait static methods. bool::size, fn() -> usize, (); + ::size, fn() -> usize, (); ::size, fn() -> usize, (); Default::default, fn() -> i32, (); i32::default, fn() -> i32, (); + ::default, fn() -> i32, (); ::default, fn() -> i32, (); Rand::rand, fn(&mut DummyRng) -> i32, (&mut dummy_rng()); i32::rand, fn(&mut DummyRng) -> i32, (&mut dummy_rng()); + ::rand, fn(&mut DummyRng) -> i32, (&mut dummy_rng()); ::rand, fn(&mut DummyRng) -> i32, (&mut dummy_rng()); Rand::rand::, fn(&mut DummyRng) -> i32, (&mut dummy_rng()); i32::rand::, fn(&mut DummyRng) -> i32, (&mut dummy_rng()); + ::rand::, fn(&mut DummyRng) -> i32, (&mut dummy_rng()); ::rand::, fn(&mut DummyRng) -> i32, (&mut dummy_rng()); // Trait non-static methods. Clone::clone, fn(&i32) -> i32, (&5); i32::clone, fn(&i32) -> i32, (&5); + ::clone, fn(&i32) -> i32, (&5); ::clone, fn(&i32) -> i32, (&5); FromIterator::from_iter, fn(OptionIter) -> Vec, (Some(5).into_iter()); Vec::from_iter, fn(OptionIter) -> Vec, (Some(5).into_iter()); + >::from_iter, fn(OptionIter) -> Vec, (Some(5).into_iter()); as FromIterator<_>>::from_iter, fn(OptionIter) -> Vec, (Some(5).into_iter()); as FromIterator<_>>::from_iter, fn(OptionIter) -> Vec, @@ -109,11 +117,14 @@ tests! { Add::add, fn(i32, i32) -> i32, (5, 6); i32::add, fn(i32, i32) -> i32, (5, 6); + ::add, fn(i32, i32) -> i32, (5, 6); >::add, fn(i32, i32) -> i32, (5, 6); >::add, fn(i32, i32) -> i32, (5, 6); String::into_cow, fn(String) -> Cow<'static, str>, ("foo".to_string()); + ::into_cow, fn(String) -> Cow<'static, str>, + ("foo".to_string()); >::into_cow, fn(String) -> Cow<'static, str>, ("foo".to_string()); >::into_cow, fn(String) -> Cow<'static, str>, -- cgit 1.4.1-3-g733a5