Auto merge of #49718 - petrochenkov:fieldcmp, r=eddyb
Hygiene 2.0: Avoid comparing fields by name
There are two separate commits here (not counting tests):
- The first one unifies named (`obj.name`) and numeric (`obj.0`) field access expressions in AST and HIR. Before field references in these expressions are resolved it doesn't matter whether the field is named or numeric (it's just a symbol) and 99% of code is common. After field references are resolved we work with
them by index for all fields (see the second commit), so it's again not important whether the field was named or numeric (this includes MIR where all fields were already by index).
(This refactoring actually fixed some bugs in HIR-based borrow checker where borrows through names (`S {
0: ref x }`) and indices (`&s.0`) weren't considered overlapping.)
- The second commit removes all by-name field comparison and instead resolves field references to their indices once, and then uses those resolutions. (There are still a few name comparisons in save-analysis, because save-analysis is weird, but they are made correctly hygienic).
Thus we are fixing a bunch of "secondary" field hygiene bugs (in borrow checker, lints).
Fixes https://github.com/rust-lang/rust/issues/46314
This commit is contained in:
commit
defcfe7142
87 changed files with 759 additions and 676 deletions
|
|
@ -7,10 +7,10 @@ LL | let _ = x.foo; //~ ERROR E0609
|
|||
= note: available fields are: `x`
|
||||
|
||||
error[E0609]: no field `1` on type `Bar`
|
||||
--> $DIR/E0609.rs:21:5
|
||||
--> $DIR/E0609.rs:21:7
|
||||
|
|
||||
LL | y.1; //~ ERROR E0609
|
||||
| ^^^
|
||||
| ^ unknown field
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +0,0 @@
|
|||
error[E0611]: field `0` of tuple-struct `a::Foo` is private
|
||||
--> $DIR/E0611.rs:21:4
|
||||
|
|
||||
LL | y.0; //~ ERROR E0611
|
||||
| ^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0611`.
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
error[E0612]: attempted out-of-bounds tuple index `1` on type `Foo`
|
||||
--> $DIR/E0612.rs:15:4
|
||||
|
|
||||
LL | y.1; //~ ERROR E0612
|
||||
| ^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0612`.
|
||||
|
|
@ -18,5 +18,5 @@ mod a {
|
|||
|
||||
fn main() {
|
||||
let y = a::Foo::new();
|
||||
y.0; //~ ERROR E0611
|
||||
y.0; //~ ERROR field `0` of struct `a::Foo` is private
|
||||
}
|
||||
9
src/test/ui/error-codes/ex-E0611.stderr
Normal file
9
src/test/ui/error-codes/ex-E0611.stderr
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
error[E0616]: field `0` of struct `a::Foo` is private
|
||||
--> $DIR/ex-E0611.rs:21:4
|
||||
|
|
||||
LL | y.0; //~ ERROR field `0` of struct `a::Foo` is private
|
||||
| ^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0616`.
|
||||
|
|
@ -12,5 +12,5 @@ struct Foo(u32);
|
|||
|
||||
fn main() {
|
||||
let y = Foo(0);
|
||||
y.1; //~ ERROR E0612
|
||||
y.1; //~ ERROR no field `1` on type `Foo`
|
||||
}
|
||||
9
src/test/ui/error-codes/ex-E0612.stderr
Normal file
9
src/test/ui/error-codes/ex-E0612.stderr
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
error[E0609]: no field `1` on type `Foo`
|
||||
--> $DIR/ex-E0612.rs:15:6
|
||||
|
|
||||
LL | y.1; //~ ERROR no field `1` on type `Foo`
|
||||
| ^ did you mean `0`?
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0609`.
|
||||
52
src/test/ui/hygiene/assoc_item_ctxt.rs
Normal file
52
src/test/ui/hygiene/assoc_item_ctxt.rs
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <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.
|
||||
|
||||
// ignore-pretty pretty-printing is unhygienic
|
||||
|
||||
#![feature(decl_macro)]
|
||||
#![allow(unused)]
|
||||
|
||||
mod ok {
|
||||
macro mac_trait_item($method: ident) {
|
||||
fn $method();
|
||||
}
|
||||
|
||||
trait Tr {
|
||||
mac_trait_item!(method);
|
||||
}
|
||||
|
||||
macro mac_trait_impl() {
|
||||
impl Tr for u8 { // OK
|
||||
fn method() {} // OK
|
||||
}
|
||||
}
|
||||
|
||||
mac_trait_impl!();
|
||||
}
|
||||
|
||||
mod error {
|
||||
macro mac_trait_item() {
|
||||
fn method();
|
||||
}
|
||||
|
||||
trait Tr {
|
||||
mac_trait_item!();
|
||||
}
|
||||
|
||||
macro mac_trait_impl() {
|
||||
impl Tr for u8 { //~ ERROR not all trait items implemented, missing: `method`
|
||||
fn method() {} //~ ERROR method `method` is not a member of trait `Tr`
|
||||
}
|
||||
}
|
||||
|
||||
mac_trait_impl!();
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
25
src/test/ui/hygiene/assoc_item_ctxt.stderr
Normal file
25
src/test/ui/hygiene/assoc_item_ctxt.stderr
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
error[E0407]: method `method` is not a member of trait `Tr`
|
||||
--> $DIR/assoc_item_ctxt.rs:45:13
|
||||
|
|
||||
LL | fn method() {} //~ ERROR method `method` is not a member of trait `Tr`
|
||||
| ^^^^^^^^^^^^^^ not a member of trait `Tr`
|
||||
...
|
||||
LL | mac_trait_impl!();
|
||||
| ------------------ in this macro invocation
|
||||
|
||||
error[E0046]: not all trait items implemented, missing: `method`
|
||||
--> $DIR/assoc_item_ctxt.rs:44:9
|
||||
|
|
||||
LL | fn method();
|
||||
| ------------ `method` from trait
|
||||
...
|
||||
LL | impl Tr for u8 { //~ ERROR not all trait items implemented, missing: `method`
|
||||
| ^^^^^^^^^^^^^^ missing `method` in implementation
|
||||
...
|
||||
LL | mac_trait_impl!();
|
||||
| ------------------ in this macro invocation
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors occurred: E0046, E0407.
|
||||
For more information about an error, try `rustc --explain E0046`.
|
||||
49
src/test/ui/hygiene/assoc_ty_bindings.rs
Normal file
49
src/test/ui/hygiene/assoc_ty_bindings.rs
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <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.
|
||||
|
||||
// ignore-pretty pretty-printing is unhygienic
|
||||
|
||||
#![feature(decl_macro, associated_type_defaults)]
|
||||
#![feature(rustc_attrs)]
|
||||
|
||||
trait Base {
|
||||
type AssocTy;
|
||||
fn f();
|
||||
}
|
||||
trait Derived: Base {
|
||||
fn g();
|
||||
}
|
||||
|
||||
macro mac() {
|
||||
type A = Base<AssocTy = u8>;
|
||||
type B = Derived<AssocTy = u8>;
|
||||
|
||||
impl Base for u8 {
|
||||
type AssocTy = u8;
|
||||
fn f() {
|
||||
let _: Self::AssocTy;
|
||||
}
|
||||
}
|
||||
impl Derived for u8 {
|
||||
fn g() {
|
||||
let _: Self::AssocTy;
|
||||
}
|
||||
}
|
||||
|
||||
fn h<T: Base, U: Derived>() {
|
||||
let _: T::AssocTy;
|
||||
let _: U::AssocTy;
|
||||
}
|
||||
}
|
||||
|
||||
mac!();
|
||||
|
||||
#[rustc_error]
|
||||
fn main() {} //~ ERROR compilation successful
|
||||
8
src/test/ui/hygiene/assoc_ty_bindings.stderr
Normal file
8
src/test/ui/hygiene/assoc_ty_bindings.stderr
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
error: compilation successful
|
||||
--> $DIR/assoc_ty_bindings.rs:49:1
|
||||
|
|
||||
LL | fn main() {} //~ ERROR compilation successful
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
21
src/test/ui/hygiene/auxiliary/intercrate.rs
Normal file
21
src/test/ui/hygiene/auxiliary/intercrate.rs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <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.
|
||||
|
||||
#![feature(decl_macro)]
|
||||
|
||||
pub mod foo {
|
||||
pub use self::bar::m;
|
||||
mod bar {
|
||||
fn f() -> u32 { 1 }
|
||||
pub macro m() {
|
||||
f();
|
||||
}
|
||||
}
|
||||
}
|
||||
32
src/test/ui/hygiene/fields-definition.rs
Normal file
32
src/test/ui/hygiene/fields-definition.rs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
// Copyright 2018 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.
|
||||
|
||||
#![feature(decl_macro)]
|
||||
|
||||
macro modern($a: ident) {
|
||||
struct Modern {
|
||||
a: u8,
|
||||
$a: u8, // OK
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! legacy {
|
||||
($a: ident) => {
|
||||
struct Legacy {
|
||||
a: u8,
|
||||
$a: u8, //~ ERROR field `a` is already declared
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
modern!(a);
|
||||
legacy!(a);
|
||||
|
||||
fn main() {}
|
||||
14
src/test/ui/hygiene/fields-definition.stderr
Normal file
14
src/test/ui/hygiene/fields-definition.stderr
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
error[E0124]: field `a` is already declared
|
||||
--> $DIR/fields-definition.rs:24:17
|
||||
|
|
||||
LL | a: u8,
|
||||
| ----- `a` first declared here
|
||||
LL | $a: u8, //~ ERROR field `a` is already declared
|
||||
| ^^ field already declared
|
||||
...
|
||||
LL | legacy!(a);
|
||||
| ----------- in this macro invocation
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0124`.
|
||||
40
src/test/ui/hygiene/fields-move.rs
Normal file
40
src/test/ui/hygiene/fields-move.rs
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
// Copyright 2018 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.
|
||||
|
||||
// issue #46314
|
||||
|
||||
#![feature(decl_macro)]
|
||||
|
||||
#[derive(Debug)]
|
||||
struct NonCopy(String);
|
||||
|
||||
struct Foo {
|
||||
x: NonCopy,
|
||||
}
|
||||
|
||||
macro copy_modern($foo: ident) {
|
||||
$foo.x
|
||||
}
|
||||
|
||||
macro_rules! copy_legacy {
|
||||
($foo: ident) => {
|
||||
$foo.x //~ ERROR use of moved value: `foo.x`
|
||||
}
|
||||
}
|
||||
|
||||
fn assert_two_copies(a: NonCopy, b: NonCopy) {
|
||||
println!("Got two copies: {:?}, {:?}", a, b);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let foo = Foo { x: NonCopy("foo".into()) };
|
||||
assert_two_copies(copy_modern!(foo), foo.x); //~ ERROR use of moved value: `foo.x`
|
||||
assert_two_copies(copy_legacy!(foo), foo.x); //~ ERROR use of moved value: `foo.x`
|
||||
}
|
||||
39
src/test/ui/hygiene/fields-move.stderr
Normal file
39
src/test/ui/hygiene/fields-move.stderr
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
error[E0382]: use of moved value: `foo.x`
|
||||
--> $DIR/fields-move.rs:38:42
|
||||
|
|
||||
LL | $foo.x
|
||||
| ------ value moved here
|
||||
...
|
||||
LL | assert_two_copies(copy_modern!(foo), foo.x); //~ ERROR use of moved value: `foo.x`
|
||||
| ^^^^^ value used here after move
|
||||
|
|
||||
= note: move occurs because `foo.x` has type `NonCopy`, which does not implement the `Copy` trait
|
||||
|
||||
error[E0382]: use of moved value: `foo.x`
|
||||
--> $DIR/fields-move.rs:28:9
|
||||
|
|
||||
LL | $foo.x
|
||||
| ------ value moved here
|
||||
...
|
||||
LL | $foo.x //~ ERROR use of moved value: `foo.x`
|
||||
| ^^^^^^ value used here after move
|
||||
...
|
||||
LL | assert_two_copies(copy_legacy!(foo), foo.x); //~ ERROR use of moved value: `foo.x`
|
||||
| ----------------- in this macro invocation
|
||||
|
|
||||
= note: move occurs because `foo.x` has type `NonCopy`, which does not implement the `Copy` trait
|
||||
|
||||
error[E0382]: use of moved value: `foo.x`
|
||||
--> $DIR/fields-move.rs:39:42
|
||||
|
|
||||
LL | $foo.x
|
||||
| ------ value moved here
|
||||
...
|
||||
LL | assert_two_copies(copy_legacy!(foo), foo.x); //~ ERROR use of moved value: `foo.x`
|
||||
| ^^^^^ value used here after move
|
||||
|
|
||||
= note: move occurs because `foo.x` has type `NonCopy`, which does not implement the `Copy` trait
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0382`.
|
||||
18
src/test/ui/hygiene/fields-numeric-borrowck.rs
Normal file
18
src/test/ui/hygiene/fields-numeric-borrowck.rs
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
// Copyright 2018 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.
|
||||
|
||||
struct S(u8);
|
||||
|
||||
fn main() {
|
||||
let mut s = S(0);
|
||||
let borrow1 = &mut s.0;
|
||||
let S { 0: ref mut borrow2 } = s;
|
||||
//~^ ERROR cannot borrow `s.0` as mutable more than once at a time
|
||||
}
|
||||
14
src/test/ui/hygiene/fields-numeric-borrowck.stderr
Normal file
14
src/test/ui/hygiene/fields-numeric-borrowck.stderr
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
error[E0499]: cannot borrow `s.0` as mutable more than once at a time
|
||||
--> $DIR/fields-numeric-borrowck.rs:16:16
|
||||
|
|
||||
LL | let borrow1 = &mut s.0;
|
||||
| --- first mutable borrow occurs here
|
||||
LL | let S { 0: ref mut borrow2 } = s;
|
||||
| ^^^^^^^^^^^^^^^ second mutable borrow occurs here
|
||||
LL | //~^ ERROR cannot borrow `s.0` as mutable more than once at a time
|
||||
LL | }
|
||||
| - first borrow ends here
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0499`.
|
||||
40
src/test/ui/hygiene/fields.rs
Normal file
40
src/test/ui/hygiene/fields.rs
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <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.
|
||||
|
||||
// ignore-pretty pretty-printing is unhygienic
|
||||
|
||||
#![feature(decl_macro)]
|
||||
|
||||
mod foo {
|
||||
struct S { x: u32 }
|
||||
struct T(u32);
|
||||
|
||||
pub macro m($S:ident, $x:ident) {{
|
||||
struct $S {
|
||||
$x: u32,
|
||||
x: i32,
|
||||
}
|
||||
|
||||
let s = S { x: 0 }; //~ ERROR type `foo::S` is private
|
||||
let _ = s.x; //~ ERROR type `foo::S` is private
|
||||
|
||||
let t = T(0); //~ ERROR type `foo::T` is private
|
||||
let _ = t.0; //~ ERROR type `foo::T` is private
|
||||
|
||||
let s = $S { $x: 0, x: 1 };
|
||||
assert_eq!((s.$x, s.x), (0, 1));
|
||||
s
|
||||
}}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let s = foo::m!(S, x);
|
||||
assert_eq!(s.x, 0);
|
||||
}
|
||||
38
src/test/ui/hygiene/fields.stderr
Normal file
38
src/test/ui/hygiene/fields.stderr
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
error: type `foo::S` is private
|
||||
--> $DIR/fields.rs:25:17
|
||||
|
|
||||
LL | let s = S { x: 0 }; //~ ERROR type `foo::S` is private
|
||||
| ^^^^^^^^^^
|
||||
...
|
||||
LL | let s = foo::m!(S, x);
|
||||
| ------------- in this macro invocation
|
||||
|
||||
error: type `foo::S` is private
|
||||
--> $DIR/fields.rs:26:17
|
||||
|
|
||||
LL | let _ = s.x; //~ ERROR type `foo::S` is private
|
||||
| ^
|
||||
...
|
||||
LL | let s = foo::m!(S, x);
|
||||
| ------------- in this macro invocation
|
||||
|
||||
error: type `foo::T` is private
|
||||
--> $DIR/fields.rs:28:17
|
||||
|
|
||||
LL | let t = T(0); //~ ERROR type `foo::T` is private
|
||||
| ^^^^
|
||||
...
|
||||
LL | let s = foo::m!(S, x);
|
||||
| ------------- in this macro invocation
|
||||
|
||||
error: type `foo::T` is private
|
||||
--> $DIR/fields.rs:29:17
|
||||
|
|
||||
LL | let _ = t.0; //~ ERROR type `foo::T` is private
|
||||
| ^
|
||||
...
|
||||
LL | let s = foo::m!(S, x);
|
||||
| ------------- in this macro invocation
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
18
src/test/ui/hygiene/for-loop.rs
Normal file
18
src/test/ui/hygiene/for-loop.rs
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
// Copyright 2014 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.
|
||||
|
||||
// for-loops are expanded in the front end, and use an `iter` ident in their expansion. Check that
|
||||
// `iter` is not accessible inside the for loop.
|
||||
|
||||
fn main() {
|
||||
for _ in 0..10 {
|
||||
iter.next(); //~ ERROR cannot find value `iter` in this scope
|
||||
}
|
||||
}
|
||||
9
src/test/ui/hygiene/for-loop.stderr
Normal file
9
src/test/ui/hygiene/for-loop.stderr
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
error[E0425]: cannot find value `iter` in this scope
|
||||
--> $DIR/for-loop.rs:16:9
|
||||
|
|
||||
LL | iter.next(); //~ ERROR cannot find value `iter` in this scope
|
||||
| ^^^^ not found in this scope
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0425`.
|
||||
68
src/test/ui/hygiene/globs.rs
Normal file
68
src/test/ui/hygiene/globs.rs
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <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.
|
||||
|
||||
#![feature(decl_macro)]
|
||||
|
||||
mod foo {
|
||||
pub fn f() {}
|
||||
}
|
||||
|
||||
mod bar {
|
||||
pub fn g() {}
|
||||
}
|
||||
|
||||
macro m($($t:tt)*) {
|
||||
$($t)*
|
||||
use foo::*;
|
||||
f();
|
||||
g(); //~ ERROR cannot find function `g` in this scope
|
||||
}
|
||||
|
||||
fn main() {
|
||||
m! {
|
||||
use bar::*;
|
||||
g();
|
||||
f(); //~ ERROR cannot find function `f` in this scope
|
||||
}
|
||||
}
|
||||
|
||||
n!(f);
|
||||
macro n($i:ident) {
|
||||
mod foo {
|
||||
pub fn $i() -> u32 { 0 }
|
||||
pub fn f() {}
|
||||
|
||||
mod test {
|
||||
use super::*;
|
||||
fn g() {
|
||||
let _: u32 = $i();
|
||||
let _: () = f();
|
||||
}
|
||||
}
|
||||
|
||||
macro n($j:ident) {
|
||||
mod test {
|
||||
use super::*;
|
||||
fn g() {
|
||||
let _: u32 = $i();
|
||||
let _: () = f();
|
||||
$j();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
n!(f);
|
||||
mod test2 {
|
||||
super::n! {
|
||||
f //~ ERROR cannot find function `f` in this scope
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
49
src/test/ui/hygiene/globs.stderr
Normal file
49
src/test/ui/hygiene/globs.stderr
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
error[E0425]: cannot find function `f` in this scope
|
||||
--> $DIR/globs.rs:32:9
|
||||
|
|
||||
LL | f(); //~ ERROR cannot find function `f` in this scope
|
||||
| ^ not found in this scope
|
||||
help: possible candidates are found in other modules, you can import them into scope
|
||||
|
|
||||
LL | use foo::f;
|
||||
|
|
||||
LL | use foo::f;
|
||||
|
|
||||
LL | use foo::f;
|
||||
|
|
||||
|
||||
error[E0425]: cannot find function `g` in this scope
|
||||
--> $DIR/globs.rs:25:5
|
||||
|
|
||||
LL | g(); //~ ERROR cannot find function `g` in this scope
|
||||
| ^ not found in this scope
|
||||
...
|
||||
LL | / m! {
|
||||
LL | | use bar::*;
|
||||
LL | | g();
|
||||
LL | | f(); //~ ERROR cannot find function `f` in this scope
|
||||
LL | | }
|
||||
| |_____- in this macro invocation
|
||||
help: possible candidates are found in other modules, you can import them into scope
|
||||
|
|
||||
LL | use bar::g;
|
||||
|
|
||||
LL | use foo::test2::test::g;
|
||||
|
|
||||
LL | use foo::test::g;
|
||||
|
|
||||
LL | use foo::test::g;
|
||||
|
|
||||
|
||||
error[E0425]: cannot find function `f` in this scope
|
||||
--> $DIR/globs.rs:64:17
|
||||
|
|
||||
LL | n!(f);
|
||||
| ------ in this macro invocation
|
||||
...
|
||||
LL | f //~ ERROR cannot find function `f` in this scope
|
||||
| ^ not found in this scope
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0425`.
|
||||
44
src/test/ui/hygiene/impl_items.rs
Normal file
44
src/test/ui/hygiene/impl_items.rs
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <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.
|
||||
|
||||
// ignore-pretty pretty-printing is unhygienic
|
||||
|
||||
#![feature(decl_macro)]
|
||||
|
||||
mod foo {
|
||||
struct S;
|
||||
impl S {
|
||||
fn f(&self) {}
|
||||
}
|
||||
|
||||
pub macro m() {
|
||||
let _: () = S.f(); //~ ERROR type `for<'r> fn(&'r foo::S) {foo::S::f}` is private
|
||||
}
|
||||
}
|
||||
|
||||
struct S;
|
||||
|
||||
macro m($f:ident) {
|
||||
impl S {
|
||||
fn f(&self) -> u32 { 0 }
|
||||
fn $f(&self) -> i32 { 0 }
|
||||
}
|
||||
fn f() {
|
||||
let _: u32 = S.f();
|
||||
let _: i32 = S.$f();
|
||||
}
|
||||
}
|
||||
|
||||
m!(f);
|
||||
|
||||
fn main() {
|
||||
let _: i32 = S.f();
|
||||
foo::m!();
|
||||
}
|
||||
11
src/test/ui/hygiene/impl_items.stderr
Normal file
11
src/test/ui/hygiene/impl_items.stderr
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
error: type `for<'r> fn(&'r foo::S) {foo::S::f}` is private
|
||||
--> $DIR/impl_items.rs:22:23
|
||||
|
|
||||
LL | let _: () = S.f(); //~ ERROR type `for<'r> fn(&'r foo::S) {foo::S::f}` is private
|
||||
| ^
|
||||
...
|
||||
LL | foo::m!();
|
||||
| ---------- in this macro invocation
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
23
src/test/ui/hygiene/intercrate.rs
Normal file
23
src/test/ui/hygiene/intercrate.rs
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <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.
|
||||
|
||||
// ignore-pretty pretty-printing is unhygienic
|
||||
|
||||
// aux-build:intercrate.rs
|
||||
|
||||
// error-pattern:type `fn() -> u32 {intercrate::foo::bar::f}` is private
|
||||
|
||||
#![feature(decl_macro)]
|
||||
|
||||
extern crate intercrate;
|
||||
|
||||
fn main() {
|
||||
assert_eq!(intercrate::foo::m!(), 1);
|
||||
}
|
||||
10
src/test/ui/hygiene/intercrate.stderr
Normal file
10
src/test/ui/hygiene/intercrate.stderr
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
error: type `fn() -> u32 {intercrate::foo::bar::f}` is private
|
||||
--> $DIR/intercrate.rs:22:16
|
||||
|
|
||||
LL | assert_eq!(intercrate::foo::m!(), 1);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
27
src/test/ui/hygiene/nested_macro_privacy.rs
Normal file
27
src/test/ui/hygiene/nested_macro_privacy.rs
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <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.
|
||||
|
||||
#![feature(decl_macro)]
|
||||
|
||||
macro n($foo:ident, $S:ident, $i:ident, $m:ident) {
|
||||
mod $foo {
|
||||
#[derive(Default)]
|
||||
pub struct $S { $i: u32 }
|
||||
pub macro $m($e:expr) { $e.$i }
|
||||
}
|
||||
}
|
||||
|
||||
n!(foo, S, i, m);
|
||||
|
||||
fn main() {
|
||||
use foo::{S, m};
|
||||
S::default().i; //~ ERROR field `i` of struct `foo::S` is private
|
||||
m!(S::default()); // ok
|
||||
}
|
||||
9
src/test/ui/hygiene/nested_macro_privacy.stderr
Normal file
9
src/test/ui/hygiene/nested_macro_privacy.stderr
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
error[E0616]: field `i` of struct `foo::S` is private
|
||||
--> $DIR/nested_macro_privacy.rs:25:5
|
||||
|
|
||||
LL | S::default().i; //~ ERROR field `i` of struct `foo::S` is private
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0616`.
|
||||
25
src/test/ui/hygiene/no_implicit_prelude.rs
Normal file
25
src/test/ui/hygiene/no_implicit_prelude.rs
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <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.
|
||||
|
||||
#![feature(decl_macro)]
|
||||
|
||||
mod foo {
|
||||
pub macro m() { Vec::new(); ().clone() }
|
||||
fn f() { ::bar::m!(); }
|
||||
}
|
||||
|
||||
#[no_implicit_prelude]
|
||||
mod bar {
|
||||
pub macro m() {
|
||||
Vec::new(); //~ ERROR failed to resolve
|
||||
().clone() //~ ERROR no method named `clone` found
|
||||
}
|
||||
fn f() { ::foo::m!(); }
|
||||
}
|
||||
30
src/test/ui/hygiene/no_implicit_prelude.stderr
Normal file
30
src/test/ui/hygiene/no_implicit_prelude.stderr
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
error[E0433]: failed to resolve. Use of undeclared type or module `Vec`
|
||||
--> $DIR/no_implicit_prelude.rs:21:9
|
||||
|
|
||||
LL | fn f() { ::bar::m!(); }
|
||||
| ------------ in this macro invocation
|
||||
...
|
||||
LL | Vec::new(); //~ ERROR failed to resolve
|
||||
| ^^^ Use of undeclared type or module `Vec`
|
||||
|
||||
error[E0601]: `main` function not found in crate `no_implicit_prelude`
|
||||
|
|
||||
= note: consider adding a `main` function to `$DIR/no_implicit_prelude.rs`
|
||||
|
||||
error[E0599]: no method named `clone` found for type `()` in the current scope
|
||||
--> $DIR/no_implicit_prelude.rs:22:12
|
||||
|
|
||||
LL | fn f() { ::bar::m!(); }
|
||||
| ------------ in this macro invocation
|
||||
...
|
||||
LL | ().clone() //~ ERROR no method named `clone` found
|
||||
| ^^^^^
|
||||
|
|
||||
= help: items from traits can only be used if the trait is in scope
|
||||
= note: the following trait is implemented but not in scope, perhaps add a `use` for it:
|
||||
candidate #1: `use std::clone::Clone;`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
Some errors occurred: E0433, E0599, E0601.
|
||||
For more information about an error, try `rustc --explain E0433`.
|
||||
16
src/test/ui/hygiene/pattern-macro.rs
Normal file
16
src/test/ui/hygiene/pattern-macro.rs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
// Copyright 2014 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.
|
||||
|
||||
macro_rules! foo { () => ( x ) }
|
||||
|
||||
fn main() {
|
||||
let foo!() = 2;
|
||||
x + 1; //~ ERROR cannot find value `x` in this scope
|
||||
}
|
||||
9
src/test/ui/hygiene/pattern-macro.stderr
Normal file
9
src/test/ui/hygiene/pattern-macro.stderr
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
error[E0425]: cannot find value `x` in this scope
|
||||
--> $DIR/pattern-macro.rs:15:5
|
||||
|
|
||||
LL | x + 1; //~ ERROR cannot find value `x` in this scope
|
||||
| ^ not found in this scope
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0425`.
|
||||
28
src/test/ui/hygiene/privacy.rs
Normal file
28
src/test/ui/hygiene/privacy.rs
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <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.
|
||||
|
||||
#![feature(decl_macro)]
|
||||
|
||||
mod foo {
|
||||
fn f() {}
|
||||
|
||||
pub macro m($e:expr) {
|
||||
f();
|
||||
self::f();
|
||||
::foo::f();
|
||||
$e
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
foo::m!(
|
||||
foo::f() //~ ERROR `f` is private
|
||||
);
|
||||
}
|
||||
9
src/test/ui/hygiene/privacy.stderr
Normal file
9
src/test/ui/hygiene/privacy.stderr
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
error[E0603]: function `f` is private
|
||||
--> $DIR/privacy.rs:26:9
|
||||
|
|
||||
LL | foo::f() //~ ERROR `f` is private
|
||||
| ^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0603`.
|
||||
31
src/test/ui/hygiene/trait_items.rs
Normal file
31
src/test/ui/hygiene/trait_items.rs
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <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.
|
||||
|
||||
#![feature(decl_macro)]
|
||||
|
||||
mod foo {
|
||||
pub trait T {
|
||||
fn f(&self) {}
|
||||
}
|
||||
impl T for () {}
|
||||
}
|
||||
|
||||
mod bar {
|
||||
use foo::*;
|
||||
pub macro m() { ().f() }
|
||||
fn f() { ::baz::m!(); }
|
||||
}
|
||||
|
||||
mod baz {
|
||||
pub macro m() { ().f() } //~ ERROR no method named `f` found for type `()` in the current scope
|
||||
fn f() { ::bar::m!(); }
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
16
src/test/ui/hygiene/trait_items.stderr
Normal file
16
src/test/ui/hygiene/trait_items.stderr
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
error[E0599]: no method named `f` found for type `()` in the current scope
|
||||
--> $DIR/trait_items.rs:27:24
|
||||
|
|
||||
LL | fn f() { ::baz::m!(); }
|
||||
| ------------ in this macro invocation
|
||||
...
|
||||
LL | pub macro m() { ().f() } //~ ERROR no method named `f` found for type `()` in the current scope
|
||||
| ^
|
||||
|
|
||||
= help: items from traits can only be used if the trait is in scope
|
||||
= note: the following trait is implemented but not in scope, perhaps add a `use` for it:
|
||||
candidate #1: `use foo::T;`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0599`.
|
||||
|
|
@ -16,7 +16,7 @@ struct Verdict(Guilty, Option<FineDollars>);
|
|||
fn main() {
|
||||
let justice = Verdict(true, Some(2718));
|
||||
let _condemned = justice.00;
|
||||
//~^ ERROR invalid tuple or struct index
|
||||
//~^ ERROR no field `00` on type `Verdict`
|
||||
let _punishment = justice.001;
|
||||
//~^ ERROR invalid tuple or struct index
|
||||
//~^ ERROR no field `001` on type `Verdict`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,17 @@
|
|||
error: invalid tuple or struct index
|
||||
error[E0609]: no field `00` on type `Verdict`
|
||||
--> $DIR/issue-47073-zero-padded-tuple-struct-indices.rs:18:30
|
||||
|
|
||||
LL | let _condemned = justice.00;
|
||||
| ^^ help: try simplifying the index: `0`
|
||||
| ^^ did you mean `0`?
|
||||
|
||||
error: invalid tuple or struct index
|
||||
error[E0609]: no field `001` on type `Verdict`
|
||||
--> $DIR/issue-47073-zero-padded-tuple-struct-indices.rs:20:31
|
||||
|
|
||||
LL | let _punishment = justice.001;
|
||||
| ^^^ help: try simplifying the index: `1`
|
||||
| ^^^ unknown field
|
||||
|
|
||||
= note: available fields are: `0`, `1`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0609`.
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ macro_rules! fake_field_stmt {
|
|||
|
||||
macro_rules! fake_anon_field_stmt {
|
||||
() => {
|
||||
(1).0 //~ ERROR no field
|
||||
(1).0 //~ ERROR doesn't have fields
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -42,7 +42,7 @@ macro_rules! fake_field_expr {
|
|||
|
||||
macro_rules! fake_anon_field_expr {
|
||||
() => {
|
||||
(1).0 //~ ERROR no field
|
||||
(1).0 //~ ERROR doesn't have fields
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,11 +16,11 @@ LL | 1.fake //~ ERROR doesn't have fields
|
|||
LL | fake_field_stmt!();
|
||||
| ------------------- in this macro invocation
|
||||
|
||||
error[E0609]: no field `0` on type `{integer}`
|
||||
--> $DIR/macro-backtrace-invalid-internals.rs:27:11
|
||||
error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields
|
||||
--> $DIR/macro-backtrace-invalid-internals.rs:27:15
|
||||
|
|
||||
LL | (1).0 //~ ERROR no field
|
||||
| ^^^^^
|
||||
LL | (1).0 //~ ERROR doesn't have fields
|
||||
| ^
|
||||
...
|
||||
LL | fake_anon_field_stmt!();
|
||||
| ------------------------ in this macro invocation
|
||||
|
|
@ -56,11 +56,11 @@ LL | 1.fake //~ ERROR doesn't have fields
|
|||
LL | let _ = fake_field_expr!();
|
||||
| ------------------ in this macro invocation
|
||||
|
||||
error[E0609]: no field `0` on type `{integer}`
|
||||
--> $DIR/macro-backtrace-invalid-internals.rs:45:11
|
||||
error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields
|
||||
--> $DIR/macro-backtrace-invalid-internals.rs:45:15
|
||||
|
|
||||
LL | (1).0 //~ ERROR no field
|
||||
| ^^^^^
|
||||
LL | (1).0 //~ ERROR doesn't have fields
|
||||
| ^
|
||||
...
|
||||
LL | let _ = fake_anon_field_expr!();
|
||||
| ----------------------- in this macro invocation
|
||||
|
|
@ -80,5 +80,5 @@ LL | 2.0_f32.powi(2) //~ ERROR can't call method `powi` on ambiguous n
|
|||
|
||||
error: aborting due to 8 previous errors
|
||||
|
||||
Some errors occurred: E0599, E0609, E0610, E0689.
|
||||
Some errors occurred: E0599, E0610, E0689.
|
||||
For more information about an error, try `rustc --explain E0599`.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue