Skip to content

Commit 2ea468e

Browse files
committed
dedup diagnostics default params handling
1 parent 154eba6 commit 2ea468e

File tree

9 files changed

+72
-131
lines changed

9 files changed

+72
-131
lines changed

compiler/rustc_infer/src/infer/error_reporting/mod.rs

+10-46
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,8 @@ use rustc_hir::{Item, ItemKind, Node};
6767
use rustc_middle::dep_graph::DepContext;
6868
use rustc_middle::ty::print::with_no_trimmed_paths;
6969
use rustc_middle::ty::{
70-
self,
71-
error::TypeError,
72-
subst::{GenericArgKind, Subst, SubstsRef},
73-
Binder, EarlyBinder, List, Region, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable,
70+
self, error::TypeError, Binder, List, Region, Subst, Ty, TyCtxt, TypeFoldable,
71+
TypeSuperFoldable,
7472
};
7573
use rustc_span::{sym, symbol::kw, BytePos, DesugaringKind, Pos, Span};
7674
use rustc_target::spec::abi;
@@ -926,10 +924,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
926924
mut t1_out: &mut DiagnosticStyledString,
927925
mut t2_out: &mut DiagnosticStyledString,
928926
path: String,
929-
sub: ty::subst::SubstsRef<'tcx>,
927+
sub: &'tcx [ty::GenericArg<'tcx>],
930928
other_path: String,
931929
other_ty: Ty<'tcx>,
932930
) -> Option<()> {
931+
// FIXME/HACK: Go back to `SubstsRef` to use its inherent methods,
932+
// ideally that shouldn't be necessary.
933+
let sub = self.tcx.intern_substs(sub);
933934
for (i, ta) in sub.types().enumerate() {
934935
if ta == other_ty {
935936
self.highlight_outer(&mut t1_out, &mut t2_out, path, sub, i, other_ty);
@@ -960,45 +961,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
960961
}
961962
}
962963

963-
/// For generic types with parameters with defaults, remove the parameters corresponding to
964-
/// the defaults. This repeats a lot of the logic found in `ty::print::pretty`.
965-
fn strip_generic_default_params(
966-
&self,
967-
def_id: DefId,
968-
substs: ty::subst::SubstsRef<'tcx>,
969-
) -> SubstsRef<'tcx> {
970-
let generics = self.tcx.generics_of(def_id);
971-
let mut num_supplied_defaults = 0;
972-
973-
let default_params = generics.params.iter().rev().filter_map(|param| match param.kind {
974-
ty::GenericParamDefKind::Type { has_default: true, .. } => Some(param.def_id),
975-
ty::GenericParamDefKind::Const { has_default: true } => Some(param.def_id),
976-
_ => None,
977-
});
978-
for (def_id, actual) in iter::zip(default_params, substs.iter().rev()) {
979-
match actual.unpack() {
980-
GenericArgKind::Const(c) => {
981-
if EarlyBinder(self.tcx.const_param_default(def_id)).subst(self.tcx, substs)
982-
!= c
983-
{
984-
break;
985-
}
986-
}
987-
GenericArgKind::Type(ty) => {
988-
if self.tcx.bound_type_of(def_id).subst(self.tcx, substs) != ty {
989-
break;
990-
}
991-
}
992-
_ => break,
993-
}
994-
num_supplied_defaults += 1;
995-
}
996-
let len = generics.params.len();
997-
let mut generics = generics.clone();
998-
generics.params.truncate(len - num_supplied_defaults);
999-
substs.truncate_to(self.tcx, &generics)
1000-
}
1001-
1002964
/// Given two `fn` signatures highlight only sub-parts that are different.
1003965
fn cmp_fn_sig(
1004966
&self,
@@ -1156,8 +1118,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
11561118
(&ty::Adt(def1, sub1), &ty::Adt(def2, sub2)) => {
11571119
let did1 = def1.did();
11581120
let did2 = def2.did();
1159-
let sub_no_defaults_1 = self.strip_generic_default_params(did1, sub1);
1160-
let sub_no_defaults_2 = self.strip_generic_default_params(did2, sub2);
1121+
let sub_no_defaults_1 =
1122+
self.tcx.generics_of(did1).own_substs_no_defaults(self.tcx, sub1);
1123+
let sub_no_defaults_2 =
1124+
self.tcx.generics_of(did2).own_substs_no_defaults(self.tcx, sub2);
11611125
let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new());
11621126
let path1 = self.tcx.def_path_str(did1);
11631127
let path2 = self.tcx.def_path_str(did2);

compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs

+3-21
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use rustc_middle::infer::unify_key::ConstVariableOriginKind;
1111
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
1212
use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Print, Printer};
1313
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst, SubstsRef};
14-
use rustc_middle::ty::{self, DefIdTree, GenericParamDefKind, InferConst};
14+
use rustc_middle::ty::{self, DefIdTree, InferConst};
1515
use rustc_middle::ty::{Ty, TyCtxt, TypeckResults};
1616
use rustc_span::symbol::{kw, Ident};
1717
use rustc_span::{BytePos, Span};
@@ -958,26 +958,8 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> {
958958
generics.own_substs(substs).iter().position(|&arg| self.generic_arg_is_target(arg))
959959
{
960960
let substs = self.infcx.resolve_vars_if_possible(substs);
961-
let num_args = generics
962-
.params
963-
.iter()
964-
.rev()
965-
.filter(|&p| !matches!(p.kind, GenericParamDefKind::Lifetime))
966-
.skip_while(|&param| {
967-
if let Some(default) = param.default_value(tcx) {
968-
// FIXME: Using structural comparisions has a bunch of false negatives.
969-
//
970-
// We should instead try to replace inference variables with placeholders and
971-
// then use `infcx.can_eq`. That probably should be a separate method
972-
// generally used during error reporting.
973-
default.subst(tcx, substs) == substs[param.index as usize]
974-
} else {
975-
false
976-
}
977-
})
978-
.count();
979-
let generic_args =
980-
&generics.own_substs(substs)[generics.own_counts().lifetimes..][..num_args];
961+
let generic_args = &generics.own_substs_no_defaults(tcx, substs)
962+
[generics.own_counts().lifetimes..];
981963
let span = match expr.kind {
982964
ExprKind::MethodCall(path, _, _) => path.ident.span,
983965
_ => expr.span,

compiler/rustc_middle/src/ty/generics.rs

+36-1
Original file line numberDiff line numberDiff line change
@@ -228,8 +228,43 @@ impl<'tcx> Generics {
228228
})
229229
}
230230

