diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 67dc069da41..3ae3671b593 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -865,7 +865,7 @@ impl<'a> LoweringContext<'a> { data: &AngleBracketedParameterData, param_mode: ParamMode) -> hir::AngleBracketedParameterData { - let &AngleBracketedParameterData { ref lifetimes, ref types, ref bindings } = data; + let &AngleBracketedParameterData { ref lifetimes, ref types, ref bindings, .. } = data; hir::AngleBracketedParameterData { lifetimes: self.lower_lifetimes(lifetimes), types: types.iter().map(|ty| self.lower_ty(ty)).collect(), diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index e8331cc5397..38d8555334c 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -195,10 +195,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> { match item.node { ItemKind::Use(ref view_path) => { let path = view_path.node.path(); - if path.segments.iter().any(|segment| segment.parameters.is_some()) { - self.err_handler() - .span_err(path.span, "generic arguments in import path"); - } + path.segments.iter().find(|segment| segment.parameters.is_some()).map(|segment| { + self.err_handler().span_err(segment.parameters.as_ref().unwrap().span(), + "generic arguments in import path"); + }); } ItemKind::Impl(.., Some(..), _, ref impl_items) => { self.invalid_visibility(&item.vis, item.span, None); @@ -297,10 +297,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> { fn visit_vis(&mut self, vis: &'a Visibility) { match *vis { Visibility::Restricted { ref path, .. } => { - if path.segments.iter().any(|segment| segment.parameters.is_some()) { - self.err_handler() - .span_err(path.span, "generic arguments in visibility path"); - } + path.segments.iter().find(|segment| segment.parameters.is_some()).map(|segment| { + self.err_handler().span_err(segment.parameters.as_ref().unwrap().span(), + "generic arguments in visibility path"); + }); } _ => {} } diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index c256b42f1bd..f8f9b27f148 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -386,9 +386,10 @@ impl<'a> Resolver<'a> { fn resolve_macro_to_def(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, force: bool) -> Result { let ast::Path { ref segments, span } = *path; - if segments.iter().any(|segment| segment.parameters.is_some()) { - self.session.span_err(span, "generic arguments in macro path"); - } + segments.iter().find(|segment| segment.parameters.is_some()).map(|segment| { + self.session.span_err(segment.parameters.as_ref().unwrap().span(), + "generic arguments in macro path"); + }); let path: Vec<_> = segments.iter().map(|seg| respan(seg.span, seg.identifier)).collect(); let invocation = self.invocations[&scope]; diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 544afc5d6f6..4fc73787353 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -153,14 +153,10 @@ pub enum PathParameters { } impl PathParameters { - pub fn span(&self, fallback: Span) -> Span { + pub fn span(&self) -> Span { match *self { - AngleBracketed(ref data) => { - data.lifetimes.get(0).map(|x| x.span).or_else(|| - data.types.get(0).map(|x| x.span)).or_else(|| - data.bindings.get(0).map(|x| x.span)).unwrap_or(fallback) - } - Parenthesized(ref data) => data.span + AngleBracketed(ref data) => data.span, + Parenthesized(ref data) => data.span, } } } @@ -168,6 +164,8 @@ impl PathParameters { /// A path like `Foo<'a, T>` #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Default)] pub struct AngleBracketedParameterData { + /// Overall span + pub span: Span, /// The lifetime parameters for this path segment. pub lifetimes: Vec, /// The type parameters for this path segment, if present. diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index af9143eadbc..e004f7354eb 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -312,7 +312,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { self.path_all(span, true, strs, Vec::new(), Vec::new(), Vec::new()) } fn path_all(&self, - sp: Span, + span: Span, global: bool, mut idents: Vec , lifetimes: Vec, @@ -322,24 +322,17 @@ impl<'a> AstBuilder for ExtCtxt<'a> { let last_identifier = idents.pop().unwrap(); let mut segments: Vec = Vec::new(); if global { - segments.push(ast::PathSegment::crate_root(sp)); + segments.push(ast::PathSegment::crate_root(span)); } - segments.extend(idents.into_iter().map(|i| ast::PathSegment::from_ident(i, sp))); + segments.extend(idents.into_iter().map(|i| ast::PathSegment::from_ident(i, span))); let parameters = if !lifetimes.is_empty() || !types.is_empty() || !bindings.is_empty() { - ast::AngleBracketedParameterData { lifetimes, types, bindings }.into() + ast::AngleBracketedParameterData { lifetimes, types, bindings, span }.into() } else { None }; - segments.push(ast::PathSegment { - identifier: last_identifier, - span: sp, - parameters: parameters - }); - ast::Path { - span: sp, - segments: segments, - } + segments.push(ast::PathSegment { identifier: last_identifier, span, parameters }); + ast::Path { span, segments } } /// Constructs a qualified path. @@ -366,7 +359,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { -> (ast::QSelf, ast::Path) { let mut path = trait_path; let parameters = if !lifetimes.is_empty() || !types.is_empty() || !bindings.is_empty() { - ast::AngleBracketedParameterData { lifetimes, types, bindings }.into() + ast::AngleBracketedParameterData { lifetimes, types, bindings, span: ident.span }.into() } else { None }; diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index eaec1eef172..8c616df858a 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -471,10 +471,11 @@ pub fn noop_fold_angle_bracketed_parameter_data(data: AngleBracketedP fld: &mut T) -> AngleBracketedParameterData { - let AngleBracketedParameterData { lifetimes, types, bindings } = data; + let AngleBracketedParameterData { lifetimes, types, bindings, span } = data; AngleBracketedParameterData { lifetimes: fld.fold_lifetimes(lifetimes), types: types.move_map(|ty| fld.fold_ty(ty)), - bindings: bindings.move_map(|b| fld.fold_ty_binding(b)) } + bindings: bindings.move_map(|b| fld.fold_ty_binding(b)), + span: fld.new_span(span) } } pub fn noop_fold_parenthesized_parameter_data(data: ParenthesizedParameterData, diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 833a10efa0b..d1591a219b3 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1808,8 +1808,8 @@ impl<'a> Parser<'a> { // `<'a, T, A = U>` let (lifetimes, types, bindings) = self.parse_generic_args()?; self.expect_gt()?; - let _span = lo.to(self.prev_span); - AngleBracketedParameterData { lifetimes, types, bindings }.into() + let span = lo.to(self.prev_span); + AngleBracketedParameterData { lifetimes, types, bindings, span }.into() } else { // `(T, U) -> R` self.bump(); // `(` @@ -2357,7 +2357,7 @@ impl<'a> Parser<'a> { _ => { // Field access `expr.f` if let Some(parameters) = segment.parameters { - self.span_err(parameters.span(segment.span), + self.span_err(parameters.span(), "field expressions may not have generic arguments"); } diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index 820adc60999..3a701f91314 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -239,6 +239,12 @@ pub struct SpanLabel { pub label: Option, } +impl Default for Span { + fn default() -> Self { + DUMMY_SP + } +} + impl serialize::UseSpecializedEncodable for Span { fn default_encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_struct("Span", 2, |s| { diff --git a/src/test/compile-fail/macro-with-seps-err-msg.rs b/src/test/compile-fail/macro-with-seps-err-msg.rs index 8e0c451959d..0f123997ca1 100644 --- a/src/test/compile-fail/macro-with-seps-err-msg.rs +++ b/src/test/compile-fail/macro-with-seps-err-msg.rs @@ -10,28 +10,8 @@ // gate-test-use_extern_macros -macro_rules! m { - ($p1: path) => { - #[derive($p1)] struct U; - } -} - fn main() { globnar::brotz!(); //~ ERROR non-ident macro paths are experimental #[derive(foo::Bar)] struct T; //~ ERROR non-ident macro paths are experimental ::foo!(); //~ ERROR non-ident macro paths are experimental - - foo::!(); - //~^ ERROR generic arguments in macro path - //~| ERROR generic arguments in macro path - //~| ERROR generic arguments in macro path - foo::<>!(); - //~^ ERROR generic arguments in macro path - //~| ERROR generic arguments in macro path - //~| ERROR generic arguments in macro path - m!(MyTrait<>); - //~^ ERROR generic arguments in macro path - //~| ERROR generic arguments in macro path - //~| ERROR generic arguments in macro path - //~| ERROR generic arguments in macro path } diff --git a/src/test/compile-fail/import-ty-params.rs b/src/test/ui/span/import-ty-params.rs similarity index 100% rename from src/test/compile-fail/import-ty-params.rs rename to src/test/ui/span/import-ty-params.rs diff --git a/src/test/ui/span/import-ty-params.stderr b/src/test/ui/span/import-ty-params.stderr new file mode 100644 index 00000000000..de959a14cc5 --- /dev/null +++ b/src/test/ui/span/import-ty-params.stderr @@ -0,0 +1,14 @@ +error: generic arguments in import path + --> $DIR/import-ty-params.rs:24:25 + | +24 | import! { a::b::c::S } //~ ERROR generic arguments in import path + | ^^^^ + +error: generic arguments in import path + --> $DIR/import-ty-params.rs:27:25 + | +27 | import! { a::b::c::S<> } //~ ERROR generic arguments in import path + | ^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/span/macro-ty-params.rs b/src/test/ui/span/macro-ty-params.rs new file mode 100644 index 00000000000..08a7518dff9 --- /dev/null +++ b/src/test/ui/span/macro-ty-params.rs @@ -0,0 +1,31 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +macro_rules! m { + ($p1: path) => { + #[derive($p1)] struct U; + } +} + +fn main() { + foo::!(); + //~^ ERROR generic arguments in macro path + //~| ERROR generic arguments in macro path + //~| ERROR generic arguments in macro path + foo::<>!(); + //~^ ERROR generic arguments in macro path + //~| ERROR generic arguments in macro path + //~| ERROR generic arguments in macro path + m!(MyTrait<>); + //~^ ERROR generic arguments in macro path + //~| ERROR generic arguments in macro path + //~| ERROR generic arguments in macro path + //~| ERROR generic arguments in macro path +} diff --git a/src/test/ui/span/macro-ty-params.stderr b/src/test/ui/span/macro-ty-params.stderr new file mode 100644 index 00000000000..ff3847ce1fa --- /dev/null +++ b/src/test/ui/span/macro-ty-params.stderr @@ -0,0 +1,62 @@ +error: generic arguments in macro path + --> $DIR/macro-ty-params.rs:18:8 + | +18 | foo::!(); + | ^^^^^ + +error: generic arguments in macro path + --> $DIR/macro-ty-params.rs:22:8 + | +22 | foo::<>!(); + | ^^^^ + +error: generic arguments in macro path + --> $DIR/macro-ty-params.rs:26:15 + | +26 | m!(MyTrait<>); + | ^^ + +error: generic arguments in macro path + --> $DIR/macro-ty-params.rs:26:15 + | +26 | m!(MyTrait<>); + | ^^ + +error: generic arguments in macro path + --> $DIR/macro-ty-params.rs:26:15 + | +26 | m!(MyTrait<>); + | ^^ + +error: generic arguments in macro path + --> $DIR/macro-ty-params.rs:22:8 + | +22 | foo::<>!(); + | ^^^^ + +error: generic arguments in macro path + --> $DIR/macro-ty-params.rs:18:8 + | +18 | foo::!(); + | ^^^^^ + +error: generic arguments in macro path + --> $DIR/macro-ty-params.rs:18:8 + | +18 | foo::!(); + | ^^^^^ + +error: generic arguments in macro path + --> $DIR/macro-ty-params.rs:22:8 + | +22 | foo::<>!(); + | ^^^^ + +error: generic arguments in macro path + --> $DIR/macro-ty-params.rs:26:15 + | +26 | m!(MyTrait<>); + | ^^ + +error: aborting due to 10 previous errors + diff --git a/src/test/compile-fail/privacy/restricted/ty-params.rs b/src/test/ui/span/visibility-ty-params.rs similarity index 100% rename from src/test/compile-fail/privacy/restricted/ty-params.rs rename to src/test/ui/span/visibility-ty-params.rs diff --git a/src/test/ui/span/visibility-ty-params.stderr b/src/test/ui/span/visibility-ty-params.stderr new file mode 100644 index 00000000000..0460b7ca025 --- /dev/null +++ b/src/test/ui/span/visibility-ty-params.stderr @@ -0,0 +1,22 @@ +error[E0577]: expected module, found struct `S` + --> $DIR/visibility-ty-params.rs:16:5 + | +16 | m!{ S } //~ ERROR generic arguments in visibility path + | -^^^^ + | | + | did you mean `m`? + +error: generic arguments in visibility path + --> $DIR/visibility-ty-params.rs:16:6 + | +16 | m!{ S } //~ ERROR generic arguments in visibility path + | ^^^^ + +error: generic arguments in visibility path + --> $DIR/visibility-ty-params.rs:20:10 + | +20 | m!{ m<> } //~ ERROR generic arguments in visibility path + | ^^ + +error: aborting due to 3 previous errors +