]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #41542 - petrochenkov:objpars2, r=nikomatsakis
authorbors <bors@rust-lang.org>
Fri, 28 Apr 2017 22:28:11 +0000 (22:28 +0000)
committerbors <bors@rust-lang.org>
Fri, 28 Apr 2017 22:28:11 +0000 (22:28 +0000)
syntax: Parse trait object types starting with a lifetime bound

Fixes https://github.com/rust-lang/rust/issues/39085

This was originally implemented in https://github.com/rust-lang/rust/pull/40043, then reverted, then there was some [agreement](https://github.com/rust-lang/rust/issues/39318#issuecomment-289108720) that it should be supported.
(This is hopefully the last PR related to bound parsing.)

1  2 
src/libsyntax/parse/parser.rs

index cba77335143710d89e83d091dc2ead945c58e6b5,c7f4512301c841a2631ae1e860c5ee2b53771710..84d53dbef7c884ae6f2b95205f646f7db8b9e4f9
@@@ -57,11 -57,9 +57,11 @@@ use tokenstream::{self, Delimited, Thin
  use symbol::{Symbol, keywords};
  use util::ThinVec;
  
 +use std::cmp;
  use std::collections::HashSet;
 -use std::{cmp, mem, slice};
 +use std::mem;
  use std::path::{self, Path, PathBuf};
 +use std::slice;
  
  bitflags! {
      flags Restrictions: u8 {
@@@ -1453,9 -1451,9 +1453,9 @@@ impl<'a> Parser<'a> 
          } else if self.eat_keyword(keywords::Impl) {
              // FIXME: figure out priority of `+` in `impl Trait1 + Trait2` (#34511).
              TyKind::ImplTrait(self.parse_ty_param_bounds()?)
-         } else if self.check(&token::Question) {
+         } else if self.check(&token::Question) ||
+                   self.check_lifetime() && self.look_ahead(1, |t| t == &token::BinOp(token::Plus)){
              // Bound list (trait object type)
-             // Bound lists starting with `'lt` are not currently supported (#40043)
              TyKind::TraitObject(self.parse_ty_param_bounds_common(allow_plus)?)
          } else {
              let msg = format!("expected type, found {}", self.this_token_descr());
      ///    impl<T> Foo { ... }
      ///    impl<T> ToString for &'static T { ... }
      ///    impl Send for .. {}
 -    fn parse_item_impl(&mut self, unsafety: ast::Unsafety) -> PResult<'a, ItemInfo> {
 +    fn parse_item_impl(&mut self,
 +                       unsafety: ast::Unsafety,
 +                       defaultness: Defaultness) -> PResult<'a, ItemInfo> {
          let impl_span = self.span;
  
          // First, parse type parameters if necessary.
                                            allowed to have generics");
              }
  
 +            if let ast::Defaultness::Default = defaultness {
 +                self.span_err(impl_span, "`default impl` is not allowed for \
 +                                         default trait implementations");
 +            }
 +
              self.expect(&token::OpenDelim(token::Brace))?;
              self.expect(&token::CloseDelim(token::Brace))?;
              Ok((keywords::Invalid.ident(),
              }
  
              Ok((keywords::Invalid.ident(),
 -             ItemKind::Impl(unsafety, polarity, generics, opt_trait, ty, impl_items),
 +             ItemKind::Impl(unsafety, polarity, defaultness, generics, opt_trait, ty, impl_items),
               Some(attrs)))
          }
      }
              }
              let mut err = self.diagnostic().struct_span_err(id_sp,
                  "cannot declare a new module at this location");
 -            let this_module = match self.directory.path.file_name() {
 -                Some(file_name) => file_name.to_str().unwrap().to_owned(),
 -                None => self.root_module_name.as_ref().unwrap().clone(),
 -            };
 -            err.span_note(id_sp,
 -                          &format!("maybe move this module `{0}` to its own directory \
 -                                    via `{0}{1}mod.rs`",
 -                                   this_module,
 -                                   path::MAIN_SEPARATOR));
 +            if id_sp != syntax_pos::DUMMY_SP {
 +                let src_path = PathBuf::from(self.sess.codemap().span_to_filename(id_sp));
 +                if let Some(stem) = src_path.file_stem() {
 +                    let mut dest_path = src_path.clone();
 +                    dest_path.set_file_name(stem);
 +                    dest_path.push("mod.rs");
 +                    err.span_note(id_sp,
 +                                  &format!("maybe move this module `{}` to its own \
 +                                            directory via `{}`", src_path.to_string_lossy(),
 +                                           dest_path.to_string_lossy()));
 +                }
 +            }
              if paths.path_exists {
                  err.span_note(id_sp,
                                &format!("... or maybe `use` the module `{}` instead \
                                          of possibly redeclaring it",
                                         paths.name));
 -                Err(err)
 -            } else {
 -                Err(err)
              }
 +            Err(err)
          } else {
              paths.result.map_err(|err| self.span_fatal_err(id_sp, err))
          }
                                      maybe_append(attrs, extra_attrs));
              return Ok(Some(item));
          }
 -        if self.check_keyword(keywords::Unsafe) &&
 -            self.look_ahead(1, |t| t.is_keyword(keywords::Impl))
 +        if (self.check_keyword(keywords::Unsafe) &&
 +            self.look_ahead(1, |t| t.is_keyword(keywords::Impl))) ||
 +           (self.check_keyword(keywords::Default) &&
 +            self.look_ahead(1, |t| t.is_keyword(keywords::Unsafe)) &&
 +            self.look_ahead(2, |t| t.is_keyword(keywords::Impl)))
          {
              // IMPL ITEM
 +            let defaultness = self.parse_defaultness()?;
              self.expect_keyword(keywords::Unsafe)?;
              self.expect_keyword(keywords::Impl)?;
 -            let (ident, item_, extra_attrs) = self.parse_item_impl(ast::Unsafety::Unsafe)?;
 +            let (ident,
 +                 item_,
 +                 extra_attrs) = self.parse_item_impl(ast::Unsafety::Unsafe, defaultness)?;
              let prev_span = self.prev_span;
              let item = self.mk_item(lo.to(prev_span),
                                      ident,
                                      maybe_append(attrs, extra_attrs));
              return Ok(Some(item));
          }
 -        if self.eat_keyword(keywords::Impl) {
 +        if (self.check_keyword(keywords::Impl)) ||
 +           (self.check_keyword(keywords::Default) &&
 +            self.look_ahead(1, |t| t.is_keyword(keywords::Impl)))
 +        {
              // IMPL ITEM
 -            let (ident, item_, extra_attrs) = self.parse_item_impl(ast::Unsafety::Normal)?;
 +            let defaultness = self.parse_defaultness()?;
 +            self.expect_keyword(keywords::Impl)?;
 +            let (ident,
 +                 item_,
 +                 extra_attrs) = self.parse_item_impl(ast::Unsafety::Normal, defaultness)?;
              let prev_span = self.prev_span;
              let item = self.mk_item(lo.to(prev_span),
                                      ident,