From 7ffd46c9246e1355b2bcec4f0d38450548de7730 Mon Sep 17 00:00:00 2001 From: Daan Sprenkels Date: Fri, 24 Jun 2016 23:31:00 +0200 Subject: [PATCH 01/20] add regression test for #33455 --- src/test/parse-fail/issue-33455.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/test/parse-fail/issue-33455.rs diff --git a/src/test/parse-fail/issue-33455.rs b/src/test/parse-fail/issue-33455.rs new file mode 100644 index 0000000000000..96070332f06df --- /dev/null +++ b/src/test/parse-fail/issue-33455.rs @@ -0,0 +1,11 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use foo.bar; //~ ERROR expected one of `::`, `;`, or `as`, found `.` From 58955dee66a09a81db2dda83f49adf4436bfd6d4 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 25 Jun 2016 14:21:45 +0200 Subject: [PATCH 02/20] Add new error codes and improve some explanations --- src/librustc_resolve/diagnostics.rs | 289 ++++++++++++++++++++-------- 1 file changed, 207 insertions(+), 82 deletions(-) diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 208b5f11e20d1..7269a62b6063a 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -16,6 +16,8 @@ register_long_diagnostics! { E0154: r##" +## Note: this error code is no longer emitted by the compiler. + Imports (`use` statements) are not allowed after non-item statements, such as variable declarations and expression statements. @@ -50,6 +52,8 @@ https://doc.rust-lang.org/reference.html#statements "##, E0251: r##" +## Note: this error code is no longer emitted by the compiler. + Two items of the same name cannot be imported without rebinding one of the items under a new local name. @@ -75,9 +79,9 @@ E0252: r##" Two items of the same name cannot be imported without rebinding one of the items under a new local name. -An example of this error: +Erroneous code example: -```compile_fail +```compile_fail,E0252 use foo::baz; use bar::baz; // error, do `use bar::baz as quux` instead @@ -87,6 +91,41 @@ mod foo { pub struct baz; } +mod bar { + pub mod baz {} +} +``` + +You can use aliases in order to fix this error. Example: + +``` +use foo::baz as foo_baz; +use bar::baz; // ok! + +fn main() {} + +mod foo { + pub struct baz; +} + +mod bar { + pub mod baz {} +} +``` + +Or you can reference the item with its parent: + +``` +use bar::baz; + +fn main() { + let x = foo::baz; // ok! +} + +mod foo { + pub struct baz; +} + mod bar { pub mod baz {} } @@ -95,9 +134,11 @@ mod bar { E0253: r##" Attempt was made to import an unimportable value. This can happen when trying -to import a method from a trait. An example of this error: +to import a method from a trait. -```compile_fail +Erroneous code example: + +```compile_fail,E0253 mod foo { pub trait MyTrait { fn do_something(); @@ -105,6 +146,8 @@ mod foo { } use foo::MyTrait::do_something; + +fn main() {} ``` It's invalid to directly import methods belonging to a trait or concrete type. @@ -114,10 +157,10 @@ E0255: r##" You can't import a value whose name is the same as another value defined in the module. -An example of this error: +Erroneous code example: -```compile_fail -use bar::foo; // error, do `use bar::foo as baz` instead +```compile_fail,E0255 +use bar::foo; // error: an item named `foo` is already in scope fn foo() {} @@ -127,9 +170,39 @@ mod bar { fn main() {} ``` + +You can use aliases in order to fix this error. Example: + +``` +use bar::foo as bar_foo; // ok! + +fn foo() {} + +mod bar { + pub fn foo() {} +} + +fn main() {} +``` + +Or you can reference the item with its parent: + +``` +fn foo() {} + +mod bar { + pub fn foo() {} +} + +fn main() { + bar::foo(); // we get the item by referring to its parent +} +``` "##, E0256: r##" +## Note: this error code is no longer emitted by the compiler. + You can't import a type or module when the name of the item being imported is the same as another type or submodule defined in the module. @@ -154,9 +227,11 @@ that has been imported into the current module. Erroneous code example: -```compile_fail -extern crate a; -extern crate crate_a as a; +```compile_fail,E0259 +extern crate std; +extern crate libc as std; + +fn main() {} ``` The solution is to choose a different name that doesn't conflict with any @@ -165,17 +240,17 @@ external crate imported into the current module. Correct example: ```ignore -extern crate a; -extern crate crate_a as other_name; +extern crate std; +extern crate libc as other_name; ``` "##, E0260: r##" The name for an item declaration conflicts with an external crate's name. -For instance: +Erroneous code example: -```ignore +```ignore,E0260 extern crate abc; struct abc; @@ -206,10 +281,10 @@ https://doc.rust-lang.org/reference.html#statements "##, E0364: r##" -Private items cannot be publicly re-exported. This error indicates that you +Private items cannot be publicly re-exported. This error indicates that you attempted to `pub use` a type or value that was not itself public. -Here is an example that demonstrates the error: +Erroneous code example: ```compile_fail mod foo { @@ -217,17 +292,21 @@ mod foo { } pub use foo::X; + +fn main() {} ``` The solution to this problem is to ensure that the items that you are re-exporting are themselves marked with `pub`: -```ignore +``` mod foo { pub const X: u32 = 1; } pub use foo::X; + +fn main() {} ``` See the 'Use Declarations' section of the reference for more information on @@ -240,25 +319,29 @@ E0365: r##" Private modules cannot be publicly re-exported. This error indicates that you attempted to `pub use` a module that was not itself public. -Here is an example that demonstrates the error: +Erroneous code example: -```compile_fail +```compile_fail,E0365 mod foo { pub const X: u32 = 1; } pub use foo as foo2; + +fn main() {} ``` The solution to this problem is to ensure that the module that you are re-exporting is itself marked with `pub`: -```ignore +``` pub mod foo { pub const X: u32 = 1; } pub use foo as foo2; + +fn main() {} ``` See the 'Use Declarations' section of the reference for more information @@ -269,9 +352,11 @@ https://doc.rust-lang.org/reference.html#use-declarations E0401: r##" Inner items do not inherit type parameters from the functions they are embedded -in. For example, this will not compile: +in. -```compile_fail +Erroneous code example: + +```compile_fail,E0401 fn foo(x: T) { fn bar(y: T) { // T is defined in the "outer" function // .. @@ -282,7 +367,7 @@ fn foo(x: T) { Nor will this: -```compile_fail +```compile_fail,E0401 fn foo(x: T) { type MaybeT = Option; // ... @@ -291,7 +376,7 @@ fn foo(x: T) { Or this: -```compile_fail +```compile_fail,E0401 fn foo(x: T) { struct Foo { x: T, @@ -374,9 +459,11 @@ closures or copying the parameters should still work. "##, E0403: r##" -Some type parameters have the same name. Example of erroneous code: +Some type parameters have the same name. -```compile_fail +Erroneous code example: + +```compile_fail,E0403 fn foo(s: T, u: T) {} // error: the name `T` is already used for a type // parameter in this type parameter list ``` @@ -390,10 +477,11 @@ fn foo(s: T, u: Y) {} // ok! "##, E0404: r##" -You tried to implement something which was not a trait on an object. Example of -erroneous code: +You tried to implement something which was not a trait on an object. -```compile_fail +Erroneous code example: + +```compile_fail,E0404 struct Foo; struct Bar; @@ -416,9 +504,11 @@ impl Foo for Bar { // ok! "##, E0405: r##" -The code refers to a trait that is not in scope. Example of erroneous code: +The code refers to a trait that is not in scope. -```compile_fail +Erroneous code example: + +```compile_fail,E0405 struct Foo; impl SomeTrait for Foo {} // error: trait `SomeTrait` is not in scope @@ -446,9 +536,11 @@ impl SomeTrait for Foo { // ok! E0407: r##" A definition of a method not in the implemented trait was given in a trait -implementation. Example of erroneous code: +implementation. -```compile_fail +Erroneous code example: + +```compile_fail,E0407 trait Foo { fn a(); } @@ -501,9 +593,9 @@ E0408: r##" An "or" pattern was used where the variable bindings are not consistently bound across patterns. -Example of erroneous code: +Erroneous code example: -```compile_fail +```compile_fail,E0408 match x { Some(y) | None => { /* use y */ } // error: variable `y` from pattern #1 is // not bound in pattern #2 @@ -545,9 +637,9 @@ E0409: r##" An "or" pattern was used where the variable bindings are not consistently bound across patterns. -Example of erroneous code: +Erroneous code example: -```compile_fail +```compile_fail,E0409 let x = (0, 2); match x { (0, ref y) | (y, 0) => { /* use y */} // error: variable `y` is bound with @@ -583,9 +675,11 @@ match x { "##, E0411: r##" -The `Self` keyword was used outside an impl or a trait. Erroneous code example: +The `Self` keyword was used outside an impl or a trait. -```compile_fail +Erroneous code example: + +```compile_fail,E0411 ::foo; // error: use of `Self` outside of an impl or trait ``` @@ -639,9 +733,11 @@ trait Baz : Foo + Foo2 { "##, E0412: r##" -The type name used is not in scope. Example of erroneous codes: +The type name used is not in scope. -```compile_fail +Erroneous code examples: + +```compile_fail,E0412 impl Something {} // error: type name `Something` is not in scope // or: @@ -678,9 +774,11 @@ fn foo(x: T) {} // ok! "##, E0415: r##" -More than one function parameter have the same name. Example of erroneous code: +More than one function parameter have the same name. -```compile_fail +Erroneous code example: + +```compile_fail,E0415 fn foo(f: i32, f: i32) {} // error: identifier `f` is bound more than // once in this parameter list ``` @@ -693,9 +791,11 @@ fn foo(f: i32, g: i32) {} // ok! "##, E0416: r##" -An identifier is bound more than once in a pattern. Example of erroneous code: +An identifier is bound more than once in a pattern. -```compile_fail +Erroneous code example: + +```compile_fail,E0416 match (1, 2) { (x, x) => {} // error: identifier `x` is bound more than once in the // same pattern @@ -722,9 +822,10 @@ match (A, B, C) { E0422: r##" You are trying to use an identifier that is either undefined or not a struct. -For instance: -``` compile_fail +Erroneous code example: + +``` compile_fail,E0422 fn main () { let x = Foo { x: 1, y: 2 }; } @@ -733,7 +834,7 @@ fn main () { In this case, `Foo` is undefined, so it inherently isn't anything, and definitely not a struct. -```compile_fail +```compile_fail,E0422 fn main () { let foo = 1; let x = foo { x: 1, y: 2 }; @@ -745,10 +846,11 @@ one. "##, E0423: r##" -A `struct` variant name was used like a function name. Example of erroneous -code: +A `struct` variant name was used like a function name. -```compile_fail +Erroneous code example: + +```compile_fail,E0423 struct Foo { a: bool}; let f = Foo(); @@ -767,9 +869,11 @@ let f = Foo(); // ok! "##, E0424: r##" -The `self` keyword was used in a static method. Example of erroneous code: +The `self` keyword was used in a static method. -```compile_fail +Erroneous code example: + +```compile_fail,E0424 struct Foo; impl Foo { @@ -799,9 +903,11 @@ impl Foo { "##, E0425: r##" -An unresolved name was used. Example of erroneous codes: +An unresolved name was used. -```compile_fail +Erroneous code examples: + +```compile_fail,E0425 something_that_doesnt_exist::foo; // error: unresolved name `something_that_doesnt_exist::foo` @@ -846,9 +952,11 @@ let x = unknown_variable; // ok! "##, E0426: r##" -An undeclared label was used. Example of erroneous code: +An undeclared label was used. -```compile_fail +Erroneous code example: + +```compile_fail,E0426 loop { break 'a; // error: use of undeclared label `'a` } @@ -864,10 +972,11 @@ Please verify you spelt or declare the label correctly. Example: "##, E0428: r##" -A type or module has been defined more than once. Example of erroneous -code: +A type or module has been defined more than once. -```compile_fail +Erroneous code example: + +```compile_fail,E0428 struct Bar; struct Bar; // error: duplicate definition of value `Bar` ``` @@ -885,9 +994,9 @@ E0429: r##" The `self` keyword cannot appear alone as the last segment in a `use` declaration. -Example of erroneous code: +Erroneous code example: -```compile_fail +```compile_fail,E0429 use std::fmt::self; // error: `self` imports are only allowed within a { } list ``` @@ -906,9 +1015,11 @@ use std::fmt; "##, E0430: r##" -The `self` import appears more than once in the list. Erroneous code example: +The `self` import appears more than once in the list. -```compile_fail +Erroneous code example: + +```compile_fail,E0430 use something::{self, self}; // error: `self` import can only appear once in // the list ``` @@ -922,9 +1033,11 @@ use something::self; // ok! "##, E0431: r##" -An invalid `self` import was made. Erroneous code example: +An invalid `self` import was made. -```compile_fail +Erroneous code example: + +```compile_fail,E0431 use {self}; // error: `self` import can only appear in an import list with a // non-empty prefix ``` @@ -934,9 +1047,11 @@ or verify you didn't misspell it. "##, E0432: r##" -An import was unresolved. Erroneous code example: +An import was unresolved. -```compile_fail +Erroneous code example: + +```compile_fail,E0432 use something::Foo; // error: unresolved import `something::Foo`. ``` @@ -965,14 +1080,23 @@ use homura::Madoka; "##, E0433: r##" -Invalid import. Example of erroneous code: +An undeclared type or module was used. -```compile_fail -use something_which_doesnt_exist; -// error: unresolved import `something_which_doesnt_exist` +Erroneous code example: + +```compile_fail,E0433 +let map = HashMap::new(); +// error: failed to resolve. Use of undeclared type or module `HashMap` ``` -Please verify you didn't misspell the import's name. +Please verify you didn't misspell the type/module's name or that you didn't +forgot to import it: + + +``` +use std::collections::HashMap; // HashMap has been imported. +let map: HashMap = HashMap::new(); // So it can be used! +``` "##, E0434: r##" @@ -980,9 +1104,9 @@ This error indicates that a variable usage inside an inner function is invalid because the variable comes from a dynamic environment. Inner functions do not have access to their containing environment. -Example of erroneous code: +Erroneous code example: -```compile_fail +```compile_fail,E0434 fn foo() { let y = 5; fn bar() -> u32 { @@ -1021,10 +1145,11 @@ fn foo() { "##, E0435: r##" -A non-constant value was used to initialise a constant. Example of erroneous -code: +A non-constant value was used to initialise a constant. -```compile_fail +Erroneous code example: + +```compile_fail,E0435 let foo = 42u32; const FOO : u32 = foo; // error: attempt to use a non-constant value in a // constant @@ -1050,9 +1175,9 @@ the trait in question. This error indicates that you attempted to implement an associated type whose name does not match the name of any associated type in the trait. -Here is an example that demonstrates the error: +Erroneous code example: -```compile_fail +```compile_fail,E0437 trait Foo {} impl Foo for i32 { @@ -1075,9 +1200,9 @@ members of the trait in question. This error indicates that you attempted to implement an associated constant whose name does not match the name of any associated constant in the trait. -Here is an example that demonstrates the error: +Erroneous code example: -```compile_fail +```compile_fail,E0438 #![feature(associated_consts)] trait Foo {} From e01a2ba2743bb72d86bf96df72af98ab06ad47eb Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Mon, 27 Jun 2016 03:15:06 +0000 Subject: [PATCH 03/20] Forbid type parameters and global paths in macro invocations --- src/libsyntax/ext/expand.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 5beb49372077e..89e346be94416 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -214,7 +214,7 @@ fn expand_mac_invoc(mac: ast::Mac, ident: Option, attrs: Vec 1 { + if path.segments.len() > 1 || path.global || !path.segments[0].parameters.is_empty() { fld.cx.span_err(path.span, "expected macro name without module separators"); return None; } From b4611b1ff29d93ba9a03932b316935cbfd076ed9 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Mon, 27 Jun 2016 03:17:55 +0000 Subject: [PATCH 04/20] Add regression test --- src/test/compile-fail/macro-with-seps-err-msg.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/compile-fail/macro-with-seps-err-msg.rs b/src/test/compile-fail/macro-with-seps-err-msg.rs index 95250e36b8685..408bb15ba28cd 100644 --- a/src/test/compile-fail/macro-with-seps-err-msg.rs +++ b/src/test/compile-fail/macro-with-seps-err-msg.rs @@ -8,8 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern:expected macro name without module separators - fn main() { - globnar::brotz!(); + globnar::brotz!(); //~ ERROR expected macro name without module separators + ::foo!(); //~ ERROR expected macro name without module separators + foo::!(); //~ ERROR expected macro name without module separators } From b8f9c88c2d86135f4d1c170be67d9d15c63b358a Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 27 Jun 2016 11:42:52 +0200 Subject: [PATCH 05/20] Revert "skip double negation in const eval" This reverts commit 735c018974e5570ea13fd887aa70a011a5b8e7b8. --- src/librustc_const_eval/eval.rs | 89 +++++++++----------- src/test/compile-fail/lint-type-overflow2.rs | 1 + 2 files changed, 42 insertions(+), 48 deletions(-) diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index 34dce44004823..4018260263c2c 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -543,54 +543,47 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let result = match e.node { hir::ExprUnary(hir::UnNeg, ref inner) => { // unary neg literals already got their sign during creation - match inner.node { - hir::ExprLit(ref lit) => { - use syntax::ast::*; - use syntax::ast::LitIntType::*; - const I8_OVERFLOW: u64 = ::std::i8::MAX as u64 + 1; - const I16_OVERFLOW: u64 = ::std::i16::MAX as u64 + 1; - const I32_OVERFLOW: u64 = ::std::i32::MAX as u64 + 1; - const I64_OVERFLOW: u64 = ::std::i64::MAX as u64 + 1; - match (&lit.node, ety.map(|t| &t.sty)) { - (&LitKind::Int(I8_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I8))) | - (&LitKind::Int(I8_OVERFLOW, Signed(IntTy::I8)), _) => { - return Ok(Integral(I8(::std::i8::MIN))) - }, - (&LitKind::Int(I16_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I16))) | - (&LitKind::Int(I16_OVERFLOW, Signed(IntTy::I16)), _) => { - return Ok(Integral(I16(::std::i16::MIN))) - }, - (&LitKind::Int(I32_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I32))) | - (&LitKind::Int(I32_OVERFLOW, Signed(IntTy::I32)), _) => { - return Ok(Integral(I32(::std::i32::MIN))) - }, - (&LitKind::Int(I64_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I64))) | - (&LitKind::Int(I64_OVERFLOW, Signed(IntTy::I64)), _) => { - return Ok(Integral(I64(::std::i64::MIN))) - }, - (&LitKind::Int(n, Unsuffixed), Some(&ty::TyInt(IntTy::Is))) | - (&LitKind::Int(n, Signed(IntTy::Is)), _) => { - match tcx.sess.target.int_type { - IntTy::I16 => if n == I16_OVERFLOW { - return Ok(Integral(Isize(Is16(::std::i16::MIN)))); - }, - IntTy::I32 => if n == I32_OVERFLOW { - return Ok(Integral(Isize(Is32(::std::i32::MIN)))); - }, - IntTy::I64 => if n == I64_OVERFLOW { - return Ok(Integral(Isize(Is64(::std::i64::MIN)))); - }, - _ => bug!(), - } - }, - _ => {}, - } - }, - hir::ExprUnary(hir::UnNeg, ref inner) => { - // skip `--$expr` - return eval_const_expr_partial(tcx, inner, ty_hint, fn_args); - }, - _ => {}, + if let hir::ExprLit(ref lit) = inner.node { + use syntax::ast::*; + use syntax::ast::LitIntType::*; + const I8_OVERFLOW: u64 = ::std::i8::MAX as u64 + 1; + const I16_OVERFLOW: u64 = ::std::i16::MAX as u64 + 1; + const I32_OVERFLOW: u64 = ::std::i32::MAX as u64 + 1; + const I64_OVERFLOW: u64 = ::std::i64::MAX as u64 + 1; + match (&lit.node, ety.map(|t| &t.sty)) { + (&LitKind::Int(I8_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I8))) | + (&LitKind::Int(I8_OVERFLOW, Signed(IntTy::I8)), _) => { + return Ok(Integral(I8(::std::i8::MIN))) + }, + (&LitKind::Int(I16_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I16))) | + (&LitKind::Int(I16_OVERFLOW, Signed(IntTy::I16)), _) => { + return Ok(Integral(I16(::std::i16::MIN))) + }, + (&LitKind::Int(I32_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I32))) | + (&LitKind::Int(I32_OVERFLOW, Signed(IntTy::I32)), _) => { + return Ok(Integral(I32(::std::i32::MIN))) + }, + (&LitKind::Int(I64_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I64))) | + (&LitKind::Int(I64_OVERFLOW, Signed(IntTy::I64)), _) => { + return Ok(Integral(I64(::std::i64::MIN))) + }, + (&LitKind::Int(n, Unsuffixed), Some(&ty::TyInt(IntTy::Is))) | + (&LitKind::Int(n, Signed(IntTy::Is)), _) => { + match tcx.sess.target.int_type { + IntTy::I16 => if n == I16_OVERFLOW { + return Ok(Integral(Isize(Is16(::std::i16::MIN)))); + }, + IntTy::I32 => if n == I32_OVERFLOW { + return Ok(Integral(Isize(Is32(::std::i32::MIN)))); + }, + IntTy::I64 => if n == I64_OVERFLOW { + return Ok(Integral(Isize(Is64(::std::i64::MIN)))); + }, + _ => bug!(), + } + }, + _ => {}, + } } match eval_const_expr_partial(tcx, &inner, ty_hint, fn_args)? { Float(f) => Float(-f), diff --git a/src/test/compile-fail/lint-type-overflow2.rs b/src/test/compile-fail/lint-type-overflow2.rs index 9499d732a3835..e99dfb9aa0f0e 100644 --- a/src/test/compile-fail/lint-type-overflow2.rs +++ b/src/test/compile-fail/lint-type-overflow2.rs @@ -15,6 +15,7 @@ #[allow(unused_variables)] fn main() { let x2: i8 = --128; //~ error: literal out of range for i8 + //~^ error: attempted to negate with overflow let x = -3.40282348e+38_f32; //~ error: literal out of range for f32 let x = 3.40282348e+38_f32; //~ error: literal out of range for f32 From f41de0ff3ad2d7b54a9bae86aadeaf3796579a7e Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Mon, 27 Jun 2016 14:31:23 -0400 Subject: [PATCH 06/20] Disable debuginfo tests for a given blacklist of LLDB versions --- src/tools/compiletest/src/main.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index cc687b532047e..6830f32bb2ce1 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -254,6 +254,17 @@ pub fn run_tests(config: &Config) { match config.mode { DebugInfoLldb => { + if let Some(lldb_version) = config.lldb_version.as_ref() { + if is_blacklisted_lldb_version(&lldb_version[..]) { + println!("WARNING: The used version of LLDB ({}) has a \ + known issue that breaks debuginfo tests. See \ + issue #32520 for more information. Skipping all \ + LLDB-based tests!", + lldb_version); + return + } + } + // Some older versions of LLDB seem to have problems with multiple // instances running in parallel, so only run one test thread at a // time. @@ -524,3 +535,7 @@ fn extract_lldb_version(full_version_line: Option) -> Option { } None } + +fn is_blacklisted_lldb_version(version: &str) -> bool { + version == "350" +} From beebaf1366d84425cb52074a710d4bc560f3d2c3 Mon Sep 17 00:00:00 2001 From: Oliver Middleton Date: Mon, 27 Jun 2016 23:10:13 +0100 Subject: [PATCH 07/20] rustdoc: Fix a few stripping issues We need to recurse into stripped modules to strip things like impl methods but when doing so we must not add any items to the `retained` set. --- src/librustdoc/passes.rs | 58 ++++++++++++++++++++---------- src/test/rustdoc/hidden-impls.rs | 27 ++++++++++++++ src/test/rustdoc/hidden-methods.rs | 39 ++++++++++++++++++++ 3 files changed, 106 insertions(+), 18 deletions(-) create mode 100644 src/test/rustdoc/hidden-impls.rs create mode 100644 src/test/rustdoc/hidden-methods.rs diff --git a/src/librustdoc/passes.rs b/src/librustdoc/passes.rs index 1980d1f9cc45f..b8e40790646a7 100644 --- a/src/librustdoc/passes.rs +++ b/src/librustdoc/passes.rs @@ -12,6 +12,7 @@ use rustc::hir::def_id::DefId; use rustc::middle::privacy::AccessLevels; use rustc::util::nodemap::DefIdSet; use std::cmp; +use std::mem; use std::string::String; use std::usize; @@ -29,7 +30,8 @@ pub fn strip_hidden(krate: clean::Crate) -> plugins::PluginResult { // strip all #[doc(hidden)] items let krate = { struct Stripper<'a> { - retained: &'a mut DefIdSet + retained: &'a mut DefIdSet, + update_retained: bool, } impl<'a> fold::DocFolder for Stripper<'a> { fn fold_item(&mut self, i: Item) -> Option { @@ -38,17 +40,25 @@ pub fn strip_hidden(krate: clean::Crate) -> plugins::PluginResult { // use a dedicated hidden item for given item type if any match i.inner { clean::StructFieldItem(..) | clean::ModuleItem(..) => { - return Strip(i).fold() + // We need to recurse into stripped modules to + // strip things like impl methods but when doing so + // we must not add any items to the `retained` set. + let old = mem::replace(&mut self.update_retained, false); + let ret = Strip(self.fold_item_recur(i).unwrap()).fold(); + self.update_retained = old; + return ret; } _ => return None, } } else { - self.retained.insert(i.def_id); + if self.update_retained { + self.retained.insert(i.def_id); + } } self.fold_item_recur(i) } } - let mut stripper = Stripper{ retained: &mut retained }; + let mut stripper = Stripper{ retained: &mut retained, update_retained: true }; stripper.fold_crate(krate) }; @@ -69,6 +79,7 @@ pub fn strip_private(mut krate: clean::Crate) -> plugins::PluginResult { let mut stripper = Stripper { retained: &mut retained, access_levels: &access_levels, + update_retained: true, }; krate = ImportStripper.fold_crate(stripper.fold_crate(krate)); } @@ -81,12 +92,21 @@ pub fn strip_private(mut krate: clean::Crate) -> plugins::PluginResult { struct Stripper<'a> { retained: &'a mut DefIdSet, access_levels: &'a AccessLevels, + update_retained: bool, } impl<'a> fold::DocFolder for Stripper<'a> { fn fold_item(&mut self, i: Item) -> Option { match i.inner { - clean::StrippedItem(..) => return Some(i), + clean::StrippedItem(..) => { + // We need to recurse into stripped modules to strip things + // like impl methods but when doing so we must not add any + // items to the `retained` set. + let old = mem::replace(&mut self.update_retained, false); + let ret = self.fold_item_recur(i); + self.update_retained = old; + return ret; + } // These items can all get re-exported clean::TypedefItem(..) | clean::StaticItem(..) | clean::StructItem(..) | clean::EnumItem(..) | @@ -109,18 +129,13 @@ impl<'a> fold::DocFolder for Stripper<'a> { clean::ModuleItem(..) => { if i.def_id.is_local() && i.visibility != Some(clean::Public) { - return Strip(self.fold_item_recur(i).unwrap()).fold() + let old = mem::replace(&mut self.update_retained, false); + let ret = Strip(self.fold_item_recur(i).unwrap()).fold(); + self.update_retained = old; + return ret; } } - // trait impls for private items should be stripped - clean::ImplItem(clean::Impl{ - for_: clean::ResolvedPath{ did, is_generic, .. }, .. - }) => { - if did.is_local() && !is_generic && !self.access_levels.is_exported(did) { - return None; - } - } // handled in the `strip-priv-imports` pass clean::ExternCrateItem(..) | clean::ImportItem(..) => {} @@ -152,7 +167,9 @@ impl<'a> fold::DocFolder for Stripper<'a> { }; let i = if fastreturn { - self.retained.insert(i.def_id); + if self.update_retained { + self.retained.insert(i.def_id); + } return Some(i); } else { self.fold_item_recur(i) @@ -160,13 +177,14 @@ impl<'a> fold::DocFolder for Stripper<'a> { i.and_then(|i| { match i.inner { - // emptied modules/impls have no need to exist + // emptied modules have no need to exist clean::ModuleItem(ref m) if m.items.is_empty() && i.doc_value().is_none() => None, - clean::ImplItem(ref i) if i.items.is_empty() => None, _ => { - self.retained.insert(i.def_id); + if self.update_retained { + self.retained.insert(i.def_id); + } Some(i) } } @@ -182,6 +200,10 @@ struct ImplStripper<'a> { impl<'a> fold::DocFolder for ImplStripper<'a> { fn fold_item(&mut self, i: Item) -> Option { if let clean::ImplItem(ref imp) = i.inner { + // emptied none trait impls can be stripped + if imp.trait_.is_none() && imp.items.is_empty() { + return None; + } if let Some(did) = imp.for_.def_id() { if did.is_local() && !imp.for_.is_generic() && !self.retained.contains(&did) diff --git a/src/test/rustdoc/hidden-impls.rs b/src/test/rustdoc/hidden-impls.rs new file mode 100644 index 0000000000000..203c56e9e2e00 --- /dev/null +++ b/src/test/rustdoc/hidden-impls.rs @@ -0,0 +1,27 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_name = "foo"] + +mod hidden { + #[derive(Clone)] + pub struct Foo; +} + +#[doc(hidden)] +pub mod __hidden { + pub use hidden::Foo; +} + +// @has foo/trait.Clone.html +// @!has - 'Foo' +// @has implementors/foo/trait.Clone.js +// @!has - 'Foo' +pub use std::clone::Clone; diff --git a/src/test/rustdoc/hidden-methods.rs b/src/test/rustdoc/hidden-methods.rs new file mode 100644 index 0000000000000..18f5f086cd1a4 --- /dev/null +++ b/src/test/rustdoc/hidden-methods.rs @@ -0,0 +1,39 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_name = "foo"] + +#[doc(hidden)] +pub mod hidden { + pub struct Foo; + + impl Foo { + #[doc(hidden)] + pub fn this_should_be_hidden() {} + } + + pub struct Bar; + + impl Bar { + fn this_should_be_hidden() {} + } +} + +// @has foo/struct.Foo.html +// @!has - 'Methods' +// @!has - 'impl Foo' +// @!has - 'this_should_be_hidden' +pub use hidden::Foo; + +// @has foo/struct.Bar.html +// @!has - 'Methods' +// @!has - 'impl Bar' +// @!has - 'this_should_be_hidden' +pub use hidden::Bar; From b968ee36564abd96da72c381f49bf8009f4b1870 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Tue, 14 Jun 2016 06:48:24 +0000 Subject: [PATCH 08/20] cleanup: don't count attributes on an item in a statement position as on the statement --- src/libsyntax/attr.rs | 4 ++-- src/libsyntax/config.rs | 7 +------ 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index da2967e306f65..3c88fb8f6703b 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -839,7 +839,7 @@ impl HasAttrs for StmtKind { fn attrs(&self) -> &[Attribute] { match *self { StmtKind::Local(ref local) => local.attrs(), - StmtKind::Item(ref item) => item.attrs(), + StmtKind::Item(..) => &[], StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => expr.attrs(), StmtKind::Mac(ref mac) => { let (_, _, ref attrs) = **mac; @@ -851,7 +851,7 @@ impl HasAttrs for StmtKind { fn map_attrs) -> Vec>(self, f: F) -> Self { match self { StmtKind::Local(local) => StmtKind::Local(local.map_attrs(f)), - StmtKind::Item(item) => StmtKind::Item(item.map_attrs(f)), + StmtKind::Item(..) => self, StmtKind::Expr(expr) => StmtKind::Expr(expr.map_attrs(f)), StmtKind::Semi(expr) => StmtKind::Semi(expr.map_attrs(f)), StmtKind::Mac(mac) => StmtKind::Mac(mac.map(|(mac, style, attrs)| { diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index 961763c6025fd..eaf82f5f43ded 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -213,12 +213,7 @@ impl<'a> fold::Folder for StripUnconfigured<'a> { } fn fold_stmt(&mut self, stmt: ast::Stmt) -> SmallVector { - // avoid calling `visit_stmt_or_expr_attrs` on items - match stmt.node { - ast::StmtKind::Item(_) => {} - _ => self.visit_stmt_or_expr_attrs(stmt.attrs()), - } - + self.visit_stmt_or_expr_attrs(stmt.attrs()); self.configure(stmt).map(|stmt| fold::noop_fold_stmt(stmt, self)) .unwrap_or(SmallVector::zero()) } From 2dc15f2b96bad1c03fde93640b2d092600b0bf0c Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Fri, 17 Jun 2016 11:02:42 +0000 Subject: [PATCH 09/20] cleanup: use `DummyResult` to implement `MacroGenerable::dummy` --- src/libsyntax/ext/base.rs | 4 ++++ src/libsyntax/ext/expand.rs | 32 +++++++++++++------------------- 2 files changed, 17 insertions(+), 19 deletions(-) diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 757b039fcac8a..ca38ef068d05f 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -443,6 +443,10 @@ impl MacResult for DummyResult { span: self.span, })) } + + fn make_ty(self: Box) -> Option> { + Some(DummyResult::raw_ty(self.span)) + } } /// An enum representing the different kinds of syntax extensions. diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 3036a88430a2b..a0bbdd8db7a48 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -43,18 +43,19 @@ trait MacroGenerable: Sized { fn fold_with(self, folder: &mut F) -> Self; fn visit_with(&self, visitor: &mut V); - // Return a placeholder expansion to allow compilation to continue after an erroring expansion. - fn dummy(span: Span) -> Self; - // The user-friendly name of the node type (e.g. "expression", "item", etc.) for diagnostics. fn kind_name() -> &'static str; + + // Return a placeholder expansion to allow compilation to continue after an erroring expansion. + fn dummy(span: Span) -> Self { + Self::make_with(DummyResult::any(span)).unwrap() + } } macro_rules! impl_macro_generable { ($($ty:ty: $kind_name:expr, .$make:ident, $(.$fold:ident)* $(lift .$fold_elt:ident)*, - $(.$visit:ident)* $(lift .$visit_elt:ident)*, - |$span:ident| $dummy:expr;)*) => { $( + $(.$visit:ident)* $(lift .$visit_elt:ident)*;)*) => { $( impl MacroGenerable for $ty { fn kind_name() -> &'static str { $kind_name } fn make_with<'a>(result: Box) -> Option { result.$make() } @@ -66,31 +67,24 @@ macro_rules! impl_macro_generable { $( visitor.$visit(self) )* $( for item in self.as_slice() { visitor. $visit_elt (item) } )* } - fn dummy($span: Span) -> Self { $dummy } } )* } } impl_macro_generable! { - P: "pattern", .make_pat, .fold_pat, .visit_pat, |span| P(DummyResult::raw_pat(span)); - P: "type", .make_ty, .fold_ty, .visit_ty, |span| DummyResult::raw_ty(span); - P: - "expression", .make_expr, .fold_expr, .visit_expr, |span| DummyResult::raw_expr(span); - SmallVector: - "statement", .make_stmts, lift .fold_stmt, lift .visit_stmt, |_span| SmallVector::zero(); - SmallVector>: - "item", .make_items, lift .fold_item, lift .visit_item, |_span| SmallVector::zero(); + P: "expression", .make_expr, .fold_expr, .visit_expr; + P: "pattern", .make_pat, .fold_pat, .visit_pat; + P: "type", .make_ty, .fold_ty, .visit_ty; + SmallVector: "statement", .make_stmts, lift .fold_stmt, lift .visit_stmt; + SmallVector>: "item", .make_items, lift .fold_item, lift .visit_item; SmallVector: - "trait item", .make_trait_items, lift .fold_trait_item, lift .visit_trait_item, - |_span| SmallVector::zero(); + "trait item", .make_trait_items, lift .fold_trait_item, lift .visit_trait_item; SmallVector: - "impl item", .make_impl_items, lift .fold_impl_item, lift .visit_impl_item, - |_span| SmallVector::zero(); + "impl item", .make_impl_items, lift .fold_impl_item, lift .visit_impl_item; } impl MacroGenerable for Option> { fn kind_name() -> &'static str { "expression" } - fn dummy(_span: Span) -> Self { None } fn make_with<'a>(result: Box) -> Option { result.make_expr().map(Some) } From 4a13bcb4fbd2a305ebc6906960a00f72342295a9 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Sun, 19 Jun 2016 22:32:51 +0000 Subject: [PATCH 10/20] groundwork: use `resolve_identifier` instead of `resolve_path` to classify ident patterns --- src/librustc_resolve/lib.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 8ffa95ec7e96f..00d6bc69bdf51 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -2287,24 +2287,25 @@ impl<'a> Resolver<'a> { PatKind::Ident(bmode, ref ident, ref opt_pat) => { // First try to resolve the identifier as some existing // entity, then fall back to a fresh binding. - let resolution = if let Ok(resolution) = self.resolve_path(pat.id, - &Path::from_ident(ident.span, ident.node), 0, ValueNS) { + let local_def = self.resolve_identifier(ident.node, ValueNS, true); + let resolution = if let Some(LocalDef { def, .. }) = local_def { let always_binding = !pat_src.is_refutable() || opt_pat.is_some() || bmode != BindingMode::ByValue(Mutability::Immutable); - match resolution.base_def { + match def { Def::Struct(..) | Def::Variant(..) | Def::Const(..) | Def::AssociatedConst(..) if !always_binding => { // A constant, unit variant, etc pattern. - resolution + PathResolution::new(def) } Def::Struct(..) | Def::Variant(..) | Def::Const(..) | Def::AssociatedConst(..) | Def::Static(..) => { // A fresh binding that shadows something unacceptable. + let kind_name = PathResolution::new(def).kind_name(); resolve_error( self, ident.span, ResolutionError::BindingShadowsSomethingUnacceptable( - pat_src.descr(), resolution.kind_name(), ident.node.name) + pat_src.descr(), kind_name, ident.node.name) ); err_path_resolution() } From 36a4eb994099ad9763c32b229cac645cf76dff7a Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Wed, 22 Jun 2016 01:16:56 +0000 Subject: [PATCH 11/20] cleanup: refactor away `ast::NodeIdAssigner` --- src/librustc/hir/lowering.rs | 21 +++++++++++++-------- src/librustc/session/mod.rs | 19 ++++--------------- src/librustc_driver/driver.rs | 6 ++---- src/librustc_metadata/astencode.rs | 21 +-------------------- src/libsyntax/ast.rs | 10 ---------- 5 files changed, 20 insertions(+), 57 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 5b655522f342f..2cc39412182dc 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -50,6 +50,7 @@ use session::Session; use std::collections::BTreeMap; use std::iter; use syntax::ast::*; +use syntax::errors; use syntax::ptr::P; use syntax::codemap::{respan, Spanned}; use syntax::parse::token; @@ -60,7 +61,7 @@ use syntax_pos::Span; pub struct LoweringContext<'a> { crate_root: Option<&'static str>, // Use to assign ids to hir nodes that do not directly correspond to an ast node - id_assigner: &'a NodeIdAssigner, + sess: Option<&'a Session>, // As we walk the AST we must keep track of the current 'parent' def id (in // the form of a DefIndex) so that if we create a new node which introduces // a definition, then we can properly create the def id. @@ -99,7 +100,6 @@ impl Resolver for DummyResolver { pub fn lower_crate(sess: &Session, krate: &Crate, - id_assigner: &NodeIdAssigner, resolver: &mut Resolver) -> hir::Crate { // We're constructing the HIR here; we don't care what we will @@ -115,17 +115,17 @@ pub fn lower_crate(sess: &Session, } else { Some("std") }, - id_assigner: id_assigner, + sess: Some(sess), parent_def: None, resolver: resolver, }.lower_crate(krate) } impl<'a> LoweringContext<'a> { - pub fn testing_context(id_assigner: &'a NodeIdAssigner, resolver: &'a mut Resolver) -> Self { + pub fn testing_context(resolver: &'a mut Resolver) -> Self { LoweringContext { crate_root: None, - id_assigner: id_assigner, + sess: None, parent_def: None, resolver: resolver, } @@ -161,7 +161,12 @@ impl<'a> LoweringContext<'a> { } fn next_id(&self) -> NodeId { - self.id_assigner.next_node_id() + self.sess.map(Session::next_node_id).unwrap_or(0) + } + + fn diagnostic(&self) -> &errors::Handler { + self.sess.map(Session::diagnostic) + .unwrap_or_else(|| panic!("this lowerer cannot emit diagnostics")) } fn str_to_ident(&self, s: &'static str) -> Name { @@ -786,7 +791,7 @@ impl<'a> LoweringContext<'a> { if let Some(SelfKind::Explicit(..)) = sig.decl.get_self().map(|eself| eself.node) { match hir_sig.decl.get_self().map(|eself| eself.node) { Some(hir::SelfKind::Value(..)) | Some(hir::SelfKind::Region(..)) => { - self.id_assigner.diagnostic().span_err(sig.decl.inputs[0].ty.span, + self.diagnostic().span_err(sig.decl.inputs[0].ty.span, "the type placeholder `_` is not allowed within types on item signatures"); } _ => {} @@ -1212,7 +1217,7 @@ impl<'a> LoweringContext<'a> { make_struct(self, e, &["RangeInclusive", "NonEmpty"], &[("start", e1), ("end", e2)]), - _ => panic!(self.id_assigner.diagnostic() + _ => panic!(self.diagnostic() .span_fatal(e.span, "inclusive range with no end")), }; } diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 77259cea24d28..fdaf182c60542 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -20,7 +20,7 @@ use ty::tls; use util::nodemap::{NodeMap, FnvHashMap}; use mir::transform as mir_pass; -use syntax::ast::{NodeId, NodeIdAssigner, Name}; +use syntax::ast::{NodeId, Name}; use errors::{self, DiagnosticBuilder}; use errors::emitter::{Emitter, BasicEmitter, EmitterWriter}; use syntax::json::JsonEmitter; @@ -272,6 +272,9 @@ impl Session { id } + pub fn next_node_id(&self) -> NodeId { + self.reserve_node_ids(1) + } pub fn diagnostic<'a>(&'a self) -> &'a errors::Handler { &self.parse_sess.span_diagnostic } @@ -345,20 +348,6 @@ impl Session { } } -impl NodeIdAssigner for Session { - fn next_node_id(&self) -> NodeId { - self.reserve_node_ids(1) - } - - fn peek_node_id(&self) -> NodeId { - self.next_node_id.get().checked_add(1).unwrap() - } - - fn diagnostic(&self) -> &errors::Handler { - self.diagnostic() - } -} - fn split_msg_into_multilines(msg: &str) -> Option { // Conditions for enabling multi-line errors: if !msg.contains("mismatched types") && diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index eb442c0a34e74..980f0eeca184e 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -49,13 +49,11 @@ use std::ffi::{OsString, OsStr}; use std::fs; use std::io::{self, Write}; use std::path::{Path, PathBuf}; -use syntax::ast::{self, NodeIdAssigner}; +use syntax::{ast, diagnostics, visit}; use syntax::attr::{self, AttrMetaMethods}; -use syntax::diagnostics; use syntax::fold::Folder; use syntax::parse::{self, PResult, token}; use syntax::util::node_count::NodeCounter; -use syntax::visit; use syntax; use syntax_ext; @@ -823,7 +821,7 @@ pub fn lower_and_resolve<'a>(sess: &Session, // Lower ast -> hir. let hir_forest = time(sess.time_passes(), "lowering ast -> hir", || { - hir_map::Forest::new(lower_crate(sess, krate, sess, &mut resolver), dep_graph) + hir_map::Forest::new(lower_crate(sess, krate, &mut resolver), dep_graph) }); (ty::CrateAnalysis { diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs index dc37bdf6322af..7ef00b971c57b 100644 --- a/src/librustc_metadata/astencode.rs +++ b/src/librustc_metadata/astencode.rs @@ -38,7 +38,6 @@ use rustc::ty::subst; use rustc::ty::{self, Ty, TyCtxt}; use syntax::ast; -use syntax::ast::NodeIdAssigner; use syntax::ptr::P; use syntax_pos; @@ -56,7 +55,6 @@ use rustc_serialize::{Encodable, EncoderHelpers}; #[cfg(test)] use std::io::Cursor; #[cfg(test)] use syntax::parse; -#[cfg(test)] use syntax::ast::NodeId; #[cfg(test)] use rustc::hir::print as pprust; #[cfg(test)] use rustc::hir::lowering::{LoweringContext, DummyResolver}; @@ -1295,22 +1293,6 @@ impl FakeExtCtxt for parse::ParseSess { fn parse_sess(&self) -> &parse::ParseSess { self } } -#[cfg(test)] -struct FakeNodeIdAssigner; - -#[cfg(test)] -// It should go without saying that this may give unexpected results. Avoid -// lowering anything which needs new nodes. -impl NodeIdAssigner for FakeNodeIdAssigner { - fn next_node_id(&self) -> NodeId { - 0 - } - - fn peek_node_id(&self) -> NodeId { - 0 - } -} - #[cfg(test)] fn mk_ctxt() -> parse::ParseSess { parse::ParseSess::new() @@ -1318,9 +1300,8 @@ fn mk_ctxt() -> parse::ParseSess { #[cfg(test)] fn with_testing_context T>(f: F) -> T { - let assigner = FakeNodeIdAssigner; let mut resolver = DummyResolver; - let mut lcx = LoweringContext::testing_context(&assigner, &mut resolver); + let mut lcx = LoweringContext::testing_context(&mut resolver); f(&mut lcx) } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index a352715b20b12..cc033cec8b8b1 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -19,7 +19,6 @@ pub use util::ThinVec; use syntax_pos::{mk_sp, Span, DUMMY_SP, ExpnId}; use codemap::{respan, Spanned}; use abi::Abi; -use errors; use parse::token::{self, keywords, InternedString}; use print::pprust; use ptr::P; @@ -362,15 +361,6 @@ pub const CRATE_NODE_ID: NodeId = 0; /// small, positive ids. pub const DUMMY_NODE_ID: NodeId = !0; -pub trait NodeIdAssigner { - fn next_node_id(&self) -> NodeId; - fn peek_node_id(&self) -> NodeId; - - fn diagnostic(&self) -> &errors::Handler { - panic!("this ID assigner cannot emit diagnostics") - } -} - /// The AST represents all type param bounds as types. /// typeck::collect::compute_bounds matches these against /// the "special" built-in traits (see middle::lang_items) and From ec0c150152c85435a23160b0db3472580a76fb74 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Wed, 22 Jun 2016 01:54:34 +0000 Subject: [PATCH 12/20] groundwork: refactor the interface that `resolve` exposes to `driver` --- src/librustc_driver/driver.rs | 73 ++++++++++++++-------------------- src/librustc_resolve/lib.rs | 75 ++++++++++++++--------------------- 2 files changed, 60 insertions(+), 88 deletions(-) diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 980f0eeca184e..006616416d7f0 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use rustc::dep_graph::DepGraph; use rustc::hir; use rustc::hir::{map as hir_map, FreevarMap, TraitMap}; use rustc::hir::def::DefMap; @@ -27,7 +26,7 @@ use rustc::util::nodemap::NodeSet; use rustc_back::sha2::{Sha256, Digest}; use rustc_borrowck as borrowck; use rustc_incremental; -use rustc_resolve as resolve; +use rustc_resolve::{MakeGlobMap, Resolver}; use rustc_metadata::macro_import; use rustc_metadata::creader::read_local_crates; use rustc_metadata::cstore::CStore; @@ -291,7 +290,7 @@ pub struct CompileController<'a> { pub after_analysis: PhaseController<'a>, pub after_llvm: PhaseController<'a>, - pub make_glob_map: resolve::MakeGlobMap, + pub make_glob_map: MakeGlobMap, } impl<'a> CompileController<'a> { @@ -303,7 +302,7 @@ impl<'a> CompileController<'a> { after_hir_lowering: PhaseController::basic(), after_analysis: PhaseController::basic(), after_llvm: PhaseController::basic(), - make_glob_map: resolve::MakeGlobMap::No, + make_glob_map: MakeGlobMap::No, } } } @@ -562,7 +561,7 @@ pub fn phase_2_configure_and_expand<'a>(sess: &Session, mut krate: ast::Crate, crate_name: &'a str, addl_plugins: Option>, - make_glob_map: resolve::MakeGlobMap) + make_glob_map: MakeGlobMap) -> Result, usize> { let time_passes = sess.time_passes(); @@ -728,7 +727,7 @@ pub fn phase_2_configure_and_expand<'a>(sess: &Session, krate = assign_node_ids(sess, krate); // Collect defintions for def ids. - let mut defs = + let defs = time(sess.time_passes(), "collecting defs", || hir_map::collect_definitions(&krate)); time(sess.time_passes(), @@ -743,8 +742,17 @@ pub fn phase_2_configure_and_expand<'a>(sess: &Session, "AST validation", || ast_validation::check_crate(sess, &krate)); - let (analysis, resolutions, hir_forest) = - lower_and_resolve(sess, crate_name, &mut defs, &krate, &sess.dep_graph, make_glob_map); + let resolver_arenas = Resolver::arenas(); + let mut resolver = Resolver::new(sess, defs, make_glob_map, &resolver_arenas); + + time(sess.time_passes(), "name resolution", || { + resolver.resolve_crate(&krate); + }); + + // Lower ast -> hir. + let hir_forest = time(sess.time_passes(), "lowering ast -> hir", || { + hir_map::Forest::new(lower_crate(sess, &krate, &mut resolver), &sess.dep_graph) + }); // Discard MTWT tables that aren't required past lowering to HIR. if !keep_mtwt_tables(sess) { @@ -753,9 +761,20 @@ pub fn phase_2_configure_and_expand<'a>(sess: &Session, Ok(ExpansionResult { expanded_crate: krate, - defs: defs, - analysis: analysis, - resolutions: resolutions, + defs: resolver.definitions, + analysis: ty::CrateAnalysis { + export_map: resolver.export_map, + access_levels: AccessLevels::default(), + reachable: NodeSet(), + name: crate_name, + glob_map: if resolver.make_glob_map { Some(resolver.glob_map) } else { None }, + }, + resolutions: Resolutions { + def_map: resolver.def_map, + freevars: resolver.freevars, + trait_map: resolver.trait_map, + maybe_unused_trait_imports: resolver.maybe_unused_trait_imports, + }, hir_forest: hir_forest }) } @@ -807,38 +826,6 @@ pub fn assign_node_ids(sess: &Session, krate: ast::Crate) -> ast::Crate { krate } -pub fn lower_and_resolve<'a>(sess: &Session, - id: &'a str, - defs: &mut hir_map::Definitions, - krate: &ast::Crate, - dep_graph: &DepGraph, - make_glob_map: resolve::MakeGlobMap) - -> (ty::CrateAnalysis<'a>, Resolutions, hir_map::Forest) { - resolve::with_resolver(sess, defs, make_glob_map, |mut resolver| { - time(sess.time_passes(), "name resolution", || { - resolve::resolve_crate(&mut resolver, krate); - }); - - // Lower ast -> hir. - let hir_forest = time(sess.time_passes(), "lowering ast -> hir", || { - hir_map::Forest::new(lower_crate(sess, krate, &mut resolver), dep_graph) - }); - - (ty::CrateAnalysis { - export_map: resolver.export_map, - access_levels: AccessLevels::default(), - reachable: NodeSet(), - name: &id, - glob_map: if resolver.make_glob_map { Some(resolver.glob_map) } else { None }, - }, Resolutions { - def_map: resolver.def_map, - freevars: resolver.freevars, - trait_map: resolver.trait_map, - maybe_unused_trait_imports: resolver.maybe_unused_trait_imports, - }, hir_forest) - }) -} - /// Run the resolution, typechecking, region checking and other /// miscellaneous analysis passes on the crate. Return various /// structures carrying the results of the analysis. diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 00d6bc69bdf51..073f06d1c1e0d 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -925,7 +925,7 @@ impl PrimitiveTypeTable { pub struct Resolver<'a> { session: &'a Session, - definitions: &'a mut Definitions, + pub definitions: Definitions, graph_root: Module<'a>, @@ -1001,7 +1001,7 @@ pub struct Resolver<'a> { arenas: &'a ResolverArenas<'a>, } -struct ResolverArenas<'a> { +pub struct ResolverArenas<'a> { modules: arena::TypedArena>, local_modules: RefCell>>, name_bindings: arena::TypedArena>, @@ -1079,7 +1079,7 @@ impl<'a> hir::lowering::Resolver for Resolver<'a> { } fn definitions(&mut self) -> Option<&mut Definitions> { - Some(self.definitions) + Some(&mut self.definitions) } } @@ -1100,11 +1100,11 @@ impl Named for hir::PathSegment { } impl<'a> Resolver<'a> { - fn new(session: &'a Session, - definitions: &'a mut Definitions, - make_glob_map: MakeGlobMap, - arenas: &'a ResolverArenas<'a>) - -> Resolver<'a> { + pub fn new(session: &'a Session, + definitions: Definitions, + make_glob_map: MakeGlobMap, + arenas: &'a ResolverArenas<'a>) + -> Resolver<'a> { let root_def_id = definitions.local_def_id(CRATE_NODE_ID); let graph_root = ModuleS::new(NoParentLink, Some(Def::Mod(root_def_id)), false, arenas); @@ -1158,7 +1158,7 @@ impl<'a> Resolver<'a> { } } - fn arenas() -> ResolverArenas<'a> { + pub fn arenas() -> ResolverArenas<'a> { ResolverArenas { modules: arena::TypedArena::new(), local_modules: RefCell::new(Vec::new()), @@ -1168,6 +1168,27 @@ impl<'a> Resolver<'a> { } } + /// Entry point to crate resolution. + pub fn resolve_crate(&mut self, krate: &Crate) { + // Currently, we ignore the name resolution data structures for + // the purposes of dependency tracking. Instead we will run name + // resolution and include its output in the hash of each item, + // much like we do for macro expansion. In other words, the hash + // reflects not just its contents but the results of name + // resolution on those contents. Hopefully we'll push this back at + // some point. + let _ignore = self.session.dep_graph.in_ignore(); + + self.build_reduced_graph(krate); + resolve_imports::resolve_imports(self); + + self.current_module = self.graph_root; + visit::walk_crate(self, krate); + + check_unused::check_crate(self, krate); + self.report_privacy_errors(); + } + fn new_module(&self, parent_link: ParentLink<'a>, def: Option, external: bool) -> Module<'a> { self.arenas.alloc_module(ModuleS::new(parent_link, def, external, self.arenas)) @@ -1568,12 +1589,6 @@ impl<'a> Resolver<'a> { None } - fn resolve_crate(&mut self, krate: &Crate) { - debug!("(resolving crate) starting"); - self.current_module = self.graph_root; - visit::walk_crate(self, krate); - } - fn resolve_item(&mut self, item: &Item) { let name = item.ident.name; @@ -3455,34 +3470,4 @@ pub enum MakeGlobMap { No, } -/// Entry point to crate resolution. -pub fn resolve_crate<'a, 'b>(resolver: &'b mut Resolver<'a>, krate: &'b Crate) { - // Currently, we ignore the name resolution data structures for - // the purposes of dependency tracking. Instead we will run name - // resolution and include its output in the hash of each item, - // much like we do for macro expansion. In other words, the hash - // reflects not just its contents but the results of name - // resolution on those contents. Hopefully we'll push this back at - // some point. - let _ignore = resolver.session.dep_graph.in_ignore(); - - resolver.build_reduced_graph(krate); - resolve_imports::resolve_imports(resolver); - resolver.resolve_crate(krate); - - check_unused::check_crate(resolver, krate); - resolver.report_privacy_errors(); -} - -pub fn with_resolver<'a, T, F>(session: &'a Session, - definitions: &'a mut Definitions, - make_glob_map: MakeGlobMap, - f: F) -> T - where F: for<'b> FnOnce(Resolver<'b>) -> T, -{ - let arenas = Resolver::arenas(); - let resolver = Resolver::new(session, definitions, make_glob_map, &arenas); - f(resolver) -} - __build_diagnostic_array! { librustc_resolve, DIAGNOSTICS } From e58963d3e45895c150a8c5894c2b7ad87b448568 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Wed, 22 Jun 2016 01:55:42 +0000 Subject: [PATCH 13/20] groundwork: create the `Resolver` earlier in phase 2 --- src/librustc/hir/map/def_collector.rs | 8 ++++---- src/librustc/hir/map/definitions.rs | 8 +++++++- src/librustc/hir/map/mod.rs | 10 +--------- src/librustc_driver/driver.rs | 16 ++++++++-------- src/librustc_resolve/lib.rs | 11 ++++------- 5 files changed, 24 insertions(+), 29 deletions(-) diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index ccb3e154d9204..2b89695ab41ca 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -25,15 +25,15 @@ pub struct DefCollector<'ast> { // If we are walking HIR (c.f., AST), we need to keep a reference to the // crate. hir_crate: Option<&'ast hir::Crate>, - pub definitions: Definitions, + definitions: &'ast mut Definitions, parent_def: Option, } impl<'ast> DefCollector<'ast> { - pub fn root() -> DefCollector<'ast> { + pub fn root(definitions: &'ast mut Definitions) -> DefCollector<'ast> { let mut collector = DefCollector { hir_crate: None, - definitions: Definitions::new(), + definitions: definitions, parent_def: None, }; let root = collector.create_def_with_parent(None, CRATE_NODE_ID, DefPathData::CrateRoot); @@ -48,7 +48,7 @@ impl<'ast> DefCollector<'ast> { pub fn extend(parent_node: NodeId, parent_def_path: DefPath, parent_def_id: DefId, - definitions: Definitions) + definitions: &'ast mut Definitions) -> DefCollector<'ast> { let mut collector = DefCollector { hir_crate: None, diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index d66df3e4e8fd2..3317585f820aa 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -10,8 +10,9 @@ use middle::cstore::LOCAL_CRATE; use hir::def_id::{DefId, DefIndex}; +use hir::map::def_collector::DefCollector; use rustc_data_structures::fnv::FnvHashMap; -use syntax::ast; +use syntax::{ast, visit}; use syntax::parse::token::InternedString; use util::nodemap::NodeMap; @@ -189,6 +190,11 @@ impl Definitions { } } + pub fn collect(&mut self, krate: &ast::Crate) { + let mut def_collector = DefCollector::root(self); + visit::walk_crate(&mut def_collector, krate); + } + /// Get the number of definitions. pub fn len(&self) -> usize { self.data.len() diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index f9fb8ac66b7ef..960e32ae99faf 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -24,7 +24,6 @@ use hir::def_id::{CRATE_DEF_INDEX, DefId, DefIndex}; use syntax::abi::Abi; use syntax::ast::{self, Name, NodeId, DUMMY_NODE_ID, }; use syntax::codemap::Spanned; -use syntax::visit; use syntax_pos::Span; use hir::*; @@ -780,12 +779,6 @@ impl Folder for IdAndSpanUpdater { } } -pub fn collect_definitions<'ast>(krate: &'ast ast::Crate) -> Definitions { - let mut def_collector = DefCollector::root(); - visit::walk_crate(&mut def_collector, krate); - def_collector.definitions -} - pub fn map_crate<'ast>(forest: &'ast mut Forest, definitions: Definitions) -> Map<'ast> { @@ -842,13 +835,12 @@ pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>, let ii = map.forest.inlined_items.alloc(ii); let ii_parent_id = fld.new_id(DUMMY_NODE_ID); - let defs = mem::replace(&mut *map.definitions.borrow_mut(), Definitions::new()); + let defs = &mut *map.definitions.borrow_mut(); let mut def_collector = DefCollector::extend(ii_parent_id, parent_def_path.clone(), parent_def_id, defs); def_collector.walk_item(ii, map.krate()); - *map.definitions.borrow_mut() = def_collector.definitions; let mut collector = NodeCollector::extend(map.krate(), ii, diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 006616416d7f0..46009e5813094 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -726,13 +726,16 @@ pub fn phase_2_configure_and_expand<'a>(sess: &Session, krate = assign_node_ids(sess, krate); + let resolver_arenas = Resolver::arenas(); + let mut resolver = Resolver::new(sess, make_glob_map, &resolver_arenas); + // Collect defintions for def ids. - let defs = - time(sess.time_passes(), "collecting defs", || hir_map::collect_definitions(&krate)); + time(sess.time_passes(), "collecting defs", || resolver.definitions.collect(&krate)); - time(sess.time_passes(), - "external crate/lib resolution", - || read_local_crates(sess, &cstore, &defs, &krate, crate_name, &sess.dep_graph)); + time(sess.time_passes(), "external crate/lib resolution", || { + let defs = &resolver.definitions; + read_local_crates(sess, &cstore, defs, &krate, crate_name, &sess.dep_graph) + }); time(sess.time_passes(), "early lint checks", @@ -742,9 +745,6 @@ pub fn phase_2_configure_and_expand<'a>(sess: &Session, "AST validation", || ast_validation::check_crate(sess, &krate)); - let resolver_arenas = Resolver::arenas(); - let mut resolver = Resolver::new(sess, defs, make_glob_map, &resolver_arenas); - time(sess.time_passes(), "name resolution", || { resolver.resolve_crate(&krate); }); diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 073f06d1c1e0d..9c9e3ff037bc4 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -47,7 +47,7 @@ use rustc::hir::{self, PrimTy, TyBool, TyChar, TyFloat, TyInt, TyUint, TyStr}; use rustc::session::Session; use rustc::lint; use rustc::hir::def::*; -use rustc::hir::def_id::DefId; +use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId}; use rustc::ty; use rustc::ty::subst::{ParamSpace, FnSpace, TypeSpace}; use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap}; @@ -1100,12 +1100,9 @@ impl Named for hir::PathSegment { } impl<'a> Resolver<'a> { - pub fn new(session: &'a Session, - definitions: Definitions, - make_glob_map: MakeGlobMap, - arenas: &'a ResolverArenas<'a>) + pub fn new(session: &'a Session, make_glob_map: MakeGlobMap, arenas: &'a ResolverArenas<'a>) -> Resolver<'a> { - let root_def_id = definitions.local_def_id(CRATE_NODE_ID); + let root_def_id = DefId::local(CRATE_DEF_INDEX); let graph_root = ModuleS::new(NoParentLink, Some(Def::Mod(root_def_id)), false, arenas); let graph_root = arenas.alloc_module(graph_root); @@ -1115,7 +1112,7 @@ impl<'a> Resolver<'a> { Resolver { session: session, - definitions: definitions, + definitions: Definitions::new(), // The outermost module has def ID 0; this is not reflected in the // AST. From f05da01dbe3ce8e7460a1d47d489f85a1fa1cbb7 Mon Sep 17 00:00:00 2001 From: Oliver Middleton Date: Tue, 28 Jun 2016 22:50:44 +0100 Subject: [PATCH 14/20] rustdoc: Fix empty Implementations section on some module pages These are caused by `DefaultImpl`s. --- src/librustdoc/html/render.rs | 3 +++ src/test/rustdoc/module-impls.rs | 15 +++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 src/test/rustdoc/module-impls.rs diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index f63d37b34032e..48acf31b99367 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1696,6 +1696,9 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, document(w, cx, item)?; let mut indices = (0..items.len()).filter(|i| { + if let clean::DefaultImplItem(..) = items[*i].inner { + return false; + } !cx.maybe_ignore_item(&items[*i]) }).collect::>(); diff --git a/src/test/rustdoc/module-impls.rs b/src/test/rustdoc/module-impls.rs new file mode 100644 index 0000000000000..7be3c50073166 --- /dev/null +++ b/src/test/rustdoc/module-impls.rs @@ -0,0 +1,15 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_name = "foo"] + +pub use std::marker::Send; + +// @!has foo/index.html 'Implementations' From 232783c9148045e811034985ff7ccbb1520a7a24 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Tue, 28 Jun 2016 23:03:56 +0000 Subject: [PATCH 15/20] Fix infinite loop on recursive module exports in an extern crate --- src/librustc_resolve/lib.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 8ffa95ec7e96f..f983646479b94 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -3194,7 +3194,9 @@ impl<'a> Resolver<'a> { if !in_module_is_extern || name_binding.vis == ty::Visibility::Public { // add the module to the lookup let is_extern = in_module_is_extern || name_binding.is_extern_crate(); - worklist.push((module, path_segments, is_extern)); + if !worklist.iter().any(|&(m, _, _)| m.def == module.def) { + worklist.push((module, path_segments, is_extern)); + } } } }) From 9ffe1c9fba7d1327b1836188f76ca430e0333690 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Wed, 29 Jun 2016 00:18:07 +0000 Subject: [PATCH 16/20] Add regression test --- .../compile-fail/auxiliary/recursive_reexports.rs | 13 +++++++++++++ src/test/compile-fail/recursive-reexports.rs | 15 +++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 src/test/compile-fail/auxiliary/recursive_reexports.rs create mode 100644 src/test/compile-fail/recursive-reexports.rs diff --git a/src/test/compile-fail/auxiliary/recursive_reexports.rs b/src/test/compile-fail/auxiliary/recursive_reexports.rs new file mode 100644 index 0000000000000..1186e3d62f73a --- /dev/null +++ b/src/test/compile-fail/auxiliary/recursive_reexports.rs @@ -0,0 +1,13 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub mod foo { + pub use foo; +} diff --git a/src/test/compile-fail/recursive-reexports.rs b/src/test/compile-fail/recursive-reexports.rs new file mode 100644 index 0000000000000..6fd52beeec62c --- /dev/null +++ b/src/test/compile-fail/recursive-reexports.rs @@ -0,0 +1,15 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:recursive_reexports.rs + +fn f() -> recursive_reexports::S {} //~ ERROR undeclared + +fn main() {} From 66ef652559ab670b4f7c3be973e019f0d55b3644 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Fri, 24 Jun 2016 03:23:44 +0000 Subject: [PATCH 17/20] Disallow `derive` on items with type macros --- src/libsyntax_ext/deriving/generic/mod.rs | 18 ++++++++++++++---- src/test/compile-fail/issue-32950.rs | 12 ++++++------ 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index 647e414a7fd27..e01f4ed1f9bd2 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -345,15 +345,18 @@ pub fn combine_substructure<'a>(f: CombineSubstructureFunc<'a>) /// This method helps to extract all the type parameters referenced from a /// type. For a type parameter ``, it looks for either a `TyPath` that /// is not global and starts with `T`, or a `TyQPath`. -fn find_type_parameters(ty: &ast::Ty, ty_param_names: &[ast::Name]) -> Vec> { +fn find_type_parameters(ty: &ast::Ty, ty_param_names: &[ast::Name], span: Span, cx: &ExtCtxt) + -> Vec> { use syntax::visit; - struct Visitor<'a> { + struct Visitor<'a, 'b: 'a> { + cx: &'a ExtCtxt<'b>, + span: Span, ty_param_names: &'a [ast::Name], types: Vec>, } - impl<'a> visit::Visitor for Visitor<'a> { + impl<'a, 'b> visit::Visitor for Visitor<'a, 'b> { fn visit_ty(&mut self, ty: &ast::Ty) { match ty.node { ast::TyKind::Path(_, ref path) if !path.global => { @@ -371,11 +374,18 @@ fn find_type_parameters(ty: &ast::Ty, ty_param_names: &[ast::Name]) -> Vec TraitDef<'a> { let mut processed_field_types = HashSet::new(); for field_ty in field_tys { - let tys = find_type_parameters(&field_ty, &ty_param_names); + let tys = find_type_parameters(&field_ty, &ty_param_names, self.span, cx); for ty in tys { // if we have already handled this type, skip it diff --git a/src/test/compile-fail/issue-32950.rs b/src/test/compile-fail/issue-32950.rs index e47ebdd6a6938..e8ca1c1fa98ff 100644 --- a/src/test/compile-fail/issue-32950.rs +++ b/src/test/compile-fail/issue-32950.rs @@ -8,11 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(type_macros, concat_idents, rustc_attrs)] -#![allow(unused)] +#![feature(type_macros, concat_idents)] -#[derive(Debug)] struct FooBar; -#[derive(Debug)] struct Baz(T, concat_idents!(Foo, Bar)); +#[derive(Debug)] //~ NOTE in this expansion +struct Baz( + concat_idents!(Foo, Bar) //~ ERROR `derive` cannot be used on items with type macros +); -#[rustc_error] -fn main() {} //~ ERROR compilation successful +fn main() {} From a595ffaac5045eb8950785f050f9e0b76cc4f3eb Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Fri, 24 Jun 2016 03:25:37 +0000 Subject: [PATCH 18/20] Treat `MultiDecorator`s as a special case of `MultiModifier`s --- src/libsyntax/ext/expand.rs | 111 +++++++++++------------------------- 1 file changed, 33 insertions(+), 78 deletions(-) diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 3036a88430a2b..a10d890014017 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -691,7 +691,7 @@ impl<'a> Folder for PatIdentRenamer<'a> { } fn expand_multi_modified(a: Annotatable, fld: &mut MacroExpander) -> SmallVector { - let new_items: SmallVector = match a { + match a { Annotatable::Item(it) => match it.node { ast::ItemKind::Mac(..) => { it.and_then(|it| match it.node { @@ -728,63 +728,6 @@ fn expand_multi_modified(a: Annotatable, fld: &mut MacroExpander) -> SmallVector expand_impl_item(ii.unwrap(), fld).into_iter(). map(|ii| Annotatable::ImplItem(P(ii))).collect() } - }; - - new_items.into_iter().flat_map(|a| decorate(a, fld)).collect() -} - -fn decorate(a: Annotatable, fld: &mut MacroExpander) -> SmallVector { - let mut decorator_items = SmallVector::zero(); - let mut new_attrs = Vec::new(); - expand_decorators(a.clone(), fld, &mut decorator_items, &mut new_attrs); - - let mut new_items = SmallVector::one(a.fold_attrs(new_attrs)); - new_items.push_all(decorator_items); - new_items -} - -fn expand_decorators(a: Annotatable, - fld: &mut MacroExpander, - decorator_items: &mut SmallVector, - new_attrs: &mut Vec) -{ - for attr in a.attrs() { - let mname = intern(&attr.name()); - match fld.cx.syntax_env.find(mname) { - Some(rc) => match *rc { - MultiDecorator(ref dec) => { - attr::mark_used(&attr); - - fld.cx.bt_push(ExpnInfo { - call_site: attr.span, - callee: NameAndSpan { - format: MacroAttribute(mname), - span: Some(attr.span), - // attributes can do whatever they like, - // for now. - allow_internal_unstable: true, - } - }); - - let mut items: SmallVector = SmallVector::zero(); - dec.expand(fld.cx, - attr.span, - &attr.node.value, - &a, - &mut |ann| items.push(ann)); - - for item in items { - for configured_item in item.fold_with(&mut fld.strip_unconfigured()) { - decorator_items.extend(expand_annotatable(configured_item, fld)); - } - } - - fld.cx.bt_pop(); - } - _ => new_attrs.push((*attr).clone()), - }, - _ => new_attrs.push((*attr).clone()), - } } } @@ -793,9 +736,12 @@ fn expand_annotatable(mut item: Annotatable, fld: &mut MacroExpander) -> SmallVe item = item.map_attrs(|mut attrs| { for i in 0..attrs.len() { if let Some(extension) = fld.cx.syntax_env.find(intern(&attrs[i].name())) { - if let MultiModifier(..) = *extension { - multi_modifier = Some((attrs.remove(i), extension)); - break; + match *extension { + MultiModifier(..) | MultiDecorator(..) => { + multi_modifier = Some((attrs.remove(i), extension)); + break; + } + _ => {} } } } @@ -804,23 +750,32 @@ fn expand_annotatable(mut item: Annotatable, fld: &mut MacroExpander) -> SmallVe match multi_modifier { None => expand_multi_modified(item, fld), - Some((attr, extension)) => match *extension { - MultiModifier(ref mac) => { - attr::mark_used(&attr); - fld.cx.bt_push(ExpnInfo { - call_site: attr.span, - callee: NameAndSpan { - format: MacroAttribute(intern(&attr.name())), - span: Some(attr.span), - // attributes can do whatever they like, for now - allow_internal_unstable: true, - } - }); - let modified = mac.expand(fld.cx, attr.span, &attr.node.value, item); - fld.cx.bt_pop(); - modified.into_iter().flat_map(|it| expand_annotatable(it, fld)).collect() - } - _ => unreachable!(), + Some((attr, extension)) => { + attr::mark_used(&attr); + fld.cx.bt_push(ExpnInfo { + call_site: attr.span, + callee: NameAndSpan { + format: MacroAttribute(intern(&attr.name())), + span: Some(attr.span), + // attributes can do whatever they like, for now + allow_internal_unstable: true, + } + }); + + let modified = match *extension { + MultiModifier(ref mac) => mac.expand(fld.cx, attr.span, &attr.node.value, item), + MultiDecorator(ref mac) => { + let mut items = Vec::new(); + mac.expand(fld.cx, attr.span, &attr.node.value, &item, + &mut |item| items.push(item)); + items.push(item); + items + } + _ => unreachable!(), + }; + + fld.cx.bt_pop(); + modified.into_iter().flat_map(|it| expand_annotatable(it, fld)).collect() } } } From a9d25f8b5936bc5477c8318fa4ddd315a2df55b5 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Wed, 29 Jun 2016 06:40:05 +0000 Subject: [PATCH 19/20] Refactor away `parser.commit_stmt_expecting()` --- src/libsyntax/parse/parser.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 813d90103b887..20a54228d016c 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -553,10 +553,6 @@ impl<'a> Parser<'a> { self.expect_one_of(edible, inedible) } - pub fn commit_stmt_expecting(&mut self, edible: token::Token) -> PResult<'a, ()> { - self.commit_stmt(&[edible], &[]) - } - /// returns the span of expr, if it was not interpolated or the span of the interpolated token fn interpolated_or_expr_span(&self, expr: PResult<'a, P>) @@ -4122,7 +4118,7 @@ impl<'a> Parser<'a> { _ => { // all other kinds of statements: let mut hi = span.hi; if classify::stmt_ends_with_semi(&node) { - self.commit_stmt_expecting(token::Semi)?; + self.commit_stmt(&[token::Semi], &[])?; hi = self.last_span.hi; } From 8557a2e18c755ef269aa54b067cfc323e97d9a11 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Sun, 19 Jun 2016 02:00:11 +0000 Subject: [PATCH 20/20] Give `ast::ExprKind::Paren` no-op expressions the same node ids as their children. --- src/libsyntax/fold.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 6789e7be058bf..ed6f09eed645f 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -1102,7 +1102,6 @@ pub fn noop_fold_pat(p: P, folder: &mut T) -> P { pub fn noop_fold_expr(Expr {id, node, span, attrs}: Expr, folder: &mut T) -> Expr { Expr { - id: folder.new_id(id), node: match node { ExprKind::Box(e) => { ExprKind::Box(folder.fold_expr(e)) @@ -1270,9 +1269,19 @@ pub fn noop_fold_expr(Expr {id, node, span, attrs}: Expr, folder: &mu fields.move_map(|x| folder.fold_field(x)), maybe_expr.map(|x| folder.fold_expr(x))) }, - ExprKind::Paren(ex) => ExprKind::Paren(folder.fold_expr(ex)), + ExprKind::Paren(ex) => { + let sub_expr = folder.fold_expr(ex); + return Expr { + // Nodes that are equal modulo `Paren` sugar no-ops should have the same ids. + id: sub_expr.id, + node: ExprKind::Paren(sub_expr), + span: folder.new_span(span), + attrs: fold_attrs(attrs.into(), folder).into(), + }; + } ExprKind::Try(ex) => ExprKind::Try(folder.fold_expr(ex)), }, + id: folder.new_id(id), span: folder.new_span(span), attrs: fold_attrs(attrs.into(), folder).into(), }