Skip to content

Commit c17db9f

Browse files
bors[bot]pnevyk
andauthored
Merge #11107
11107: Fix generic type substitution in impl trait with assoc type r=pnevyk a=pnevyk Fixes #11045 The path transform now detects if a type parameter that is being substituted has an associated type. In that case it is necessary (or safe in general case) to fully qualify the substitution with a trait which the associated type belongs to. This PR also fixes the previous wrong behavior of the substitution that could create an invalid tree `PATH_TYPE -> PATH_TYPE -> ...`. Co-authored-by: Petr Nevyhoštěný <[email protected]>
2 parents 54c9998 + a710b87 commit c17db9f

File tree

3 files changed

+468
-11
lines changed

3 files changed

+468
-11
lines changed

crates/ide_assists/src/handlers/add_missing_impl_members.rs

Lines changed: 362 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -942,4 +942,366 @@ impl FooB for Foo {
942942
"#,
943943
)
944944
}
945+
946+
#[test]
947+
fn test_assoc_type_when_trait_with_same_name_in_scope() {
948+
check_assist(
949+
add_missing_impl_members,
950+
r#"
951+
pub trait Foo {}
952+
953+
pub trait Types {
954+
type Foo;
955+
}
956+
957+
pub trait Behavior<T: Types> {
958+
fn reproduce(&self, foo: T::Foo);
959+
}
960+
961+
pub struct Impl;
962+
963+
impl<T: Types> Behavior<T> for Impl { $0 }"#,
964+
r#"
965+
pub trait Foo {}
966+
967+
pub trait Types {
968+
type Foo;
969+
}
970+
971+
pub trait Behavior<T: Types> {
972+
fn reproduce(&self, foo: T::Foo);
973+
}
974+
975+
pub struct Impl;
976+
977+
impl<T: Types> Behavior<T> for Impl {
978+
fn reproduce(&self, foo: <T as Types>::Foo) {
979+
${0:todo!()}
980+
}
981+
}"#,
982+
);
983+
}
984+
985+
#[test]
986+
fn test_assoc_type_on_concrete_type() {
987+
check_assist(
988+
add_missing_impl_members,
989+
r#"
990+
pub trait Types {
991+
type Foo;
992+
}
993+
994+
impl Types for u32 {
995+
type Foo = bool;
996+
}
997+
998+
pub trait Behavior<T: Types> {
999+
fn reproduce(&self, foo: T::Foo);
1000+
}
1001+
1002+
pub struct Impl;
1003+
1004+
impl Behavior<u32> for Impl { $0 }"#,
1005+
r#"
1006+
pub trait Types {
1007+
type Foo;
1008+
}
1009+
1010+
impl Types for u32 {
1011+
type Foo = bool;
1012+
}
1013+
1014+
pub trait Behavior<T: Types> {
1015+
fn reproduce(&self, foo: T::Foo);
1016+
}
1017+
1018+
pub struct Impl;
1019+
1020+
impl Behavior<u32> for Impl {
1021+
fn reproduce(&self, foo: <u32 as Types>::Foo) {
1022+
${0:todo!()}
1023+
}
1024+
}"#,
1025+
);
1026+
}
1027+
1028+
#[test]
1029+
fn test_assoc_type_on_concrete_type_qualified() {
1030+
check_assist(
1031+
add_missing_impl_members,
1032+
r#"
1033+
pub trait Types {
1034+
type Foo;
1035+
}
1036+
1037+
impl Types for std::string::String {
1038+
type Foo = bool;
1039+
}
1040+
1041+
pub trait Behavior<T: Types> {
1042+
fn reproduce(&self, foo: T::Foo);
1043+
}
1044+
1045+
pub struct Impl;
1046+
1047+
impl Behavior<std::string::String> for Impl { $0 }"#,
1048+
r#"
1049+
pub trait Types {
1050+
type Foo;
1051+
}
1052+
1053+
impl Types for std::string::String {
1054+
type Foo = bool;
1055+
}
1056+
1057+
pub trait Behavior<T: Types> {
1058+
fn reproduce(&self, foo: T::Foo);
1059+
}
1060+
1061+
pub struct Impl;
1062+
1063+
impl Behavior<std::string::String> for Impl {
1064+
fn reproduce(&self, foo: <std::string::String as Types>::Foo) {
1065+
${0:todo!()}
1066+
}
1067+
}"#,
1068+
);
1069+
}
1070+
1071+
#[test]
1072+
fn test_assoc_type_on_concrete_type_multi_option_ambiguous() {
1073+
check_assist(
1074+
add_missing_impl_members,
1075+
r#"
1076+
pub trait Types {
1077+
type Foo;
1078+
}
1079+
1080+
pub trait Types2 {
1081+
type Foo;
1082+
}
1083+
1084+
impl Types for u32 {
1085+
type Foo = bool;
1086+
}
1087+
1088+
impl Types2 for u32 {
1089+
type Foo = String;
1090+
}
1091+
1092+
pub trait Behavior<T: Types + Types2> {
1093+
fn reproduce(&self, foo: <T as Types2>::Foo);
1094+
}
1095+
1096+
pub struct Impl;
1097+
1098+
impl Behavior<u32> for Impl { $0 }"#,
1099+
r#"
1100+
pub trait Types {
1101+
type Foo;
1102+
}
1103+
1104+
pub trait Types2 {
1105+
type Foo;
1106+
}
1107+
1108+
impl Types for u32 {
1109+
type Foo = bool;
1110+
}
1111+
1112+
impl Types2 for u32 {
1113+
type Foo = String;
1114+
}
1115+
1116+
pub trait Behavior<T: Types + Types2> {
1117+
fn reproduce(&self, foo: <T as Types2>::Foo);
1118+
}
1119+
1120+
pub struct Impl;
1121+
1122+
impl Behavior<u32> for Impl {
1123+
fn reproduce(&self, foo: <u32 as Types2>::Foo) {
1124+
${0:todo!()}
1125+
}
1126+
}"#,
1127+
);
1128+
}
1129+
1130+
#[test]
1131+
fn test_assoc_type_on_concrete_type_multi_option() {
1132+
check_assist(
1133+
add_missing_impl_members,
1134+
r#"
1135+
pub trait Types {
1136+
type Foo;
1137+
}
1138+
1139+
pub trait Types2 {
1140+
type Bar;
1141+
}
1142+
1143+
impl Types for u32 {
1144+
type Foo = bool;
1145+
}
1146+
1147+
impl Types2 for u32 {
1148+
type Bar = String;
1149+
}
1150+
1151+
pub trait Behavior<T: Types + Types2> {
1152+
fn reproduce(&self, foo: T::Bar);
1153+
}
1154+
1155+
pub struct Impl;
1156+
1157+
impl Behavior<u32> for Impl { $0 }"#,
1158+
r#"
1159+
pub trait Types {
1160+
type Foo;
1161+
}
1162+
1163+
pub trait Types2 {
1164+
type Bar;
1165+
}
1166+
1167+
impl Types for u32 {
1168+
type Foo = bool;
1169+
}
1170+
1171+
impl Types2 for u32 {
1172+
type Bar = String;
1173+
}
1174+
1175+
pub trait Behavior<T: Types + Types2> {
1176+
fn reproduce(&self, foo: T::Bar);
1177+
}
1178+
1179+
pub struct Impl;
1180+
1181+
impl Behavior<u32> for Impl {
1182+
fn reproduce(&self, foo: <u32 as Types2>::Bar) {
1183+
${0:todo!()}
1184+
}
1185+
}"#,
1186+
);
1187+
}
1188+
1189+
#[test]
1190+
fn test_assoc_type_on_concrete_type_multi_option_foreign() {
1191+
check_assist(
1192+
add_missing_impl_members,
1193+
r#"
1194+
mod bar {
1195+
pub trait Types2 {
1196+
type Bar;
1197+
}
1198+
}
1199+
1200+
pub trait Types {
1201+
type Foo;
1202+
}
1203+
1204+
impl Types for u32 {
1205+
type Foo = bool;
1206+
}
1207+
1208+
impl bar::Types2 for u32 {
1209+
type Bar = String;
1210+
}
1211+
1212+
pub trait Behavior<T: Types + bar::Types2> {
1213+
fn reproduce(&self, foo: T::Bar);
1214+
}
1215+
1216+
pub struct Impl;
1217+
1218+
impl Behavior<u32> for Impl { $0 }"#,
1219+
r#"
1220+
mod bar {
1221+
pub trait Types2 {
1222+
type Bar;
1223+
}
1224+
}
1225+
1226+
pub trait Types {
1227+
type Foo;
1228+
}
1229+
1230+
impl Types for u32 {
1231+
type Foo = bool;
1232+
}
1233+
1234+
impl bar::Types2 for u32 {
1235+
type Bar = String;
1236+
}
1237+
1238+
pub trait Behavior<T: Types + bar::Types2> {
1239+
fn reproduce(&self, foo: T::Bar);
1240+
}
1241+
1242+
pub struct Impl;
1243+
1244+
impl Behavior<u32> for Impl {
1245+
fn reproduce(&self, foo: <u32 as bar::Types2>::Bar) {
1246+
${0:todo!()}
1247+
}
1248+
}"#,
1249+
);
1250+
}
1251+
1252+
#[test]
1253+
fn test_transform_path_in_path_expr() {
1254+
check_assist(
1255+
add_missing_default_members,
1256+
r#"
1257+
pub trait Const {
1258+
const FOO: u32;
1259+
}
1260+
1261+
pub trait Trait<T: Const> {
1262+
fn foo() -> bool {
1263+
match T::FOO {
1264+
0 => true,
1265+
_ => false,
1266+
}
1267+
}
1268+
}
1269+
1270+
impl Const for u32 {
1271+
const FOO: u32 = 1;
1272+
}
1273+
1274+
struct Impl;
1275+
1276+
impl Trait<u32> for Impl { $0 }"#,
1277+
r#"
1278+
pub trait Const {
1279+
const FOO: u32;
1280+
}
1281+
1282+
pub trait Trait<T: Const> {
1283+
fn foo() -> bool {
1284+
match T::FOO {
1285+
0 => true,
1286+
_ => false,
1287+
}
1288+
}
1289+
}
1290+
1291+
impl Const for u32 {
1292+
const FOO: u32 = 1;
1293+
}
1294+
1295+
struct Impl;
1296+
1297+
impl Trait<u32> for Impl {
1298+
$0fn foo() -> bool {
1299+
match <u32 as Const>::FOO {
1300+
0 => true,
1301+
_ => false,
1302+
}
1303+
}
1304+
}"#,
1305+
);
1306+
}
9451307
}

0 commit comments

Comments
 (0)