diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 7cfd5b5f861a4..30ed9cf1f54fe 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -1823,6 +1823,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { "too many leading `super` keywords".to_string(), "there are too many leading `super` keywords".to_string(), None, + None, ) }, ); @@ -1889,7 +1890,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { "can only be used in path start position".to_string(), ) }; - (message, label, None) + (message, label, None, None) }, ); } @@ -2000,10 +2001,28 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { module_had_parse_errors, module, || { + let import_inherent_item_error_flag = + self.tcx.features().import_trait_associated_functions() + && matches!( + res, + Res::Def( + DefKind::Struct + | DefKind::Enum + | DefKind::Union + | DefKind::ForeignTy, + _ + ) + ); + // Show a different error message for items that can have associated items. let label = format!( - "`{ident}` is {} {}, not a module", + "`{ident}` is {} {}, not a module{}", res.article(), - res.descr() + res.descr(), + if import_inherent_item_error_flag { + " or a trait" + } else { + "" + } ); let scope = match &path[..segment_idx] { [.., prev] => { @@ -2018,7 +2037,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // FIXME: reword, as the reason we expected a module is because of // the following path segment. let message = format!("cannot find module `{ident}` in {scope}"); - (message, label, None) + let note = if import_inherent_item_error_flag { + Some( + "cannot import inherent associated items, only trait associated items".to_string(), + ) + } else { + None + }; + (message, label, None, note) }, ); } @@ -2043,18 +2069,20 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { module_had_parse_errors, module, || { - this.get_mut().report_path_resolution_error( - path, - opt_ns, - parent_scope, - ribs, - ignore_decl, - ignore_import, - module, - segment_idx, - ident, - diag_metadata, - ) + let (message, label, suggestion) = + this.get_mut().report_path_resolution_error( + path, + opt_ns, + parent_scope, + ribs, + ignore_decl, + ignore_import, + module, + segment_idx, + ident, + diag_metadata, + ); + (message, label, suggestion, None) }, ); } diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 704c316bce650..0c12fc8c39f01 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -1046,6 +1046,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { module, error_implied_by_parse_error: _, message, + note: _, } => { if no_ambiguity { assert!(import.imported_module.get().is_none()); @@ -1069,6 +1070,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { suggestion, module, segment_name, + note, .. } => { if no_ambiguity { @@ -1097,7 +1099,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { None => UnresolvedImportError { span, label: Some(label), - note: None, + note, suggestion, candidates: None, segment: Some(segment_name), @@ -1325,6 +1327,20 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { _ => (lev_suggestion, None), }; + // If importing of trait asscoiated items is enabled, an also find an + // `Enum`, then note that inherent associated items cannot be imported. + let note = if self.tcx.features().import_trait_associated_functions() + && let PathResult::Module(ModuleOrUniformRoot::Module(m)) = path_res + && let Some(Res::Def(DefKind::Enum, _)) = m.res() + { + note.or(Some( + "cannot import inherent associated items, only trait associated items" + .to_string(), + )) + } else { + note + }; + let label = match module { ModuleOrUniformRoot::Module(module) => { let module_str = module_to_string(module); diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index f72abaa37201e..3dee227b97986 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -4891,6 +4891,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { segment_name, error_implied_by_parse_error: _, message, + note: _, } => { return Err(respan( span, diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index b88227264537f..5f2d4e2370839 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -478,6 +478,7 @@ enum PathResult<'ra> { segment_name: Symbol, error_implied_by_parse_error: bool, message: String, + note: Option, }, } @@ -488,13 +489,18 @@ impl<'ra> PathResult<'ra> { finalize: bool, error_implied_by_parse_error: bool, module: Option>, - label_and_suggestion: impl FnOnce() -> (String, String, Option), + label_and_suggestion_and_note: impl FnOnce() -> ( + String, + String, + Option, + Option, + ), ) -> PathResult<'ra> { - let (message, label, suggestion) = if finalize { - label_and_suggestion() + let (message, label, suggestion, note) = if finalize { + label_and_suggestion_and_note() } else { // FIXME: this output isn't actually present in the test suite. - (format!("cannot find `{ident}` in this scope"), String::new(), None) + (format!("cannot find `{ident}` in this scope"), String::new(), None, None) }; PathResult::Failed { span: ident.span, @@ -505,6 +511,7 @@ impl<'ra> PathResult<'ra> { module, error_implied_by_parse_error, message, + note, } } } diff --git a/tests/ui/imports/import-inherent-148009.rs b/tests/ui/imports/import-inherent-148009.rs new file mode 100644 index 0000000000000..81d176ca182c5 --- /dev/null +++ b/tests/ui/imports/import-inherent-148009.rs @@ -0,0 +1,68 @@ +//! Check that when the feature `import_trait_associated_functions` is enabled, +//! and one trys to import inherent associated items, the error message is +//! updated to reflect that only trait associated items can be imported. +//! +//! Regression test for . + +//@ check-fail + +#![feature(import_trait_associated_functions, extern_types)] + +pub struct TestStruct; + +impl TestStruct { + pub fn m1() {} + pub const C1: usize = 0; +} + +pub use self::TestStruct::{C1, m1}; +//~^ ERROR unresolved import `self::TestStruct` [E0432] +//~| NOTE `TestStruct` is a struct, not a module or a trait +//~| NOTE cannot import inherent associated items, only trait associated items + +pub union TestUnion { + pub f: f32, + pub i: i32, +} + +impl TestUnion { + pub fn m2() {} + pub const C2: usize = 0; +} + +pub use self::TestUnion::{C2, m2}; +//~^ ERROR unresolved import `self::TestUnion` [E0432] +//~| NOTE `TestUnion` is a union, not a module or a trait +//~| NOTE cannot import inherent associated items, only trait associated items + +pub enum TestEnum { + V1, + V2, +} + +impl TestEnum { + pub fn m3() {} + pub const C3: usize = 0; +} + +pub use self::TestEnum::{C3, m3}; +//~^ ERROR unresolved imports `self::TestEnum::C3`, `self::TestEnum::m3` [E0432] +//~| NOTE no `m3` in `TestEnum` +//~| NOTE no `C3` in `TestEnum` +//~| NOTE cannot import inherent associated items, only trait associated items + +extern "C" { + pub type TestForeignTy; +} + +impl TestForeignTy { + pub fn m4() {} + pub const C4: usize = 0; +} + +pub use self::TestForeignTy::{C4, m4}; +//~^ ERROR unresolved import `self::TestForeignTy` [E0432] +//~| NOTE `TestForeignTy` is a foreign type, not a module or a trait +//~| NOTE cannot import inherent associated items, only trait associated items + +fn main() {} diff --git a/tests/ui/imports/import-inherent-148009.stderr b/tests/ui/imports/import-inherent-148009.stderr new file mode 100644 index 0000000000000..3265a0f54b65c --- /dev/null +++ b/tests/ui/imports/import-inherent-148009.stderr @@ -0,0 +1,37 @@ +error[E0432]: unresolved import `self::TestStruct` + --> $DIR/import-inherent-148009.rs:18:15 + | +LL | pub use self::TestStruct::{C1, m1}; + | ^^^^^^^^^^ `TestStruct` is a struct, not a module or a trait + | + = note: cannot import inherent associated items, only trait associated items + +error[E0432]: unresolved import `self::TestUnion` + --> $DIR/import-inherent-148009.rs:33:15 + | +LL | pub use self::TestUnion::{C2, m2}; + | ^^^^^^^^^ `TestUnion` is a union, not a module or a trait + | + = note: cannot import inherent associated items, only trait associated items + +error[E0432]: unresolved imports `self::TestEnum::C3`, `self::TestEnum::m3` + --> $DIR/import-inherent-148009.rs:48:26 + | +LL | pub use self::TestEnum::{C3, m3}; + | ^^ ^^ no `m3` in `TestEnum` + | | + | no `C3` in `TestEnum` + | + = note: cannot import inherent associated items, only trait associated items + +error[E0432]: unresolved import `self::TestForeignTy` + --> $DIR/import-inherent-148009.rs:63:15 + | +LL | pub use self::TestForeignTy::{C4, m4}; + | ^^^^^^^^^^^^^ `TestForeignTy` is a foreign type, not a module or a trait + | + = note: cannot import inherent associated items, only trait associated items + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0432`.