diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index afa2da3d561b7..eea767cd868a4 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -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> for ty::TyS<'tcx> { fn hash_stable(&self, hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 9f0ee92930d39..60bf321277cfd 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2921,29 +2921,34 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { .emit(); self.tcx().types.err } else { - 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)); + 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 } } diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 4f1eb929b8e83..6ccfab0a324b6 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -4096,7 +4096,7 @@ assert_eq!(!Question::No, true); "##, E0609: r##" -An attempt to access a non-existent field in a struct was performed. +Attempted to access a non-existent field in a struct. Erroneous code example: @@ -4109,8 +4109,8 @@ let s = StructWithFields { x: 0 }; println!("{}", s.foo); // error: no field `foo` on type `StructWithFields` ``` -To fix this error, check if you didn't misspell the field's name or that the -field actually exist. Example: +To fix this error, check that you didn't misspell the field's name or that the +field actually exists. Example: ``` struct StructWithFields { @@ -4122,6 +4122,36 @@ 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! { diff --git a/src/test/compile-fail/E0610.rs b/src/test/compile-fail/E0610.rs new file mode 100644 index 0000000000000..522d8b0b9438f --- /dev/null +++ b/src/test/compile-fail/E0610.rs @@ -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 or the MIT license +// , 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 +} diff --git a/src/test/compile-fail/attempted-access-non-fatal.rs b/src/test/compile-fail/attempted-access-non-fatal.rs index fe8e793ed781a..3d6c46f5ce3e1 100644 --- a/src/test/compile-fail/attempted-access-non-fatal.rs +++ b/src/test/compile-fail/attempted-access-non-fatal.rs @@ -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] } diff --git a/src/test/compile-fail/issue-24363.rs b/src/test/compile-fail/issue-24363.rs index 03cae6e64ef5e..619ad74ad00e2 100644 --- a/src/test/compile-fail/issue-24363.rs +++ b/src/test/compile-fail/issue-24363.rs @@ -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 ^ ]; diff --git a/src/test/compile-fail/parse-error-correct.rs b/src/test/compile-fail/parse-error-correct.rs index 17b58a9f7c298..7dedfcf27275b 100644 --- a/src/test/compile-fail/parse-error-correct.rs +++ b/src/test/compile-fail/parse-error-correct.rs @@ -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 } diff --git a/src/test/ui/macros/macro-backtrace-invalid-internals.stderr b/src/test/ui/macros/macro-backtrace-invalid-internals.stderr index 9694783b08b94..95db694a0c61f 100644 --- a/src/test/ui/macros/macro-backtrace-invalid-internals.stderr +++ b/src/test/ui/macros/macro-backtrace-invalid-internals.stderr @@ -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[E0609]: 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 @@ -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[E0609]: 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