231+
/// Returns the substs corresponding to the generic parameters
232+
/// of this item, excluding `Self`.
233+
pub fn own_substs_no_defaults(
234+
&'tcx self,
235+
tcx: TyCtxt<'tcx>,
236+
substs: &'tcx [ty::GenericArg<'tcx>],
237+
) -> &'tcx [ty::GenericArg<'tcx>] {
238+
let mut own_params = self.parent_count..self.count();
239+
if self.has_self && self.parent.is_none() {
240+
own_params.start = 1;
241+
}
242+
243+
// Filter the default arguments.
244+
//
245+
// This currently uses structural equality instead
246+
// of semantic equivalance. While not ideal, that's
247+
// good enough for now as this should only be used
248+
// for diagnostics anyways.
249+
own_params.end -= self
250+
.params
251+
.iter()
252+
.rev()
253+
.take_while(|param| {
254+
param.default_value(tcx).map_or(false, |default| {
255+
default.subst(tcx, substs) == substs[param.index as usize]
256+
})
257+
})
258+
.count();
259+
260+
&substs[own_params]
261+
}
262+
231263
/// Returns the substs corresponding to the generic parameters of this item, excluding `Self`.
232-
pub fn own_substs(&'tcx self, substs: SubstsRef<'tcx>) -> &'tcx [ty::GenericArg<'tcx>] {
264+
pub fn own_substs(
265+
&'tcx self,
266+
substs: &'tcx [ty::GenericArg<'tcx>],
267+
) -> &'tcx [ty::GenericArg<'tcx>] {
233268
let own = &substs[self.parent_count..][..self.params.len()];
234269
if self.has_self && self.parent.is_none() { &own[1..] } else { &own }
235270
}

compiler/rustc_middle/src/ty/print/mod.rs

