Skip to content

Commit 8a78a12

Browse files
committed
Auto merge of #43438 - petrochenkov:path, r=jseyfried
syntax: Simplify parsing of paths Discern between `Path` and `Path<>` in AST (but not in HIR). Give span to angle bracketed generic arguments (`::<'a, T>` in `path::segment::<'a, T>`). This is a refactoring in preparation for https://internals.rust-lang.org/t/macro-path-uses-novel-syntax/5561/3, but it doesn't add anything to the grammar yet. r? @jseyfried
2 parents 52a3309 + 1e8a7f6 commit 8a78a12

20 files changed

+301
-311
lines changed

Diff for: src/librustc/hir/lowering.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -865,7 +865,7 @@ impl<'a> LoweringContext<'a> {
865865
data: &AngleBracketedParameterData,
866866
param_mode: ParamMode)
867867
-> hir::AngleBracketedParameterData {
868-
let &AngleBracketedParameterData { ref lifetimes, ref types, ref bindings } = data;
868+
let &AngleBracketedParameterData { ref lifetimes, ref types, ref bindings, .. } = data;
869869
hir::AngleBracketedParameterData {
870870
lifetimes: self.lower_lifetimes(lifetimes),
871871
types: types.iter().map(|ty| self.lower_ty(ty)).collect(),

Diff for: src/librustc_passes/ast_validation.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -195,10 +195,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
195195
match item.node {
196196
ItemKind::Use(ref view_path) => {
197197
let path = view_path.node.path();
198-
if path.segments.iter().any(|segment| segment.parameters.is_some()) {
199-
self.err_handler()
200-
.span_err(path.span, "type or lifetime parameters in import path");
201-
}
198+
path.segments.iter().find(|segment| segment.parameters.is_some()).map(|segment| {
199+
self.err_handler().span_err(segment.parameters.as_ref().unwrap().span(),
200+
"generic arguments in import path");
201+
});
202202
}
203203
ItemKind::Impl(.., Some(..), _, ref impl_items) => {
204204
self.invalid_visibility(&item.vis, item.span, None);
@@ -297,10 +297,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
297297
fn visit_vis(&mut self, vis: &'a Visibility) {
298298
match *vis {
299299
Visibility::Restricted { ref path, .. } => {
300-
if !path.segments.iter().all(|segment| segment.parameters.is_none()) {
301-
self.err_handler()
302-
.span_err(path.span, "type or lifetime parameters in visibility path");
303-
}
300+
path.segments.iter().find(|segment| segment.parameters.is_some()).map(|segment| {
301+
self.err_handler().span_err(segment.parameters.as_ref().unwrap().span(),
302+
"generic arguments in visibility path");
303+
});
304304
}
305305
_ => {}
306306
}

Diff for: src/librustc_resolve/macros.rs

+13-7
Original file line numberDiff line numberDiff line change
@@ -385,15 +385,21 @@ impl<'a> Resolver<'a> {
385385

386386
fn resolve_macro_to_def(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, force: bool)
387387
-> Result<Def, Determinacy> {
388-
let ast::Path { ref segments, span } = *path;
389-
if segments.iter().any(|segment| segment.parameters.is_some()) {
390-
let kind =
391-
if segments.last().unwrap().parameters.is_some() { "macro" } else { "module" };
392-
let msg = format!("type parameters are not allowed on {}s", kind);
393-
self.session.span_err(path.span, &msg);
394-
return Err(Determinacy::Determined);
388+
let def = self.resolve_macro_to_def_inner(scope, path, kind, force);
389+
if def != Err(Determinacy::Undetermined) {
390+
// Do not report duplicated errors on every undetermined resolution.
391+
path.segments.iter().find(|segment| segment.parameters.is_some()).map(|segment| {
392+
self.session.span_err(segment.parameters.as_ref().unwrap().span(),
393+
"generic arguments in macro path");
394+
});
395395
}
396+
def
397+
}
396398

399+
fn resolve_macro_to_def_inner(&mut self, scope: Mark, path: &ast::Path,
400+
kind: MacroKind, force: bool)
401+
-> Result<Def, Determinacy> {
402+
let ast::Path { ref segments, span } = *path;
397403
let path: Vec<_> = segments.iter().map(|seg| respan(seg.span, seg.identifier)).collect();
398404
let invocation = self.invocations[&scope];
399405
self.current_module = invocation.module.get();

Diff for: src/libsyntax/ast.rs

+23-8
Original file line numberDiff line numberDiff line change
@@ -120,12 +120,11 @@ pub struct PathSegment {
120120
pub span: Span,
121121

122122
/// Type/lifetime parameters attached to this path. They come in
123-
/// two flavors: `Path<A,B,C>` and `Path(A,B) -> C`. Note that
124-
/// this is more than just simple syntactic sugar; the use of
125-
/// parens affects the region binding rules, so we preserve the
126-
/// distinction.
127-
/// The `Option<P<..>>` wrapper is purely a size optimization;
128-
/// `None` is used to represent both `Path` and `Path<>`.
123+
/// two flavors: `Path<A,B,C>` and `Path(A,B) -> C`.
124+
/// `None` means that no parameter list is supplied (`Path`),
125+
/// `Some` means that parameter list is supplied (`Path<X, Y>`)
126+
/// but it can be empty (`Path<>`).
127+
/// `P` is used as a size optimization for the common case with no parameters.
129128
pub parameters: Option<P<PathParameters>>,
130129
}
131130

@@ -153,9 +152,20 @@ pub enum PathParameters {
153152
Parenthesized(ParenthesizedParameterData),
154153
}
155154

155+
impl PathParameters {
156+
pub fn span(&self) -> Span {
157+
match *self {
158+
AngleBracketed(ref data) => data.span,
159+
Parenthesized(ref data) => data.span,
160+
}
161+
}
162+
}
163+
156164
/// A path like `Foo<'a, T>`
157165
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Default)]
158166
pub struct AngleBracketedParameterData {
167+
/// Overall span
168+
pub span: Span,
159169
/// The lifetime parameters for this path segment.
160170
pub lifetimes: Vec<Lifetime>,
161171
/// The type parameters for this path segment, if present.
@@ -168,8 +178,13 @@ pub struct AngleBracketedParameterData {
168178

169179
impl Into<Option<P<PathParameters>>> for AngleBracketedParameterData {
170180
fn into(self) -> Option<P<PathParameters>> {
171-
let empty = self.lifetimes.is_empty() && self.types.is_empty() && self.bindings.is_empty();
172-
if empty { None } else { Some(P(PathParameters::AngleBracketed(self))) }
181+
Some(P(PathParameters::AngleBracketed(self)))
182+
}
183+
}
184+
185+
impl Into<Option<P<PathParameters>>> for ParenthesizedParameterData {
186+
fn into(self) -> Option<P<PathParameters>> {
187+
Some(P(PathParameters::Parenthesized(self)))
173188
}
174189
}
175190

Diff for: src/libsyntax/ext/base.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -608,7 +608,7 @@ pub trait Resolver {
608608
fn check_unused_macros(&self);
609609
}
610610

611-
#[derive(Copy, Clone, Debug)]
611+
#[derive(Copy, Clone, Debug, PartialEq)]
612612
pub enum Determinacy {
613613
Determined,
614614
Undetermined,

Diff for: src/libsyntax/ext/build.rs

+13-24
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
312312
self.path_all(span, true, strs, Vec::new(), Vec::new(), Vec::new())
313313
}
314314
fn path_all(&self,
315-
sp: Span,
315+
span: Span,
316316
global: bool,
317317
mut idents: Vec<ast::Ident> ,
318318
lifetimes: Vec<ast::Lifetime>,
@@ -322,28 +322,17 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
322322
let last_identifier = idents.pop().unwrap();
323323
let mut segments: Vec<ast::PathSegment> = Vec::new();
324324
if global {
325-
segments.push(ast::PathSegment::crate_root(sp));
325+
segments.push(ast::PathSegment::crate_root(span));
326326
}
327327

328-
segments.extend(idents.into_iter().map(|i| ast::PathSegment::from_ident(i, sp)));
329-
let parameters = if lifetimes.is_empty() && types.is_empty() && bindings.is_empty() {
330-
None
328+
segments.extend(idents.into_iter().map(|i| ast::PathSegment::from_ident(i, span)));
329+
let parameters = if !lifetimes.is_empty() || !types.is_empty() || !bindings.is_empty() {
330+
ast::AngleBracketedParameterData { lifetimes, types, bindings, span }.into()
331331
} else {
332-
Some(P(ast::PathParameters::AngleBracketed(ast::AngleBracketedParameterData {
333-
lifetimes: lifetimes,
334-
types: types,
335-
bindings: bindings,
336-
})))
332+
None
337333
};
338-
segments.push(ast::PathSegment {
339-
identifier: last_identifier,
340-
span: sp,
341-
parameters: parameters
342-
});
343-
ast::Path {
344-
span: sp,
345-
segments: segments,
346-
}
334+
segments.push(ast::PathSegment { identifier: last_identifier, span, parameters });
335+
ast::Path { span, segments }
347336
}
348337

349338
/// Constructs a qualified path.
@@ -369,15 +358,15 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
369358
bindings: Vec<ast::TypeBinding>)
370359
-> (ast::QSelf, ast::Path) {
371360
let mut path = trait_path;
372-
let parameters = ast::AngleBracketedParameterData {
373-
lifetimes: lifetimes,
374-
types: types,
375-
bindings: bindings,
361+
let parameters = if !lifetimes.is_empty() || !types.is_empty() || !bindings.is_empty() {
362+
ast::AngleBracketedParameterData { lifetimes, types, bindings, span: ident.span }.into()
363+
} else {
364+
None
376365
};
377366
path.segments.push(ast::PathSegment {
378367
identifier: ident.node,
379368
span: ident.span,
380-
parameters: Some(P(ast::PathParameters::AngleBracketed(parameters))),
369+
parameters: parameters,
381370
});
382371

383372
(ast::QSelf {

Diff for: src/libsyntax/fold.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -471,10 +471,11 @@ pub fn noop_fold_angle_bracketed_parameter_data<T: Folder>(data: AngleBracketedP
471471
fld: &mut T)
472472
-> AngleBracketedParameterData
473473
{
474-
let AngleBracketedParameterData { lifetimes, types, bindings } = data;
474+
let AngleBracketedParameterData { lifetimes, types, bindings, span } = data;
475475
AngleBracketedParameterData { lifetimes: fld.fold_lifetimes(lifetimes),
476476
types: types.move_map(|ty| fld.fold_ty(ty)),
477-
bindings: bindings.move_map(|b| fld.fold_ty_binding(b)) }
477+
bindings: bindings.move_map(|b| fld.fold_ty_binding(b)),
478+
span: fld.new_span(span) }
478479
}
479480

480481
pub fn noop_fold_parenthesized_parameter_data<T: Folder>(data: ParenthesizedParameterData,

0 commit comments

Comments
 (0)