Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Add E0609 #42585

Merged
merged 2 commits into from
Jun 12, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,24 @@ impl<'tcx> Hash for TyS<'tcx> {
}
}

impl<'tcx> TyS<'tcx> {
pub fn is_primitive_ty(&self) -> bool {
match self.sty {
TypeVariants::TyBool |
TypeVariants::TyChar |
TypeVariants::TyInt(_) |
TypeVariants::TyUint(_) |
TypeVariants::TyFloat(_) |
TypeVariants::TyInfer(InferTy::IntVar(_)) |
TypeVariants::TyInfer(InferTy::FloatVar(_)) |
TypeVariants::TyInfer(InferTy::FreshIntTy(_)) |
TypeVariants::TyInfer(InferTy::FreshFloatTy(_)) => true,
TypeVariants::TyRef(_, x) => x.ty.is_primitive_ty(),
_ => false,
}
}
}

impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ty::TyS<'tcx> {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
Expand Down
50 changes: 27 additions & 23 deletions src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2921,30 +2921,34 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
.emit();
self.tcx().types.err
} else {
let mut err = self.type_error_struct(field.span, |actual| {
format!("no field `{}` on type `{}`",
field.node, actual)
}, expr_t);
match expr_t.sty {
ty::TyAdt(def, _) if !def.is_enum() => {
if let Some(suggested_field_name) =
Self::suggest_field_name(def.struct_variant(), field, vec![]) {
err.span_label(field.span,
format!("did you mean `{}`?", suggested_field_name));
} else {
err.span_label(field.span,
"unknown field");
};
}
ty::TyRawPtr(..) => {
err.note(&format!("`{0}` is a native pointer; perhaps you need to deref with \
`(*{0}).{1}`",
self.tcx.hir.node_to_pretty_string(base.id),
field.node));
if !expr_t.is_primitive_ty() {
let mut err = type_error_struct!(self.tcx().sess, field.span, expr_t, E0609,
"no field `{}` on type `{}`",
field.node, expr_t);
match expr_t.sty {
ty::TyAdt(def, _) if !def.is_enum() => {
if let Some(suggested_field_name) =
Self::suggest_field_name(def.struct_variant(), field, vec![]) {
err.span_label(field.span,
format!("did you mean `{}`?", suggested_field_name));
} else {
err.span_label(field.span, "unknown field");
};
}
ty::TyRawPtr(..) => {
err.note(&format!("`{0}` is a native pointer; perhaps you need to deref \
with `(*{0}).{1}`",
self.tcx.hir.node_to_pretty_string(base.id),
field.node));
}
_ => {}
}
_ => {}
}
err.emit();
err
} else {
type_error_struct!(self.tcx().sess, field.span, expr_t, E0610,
"`{}` is a primitive type and therefore doesn't have fields",
expr_t)
}.emit();
self.tcx().types.err
}
}
Expand Down
57 changes: 57 additions & 0 deletions src/librustc_typeck/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4095,6 +4095,63 @@ assert_eq!(!Question::No, true);
```
"##,

E0609: r##"
Attempted to access a non-existent field in a struct.

Erroneous code example:

```compile_fail,E0609
struct StructWithFields {
x: u32,
}

let s = StructWithFields { x: 0 };
println!("{}", s.foo); // error: no field `foo` on type `StructWithFields`
```

To fix this error, check that you didn't misspell the field's name or that the
field actually exists. Example:

```
struct StructWithFields {
x: u32,
}

let s = StructWithFields { x: 0 };
println!("{}", s.x); // ok!
```
"##,

E0610: r##"
Attempted to access a field on a primitive type.

Erroneous code example:

```compile_fail,E0610
let x: u32 = 0;
println!("{}", x.foo); // error: `{integer}` is a primitive type, therefore
// doesn't have fields
```

Primitive types are the most basic types available in Rust and don't have
fields. To access data via named fields, struct types are used. Example:

```
// We declare struct called `Foo` containing two fields:
struct Foo {
x: u32,
y: i64,
}

