Skip to content

Commit

Permalink
Auto merge of rust-lang#42614 - GuillaumeGomez:new-error-codes, r=pnk…
Browse files Browse the repository at this point in the history
…felix

New error codes

Part of rust-lang#42229.

cc @Susurrus @frewsxcv @QuietMisdreavus
  • Loading branch information
bors committed Jun 22, 2017
2 parents ab5bec2 + ee60064 commit bd62230
Show file tree
Hide file tree
Showing 11 changed files with 401 additions and 46 deletions.
76 changes: 35 additions & 41 deletions src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2950,8 +2950,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {

if let Some((did, field_ty)) = private_candidate {
let struct_path = self.tcx().item_path_str(did);
let msg = format!("field `{}` of struct `{}` is private", field.node, struct_path);
let mut err = self.tcx().sess.struct_span_err(expr.span, &msg);
let mut err = struct_span_err!(self.tcx().sess, expr.span, E0616,
"field `{}` of struct `{}` is private",
field.node, struct_path);
// Also check if an accessible method exists, which is often what is meant.
if self.method_exists(field.span, field.node, expr_t, expr.id, false) {
err.note(&format!("a method `{}` also exists, perhaps you wish to call it",
Expand All @@ -2962,10 +2963,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
} else if field.node == keywords::Invalid.name() {
self.tcx().types.err
} else if self.method_exists(field.span, field.node, expr_t, expr.id, true) {
self.type_error_struct(field.span, |actual| {
format!("attempted to take value of method `{}` on type \
`{}`", field.node, actual)
}, expr_t)
type_error_struct!(self.tcx().sess, field.span, expr_t, E0615,
"attempted to take value of method `{}` on type `{}`",
field.node, expr_t)
.help("maybe a `()` to call it is missing? \
If not, try an anonymous function")
.emit();
Expand Down Expand Up @@ -3080,27 +3080,22 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {

if let Some((did, field_ty)) = private_candidate {
let struct_path = self.tcx().item_path_str(did);
let msg = format!("field `{}` of struct `{}` is private", idx.node, struct_path);
self.tcx().sess.span_err(expr.span, &msg);
struct_span_err!(self.tcx().sess, expr.span, E0611,
"field `{}` of tuple-struct `{}` is private",
idx.node, struct_path).emit();
return field_ty;
}

self.type_error_message(
expr.span,
|actual| {
if tuple_like {
format!("attempted out-of-bounds tuple index `{}` on \
type `{}`",
idx.node,
actual)
} else {
format!("attempted tuple index `{}` on type `{}`, but the \
type was not a tuple or tuple struct",
idx.node,
actual)
}
},
expr_t);
if tuple_like {
type_error_struct!(self.tcx().sess, expr.span, expr_t, E0612,
"attempted out-of-bounds tuple index `{}` on type `{}`",
idx.node, expr_t).emit();
} else {
type_error_struct!(self.tcx().sess, expr.span, expr_t, E0613,
"attempted to access tuple index `{}` on type `{}`, but the type \
was not a tuple or tuple struct",
idx.node, expr_t).emit();
}

self.tcx().types.err
}
Expand Down Expand Up @@ -3201,10 +3196,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
field_type_hint = tcx.types.err;
if let Some(_) = variant.find_field_named(field.name.node) {
let mut err = struct_span_err!(self.tcx.sess,
field.name.span,
E0062,
"field `{}` specified more than once",
field.name.node);
field.name.span,
E0062,
"field `{}` specified more than once",
field.name.node);

err.span_label(field.name.span, "used more than once");

Expand Down Expand Up @@ -3251,15 +3246,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
.join(", ");

struct_span_err!(tcx.sess, span, E0063,
"missing field{} {}{} in initializer of `{}`",
if remaining_fields.len() == 1 {""} else {"s"},
remaining_fields_names,
truncated_fields_error,
adt_ty)
.span_label(span, format!("missing {}{}",
remaining_fields_names,
truncated_fields_error))
.emit();
"missing field{} {}{} in initializer of `{}`",
if remaining_fields.len() == 1 { "" } else { "s" },
remaining_fields_names,
truncated_fields_error,
adt_ty)
.span_label(span, format!("missing {}{}",
remaining_fields_names,
truncated_fields_error))
.emit();
}
}

Expand Down Expand Up @@ -3492,10 +3487,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
oprnd_t = self.make_overloaded_lvalue_return_type(method).ty;
self.write_method_call(expr.id, method);
} else {
self.type_error_message(expr.span, |actual| {
format!("type `{}` cannot be \
dereferenced", actual)
}, oprnd_t);
type_error_struct!(tcx.sess, expr.span, oprnd_t, E0614,
"type `{}` cannot be dereferenced",
oprnd_t).emit();
oprnd_t = tcx.types.err;
}
}
Expand Down
247 changes: 247 additions & 0 deletions src/librustc_typeck/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4174,6 +4174,253 @@ println!("x: {}, y: {}", variable.x, variable.y);
For more information see The Rust Book: https://doc.rust-lang.org/book/
"##,

