Rollup merge of #152611 - CoCo-Japan-pan:fix-148009, r=jackh726

Modify error message of importing inherent associated items when `#[feature(import_trait_associated_functions)]` is enabled

Fixes rust-lang/rust#148009

This PR improves the diagnostic for importing inherent associated items from a struct or union when
`#[feature(import_trait_associated_functions)]` (rust-lang/rust#134691) is enabled.

Previously, this would result in a "not a module" error. This change provides a more specific error message clarifying that only trait associated items can be imported, while inherent associated items remain ineligible for import.

Enums are currently excluded from this change because their variants are valid import targets and require distinct handling.
This commit is contained in:
Jonathan Brouwer
2026-04-21 16:53:37 +02:00
committed by GitHub
6 changed files with 178 additions and 21 deletions
+44 -16
View File
@@ -1797,6 +1797,7 @@ fn record_segment_res<'r, 'ra, 'tcx>(
"too many leading `super` keywords".to_string(),
"there are too many leading `super` keywords".to_string(),
None,
None,
)
},
);
@@ -1863,7 +1864,7 @@ fn record_segment_res<'r, 'ra, 'tcx>(
"can only be used in path start position".to_string(),
)
};
(message, label, None)
(message, label, None, None)
},
);
}
@@ -1977,10 +1978,28 @@ fn record_segment_res<'r, '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] => {
@@ -1995,7 +2014,14 @@ fn record_segment_res<'r, '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)
},
);
}
@@ -2020,18 +2046,20 @@ fn record_segment_res<'r, '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)
},
);
}
+17 -1
View File
@@ -1134,6 +1134,7 @@ fn finalize_import(&mut self, import: Import<'ra>) -> Option<UnresolvedImportErr
module,
error_implied_by_parse_error: _,
message,
note: _,
} => {
if no_ambiguity {
if !self.issue_145575_hack_applied {
@@ -1159,6 +1160,7 @@ fn finalize_import(&mut self, import: Import<'ra>) -> Option<UnresolvedImportErr
suggestion,
module,
segment_name,
note,
..
} => {
if no_ambiguity {
@@ -1190,7 +1192,7 @@ fn finalize_import(&mut self, import: Import<'ra>) -> Option<UnresolvedImportErr
None => UnresolvedImportError {
span,
label: Some(label),
note: None,
note,
suggestion,
candidates: None,
segment: Some(segment_name),
@@ -1420,6 +1422,20 @@ fn finalize_import(&mut self, import: Import<'ra>) -> Option<UnresolvedImportErr
_ => (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);
+1
View File
@@ -4979,6 +4979,7 @@ fn resolve_qpath(
segment_name,
error_implied_by_parse_error: _,
message,
note: _,
} => {
return Err(respan(
span,
+11 -4
View File
@@ -481,6 +481,7 @@ enum PathResult<'ra> {
segment_name: Symbol,
error_implied_by_parse_error: bool,
message: String,
note: Option<String>,
},
}
@@ -491,13 +492,18 @@ fn failed(
finalize: bool,
error_implied_by_parse_error: bool,
module: Option<ModuleOrUniformRoot<'ra>>,
label_and_suggestion: impl FnOnce() -> (String, String, Option<Suggestion>),
label_and_suggestion_and_note: impl FnOnce() -> (
String,
String,
Option<Suggestion>,
Option<String>,
),
) -> 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,
@@ -508,6 +514,7 @@ fn failed(
module,
error_implied_by_parse_error,
message,
note,
}
}
}
@@ -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 <https://github.com/rust-lang/rust/issues/148009>.
//@ 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() {}
@@ -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`.