+1-38
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ pub trait Printer<'tcx>: Sized {
149149
// on top of the same path, but without its own generics.
150150
_ => {
151151
if !generics.params.is_empty() && substs.len() >= generics.count() {
152-
let args = self.generic_args_to_print(generics, substs);
152+
let args = generics.own_substs_no_defaults(self.tcx(), substs);
153153
return self.path_generic_args(
154154
|cx| cx.print_def_path(def_id, parent_substs),
155155
args,
@@ -184,43 +184,6 @@ pub trait Printer<'tcx>: Sized {
184184
}
185185
}
186186

187-
fn generic_args_to_print(
188-
&self,
189-
generics: &'tcx ty::Generics,
190-
substs: &'tcx [GenericArg<'tcx>],
191-
) -> &'tcx [GenericArg<'tcx>] {
192-
let mut own_params = generics.parent_count..generics.count();
193-
194-
// Don't print args for `Self` parameters (of traits).
195-
if generics.has_self && own_params.start == 0 {
196-
own_params.start = 1;
197-
}
198-
199-
// Don't print args that are the defaults of their respective parameters.
200-
own_params.end -= generics
201-
.params
202-
.iter()
203-
.rev()
204-
.take_while(|param| match param.kind {
205-
ty::GenericParamDefKind::Lifetime => false,
206-
ty::GenericParamDefKind::Type { has_default, .. } => {
207-
has_default
208-
&& substs[param.index as usize]
209-
== GenericArg::from(
210-
self.tcx().bound_type_of(param.def_id).subst(self.tcx(), substs),
211-
)
212-
}
213-
ty::GenericParamDefKind::Const { has_default } => {
214-
has_default
215-
&& substs[param.index as usize]
216-
== GenericArg::from(self.tcx().const_param_default(param.def_id))
217-
}
218-
})
219-
.count();
220-
221-
&substs[own_params]
222-
}
223-
224187
fn default_print_impl_path(
225188
self,
226189
impl_def_id: DefId,

compiler/rustc_middle/src/ty/print/pretty.rs

+12-15
Original file line numberDiff line numberDiff line change
@@ -825,12 +825,11 @@ pub trait PrettyPrinter<'tcx>:
825825

826826
for (fn_once_trait_ref, entry) in fn_traits {
827827
// Get the (single) generic ty (the args) of this FnOnce trait ref.
828-
let generics = self.generic_args_to_print(
829-
self.tcx().generics_of(fn_once_trait_ref.def_id()),
830-
fn_once_trait_ref.skip_binder().substs,
831-
);
828+
let generics = self.tcx().generics_of(fn_once_trait_ref.def_id());
829+
let args =
830+
generics.own_substs_no_defaults(self.tcx(), fn_once_trait_ref.skip_binder().substs);
832831

833-
match (entry.return_ty, generics[0].expect_ty()) {
832+
match (entry.return_ty, args[0].expect_ty()) {
834833
// We can only print `impl Fn() -> ()` if we have a tuple of args and we recorded
835834
// a return type.
836835
(Some(return_ty), arg_tys) if matches!(arg_tys.kind(), ty::Tuple(_)) => {
@@ -892,15 +891,13 @@ pub trait PrettyPrinter<'tcx>:
892891
print(trait_ref.skip_binder().print_only_trait_name())
893892
);
894893

895-
let generics = self.generic_args_to_print(
896-
self.tcx().generics_of(trait_ref.def_id()),
897-
trait_ref.skip_binder().substs,
898-
);
894+
let generics = self.tcx().generics_of(trait_ref.def_id());
895+
let args = generics.own_substs_no_defaults(self.tcx(), trait_ref.skip_binder().substs);
899896

900-
if !generics.is_empty() || !assoc_items.is_empty() {
897+
if !args.is_empty() || !assoc_items.is_empty() {
901898
let mut first = true;
902899

903-
for ty in generics {
900+
for ty in args {
904901
if first {
905902
p!("<");
906903
first = false;
@@ -1071,10 +1068,10 @@ pub trait PrettyPrinter<'tcx>:
10711068
let dummy_cx = cx.tcx().mk_ty_infer(ty::FreshTy(0));
10721069
let principal = principal.with_self_ty(cx.tcx(), dummy_cx);
10731070

1074-
let args = cx.generic_args_to_print(
1075-
cx.tcx().generics_of(principal.def_id),
1076-
principal.substs,
1077-
);
1071+
let args = cx
1072+
.tcx()
1073+
.generics_of(principal.def_id)
1074+
.own_substs_no_defaults(cx.tcx(), principal.substs);
10781075

10791076
// Don't print `'_` if there's no unerased regions.
10801077
let print_regions = args.iter().any(|arg| match arg.unpack() {

src/test/ui/const-generics/defaults/rp_impl_trait_fail.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@ impl Traitor<1, 2> for u64 {}
1515

1616

1717
fn uwu<const N: u8>() -> impl Traitor<N> {
18-
//~^ error: the trait bound `u32: Traitor<N, N>` is not satisfied
18+
//~^ error: the trait bound `u32: Traitor<N>` is not satisfied
1919
1_u32
2020
}
2121

2222
fn owo() -> impl Traitor {
23-
//~^ error: the trait bound `u64: Traitor<1_u8, 1_u8>` is not satisfied
23+
//~^ error: the trait bound `u64: Traitor` is not satisfied
2424
1_u64
2525
}
2626

src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,21 @@ LL | fn rawr() -> impl Trait {
66
|
77
= help: the trait `Trait` is implemented for `Uwu<N>`
88

9-
error[E0277]: the trait bound `u32: Traitor<N, N>` is not satisfied
9+
error[E0277]: the trait bound `u32: Traitor<N>` is not satisfied
1010
--> $DIR/rp_impl_trait_fail.rs:17:26
1111
|
1212
LL | fn uwu<const N: u8>() -> impl Traitor<N> {
13-
| ^^^^^^^^^^^^^^^ the trait `Traitor<N, N>` is not implemented for `u32`
13+
| ^^^^^^^^^^^^^^^ the trait `Traitor<N>` is not implemented for `u32`
1414
|
1515
= help: the following other types implement trait `Traitor<N, M>`:
1616
<u32 as Traitor<N, 2_u8>>
1717
<u64 as Traitor<1_u8, 2_u8>>
1818

19-
error[E0277]: the trait bound `u64: Traitor<1_u8, 1_u8>` is not satisfied
19+
error[E0277]: the trait bound `u64: Traitor` is not satisfied
2020
--> $DIR/rp_impl_trait_fail.rs:22:13
2121
|
2222
LL | fn owo() -> impl Traitor {
23-
| ^^^^^^^^^^^^ the trait `Traitor<1_u8, 1_u8>` is not implemented for `u64`
23+
| ^^^^^^^^^^^^ the trait `Traitor` is not implemented for `u64`
2424
|
2525
= help: the following other types implement trait `Traitor<N, M>`:
2626
<u32 as Traitor<N, 2_u8>>

src/test/ui/const-generics/defaults/trait_objects_fail.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,5 @@ fn main() {
2626
foo(&10_u32);
2727
//~^ error: the trait bound `u32: Trait` is not satisfied
2828
bar(&true);
29-
//~^ error: the trait bound `bool: Traitor<{_: u8}, {_: u8}>` is not satisfied
29+
//~^ error: the trait bound `bool: Traitor<{_: u8}>` is not satisfied
3030
}

src/test/ui/const-generics/defaults/trait_objects_fail.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,16 @@ LL | foo(&10_u32);
99
= help: the trait `Trait<2_u8>` is implemented for `u32`
1010
= note: required for the cast to the object type `dyn Trait`
1111

12-
error[E0277]: the trait bound `bool: Traitor<{_: u8}, {_: u8}>` is not satisfied
12+
error[E0277]: the trait bound `bool: Traitor<{_: u8}>` is not satisfied
1313
--> $DIR/trait_objects_fail.rs:28:9
1414
|
1515
LL | bar(&true);
16-
| --- ^^^^^ the trait `Traitor<{_: u8}, {_: u8}>` is not implemented for `bool`
16+
| --- ^^^^^ the trait `Traitor<{_: u8}>` is not implemented for `bool`
1717
| |
1818
| required by a bound introduced by this call
1919
|
2020
= help: the trait `Traitor<2_u8, 3_u8>` is implemented for `bool`
21-
= note: required for the cast to the object type `dyn Traitor<{_: u8}, {_: u8}>`
21+
= note: required for the cast to the object type `dyn Traitor<{_: u8}>`
2222

2323
error: aborting due to 2 previous errors
2424

0 commit comments

Comments
 (0)