mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
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:
@@ -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)
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -4979,6 +4979,7 @@ fn resolve_qpath(
|
||||
segment_name,
|
||||
error_implied_by_parse_error: _,
|
||||
message,
|
||||
note: _,
|
||||
} => {
|
||||
return Err(respan(
|
||||
span,
|
||||
|
||||
@@ -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`.
|
||||
Reference in New Issue
Block a user