about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorRaph Levien <raph@google.com>2017-02-22 09:30:46 -0800
committerRaph Levien <raph@google.com>2017-02-22 09:30:46 -0800
commitb3ee2490c2cba3f58476e520468afe0b828c0aa6 (patch)
tree7f17f972f658ed00a7c310fd1448e9ab96eb07d9 /src/libsyntax
parent81b9b3c542e0f3c3df799a9d66bb0120c7dbc44c (diff)
parentfc6f092c21a7a7249a9f8860f3cd10160aa36c02 (diff)
downloadrust-b3ee2490c2cba3f58476e520468afe0b828c0aa6.tar.gz
rust-b3ee2490c2cba3f58476e520468afe0b828c0aa6.zip
Merge branch 'master' of https://github.com/rust-lang/rust into readdir
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/diagnostic_list.rs69
-rw-r--r--src/libsyntax/ext/base.rs44
-rw-r--r--src/libsyntax/ext/expand.rs14
-rw-r--r--src/libsyntax/parse/parser.rs122
4 files changed, 193 insertions, 56 deletions
diff --git a/src/libsyntax/diagnostic_list.rs b/src/libsyntax/diagnostic_list.rs
index 2b4d1337504..2d59051ec4a 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,4 +292,5 @@ register_diagnostics! {
     E0555, // malformed feature attribute, expected #![feature(...)]
     E0556, // malformed feature, expected just one word
     E0557, // feature has been removed
+    E0584, // file for module `..` found at both .. and ..
 }
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index b5afd0c453a..b61ab74687b 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -474,6 +474,17 @@ impl MacResult for DummyResult {
 pub type BuiltinDeriveFn =
     for<'cx> fn(&'cx mut ExtCtxt, Span, &MetaItem, &Annotatable, &mut FnMut(Annotatable));
 
+/// Represents different kinds of macro invocations that can be resolved.
+#[derive(Clone, Copy, PartialEq, Eq)]
+pub enum MacroKind {
+    /// A bang macro - foo!()
+    Bang,
+    /// An attribute macro - #[foo]
+    Attr,
+    /// A derive attribute macro - #[derive(Foo)]
+    Derive,
+}
+
 /// An enum representing the different kinds of syntax extensions.
 pub enum SyntaxExtension {
     /// A syntax extension that is attached to an item and creates new items
@@ -520,6 +531,25 @@ pub enum SyntaxExtension {
     BuiltinDerive(BuiltinDeriveFn),
 }
 
+impl SyntaxExtension {
+    /// Return which kind of macro calls this syntax extension.
+    pub fn kind(&self) -> MacroKind {
+        match *self {
+            SyntaxExtension::NormalTT(..) |
+            SyntaxExtension::IdentTT(..) |
+            SyntaxExtension::ProcMacro(..) =>
+                MacroKind::Bang,
+            SyntaxExtension::MultiDecorator(..) |
+            SyntaxExtension::MultiModifier(..) |
+            SyntaxExtension::AttrProcMacro(..) =>
+                MacroKind::Attr,
+            SyntaxExtension::ProcMacroDerive(..) |
+            SyntaxExtension::BuiltinDerive(..) =>
+                MacroKind::Derive,
+        }
+    }
+}
+
 pub type NamedSyntaxExtension = (Name, SyntaxExtension);
 
 pub trait Resolver {
@@ -535,10 +565,8 @@ pub trait Resolver {
     fn resolve_imports(&mut self);
     // Resolves attribute and derive legacy macros from `#![plugin(..)]`.
     fn find_legacy_attr_invoc(&mut self, attrs: &mut Vec<Attribute>) -> Option<Attribute>;
-    fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, force: bool)
-                     -> Result<Rc<SyntaxExtension>, Determinacy>;
-    fn resolve_derive_macro(&mut self, scope: Mark, path: &ast::Path, force: bool)
-                            -> Result<Rc<SyntaxExtension>, Determinacy>;
+    fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind,
+                     force: bool) -> Result<Rc<SyntaxExtension>, Determinacy>;
 }
 
 #[derive(Copy, Clone, Debug)]
