Skip to content

Commit 804459b

Browse files
committed
Issue warnings for unnecessary path disambiguators
1 parent 7d21f21 commit 804459b

File tree

3 files changed

+32
-15
lines changed

3 files changed

+32
-15
lines changed

src/libsyntax/ext/tt/macro_parser.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -599,9 +599,7 @@ fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: &str) -> Nonterminal {
599599
panic!(FatalError)
600600
}
601601
},
602-
"path" => {
603-
token::NtPath(panictry!(p.parse_path(PathStyle::Type)))
604-
},
602+
"path" => token::NtPath(panictry!(p.parse_path_common(PathStyle::Type, false))),
605603
"meta" => token::NtMeta(panictry!(p.parse_meta_item())),
606604
"vis" => token::NtVis(panictry!(p.parse_visibility(true))),
607605
// this is not supposed to happen, since it has been checked

src/libsyntax/parse/parser.rs

+18-10
Original file line numberDiff line numberDiff line change
@@ -1755,7 +1755,7 @@ impl<'a> Parser<'a> {
17551755
self.expect(&token::ModSep)?;
17561756

17571757
let qself = QSelf { ty, position: path.segments.len() };
1758-
self.parse_path_segments(&mut path.segments, style)?;
1758+
self.parse_path_segments(&mut path.segments, style, true)?;
17591759

17601760
Ok((qself, ast::Path { segments: path.segments, span: lo.to(self.prev_span) }))
17611761
}
@@ -1770,16 +1770,20 @@ impl<'a> Parser<'a> {
17701770
/// `a::b::C::<D>` (with disambiguator)
17711771
/// `Fn(Args)` (without disambiguator)
17721772
/// `Fn::(Args)` (with disambiguator)
1773-
pub fn parse_path(&mut self, style: PathStyle) -> PResult<'a, ast::Path>
1774-
{
1773+
pub fn parse_path(&mut self, style: PathStyle) -> PResult<'a, ast::Path> {
1774+
self.parse_path_common(style, true)
1775+
}
1776+
1777+
pub fn parse_path_common(&mut self, style: PathStyle, enable_warning: bool)
1778+
-> PResult<'a, ast::Path> {
17751779
maybe_whole!(self, NtPath, |x| x);
17761780

17771781
let lo = self.meta_var_span.unwrap_or(self.span);
17781782
let mut segments = Vec::new();
17791783
if self.eat(&token::ModSep) {
17801784
segments.push(PathSegment::crate_root(lo));
17811785
}
1782-
self.parse_path_segments(&mut segments, style)?;
1786+
self.parse_path_segments(&mut segments, style, enable_warning)?;
17831787

17841788
Ok(ast::Path { segments, span: lo.to(self.prev_span) })
17851789
}
@@ -1804,18 +1808,19 @@ impl<'a> Parser<'a> {
18041808
self.parse_path(style)
18051809
}
18061810

1807-
fn parse_path_segments(&mut self, segments: &mut Vec<PathSegment>, style: PathStyle)
1808-
-> PResult<'a, ()> {
1811+
fn parse_path_segments(&mut self, segments: &mut Vec<PathSegment>, style: PathStyle,
1812+
enable_warning: bool) -> PResult<'a, ()> {
18091813
loop {
1810-
segments.push(self.parse_path_segment(style)?);
1814+
segments.push(self.parse_path_segment(style, enable_warning)?);
18111815

18121816
if self.is_import_coupler() || !self.eat(&token::ModSep) {
18131817
return Ok(());
18141818
}
18151819
}
18161820
}
18171821

1818-
fn parse_path_segment(&mut self, style: PathStyle) -> PResult<'a, PathSegment> {
1822+
fn parse_path_segment(&mut self, style: PathStyle, enable_warning: bool)
1823+
-> PResult<'a, PathSegment> {
18191824
let ident_span = self.span;
18201825
let ident = self.parse_path_segment_ident()?;
18211826

@@ -1835,7 +1840,10 @@ impl<'a> Parser<'a> {
18351840
&& self.look_ahead(1, |t| is_args_start(t)) {
18361841
// Generic arguments are found - `<`, `(`, `::<` or `::(`.
18371842
let lo = self.span;
1838-
self.eat(&token::ModSep);
1843+
if self.eat(&token::ModSep) && style == PathStyle::Type && enable_warning {
1844+
self.diagnostic().struct_span_warn(self.prev_span, "unnecessary path disambiguator")
1845+
.span_label(self.prev_span, "try removing `::`").emit();
1846+
}
18391847

18401848
let parameters = if self.eat_lt() {
18411849
// `<'a, T, A = U>`
@@ -2371,7 +2379,7 @@ impl<'a> Parser<'a> {
23712379

23722380
// Assuming we have just parsed `.`, continue parsing into an expression.
23732381
fn parse_dot_suffix(&mut self, self_arg: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> {
2374-
let segment = self.parse_path_segment(PathStyle::Expr)?;
2382+
let segment = self.parse_path_segment(PathStyle::Expr, true)?;
23752383
Ok(match self.token {
23762384
token::OpenDelim(token::Paren) => {
23772385
// Method call `expr.f()`

src/test/compile-fail/issue-36116.rs

+13-2
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,24 @@
1313
#![feature(rustc_attrs)]
1414
#![allow(unused)]
1515

16+
macro_rules! m {
17+
($p: path) => {
18+
let _ = $p(0);
19+
let _: $p;
20+
}
21+
}
22+
1623
struct Foo<T> {
1724
_a: T,
1825
}
1926

27+
struct S<T>(T);
28+
2029
fn f() {
21-
let f = Some(Foo { _a: 42 }).map(|a| a as Foo::<i32>);
22-
let g: Foo::<i32> = Foo { _a: 42 };
30+
let f = Some(Foo { _a: 42 }).map(|a| a as Foo::<i32>); //~ WARN unnecessary path disambiguator
31+
let g: Foo::<i32> = Foo { _a: 42 }; //~ WARN unnecessary path disambiguator
32+
33+
m!(S::<u8>); // OK, no warning
2334
}
2435

2536
#[rustc_error]

0 commit comments

Comments
 (0)