From ea2a684099860ae0d506e231a119c408ea4269f8 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 12 Feb 2017 14:33:17 +0100 Subject: [PATCH 1/3] Add error codes for errors in libsyntax --- src/libsyntax/diagnostic_list.rs | 4 + src/libsyntax/parse/parser.rs | 122 +++++++++++++++++++++---------- 2 files changed, 86 insertions(+), 40 deletions(-) diff --git a/src/libsyntax/diagnostic_list.rs b/src/libsyntax/diagnostic_list.rs index 2b4d13375046e..f482b818f7746 100644 --- a/src/libsyntax/diagnostic_list.rs +++ b/src/libsyntax/diagnostic_list.rs @@ -224,4 +224,8 @@ register_diagnostics! { E0555, // malformed feature attribute, expected #![feature(...)] E0556, // malformed feature, expected just one word E0557, // feature has been removed + E0583, // file not found for module + E0584, // file for module `..` found at both .. and .. + E0585, // documentation comment that doesn't document anything + E0586, // inclusive range with no end } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 2c4fa8e15edf2..464d16f53a3a7 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -219,7 +219,7 @@ fn is_ident_or_underscore(t: &token::Token) -> bool { pub struct ModulePath { pub name: String, pub path_exists: bool, - pub result: Result, + pub result: Result, } pub struct ModulePathSuccess { @@ -233,6 +233,63 @@ pub struct ModulePathError { pub help_msg: String, } +pub enum Errors { + FileNotFoundForModule { + mod_name: String, + default_path: String, + secondary_path: String, + dir_path: String, + }, + DuplicatePaths { + mod_name: String, + default_path: String, + secondary_path: String, + }, + UselessDocComment, + InclusiveRangeWithNoEnd, +} + +impl Errors { + pub fn span_err<'a>(self, sp: Span, handler: &'a errors::Handler) -> DiagnosticBuilder<'a> { + match self { + Errors::FileNotFoundForModule { ref mod_name, + ref default_path, + ref secondary_path, + ref dir_path } => { + let mut err = struct_span_err!(handler, sp, E0583, + "file not found for module `{}`", mod_name); + err.help(&format!("name the file either {} or {} inside the directory {:?}", + default_path, + secondary_path, + dir_path)); + err + } + Errors::DuplicatePaths { ref mod_name, ref default_path, ref secondary_path } => { + let mut err = struct_span_err!(handler, sp, E0584, + "file for module `{}` found at both {} and {}", + mod_name, + default_path, + secondary_path); + err.help("delete or rename one of them to remove the ambiguity"); + err + } + Errors::UselessDocComment => { + let mut err = struct_span_err!(handler, sp, E0585, + "found a documentation comment that doesn't document anything"); + err.help("doc comments must come before what they document, maybe a comment was \ + intended with `//`?"); + err + } + Errors::InclusiveRangeWithNoEnd => { + let mut err = struct_span_err!(handler, sp, E0586, + "inclusive range with no end"); + err.help("inclusive ranges must be bounded at the end (`...b` or `a...b`)"); + err + } + } + } +} + pub enum LhsExpr { NotYetParsed, AttributesParsed(ThinVec), @@ -461,10 +518,7 @@ impl<'a> Parser<'a> { } _ => { Err(if self.prev_token_kind == PrevTokenKind::DocComment { - self.span_fatal_help(self.prev_span, - "found a documentation comment that doesn't document anything", - "doc comments must come before what they document, maybe a comment was \ - intended with `//`?") + self.span_fatal_err(self.prev_span, Errors::UselessDocComment) } else { let mut err = self.fatal(&format!("expected identifier, found `{}`", self.this_token_to_string())); @@ -955,6 +1009,9 @@ impl<'a> Parser<'a> { pub fn span_fatal(&self, sp: Span, m: &str) -> DiagnosticBuilder<'a> { self.sess.span_diagnostic.struct_span_fatal(sp, m) } + pub fn span_fatal_err(&self, sp: Span, err: Errors) -> DiagnosticBuilder<'a> { + err.span_err(sp, self.diagnostic()) + } pub fn span_fatal_help(&self, sp: Span, m: &str, help: &str) -> DiagnosticBuilder<'a> { let mut err = self.sess.span_diagnostic.struct_span_fatal(sp, m); err.help(help); @@ -1944,10 +2001,7 @@ impl<'a> Parser<'a> { limits: RangeLimits) -> PResult<'a, ast::ExprKind> { if end.is_none() && limits == RangeLimits::Closed { - Err(self.span_fatal_help(self.span, - "inclusive range with no end", - "inclusive ranges must be bounded at the end \ - (`...b` or `a...b`)")) + Err(self.span_fatal_err(self.span, Errors::InclusiveRangeWithNoEnd)) } else { Ok(ExprKind::Range(start, end, limits)) } @@ -3862,10 +3916,7 @@ impl<'a> Parser<'a> { let unused_attrs = |attrs: &[_], s: &mut Self| { if attrs.len() > 0 { if s.prev_token_kind == PrevTokenKind::DocComment { - s.span_err_help(s.prev_span, - "found a documentation comment that doesn't document anything", - "doc comments must come before what they document, maybe a \ - comment was intended with `//`?"); + self.span_fatal_err(s.prev_span, Errors::UselessDocComment).emit(); } else { s.span_err(s.span, "expected statement after outer attribute"); } @@ -4998,10 +5049,8 @@ impl<'a> Parser<'a> { self.bump(); } token::CloseDelim(token::Brace) => {} - token::DocComment(_) => return Err(self.span_fatal_help(self.span, - "found a documentation comment that doesn't document anything", - "doc comments must come before what they document, maybe a comment was \ - intended with `//`?")), + token::DocComment(_) => return Err(self.span_fatal_err(self.span, + Errors::UselessDocComment)), _ => return Err(self.span_fatal_help(self.span, &format!("expected `,`, or `}}`, found `{}`", self.this_token_to_string()), "struct fields should be separated by commas")), @@ -5162,8 +5211,7 @@ impl<'a> Parser<'a> { } /// Returns either a path to a module, or . - pub fn default_submod_path(id: ast::Ident, dir_path: &Path, codemap: &CodeMap) -> ModulePath - { + pub fn default_submod_path(id: ast::Ident, dir_path: &Path, codemap: &CodeMap) -> ModulePath { let mod_name = id.to_string(); let default_path_str = format!("{}.rs", mod_name); let secondary_path_str = format!("{}/mod.rs", mod_name); @@ -5183,19 +5231,16 @@ impl<'a> Parser<'a> { directory_ownership: DirectoryOwnership::Owned, warn: false, }), - (false, false) => Err(ModulePathError { - err_msg: format!("file not found for module `{}`", mod_name), - help_msg: format!("name the file either {} or {} inside the directory {:?}", - default_path_str, - secondary_path_str, - dir_path.display()), + (false, false) => Err(Errors::FileNotFoundForModule { + mod_name: mod_name.clone(), + default_path: default_path_str, + secondary_path: secondary_path_str, + dir_path: format!("{}", dir_path.display()), }), - (true, true) => Err(ModulePathError { - err_msg: format!("file for module `{}` found at both {} and {}", - mod_name, - default_path_str, - secondary_path_str), - help_msg: "delete or rename one of them to remove the ambiguity".to_owned(), + (true, true) => Err(Errors::DuplicatePaths { + mod_name: mod_name.clone(), + default_path: default_path_str, + secondary_path: secondary_path_str, }), }; @@ -5232,7 +5277,7 @@ impl<'a> Parser<'a> { paths.name); err.span_note(id_sp, &msg); } - return Err(err); + Err(err) } else if let DirectoryOwnership::UnownedViaMod(warn) = self.directory.ownership { if warn { if let Ok(result) = paths.result { @@ -5254,15 +5299,12 @@ impl<'a> Parser<'a> { &format!("... or maybe `use` the module `{}` instead \ of possibly redeclaring it", paths.name)); - return Err(err); + Err(err) } else { - return Err(err); - }; - } - - match paths.result { - Ok(succ) => Ok(succ), - Err(err) => Err(self.span_fatal_help(id_sp, &err.err_msg, &err.help_msg)), + Err(err) + } + } else { + paths.result.map_err(|err| self.span_fatal_err(id_sp, err)) } } From 0a45dd7e711abdd3bcfb6292bba836485ee82fae Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 12 Feb 2017 15:08:15 +0100 Subject: [PATCH 2/3] Add tests for newly added error codes --- src/test/compile-fail/E0583.rs | 14 ++++++++++++++ src/test/compile-fail/E0585.rs | 14 ++++++++++++++ src/test/compile-fail/E0586.rs | 14 ++++++++++++++ 3 files changed, 42 insertions(+) create mode 100644 src/test/compile-fail/E0583.rs create mode 100644 src/test/compile-fail/E0585.rs create mode 100644 src/test/compile-fail/E0586.rs diff --git a/src/test/compile-fail/E0583.rs b/src/test/compile-fail/E0583.rs new file mode 100644 index 0000000000000..3a5255d0f5fe3 --- /dev/null +++ b/src/test/compile-fail/E0583.rs @@ -0,0 +1,14 @@ +// 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. + +mod module_that_doesnt_exist; //~ ERROR E0583 + +fn main() { +} diff --git a/src/test/compile-fail/E0585.rs b/src/test/compile-fail/E0585.rs new file mode 100644 index 0000000000000..1acaf8c0b78b6 --- /dev/null +++ b/src/test/compile-fail/E0585.rs @@ -0,0 +1,14 @@ +// 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. + +fn main() { + /// Hello! I'm useless... + //~^ ERROR E0585 +} diff --git a/src/test/compile-fail/E0586.rs b/src/test/compile-fail/E0586.rs new file mode 100644 index 0000000000000..0b063569abc17 --- /dev/null +++ b/src/test/compile-fail/E0586.rs @@ -0,0 +1,14 @@ +// 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. + +fn main() { + let tmp = vec![0, 1, 2, 3, 4, 4, 3, 3, 2, 1]; + let x = &tmp[1...]; //~ ERROR E0586 +} From b6818be41dea90e53344f84770f5e0faaacee4a8 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 12 Feb 2017 15:18:41 +0100 Subject: [PATCH 3/3] Add long error explanations --- src/libsyntax/diagnostic_list.rs | 71 ++++++++++++++++++++++++++++++-- src/libsyntax/parse/parser.rs | 34 +++++++-------- 2 files changed, 85 insertions(+), 20 deletions(-) diff --git a/src/libsyntax/diagnostic_list.rs b/src/libsyntax/diagnostic_list.rs index f482b818f7746..2d59051ec4a53 100644 --- a/src/libsyntax/diagnostic_list.rs +++ b/src/libsyntax/diagnostic_list.rs @@ -201,6 +201,74 @@ where appropriate is ongoing. Try using an unquoted name instead: pub fn something() {} ``` "##, + +E0583: r##" +A file wasn't found for an out-of-line module. + +Erroneous code example: + +```compile_fail,E0583 +mod file_that_doesnt_exist; // error: file not found for module + +fn main() {} +``` + +Please be sure that a file corresponding to the module exists. If you +want to use a module named `file_that_doesnt_exist`, you need to have a file +named `file_that_doesnt_exist.rs` or `file_that_doesnt_exist/mod.rs` in the +same directory. +"##, + +E0585: r##" +A documentation comment that doesn't document anything was found. + +Erroneous code example: + +```compile_fail,E0585 +fn main() { + // The following doc comment will fail: + /// This is a useless doc comment! +} +``` + +Documentation comments need to be followed by items, including functions, +types, modules, etc. Examples: + +``` +/// I'm documenting the following struct: +struct Foo; + +/// I'm documenting the following function: +fn foo() {} +``` +"##, + +E0586: r##" +An inclusive range was used with no end. + +Erroneous code example: + +```compile_fail,E0586 +let tmp = vec![0, 1, 2, 3, 4, 4, 3, 3, 2, 1]; +let x = &tmp[1...]; // error: inclusive range was used with no end +``` + +An inclusive range needs an end in order to *include* it. If you just need a +start and no end, use a non-inclusive range (with `..`): + +``` +let tmp = vec![0, 1, 2, 3, 4, 4, 3, 3, 2, 1]; +let x = &tmp[1..]; // ok! +``` + +Or put an end to your inclusive range: + +``` +let tmp = vec![0, 1, 2, 3, 4, 4, 3, 3, 2, 1]; +let x = &tmp[1...3]; // ok! +``` +"##, + } register_diagnostics! { @@ -224,8 +292,5 @@ register_diagnostics! { E0555, // malformed feature attribute, expected #![feature(...)] E0556, // malformed feature, expected just one word E0557, // feature has been removed - E0583, // file not found for module E0584, // file for module `..` found at both .. and .. - E0585, // documentation comment that doesn't document anything - E0586, // inclusive range with no end } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 464d16f53a3a7..b5b8a6bc0ef64 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -219,7 +219,7 @@ fn is_ident_or_underscore(t: &token::Token) -> bool { pub struct ModulePath { pub name: String, pub path_exists: bool, - pub result: Result, + pub result: Result, } pub struct ModulePathSuccess { @@ -233,7 +233,7 @@ pub struct ModulePathError { pub help_msg: String, } -pub enum Errors { +pub enum Error { FileNotFoundForModule { mod_name: String, default_path: String, @@ -249,13 +249,13 @@ pub enum Errors { InclusiveRangeWithNoEnd, } -impl Errors { +impl Error { pub fn span_err<'a>(self, sp: Span, handler: &'a errors::Handler) -> DiagnosticBuilder<'a> { match self { - Errors::FileNotFoundForModule { ref mod_name, - ref default_path, - ref secondary_path, - ref dir_path } => { + Error::FileNotFoundForModule { ref mod_name, + ref default_path, + ref secondary_path, + ref dir_path } => { let mut err = struct_span_err!(handler, sp, E0583, "file not found for module `{}`", mod_name); err.help(&format!("name the file either {} or {} inside the directory {:?}", @@ -264,7 +264,7 @@ impl Errors { dir_path)); err } - Errors::DuplicatePaths { ref mod_name, ref default_path, ref secondary_path } => { + Error::DuplicatePaths { ref mod_name, ref default_path, ref secondary_path } => { let mut err = struct_span_err!(handler, sp, E0584, "file for module `{}` found at both {} and {}", mod_name, @@ -273,14 +273,14 @@ impl Errors { err.help("delete or rename one of them to remove the ambiguity"); err } - Errors::UselessDocComment => { + Error::UselessDocComment => { let mut err = struct_span_err!(handler, sp, E0585, "found a documentation comment that doesn't document anything"); err.help("doc comments must come before what they document, maybe a comment was \ intended with `//`?"); err } - Errors::InclusiveRangeWithNoEnd => { + Error::InclusiveRangeWithNoEnd => { let mut err = struct_span_err!(handler, sp, E0586, "inclusive range with no end"); err.help("inclusive ranges must be bounded at the end (`...b` or `a...b`)"); @@ -518,7 +518,7 @@ impl<'a> Parser<'a> { } _ => { Err(if self.prev_token_kind == PrevTokenKind::DocComment { - self.span_fatal_err(self.prev_span, Errors::UselessDocComment) + self.span_fatal_err(self.prev_span, Error::UselessDocComment) } else { let mut err = self.fatal(&format!("expected identifier, found `{}`", self.this_token_to_string())); @@ -1009,7 +1009,7 @@ impl<'a> Parser<'a> { pub fn span_fatal(&self, sp: Span, m: &str) -> DiagnosticBuilder<'a> { self.sess.span_diagnostic.struct_span_fatal(sp, m) } - pub fn span_fatal_err(&self, sp: Span, err: Errors) -> DiagnosticBuilder<'a> { + pub fn span_fatal_err(&self, sp: Span, err: Error) -> DiagnosticBuilder<'a> { err.span_err(sp, self.diagnostic()) } pub fn span_fatal_help(&self, sp: Span, m: &str, help: &str) -> DiagnosticBuilder<'a> { @@ -2001,7 +2001,7 @@ impl<'a> Parser<'a> { limits: RangeLimits) -> PResult<'a, ast::ExprKind> { if end.is_none() && limits == RangeLimits::Closed { - Err(self.span_fatal_err(self.span, Errors::InclusiveRangeWithNoEnd)) + Err(self.span_fatal_err(self.span, Error::InclusiveRangeWithNoEnd)) } else { Ok(ExprKind::Range(start, end, limits)) } @@ -3916,7 +3916,7 @@ impl<'a> Parser<'a> { let unused_attrs = |attrs: &[_], s: &mut Self| { if attrs.len() > 0 { if s.prev_token_kind == PrevTokenKind::DocComment { - self.span_fatal_err(s.prev_span, Errors::UselessDocComment).emit(); + s.span_fatal_err(s.prev_span, Error::UselessDocComment).emit(); } else { s.span_err(s.span, "expected statement after outer attribute"); } @@ -5050,7 +5050,7 @@ impl<'a> Parser<'a> { } token::CloseDelim(token::Brace) => {} token::DocComment(_) => return Err(self.span_fatal_err(self.span, - Errors::UselessDocComment)), + Error::UselessDocComment)), _ => return Err(self.span_fatal_help(self.span, &format!("expected `,`, or `}}`, found `{}`", self.this_token_to_string()), "struct fields should be separated by commas")), @@ -5231,13 +5231,13 @@ impl<'a> Parser<'a> { directory_ownership: DirectoryOwnership::Owned, warn: false, }), - (false, false) => Err(Errors::FileNotFoundForModule { + (false, false) => Err(Error::FileNotFoundForModule { mod_name: mod_name.clone(), default_path: default_path_str, secondary_path: secondary_path_str, dir_path: format!("{}", dir_path.display()), }), - (true, true) => Err(Errors::DuplicatePaths { + (true, true) => Err(Error::DuplicatePaths { mod_name: mod_name.clone(), default_path: default_path_str, secondary_path: secondary_path_str,