Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 10 pull requests #33049

Merged
merged 21 commits into from
Apr 17, 2016
Merged
Changes from 1 commit
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
762d4ac
Start documenting BTreeMap's node interface
gereeter Jan 21, 2016
fa8556e
Fix review comments in BTreeMap's Node documentation
gereeter Feb 25, 2016
fbcf935
Add examples for std::ptr module functions
GuillaumeGomez Apr 14, 2016
daa48a2
Fix link in contributing page
floftar Apr 15, 2016
c1db18b
Fix f32::sin_cos and f64::sin_cos examples
Apr 16, 2016
79e68a6
Implement `Display` and `Hash` for `std::num::Wrapping`
tbu- Apr 16, 2016
6c93c92
Update casting-between-types.md
kindlychung Apr 16, 2016
869536e
Adjust example for error E0225
bluss Apr 16, 2016
e7bc939
syntax: Parse import prefixes as paths
petrochenkov Apr 17, 2016
1a374b8
Fix diagnostics for unresolved patterns
jseyfried Apr 17, 2016
2c978dc
resolve: Refactor away `DefModifiers`
jseyfried Apr 17, 2016
e59af6c
Rollup merge of #31441 - gereeter:btree-docs, r=bluss
Manishearth Apr 17, 2016
de477ed
Rollup merge of #32956 - GuillaumeGomez:ptr_examples, r=steveklabnik
Manishearth Apr 17, 2016
31bedab
Rollup merge of #33003 - fbergr:link, r=steveklabnik
Manishearth Apr 17, 2016
51c3c43
Rollup merge of #33022 - Mr4x:master, r=bluss
Manishearth Apr 17, 2016
5fc8065
Rollup merge of #33023 - tbu-:pr_wrapping_traits, r=alexcrichton
Manishearth Apr 17, 2016
43c23e5
Rollup merge of #33032 - kindlychung:patch-3, r=Manishearth
Manishearth Apr 17, 2016
4046f39
Rollup merge of #33039 - bluss:trait-obj-error, r=arielb1
Manishearth Apr 17, 2016
02e40d9
Rollup merge of #33044 - petrochenkov:prefix, r=eddyb
Manishearth Apr 17, 2016
df0eb16
Rollup merge of #33045 - jseyfried:no_def_modifiers, r=eddyb
Manishearth Apr 17, 2016
e1db767
Rollup merge of #33046 - jseyfried:fix_unresolved_pattern_diagnostics…
Manishearth Apr 17, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 35 additions & 19 deletions src/librustc_resolve/build_reduced_graph.rs
Original file line number Diff line number Diff line change
@@ -28,9 +28,9 @@ use rustc::hir::def::*;
use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
use rustc::ty::{self, VariantKind};

use syntax::ast::Name;
use syntax::ast::{Name, NodeId};
use syntax::attr::AttrMetaMethods;
use syntax::parse::token::{special_idents, SELF_KEYWORD_NAME, SUPER_KEYWORD_NAME};
use syntax::parse::token::keywords;
use syntax::codemap::{Span, DUMMY_SP};

use rustc::hir;
@@ -100,6 +100,37 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
block.stmts.iter().any(is_item)
}

fn sanity_check_import(&self, view_path: &hir::ViewPath, id: NodeId) {
let path = match view_path.node {
ViewPathSimple(_, ref path) |
ViewPathGlob (ref path) |
ViewPathList(ref path, _) => path
};

// Check for type parameters
let found_param = path.segments.iter().any(|segment| {
!segment.parameters.types().is_empty() ||
!segment.parameters.lifetimes().is_empty() ||
!segment.parameters.bindings().is_empty()
});
if found_param {
self.session.span_err(path.span,
"type or lifetime parameter is found in import path");
}

// Checking for special identifiers in path
// prevent `self` or `super` at beginning of global path
if path.global && path.segments.len() > 0 {
let first = path.segments[0].identifier.name;
if first == keywords::Super.to_name() || first == keywords::SelfValue.to_name() {
self.session.add_lint(
lint::builtin::SUPER_OR_SELF_IN_GLOBAL_PATH, id, path.span,
format!("expected identifier, found keyword `{}`", first)
);
}
}
}

