Suggest function-local constructors without enclosing function path

This commit is contained in:
Haoran Wang
2026-05-25 01:59:27 +08:00
parent 3bf5c6d99b
commit 0276d9f1f4
4 changed files with 225 additions and 3 deletions
@@ -18,7 +18,7 @@
use rustc_hir_analysis::suggest_impl_trait;
use rustc_middle::middle::stability::EvalResult;
use rustc_middle::span_bug;
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::print::{with_no_trimmed_paths, with_types_for_suggestion};
use rustc_middle::ty::{
self, Article, Binder, IsSuggestable, Ty, TyCtxt, TypeVisitableExt, Unnormalized, Upcast,
suggest_constraining_type_params,
@@ -2679,8 +2679,9 @@ pub(crate) fn suggest_compatible_variants(
let sole_field_ty = sole_field.ty(self.tcx, args).skip_norm_wip();
if self.may_coerce(expr_ty, sole_field_ty) {
let variant_path =
with_no_trimmed_paths!(self.tcx.def_path_str(variant.def_id));
let variant_path = with_types_for_suggestion!(with_no_trimmed_paths!(
self.tcx.def_path_str(variant.def_id)
));
// FIXME #56861: DRYer prelude filtering
if let Some(path) = variant_path.strip_prefix("std::prelude::")
&& let Some((_, path)) = path.split_once("::")
@@ -0,0 +1,63 @@
//@ run-rustfix
// Regression test for https://github.com/rust-lang/rust/issues/144319.
// Function-local constructors cannot be named through the enclosing function
// path. The suggestion must omit path segments that cannot be written in source,
// while preserving real path segments like local modules and enums.
#![allow(dead_code)]
fn direct_tuple_struct() {
struct Foo(bool);
struct Bar(Foo);
_ = Bar(Foo(false));
//~^ ERROR mismatched types
//~| HELP try wrapping the expression in `Foo`
}
fn enum_variant() {
enum LocalResult<T> {
Ok(T),
}
struct Bar(LocalResult<bool>);
_ = Bar(LocalResult::Ok(false));
//~^ ERROR mismatched types
//~| HELP try wrapping the expression in `LocalResult::Ok`
}
fn local_module() {
mod inner {
pub struct Foo(pub bool);
}
struct Bar(inner::Foo);
_ = Bar(inner::Foo(false));
//~^ ERROR mismatched types
//~| HELP try wrapping the expression in `inner::Foo`
}
fn closure_body() {
let _ = || {
struct Foo(bool);
struct Bar(Foo);
_ = Bar(Foo(false));
//~^ ERROR mismatched types
//~| HELP try wrapping the expression in `Foo`
};
}
fn inline_const_block() {
const {
struct Foo(bool);
struct Bar(Foo);
_ = Bar(Foo(false));
//~^ ERROR mismatched types
//~| HELP try wrapping the expression in `Foo`
};
}
pub fn main() {}
@@ -0,0 +1,63 @@
//@ run-rustfix
// Regression test for https://github.com/rust-lang/rust/issues/144319.
// Function-local constructors cannot be named through the enclosing function
// path. The suggestion must omit path segments that cannot be written in source,
// while preserving real path segments like local modules and enums.
#![allow(dead_code)]
fn direct_tuple_struct() {
struct Foo(bool);
struct Bar(Foo);
_ = Bar(false);
//~^ ERROR mismatched types
//~| HELP try wrapping the expression in `Foo`
}
fn enum_variant() {
enum LocalResult<T> {
Ok(T),
}
struct Bar(LocalResult<bool>);
_ = Bar(false);
//~^ ERROR mismatched types
//~| HELP try wrapping the expression in `LocalResult::Ok`
}
fn local_module() {
mod inner {
pub struct Foo(pub bool);
}
struct Bar(inner::Foo);
_ = Bar(false);
//~^ ERROR mismatched types
//~| HELP try wrapping the expression in `inner::Foo`
}
fn closure_body() {
let _ = || {
struct Foo(bool);
struct Bar(Foo);
_ = Bar(false);
//~^ ERROR mismatched types
//~| HELP try wrapping the expression in `Foo`
};
}
fn inline_const_block() {
const {
struct Foo(bool);
struct Bar(Foo);
_ = Bar(false);
//~^ ERROR mismatched types
//~| HELP try wrapping the expression in `Foo`
};
}
pub fn main() {}
@@ -0,0 +1,95 @@
error[E0308]: mismatched types
--> $DIR/wrap-function-local-constructors.rs:14:13
|
LL | _ = Bar(false);
| --- ^^^^^ expected `Foo`, found `bool`
| |
| arguments to this struct are incorrect
|
note: tuple struct defined here
--> $DIR/wrap-function-local-constructors.rs:12:12
|
LL | struct Bar(Foo);
| ^^^
help: try wrapping the expression in `Foo`
|
LL | _ = Bar(Foo(false));
| ++++ +
error[E0308]: mismatched types
--> $DIR/wrap-function-local-constructors.rs:25:13
|
LL | _ = Bar(false);
| --- ^^^^^ expected `LocalResult<bool>`, found `bool`
| |
| arguments to this struct are incorrect
|
= note: expected enum `LocalResult<bool>`
found type `bool`
note: tuple struct defined here
--> $DIR/wrap-function-local-constructors.rs:23:12
|
LL | struct Bar(LocalResult<bool>);
| ^^^
help: try wrapping the expression in `LocalResult::Ok`
|
LL | _ = Bar(LocalResult::Ok(false));
| ++++++++++++++++ +
error[E0308]: mismatched types
--> $DIR/wrap-function-local-constructors.rs:36:13
|
LL | _ = Bar(false);
| --- ^^^^^ expected `Foo`, found `bool`
| |
| arguments to this struct are incorrect
|
note: tuple struct defined here
--> $DIR/wrap-function-local-constructors.rs:34:12
|
LL | struct Bar(inner::Foo);
| ^^^
help: try wrapping the expression in `inner::Foo`
|
LL | _ = Bar(inner::Foo(false));
| +++++++++++ +
error[E0308]: mismatched types
--> $DIR/wrap-function-local-constructors.rs:46:17
|
LL | _ = Bar(false);
| --- ^^^^^ expected `Foo`, found `bool`
| |
| arguments to this struct are incorrect
|
note: tuple struct defined here
--> $DIR/wrap-function-local-constructors.rs:44:16
|
LL | struct Bar(Foo);
| ^^^
help: try wrapping the expression in `Foo`
|
LL | _ = Bar(Foo(false));
| ++++ +
error[E0308]: mismatched types
--> $DIR/wrap-function-local-constructors.rs:57:17
|
LL | _ = Bar(false);
| --- ^^^^^ expected `Foo`, found `bool`
| |
| arguments to this struct are incorrect
|
note: tuple struct defined here
--> $DIR/wrap-function-local-constructors.rs:55:16
|
LL | struct Bar(Foo);
| ^^^
help: try wrapping the expression in `Foo`
|
LL | _ = Bar(Foo(false));
| ++++ +
error: aborting due to 5 previous errors
For more information about this error, try `rustc --explain E0308`.