Unnamed repository; edit this file 'description' to name the repository.
Catch `#[rustc_reservation_impl = "reason"]`
And not just `#[rustc_reservation_impl]`.
This has caused a bug that took me way too long to debug. Basically, with the reservation impl `From<!> for T` overlapping with `From<T> for T`, the solver couldn't deduce from the bound `Ty: From<?var>` that `var = Ty`. Up until now this only caused some unknown types, but with the "type annotations needed" it started becoming visible, and annoying.
This is not the first time that we forget some attribute can be applied in more than one reason; perhaps we should unify handling for all `ast::Meta` kinds that have a path.
| -rw-r--r-- | crates/hir-def/src/attrs.rs | 1 | ||||
| -rw-r--r-- | crates/ide-diagnostics/src/handlers/type_must_be_known.rs | 22 |
2 files changed, 23 insertions, 0 deletions
diff --git a/crates/hir-def/src/attrs.rs b/crates/hir-def/src/attrs.rs index 43bbe99b13..90fae16ccd 100644 --- a/crates/hir-def/src/attrs.rs +++ b/crates/hir-def/src/attrs.rs @@ -140,6 +140,7 @@ fn match_attr_flags(attr_flags: &mut AttrFlags, attr: ast::Meta) -> ControlFlow< "must_use" => attr_flags.insert(AttrFlags::IS_MUST_USE), "path" => attr_flags.insert(AttrFlags::HAS_PATH), "unstable" => attr_flags.insert(AttrFlags::IS_UNSTABLE), + "rustc_reservation_impl" => attr_flags.insert(AttrFlags::RUSTC_RESERVATION_IMPL), "export_name" => { if let Some(value) = attr.value_string() && *value == *"main" diff --git a/crates/ide-diagnostics/src/handlers/type_must_be_known.rs b/crates/ide-diagnostics/src/handlers/type_must_be_known.rs index 1bae982079..a03352fe31 100644 --- a/crates/ide-diagnostics/src/handlers/type_must_be_known.rs +++ b/crates/ide-diagnostics/src/handlers/type_must_be_known.rs @@ -137,4 +137,26 @@ fn foo() { "#, ); } + + #[test] + fn regression_22263() { + check_diagnostics( + r#" +trait From<T> {} +impl<T> From<T> for T {} +#[rustc_reservation_impl = "blah blah"] +impl<T> From<!> for T {} + +fn any<T>() -> T { + loop {} +} +fn foo<T, U: From<T>>(_: T) -> U { + loop {} +} +fn bar() { + let _: () = foo(any()); +} + "#, + ); + } } |