// We create an instance of this struct:
let variable = Foo { x: 0, y: -12 };
// And we can now access its fields:
println!("x: {}, y: {}", variable.x, variable.y);
```

For more information see The Rust Book: https://doc.rust-lang.org/book/
"##,

}

register_diagnostics! {
Expand Down
11 changes: 11 additions & 0 deletions src/libsyntax/diagnostics/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,17 @@ macro_rules! struct_span_err {
})
}

#[macro_export]
macro_rules! type_error_struct {
($session:expr, $span:expr, $typ:expr, $code:ident, $($message:tt)*) => ({
if $typ.references_error() {
$session.diagnostic().struct_dummy()
} else {
struct_span_err!($session, $span, $code, $($message)*)
}
})
}

#[macro_export]
macro_rules! struct_span_warn {
($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
Expand Down
18 changes: 18 additions & 0 deletions src/test/compile-fail/E0609.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// 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.

struct Foo {
x: u32,
}

fn main() {
let x = Foo { x: 0 };
let _ = x.foo; //~ ERROR E0609
}
14 changes: 14 additions & 0 deletions src/test/compile-fail/E0610.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// 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.

fn main() {
let x = 0;
let _ = x.foo; //~ ERROR E0610
}
4 changes: 2 additions & 2 deletions src/test/compile-fail/attempted-access-non-fatal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@
// Check that bogus field access is non-fatal
fn main() {
let x = 0;
let _ = x.foo; //~ no field `foo` on type `{integer}`
let _ = x.bar; //~ no field `bar` on type `{integer}`
let _ = x.foo; //~ `{integer}` is a primitive type and therefore doesn't have fields [E0610]
let _ = x.bar; //~ `{integer}` is a primitive type and therefore doesn't have fields [E0610]
}
2 changes: 1 addition & 1 deletion src/test/compile-fail/issue-24363.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
// except according to those terms.

fn main() {
1.create_a_type_error[ //~ no field `create_a_type_error` on type `{integer}`
1.create_a_type_error[ //~ `{integer}` is a primitive type and therefore doesn't have fields
()+() //~ ERROR binary operation `+` cannot be applied
// ^ ensure that we typeck the inner expression ^
];
Expand Down
2 changes: 1 addition & 1 deletion src/test/compile-fail/parse-error-correct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,5 @@ fn main() {
let y = 42;
let x = y.; //~ ERROR unexpected token
let x = y.(); //~ ERROR unexpected token
let x = y.foo; //~ ERROR no field
let x = y.foo; //~ ERROR `{integer}` is a primitive type and therefore doesn't have fields [E061
}
2 changes: 1 addition & 1 deletion src/test/ui/did_you_mean/issue-36798.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error: no field `baz` on type `Foo`
error[E0609]: no field `baz` on type `Foo`
--> $DIR/issue-36798.rs:17:7
|
17 | f.baz;
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/did_you_mean/issue-36798_unknown_field.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error: no field `zz` on type `Foo`
error[E0609]: no field `zz` on type `Foo`
--> $DIR/issue-36798_unknown_field.rs:17:7
|
17 | f.zz;
Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/macros/macro-backtrace-invalid-internals.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ error[E0599]: no method named `fake` found for type `{integer}` in the current s
50 | fake_method_stmt!();
| -------------------- in this macro invocation

error: no field `fake` on type `{integer}`
error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields
--> $DIR/macro-backtrace-invalid-internals.rs:21:13
|
21 | 1.fake
Expand All @@ -34,7 +34,7 @@ error[E0599]: no method named `fake` found for type `{integer}` in the current s
54 | let _ = fake_method_expr!();
| ------------------- in this macro invocation

error: no field `fake` on type `{integer}`
error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields
--> $DIR/macro-backtrace-invalid-internals.rs:39:13
|
39 | 1.fake
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/mismatched_types/cast-rfc0401.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ error: casting `*const U` as `*const str` is invalid
|
= note: vtable kinds may not match

error: no field `f` on type `fn() {main}`
error[E0609]: no field `f` on type `fn() {main}`
--> $DIR/cast-rfc0401.rs:75:18
|
75 | let _ = main.f as *const u32;
Expand Down