E0611: r##"
Attempted to access a private field on a tuple-struct.
Erroneous code example:
```compile_fail,E0611
mod some_module {
pub struct Foo(u32);
impl Foo {
pub fn new() -> Foo { Foo(0) }
}
}
let y = some_module::Foo::new();
println!("{}", y.0); // error: field `0` of tuple-struct `some_module::Foo`
// is private
```
Since the field is private, you have two solutions:
1) Make the field public:
```
mod some_module {
pub struct Foo(pub u32); // The field is now public.
impl Foo {
pub fn new() -> Foo { Foo(0) }
}
}
let y = some_module::Foo::new();
println!("{}", y.0); // So we can access it directly.
```
2) Add a getter function to keep the field private but allow for accessing its
value:
```
mod some_module {
pub struct Foo(u32);
impl Foo {
pub fn new() -> Foo { Foo(0) }
// We add the getter function.
pub fn get(&self) -> &u32 { &self.0 }
}
}
let y = some_module::Foo::new();
println!("{}", y.get()); // So we can get the value through the function.
```
"##,

E0612: r##"
Attempted out-of-bounds tuple index.
Erroneous code example:
```compile_fail,E0612
struct Foo(u32);
let y = Foo(0);
println!("{}", y.1); // error: attempted out-of-bounds tuple index `1`
// on type `Foo`
```
If a tuple/tuple-struct type has n fields, you can only try to access these n
fields from 0 to (n - 1). So in this case, you can only index `0`. Example:
```
struct Foo(u32);
let y = Foo(0);
println!("{}", y.0); // ok!
```
"##,

E0613: r##"
Attempted tuple index on a type which isn't a tuple nor a tuple-struct.
Erroneous code example:
```compile_fail,E0613
struct Foo;
let y = Foo;
println!("{}", y.1); // error: attempted to access tuple index `1` on type
// `Foo`, but the type was not a tuple or tuple
// struct
```
Only tuple and tuple-struct types can be indexed this way. Example:
```
// Let's create a tuple first:
let x: (u32, u32, u32, u32) = (0, 1, 1, 2);
// You can index its fields this way:
println!("({}, {}, {}, {})", x.0, x.1, x.2, x.3);
// Now let's declare a tuple-struct:
struct TupleStruct(u32, u32, u32, u32);
// Let's instantiate it:
let x = TupleStruct(0, 1, 1, 2);
// And just like the tuple:
println!("({}, {}, {}, {})", x.0, x.1, x.2, x.3);
```
If you want to index into an array, use `[]` instead:
```
let x = &[0, 1, 1, 2];
println!("[{}, {}, {}, {}]", x[0], x[1], x[2], x[3]);
```
If you want to access a field of a struct, check the field's name wasn't
misspelled:
```
struct SomeStruct {
x: u32,
y: i32,
}
let s = SomeStruct {
x: 0,
y: -1,
};
println!("x: {} y: {}", s.x, s.y);
```
"##,

E0614: r##"
Attempted to dereference a variable which cannot be dereferenced.
Erroneous code example:
```compile_fail,E0614
let y = 0u32;
*y; // error: type `u32` cannot be dereferenced
```
Only types implementing `std::ops::Deref` can be dereferenced (such as `&T`).
Example:
```
let y = 0u32;
let x = &y;
// So here, `x` is a `&u32`, so we can dereference it:
*x; // ok!
```
"##,

E0615: r##"
Attempted to access a method like a field.
Erroneous code example:
```compile_fail,E0615
struct Foo {
x: u32,
}
impl Foo {
fn method(&self) {}
}
let f = Foo { x: 0 };
f.method; // error: attempted to take value of method `method` on type `Foo`
```
If you want to use a method, add `()` after it:
```ignore
f.method();
```
However, if you wanted to access a field of a struct check that the field name
is spelled correctly. Example:
```ignore
println!("{}", f.x);
```
"##,

E0616: r##"
Attempted to access a private field on a struct.
Erroneous code example:
```compile_fail,E0616
mod some_module {
pub struct Foo {
x: u32, // So `x` is private in here.
}
impl Foo {
pub fn new() -> Foo { Foo { x: 0 } }
}
}
let f = some_module::Foo::new();
println!("{}", f.x); // error: field `x` of struct `some_module::Foo` is private
```
If you want to access this field, you have two options:
1) Set the field public:
```
mod some_module {
pub struct Foo {
pub x: u32, // `x` is now public.
}
impl Foo {
pub fn new() -> Foo { Foo { x: 0 } }
}
}
let f = some_module::Foo::new();
println!("{}", f.x); // ok!
```
2) Add a getter function:
```
mod some_module {
pub struct Foo {
x: u32, // So `x` is still private in here.
}
impl Foo {
pub fn new() -> Foo { Foo { x: 0 } }
// We create the getter function here:
pub fn get_x(&self) -> &u32 { &self.x }
}
}
let f = some_module::Foo::new();
println!("{}", f.get_x()); // ok!
```
"##,

E0617: r##"
Attempted to pass an invalid type of variable into a variadic function.
Expand Down
22 changes: 22 additions & 0 deletions src/test/compile-fail/E0611.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// 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.

mod a {
pub struct Foo(u32);

impl Foo {
pub fn new() -> Foo { Foo(0) }
}
}

fn main() {
let y = a::Foo::new();
y.0; //~ ERROR E0611
}
Loading

0 comments on commit bd62230

Please sign in to comment.