@@ -561,12 +589,8 @@ impl Resolver for DummyResolver {
 
     fn resolve_imports(&mut self) {}
     fn find_legacy_attr_invoc(&mut self, _attrs: &mut Vec<Attribute>) -> Option<Attribute> { None }
-    fn resolve_macro(&mut self, _scope: Mark, _path: &ast::Path, _force: bool)
-                     -> Result<Rc<SyntaxExtension>, Determinacy> {
-        Err(Determinacy::Determined)
-    }
-    fn resolve_derive_macro(&mut self, _scope: Mark, _path: &ast::Path, _force: bool)
-                            -> Result<Rc<SyntaxExtension>, Determinacy> {
+    fn resolve_macro(&mut self, _scope: Mark, _path: &ast::Path, _kind: MacroKind,
+                     _force: bool) -> Result<Rc<SyntaxExtension>, Determinacy> {
         Err(Determinacy::Determined)
     }
 }
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index d011d7c2a1c..38494378f72 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -282,8 +282,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                         let mark = Mark::fresh();
                         derives.push(mark);
                         let path = ast::Path::from_ident(span, Ident::with_empty_ctxt(name));
-                        let item = match self.cx.resolver
-                                             .resolve_macro(Mark::root(), &path, false) {
+                        let item = match self.cx.resolver.resolve_macro(
+                                Mark::root(), &path, MacroKind::Derive, false) {
                             Ok(ext) => match *ext {
                                 SyntaxExtension::BuiltinDerive(..) => item_with_markers.clone(),
                                 _ => item.clone(),
@@ -369,12 +369,14 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                      -> Result<Option<Rc<SyntaxExtension>>, Determinacy> {
         let (attr, traits, item) = match invoc.kind {
             InvocationKind::Bang { ref mac, .. } => {
-                return self.cx.resolver.resolve_macro(scope, &mac.node.path, force).map(Some);
+                return self.cx.resolver.resolve_macro(scope, &mac.node.path,
+                                                      MacroKind::Bang, force).map(Some);
             }
             InvocationKind::Attr { attr: None, .. } => return Ok(None),
             InvocationKind::Derive { name, span, .. } => {
                 let path = ast::Path::from_ident(span, Ident::with_empty_ctxt(name));
-                return self.cx.resolver.resolve_derive_macro(scope, &path, force).map(Some);
+                return self.cx.resolver.resolve_macro(scope, &path,
+                                                      MacroKind::Derive, force).map(Some)
             }
             InvocationKind::Attr { ref mut attr, ref traits, ref mut item } => (attr, traits, item),
         };
@@ -385,7 +387,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
         };
 
         let mut determined = true;
-        match self.cx.resolver.resolve_macro(scope, &path, force) {
+        match self.cx.resolver.resolve_macro(scope, &path, MacroKind::Attr, force) {
             Ok(ext) => return Ok(Some(ext)),
             Err(Determinacy::Undetermined) => determined = false,
             Err(Determinacy::Determined) if force => return Err(Determinacy::Determined),
@@ -394,7 +396,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
 
         for &(name, span) in traits {
             let path = ast::Path::from_ident(span, Ident::with_empty_ctxt(name));
-            match self.cx.resolver.resolve_macro(scope, &path, force) {
+            match self.cx.resolver.resolve_macro(scope, &path, MacroKind::Derive, force) {
                 Ok(ext) => if let SyntaxExtension::ProcMacroDerive(_, ref inert_attrs) = *ext {
                     if inert_attrs.contains(&attr_name) {
                         // FIXME(jseyfried) Avoid `mem::replace` here.
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 2c4fa8e15ed..b5b8a6bc0ef 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<ModulePathSuccess, ModulePathError>,
+    pub result: Result<ModulePathSuccess, Error>,
 }
 
 pub struct ModulePathSuccess {
@@ -233,6 +233,63 @@ pub struct ModulePathError {
     pub help_msg: String,
 }
 
+pub enum Error {
+    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 Error {
+    pub fn span_err<'a>(self, sp: Span, handler: &'a errors::Handler) -> DiagnosticBuilder<'a> {
+        match self {
+            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 {:?}",
+                                  default_path,
+                                  secondary_path,
+                                  dir_path));
+                err
+            }
+            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,
+                                               default_path,
+                                               secondary_path);
+                err.help("delete or rename one of them to remove the ambiguity");
+                err
+            }
+            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
+            }
+            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`)");
+                err
+            }
+        }
+    }
+}
+
 pub enum LhsExpr {
     NotYetParsed,
     AttributesParsed(ThinVec<Attribute>),
@@ -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, Error::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: Error) -> 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, Error::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 `//`?");
+                                s.span_fatal_err(s.prev_span, Error::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,
+                                                                   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")),
@@ -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(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(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(Error::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))
         }
     }