/// Constructs the reduced graph for one item.
fn build_reduced_graph_for_item(&mut self, item: &Item, parent_ref: &mut Module<'b>) {
let parent = *parent_ref;
@@ -117,10 +148,8 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
// Extract and intern the module part of the path. For
// globs and lists, the path is found directly in the AST;
// for simple paths we have to munge the path a little.
let is_global;
let module_path: Vec<Name> = match view_path.node {
ViewPathSimple(_, ref full_path) => {
is_global = full_path.global;
full_path.segments
.split_last()
.unwrap()
@@ -132,30 +161,17 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {

ViewPathGlob(ref module_ident_path) |
ViewPathList(ref module_ident_path, _) => {
is_global = module_ident_path.global;
module_ident_path.segments
.iter()
.map(|seg| seg.identifier.name)
.collect()
}
};

// Checking for special identifiers in path
// prevent `self` or `super` at beginning of global path
if is_global && (module_path.first() == Some(&SELF_KEYWORD_NAME) ||
module_path.first() == Some(&SUPER_KEYWORD_NAME)) {
self.session.add_lint(
lint::builtin::SUPER_OR_SELF_IN_GLOBAL_PATH,
item.id,
item.span,
format!("expected identifier, found keyword `{}`",
module_path.first().unwrap().as_str()));
}
self.sanity_check_import(view_path, item.id);

// Build up the import directives.
let is_prelude = item.attrs.iter().any(|attr| {
attr.name() == special_idents::prelude_import.name.as_str()
});
let is_prelude = item.attrs.iter().any(|attr| attr.name() == "prelude_import");

match view_path.node {
ViewPathSimple(binding, ref full_path) => {
174 changes: 63 additions & 111 deletions src/libsyntax/parse/parser.rs
Original file line number Diff line number Diff line change
@@ -81,6 +81,8 @@ type ItemInfo = (Ident, ItemKind, Option<Vec<Attribute> >);
pub enum PathParsingMode {
/// A path with no type parameters; e.g. `foo::bar::Baz`
NoTypesAllowed,
/// Same as `NoTypesAllowed`, but may end with `::{` or `::*`, which are left unparsed
ImportPrefix,
/// A path with a lifetime and type parameters, with no double colons
/// before the type parameters; e.g. `foo::bar<'a>::Baz<T>`
LifetimeAndTypesWithoutColons,
@@ -589,20 +591,6 @@ impl<'a> Parser<'a> {
}
}

pub fn parse_path_list_item(&mut self) -> PResult<'a, ast::PathListItem> {
let lo = self.span.lo;
let node = if self.eat_keyword(keywords::SelfValue) {
let rename = self.parse_rename()?;
ast::PathListItemKind::Mod { id: ast::DUMMY_NODE_ID, rename: rename }
} else {
let ident = self.parse_ident()?;
let rename = self.parse_rename()?;
ast::PathListItemKind::Ident { name: ident, rename: rename, id: ast::DUMMY_NODE_ID }
};
let hi = self.last_span.hi;
Ok(spanned(lo, hi, node))
}

/// Check if the next token is `tok`, and return `true` if so.
///
/// This method will automatically add `tok` to `expected_tokens` if `tok` is not
@@ -1761,8 +1749,8 @@ impl<'a> Parser<'a> {
LifetimeAndTypesWithColons => {
self.parse_path_segments_with_colons()?
}
NoTypesAllowed => {
self.parse_path_segments_without_types()?
NoTypesAllowed | ImportPrefix => {
self.parse_path_segments_without_types(mode == ImportPrefix)?
}
};
path.segments.extend(segments);
@@ -1799,8 +1787,8 @@ impl<'a> Parser<'a> {
LifetimeAndTypesWithColons => {
self.parse_path_segments_with_colons()?
}
NoTypesAllowed => {
self.parse_path_segments_without_types()?
NoTypesAllowed | ImportPrefix => {
self.parse_path_segments_without_types(mode == ImportPrefix)?
}
};

@@ -1918,7 +1906,8 @@ impl<'a> Parser<'a> {

/// Examples:
/// - `a::b::c`
pub fn parse_path_segments_without_types(&mut self) -> PResult<'a, Vec<ast::PathSegment>> {
pub fn parse_path_segments_without_types(&mut self, import_prefix: bool)
-> PResult<'a, Vec<ast::PathSegment>> {
let mut segments = Vec::new();
loop {
// First, parse an identifier.
@@ -1930,9 +1919,11 @@ impl<'a> Parser<'a> {
parameters: ast::PathParameters::none()
});

// If we do not see a `::`, stop.
if !self.eat(&token::ModSep) {
// If we do not see a `::` or see `::{`/`::*`, stop.
if !self.check(&token::ModSep) || import_prefix && self.is_import_coupler() {
return Ok(segments);
} else {
self.bump();
}
}
}
@@ -6119,106 +6110,67 @@ impl<'a> Parser<'a> {
self.parse_item_(attrs, true, false)
}

fn parse_path_list_items(&mut self) -> PResult<'a, Vec<ast::PathListItem>> {
self.parse_unspanned_seq(&token::OpenDelim(token::Brace),
&token::CloseDelim(token::Brace),
SeqSep::trailing_allowed(token::Comma), |this| {
let lo = this.span.lo;
let node = if this.eat_keyword(keywords::SelfValue) {
let rename = this.parse_rename()?;
ast::PathListItemKind::Mod { id: ast::DUMMY_NODE_ID, rename: rename }
} else {
let ident = this.parse_ident()?;
let rename = this.parse_rename()?;
ast::PathListItemKind::Ident { name: ident, rename: rename, id: ast::DUMMY_NODE_ID }
};
let hi = this.last_span.hi;
Ok(spanned(lo, hi, node))
})
}

/// `::{` or `::*`
fn is_import_coupler(&mut self) -> bool {
self.check(&token::ModSep) &&
self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace) ||
*t == token::BinOp(token::Star))
}

/// Matches view_path : MOD? non_global_path as IDENT
/// | MOD? non_global_path MOD_SEP LBRACE RBRACE
/// | MOD? non_global_path MOD_SEP LBRACE ident_seq RBRACE
/// | MOD? non_global_path MOD_SEP STAR
/// | MOD? non_global_path
/// Matches ViewPath:
/// MOD_SEP? non_global_path
/// MOD_SEP? non_global_path as IDENT
/// MOD_SEP? non_global_path MOD_SEP STAR
/// MOD_SEP? non_global_path MOD_SEP LBRACE item_seq RBRACE
/// MOD_SEP? LBRACE item_seq RBRACE
fn parse_view_path(&mut self) -> PResult<'a, P<ViewPath>> {
let lo = self.span.lo;

// Allow a leading :: because the paths are absolute either way.
// This occurs with "use $crate::..." in macros.
let is_global = self.eat(&token::ModSep);

if self.check(&token::OpenDelim(token::Brace)) {
// use {foo,bar}
let idents = self.parse_unspanned_seq(
&token::OpenDelim(token::Brace),
&token::CloseDelim(token::Brace),
SeqSep::trailing_allowed(token::Comma),
|p| p.parse_path_list_item())?;
let path = ast::Path {
if self.check(&token::OpenDelim(token::Brace)) || self.is_import_coupler() {
// `{foo, bar}` or `::{foo, bar}`
let prefix = ast::Path {
global: self.eat(&token::ModSep),
segments: Vec::new(),
span: mk_sp(lo, self.span.hi),
global: is_global,
segments: Vec::new()
};
return Ok(P(spanned(lo, self.span.hi, ViewPathList(path, idents))));
}

let first_ident = self.parse_ident()?;
let mut path = vec!(first_ident);
if let token::ModSep = self.token {
// foo::bar or foo::{a,b,c} or foo::*
while self.check(&token::ModSep) {
let items = self.parse_path_list_items()?;
Ok(P(spanned(lo, self.span.hi, ViewPathList(prefix, items))))
} else {
let prefix = self.parse_path(ImportPrefix)?;
if self.is_import_coupler() {
// `foo::bar::{a, b}` or `foo::bar::*`
self.bump();

match self.token {
token::Ident(..) => {
let ident = self.parse_ident()?;
path.push(ident);
}

// foo::bar::{a,b,c}
token::OpenDelim(token::Brace) => {
let idents = self.parse_unspanned_seq(
&token::OpenDelim(token::Brace),
&token::CloseDelim(token::Brace),
SeqSep::trailing_allowed(token::Comma),
|p| p.parse_path_list_item()
)?;
let path = ast::Path {
span: mk_sp(lo, self.span.hi),
global: is_global,
segments: path.into_iter().map(|identifier| {
ast::PathSegment {
identifier: identifier,
parameters: ast::PathParameters::none(),
}
}).collect()
};
return Ok(P(spanned(lo, self.span.hi, ViewPathList(path, idents))));
}

// foo::bar::*
token::BinOp(token::Star) => {
if self.check(&token::BinOp(token::Star)) {
self.bump();
let path = ast::Path {
span: mk_sp(lo, self.span.hi),
global: is_global,
segments: path.into_iter().map(|identifier| {
ast::PathSegment {
identifier: identifier,
parameters: ast::PathParameters::none(),
}
}).collect()
};
return Ok(P(spanned(lo, self.span.hi, ViewPathGlob(path))));
}

// fall-through for case foo::bar::;
token::Semi => {
self.span_err(self.span, "expected identifier or `{` or `*`, found `;`");
}

_ => break
Ok(P(spanned(lo, self.span.hi, ViewPathGlob(prefix))))
} else {
let items = self.parse_path_list_items()?;
Ok(P(spanned(lo, self.span.hi, ViewPathList(prefix, items))))
}
} else {
// `foo::bar` or `foo::bar as baz`
let rename = self.parse_rename()?.
unwrap_or(prefix.segments.last().unwrap().identifier);
Ok(P(spanned(lo, self.last_span.hi, ViewPathSimple(rename, prefix))))
}
}
let mut rename_to = path[path.len() - 1];
let path = ast::Path {
span: mk_sp(lo, self.last_span.hi),
global: is_global,
segments: path.into_iter().map(|identifier| {
ast::PathSegment {
identifier: identifier,
parameters: ast::PathParameters::none(),
}
}).collect()
};
rename_to = self.parse_rename()?.unwrap_or(rename_to);
Ok(P(spanned(lo, self.last_span.hi, ViewPathSimple(rename_to, path))))
}

fn parse_rename(&mut self) -> PResult<'a, Option<Ident>> {
26 changes: 26 additions & 0 deletions src/test/compile-fail/import-prefix-macro-1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright 2016 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

mod a {
pub mod b {
pub mod c {
pub struct S;
pub struct Z;
}
}
}

macro_rules! import {
($p: path) => (use $p {S, Z}); //~ERROR expected one of `::`, `;`, or `as`, found `{`
}

import! { a::b::c }

fn main() {}
26 changes: 26 additions & 0 deletions src/test/compile-fail/import-prefix-macro-2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright 2016 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

mod a {
pub mod b {
pub mod c {
pub struct S;
pub struct Z;
}
}
}

macro_rules! import {
($p: path) => (use ::$p {S, Z}); //~ERROR expected identifier, found `a::b::c`
}

import! { a::b::c }

fn main() {}
Loading