Skip to content

Commit ca5fa66

Browse files
authored
Rollup merge of #135749 - compiler-errors:param-ordering, r=davidtwco
Do not assume const params are printed after type params Fixes #135737
2 parents 5750815 + 97e07da commit ca5fa66

File tree

4 files changed

+128
-145
lines changed

4 files changed

+128
-145
lines changed

Diff for: compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs

+121-138
Original file line numberDiff line numberDiff line change
@@ -717,53 +717,47 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
717717
value: &mut DiagStyledString,
718718
other_value: &mut DiagStyledString,
719719
name: String,
720-
sub: ty::GenericArgsRef<'tcx>,
720+
args: &[ty::GenericArg<'tcx>],
721721
pos: usize,
722722
other_ty: Ty<'tcx>,
723723
) {
724724
// `value` and `other_value` hold two incomplete type representation for display.
725725
// `name` is the path of both types being compared. `sub`
726726
value.push_highlighted(name);
727-
let len = sub.len();
728-
if len > 0 {
729-
value.push_highlighted("<");
730-
}
731727

732-
// Output the lifetimes for the first type
733-
let lifetimes = sub
734-
.regions()
735-
.map(|lifetime| {
736-
let s = lifetime.to_string();
737-
if s.is_empty() { "'_".to_string() } else { s }
738-
})
739-
.collect::<Vec<_>>()
740-
.join(", ");
741-
if !lifetimes.is_empty() {
742-
if sub.regions().count() < len {
743-
value.push_normal(lifetimes + ", ");
744-
} else {
745-
value.push_normal(lifetimes);
746-
}
728+
if args.is_empty() {
729+
return;
747730
}
731+
value.push_highlighted("<");
748732

749-
// Highlight all the type arguments that aren't at `pos` and compare the type argument at
750-
// `pos` and `other_ty`.
751-
for (i, type_arg) in sub.types().enumerate() {
752-
if i == pos {
753-
let values = self.cmp(type_arg, other_ty);
754-
value.0.extend((values.0).0);
755-
other_value.0.extend((values.1).0);
756-
} else {
757-
value.push_highlighted(type_arg.to_string());
733+
for (i, arg) in args.iter().enumerate() {
734+
if i > 0 {
735+
value.push_normal(", ");
758736
}
759737

760-
if len > 0 && i != len - 1 {
761-
value.push_normal(", ");
738+
match arg.unpack() {
739+
ty::GenericArgKind::Lifetime(lt) => {
740+
let s = lt.to_string();
741+
value.push_normal(if s.is_empty() { "'_" } else { &s });
742+
}
743+
ty::GenericArgKind::Const(ct) => {
744+
value.push_normal(ct.to_string());
745+
}
746+
// Highlight all the type arguments that aren't at `pos` and compare
747+
// the type argument at `pos` and `other_ty`.
748+
ty::GenericArgKind::Type(type_arg) => {
749+
if i == pos {
750+
let values = self.cmp(type_arg, other_ty);
751+
value.0.extend((values.0).0);
752+
other_value.0.extend((values.1).0);
753+
} else {
754+
value.push_highlighted(type_arg.to_string());
755+
}
756+
}
762757
}
763758
}
764-
if len > 0 {
765-
value.push_highlighted(">");
766-
}
759+
760+
value.push_highlighted(">");
767761
}
768762

769763
/// If `other_ty` is the same as a type argument present in `sub`, highlight `path` in `t1_out`,
@@ -791,38 +785,36 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
791785
t1_out: &mut DiagStyledString,
792786
t2_out: &mut DiagStyledString,
793787
path: String,
794-
sub: &'tcx [ty::GenericArg<'tcx>],
788+
args: &'tcx [ty::GenericArg<'tcx>],
795789
other_path: String,
796790
other_ty: Ty<'tcx>,
797-
) -> Option<()> {
798-
// FIXME/HACK: Go back to `GenericArgsRef` to use its inherent methods,
799-
// ideally that shouldn't be necessary.
800-
let sub = self.tcx.mk_args(sub);
801-
for (i, ta) in sub.types().enumerate() {
802-
if ta == other_ty {
803-
self.highlight_outer(t1_out, t2_out, path, sub, i, other_ty);
804-
return Some(());
805-
}
806-
if let ty::Adt(def, _) = ta.kind() {
807-
let path_ = self.tcx.def_path_str(def.did());
808-
if path_ == other_path {
809-
self.highlight_outer(t1_out, t2_out, path, sub, i, other_ty);
810-
return Some(());
791+
) -> bool {
792+
for (i, arg) in args.iter().enumerate() {
793+
if let Some(ta) = arg.as_type() {
794+
if ta == other_ty {
795+
self.highlight_outer(t1_out, t2_out, path, args, i, other_ty);
796+
return true;
797+
}
798+
if let ty::Adt(def, _) = ta.kind() {
799+
let path_ = self.tcx.def_path_str(def.did());
800+
if path_ == other_path {
801+
self.highlight_outer(t1_out, t2_out, path, args, i, other_ty);
802+
return true;
803+
}
811804
}
812805
}
813806
}
814-
None
807+
false
815808
}
816809

817810
/// Adds a `,` to the type representation only if it is appropriate.
818811
fn push_comma(
819812
&self,
820813
value: &mut DiagStyledString,
821814
other_value: &mut DiagStyledString,
822-
len: usize,
823815
pos: usize,
824816
) {
825-
if len > 0 && pos != len - 1 {
817+
if pos > 0 {
826818
value.push_normal(", ");
827819
other_value.push_normal(", ");
828820
}
@@ -899,10 +891,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
899891
let len2 = sig2.inputs().len();
900892
if len1 == len2 {
901893
for (i, (l, r)) in iter::zip(sig1.inputs(), sig2.inputs()).enumerate() {
894+
self.push_comma(&mut values.0, &mut values.1, i);
902895
let (x1, x2) = self.cmp(*l, *r);
903896
(values.0).0.extend(x1.0);
904897
(values.1).0.extend(x2.0);
905-
self.push_comma(&mut values.0, &mut values.1, len1, i);
906898
}
907899
} else {
908900
for (i, l) in sig1.inputs().iter().enumerate() {
@@ -1150,14 +1142,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
11501142
let len1 = sub_no_defaults_1.len();
11511143
let len2 = sub_no_defaults_2.len();
11521144
let common_len = cmp::min(len1, len2);
1153-
let remainder1: Vec<_> = sub1.types().skip(common_len).collect();
1154-
let remainder2: Vec<_> = sub2.types().skip(common_len).collect();
1145+
let remainder1 = &sub1[common_len..];
1146+
let remainder2 = &sub2[common_len..];
11551147
let common_default_params =
11561148
iter::zip(remainder1.iter().rev(), remainder2.iter().rev())
11571149
.filter(|(a, b)| a == b)
11581150
.count();
11591151
let len = sub1.len() - common_default_params;
1160-
let consts_offset = len - sub1.consts().count();
11611152

11621153
// Only draw `<...>` if there are lifetime/type arguments.
11631154
if len > 0 {
@@ -1169,70 +1160,68 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
11691160
let s = lifetime.to_string();
11701161
if s.is_empty() { "'_".to_string() } else { s }
11711162
}
1172-
// At one point we'd like to elide all lifetimes here, they are irrelevant for
1173-
// all diagnostics that use this output
1174-
//
1175-
// Foo<'x, '_, Bar>
1176-
// Foo<'y, '_, Qux>
1177-
// ^^ ^^ --- type arguments are not elided
1178-
// | |
1179-
// | elided as they were the same
1180-
// not elided, they were different, but irrelevant
1181-
//
1182-
// For bound lifetimes, keep the names of the lifetimes,
1183-
// even if they are the same so that it's clear what's happening
1184-
// if we have something like
1185-
//
1186-
// for<'r, 's> fn(Inv<'r>, Inv<'s>)
1187-
// for<'r> fn(Inv<'r>, Inv<'r>)
1188-
let lifetimes = sub1.regions().zip(sub2.regions());
1189-
for (i, lifetimes) in lifetimes.enumerate() {
1190-
let l1 = lifetime_display(lifetimes.0);
1191-
let l2 = lifetime_display(lifetimes.1);
1192-
if lifetimes.0 != lifetimes.1 {
1193-
values.0.push_highlighted(l1);
1194-
values.1.push_highlighted(l2);
1195-
} else if lifetimes.0.is_bound() || self.tcx.sess.opts.verbose {
1196-
values.0.push_normal(l1);
1197-
values.1.push_normal(l2);
1198-
} else {
1199-
values.0.push_normal("'_");
1200-
values.1.push_normal("'_");
1201-
}
1202-
self.push_comma(&mut values.0, &mut values.1, len, i);
1203-
}
12041163

1205-
// We're comparing two types with the same path, so we compare the type
1206-
// arguments for both. If they are the same, do not highlight and elide from the
1207-
// output.
1208-
// Foo<_, Bar>
1209-
// Foo<_, Qux>
1210-
// ^ elided type as this type argument was the same in both sides
1211-
let type_arguments = sub1.types().zip(sub2.types());
1212-
let regions_len = sub1.regions().count();
1213-
let num_display_types = consts_offset - regions_len;
1214-
for (i, (ta1, ta2)) in type_arguments.take(num_display_types).enumerate() {
1215-
let i = i + regions_len;
1216-
if ta1 == ta2 && !self.tcx.sess.opts.verbose {
1217-
values.0.push_normal("_");
1218-
values.1.push_normal("_");
1219-
} else {
1220-
recurse(ta1, ta2, &mut values);
1164+
for (i, (arg1, arg2)) in sub1.iter().zip(sub2).enumerate().take(len) {
1165+
self.push_comma(&mut values.0, &mut values.1, i);
1166+
match arg1.unpack() {
1167+
// At one point we'd like to elide all lifetimes here, they are
1168+
// irrelevant for all diagnostics that use this output.
1169+
//
1170+
// Foo<'x, '_, Bar>
1171+
// Foo<'y, '_, Qux>
1172+
// ^^ ^^ --- type arguments are not elided
1173+
// | |
1174+
// | elided as they were the same
1175+
// not elided, they were different, but irrelevant
1176+
//
1177+
// For bound lifetimes, keep the names of the lifetimes,
1178+
// even if they are the same so that it's clear what's happening
1179+
// if we have something like
1180+
//
1181+
// for<'r, 's> fn(Inv<'r>, Inv<'s>)
1182+
// for<'r> fn(Inv<'r>, Inv<'r>)
1183+
ty::GenericArgKind::Lifetime(l1) => {
1184+
let l1_str = lifetime_display(l1);
1185+
let l2 = arg2.expect_region();
1186+
let l2_str = lifetime_display(l2);
1187+
if l1 != l2 {
1188+
values.0.push_highlighted(l1_str);
1189+
values.1.push_highlighted(l2_str);
1190+
} else if l1.is_bound() || self.tcx.sess.opts.verbose {
1191+
values.0.push_normal(l1_str);
1192+
values.1.push_normal(l2_str);
1193+
} else {
1194+
values.0.push_normal("'_");
1195+
values.1.push_normal("'_");
1196+
}
1197+
}
1198+
ty::GenericArgKind::Type(ta1) => {
1199+
let ta2 = arg2.expect_ty();
1200+
if ta1 == ta2 && !self.tcx.sess.opts.verbose {
1201+
values.0.push_normal("_");
1202+
values.1.push_normal("_");
1203+
} else {
1204+
recurse(ta1, ta2, &mut values);
1205+
}
1206+
}
1207+
// We're comparing two types with the same path, so we compare the type
1208+
// arguments for both. If they are the same, do not highlight and elide
1209+
// from the output.
1210+
// Foo<_, Bar>
1211+
// Foo<_, Qux>
1212+
// ^ elided type as this type argument was the same in both sides
1213+
1214+
// Do the same for const arguments, if they are equal, do not highlight and
1215+
// elide them from the output.
1216+
ty::GenericArgKind::Const(ca1) => {
1217+
let ca2 = arg2.expect_const();
1218+
maybe_highlight(ca1, ca2, &mut values, self.tcx);
1219+
}
12211220
}
1222-
self.push_comma(&mut values.0, &mut values.1, len, i);
1223-
}
1224-
1225-
// Do the same for const arguments, if they are equal, do not highlight and
1226-
// elide them from the output.
1227-
let const_arguments = sub1.consts().zip(sub2.consts());
1228-
for (i, (ca1, ca2)) in const_arguments.enumerate() {
1229-
let i = i + consts_offset;
1230-
maybe_highlight(ca1, ca2, &mut values, self.tcx);
1231-
self.push_comma(&mut values.0, &mut values.1, len, i);
12321221
}
12331222

12341223
// Close the type argument bracket.
1235-
// Only draw `<...>` if there are lifetime/type arguments.
1224+
// Only draw `<...>` if there are arguments.
12361225
if len > 0 {
12371226
values.0.push_normal(">");
12381227
values.1.push_normal(">");
@@ -1244,35 +1233,29 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
12441233
// Foo<Bar<Qux>
12451234
// ------- this type argument is exactly the same as the other type
12461235
// Bar<Qux>
1247-
if self
1248-
.cmp_type_arg(
1249-
&mut values.0,
1250-
&mut values.1,
1251-
path1.clone(),
1252-
sub_no_defaults_1,
1253-
path2.clone(),
1254-
t2,
1255-
)
1256-
.is_some()
1257-
{
1236+
if self.cmp_type_arg(
1237+
&mut values.0,
1238+
&mut values.1,
1239+
path1.clone(),
1240+
sub_no_defaults_1,
1241+
path2.clone(),
1242+
t2,
1243+
) {
12581244
return values;
12591245
}
12601246
// Check for case:
12611247
// let x: Bar<Qux> = y:<Foo<Bar<Qux>>>();
12621248
// Bar<Qux>
12631249
// Foo<Bar<Qux>>
12641250
// ------- this type argument is exactly the same as the other type
1265-
if self
1266-
.cmp_type_arg(
1267-
&mut values.1,
1268-
&mut values.0,
1269-
path2,
1270-
sub_no_defaults_2,
1271-
path1,
1272-
t1,
1273-
)
1274-
.is_some()
1275-
{
1251+
if self.cmp_type_arg(
1252+
&mut values.1,
1253+
&mut values.0,
1254+
path2,
1255+
sub_no_defaults_2,
1256+
path1,
1257+
t1,
1258+
) {
12761259
return values;
12771260
}
12781261

@@ -1343,8 +1326,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
13431326
let mut values = (DiagStyledString::normal("("), DiagStyledString::normal("("));
13441327
let len = args1.len();
13451328
for (i, (left, right)) in args1.iter().zip(args2).enumerate() {
1329+
self.push_comma(&mut values.0, &mut values.1, i);
13461330
recurse(left, right, &mut values);
1347-
self.push_comma(&mut values.0, &mut values.1, len, i);
13481331
}
13491332
if len == 1 {
13501333
// Keep the output for single element tuples as `(ty,)`.

Diff for: tests/ui/self/arbitrary-self-from-method-substs-with-receiver.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ LL | assert_eq!(smart_ptr.a::<&Foo>(), 2);
5353
| ^^^^^^^^^ expected `&Foo`, found `SmartPtr<'_, Foo>`
5454
|
5555
= note: expected reference `&Foo`
56-
found struct `SmartPtr<'_, Foo, >`
56+
found struct `SmartPtr<'_, Foo>`
5757

5858
error[E0308]: mismatched types
5959
--> $DIR/arbitrary-self-from-method-substs-with-receiver.rs:62:16
@@ -62,7 +62,7 @@ LL | assert_eq!(smart_ptr.b::<&Foo>(), 1);
6262
| ^^^^^^^^^ expected `&Foo`, found `SmartPtr<'_, Foo>`
6363
|
6464
= note: expected reference `&Foo`
65-
found struct `SmartPtr<'_, Foo, >`
65+
found struct `SmartPtr<'_, Foo>`
6666

6767
error: aborting due to 8 previous errors
6868

Diff for: tests/ui/self/arbitrary-self-from-method-substs.feature.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ LL | smart_ptr.get::<&Foo>();
8383
| ^^^^^^^^^ expected `&Foo`, found `SmartPtr<'_, Foo>`
8484
|
8585
= note: expected reference `&Foo`
86-
found struct `SmartPtr<'_, Foo, >`
86+
found struct `SmartPtr<'_, Foo>`
8787

8888
error[E0271]: type mismatch resolving `<Silly as FindReceiver>::Receiver == Foo`
8989
--> $DIR/arbitrary-self-from-method-substs.rs:92:9

0 commit comments

Comments
 (0)