Rollup merge of #126575 - fmease:update-lint-type_alias_bounds, r=com… · compiler-errors/rust@ceae371 (original) (raw)
`@@ -3,17 +3,17 @@ use crate::errors::{
`
3
3
`ParenthesizedFnTraitExpansion, TraitObjectDeclaredWithNoTraits,
`
4
4
`};
`
5
5
`use crate::fluent_generated as fluent;
`
6
``
`-
use crate::hir_ty_lowering::HirTyLowerer;
`
``
6
`+
use crate::hir_ty_lowering::{AssocItemQSelf, HirTyLowerer};
`
7
7
`use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
`
8
8
`use rustc_data_structures::sorted_map::SortedMap;
`
9
9
`use rustc_data_structures::unord::UnordMap;
`
10
10
`use rustc_errors::MultiSpan;
`
11
11
`use rustc_errors::{
`
12
12
` codes::*, pluralize, struct_span_code_err, Applicability, Diag, ErrorGuaranteed,
`
13
13
`};
`
``
14
`+
use rustc_hir as hir;
`
14
15
`use rustc_hir::def::{DefKind, Res};
`
15
``
`-
use rustc_hir::def_id::{DefId, LocalDefId};
`
16
``
`-
use rustc_hir::{self as hir, Node};
`
``
16
`+
use rustc_hir::def_id::DefId;
`
17
17
`use rustc_middle::bug;
`
18
18
`use rustc_middle::query::Key;
`
19
19
`use rustc_middle::ty::print::{PrintPolyTraitRefExt as _, PrintTraitRefExt as _};
`
`@@ -116,8 +116,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
`
116
116
`pub(super) fn complain_about_assoc_item_not_found(
`
117
117
`&self,
`
118
118
`all_candidates: impl Fn() -> I,
`
119
``
`-
ty_param_name: &str,
`
120
``
`-
ty_param_def_id: Option,
`
``
119
`+
qself: AssocItemQSelf,
`
121
120
`assoc_kind: ty::AssocKind,
`
122
121
`assoc_name: Ident,
`
123
122
`span: Span,
`
`@@ -139,7 +138,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
`
139
138
`);
`
140
139
`}
`
141
140
``
142
``
`-
let assoc_kind_str = super::assoc_kind_str(assoc_kind);
`
``
141
`+
let assoc_kind_str = assoc_kind_str(assoc_kind);
`
``
142
`+
let qself_str = qself.to_string(tcx);
`
143
143
``
144
144
`` // The fallback span is needed because assoc_name
might be an Fn()
's Output
without a
``
145
145
`// valid span, so we point at the whole path segment instead.
`
`@@ -149,7 +149,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
`
149
149
`span: if is_dummy { span } else { assoc_name.span },
`
150
150
` assoc_name,
`
151
151
`assoc_kind: assoc_kind_str,
`
152
``
`-
ty_param_name,
`
``
152
`+
qself: &qself_str,
`
153
153
`label: None,
`
154
154
`sugg: None,
`
155
155
`};
`
`@@ -219,19 +219,28 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
`
219
219
` suggested_name,
`
220
220
`identically_named: suggested_name == assoc_name.name,
`
221
221
`});
`
222
``
`-
let hir = tcx.hir();
`
223
``
`-
if let Some(def_id) = ty_param_def_id
`
224
``
`-
&& let parent = hir.get_parent_item(tcx.local_def_id_to_hir_id(def_id))
`
225
``
`-
&& let Some(generics) = hir.get_generics(parent.def_id)
`
``
222
`+
if let AssocItemQSelf::TyParam(ty_param_def_id, ty_param_span) = qself
`
``
223
`` +
// Not using self.item_def_id()
here as that would yield the opaque type itself if we're
``
``
224
`+
// inside an opaque type while we're interested in the overarching type alias (TAIT).
`
``
225
`+
// FIXME: However, for trait aliases, this incorrectly returns the enclosing module...
`
``
226
`+
&& let item_def_id =
`
``
227
`+
tcx.hir().get_parent_item(tcx.local_def_id_to_hir_id(ty_param_def_id))
`
``
228
`+
// FIXME: ...which obviously won't have any generics.
`
``
229
`+
&& let Some(generics) = tcx.hir().get_generics(item_def_id.def_id)
`
226
230
`{
`
227
``
`-
if generics.bounds_for_param(def_id).flat_map(|pred| pred.bounds.iter()).any(
`
228
``
`-
|b| match b {
`
``
231
`` +
// FIXME: Suggest adding supertrait bounds if we have a Self
type param.
``
``
232
`` +
// FIXME(trait_alias): Suggest adding Self: Trait
to
``
``
233
`` +
// trait Alias = where Self::Proj:;
with trait Trait { type Proj; }
.
``
``
234
`+
if generics
`
``
235
`+
.bounds_for_param(ty_param_def_id)
`
``
236
`+
.flat_map(|pred| pred.bounds.iter())
`
``
237
`+
.any(|b| match b {
`
229
238
` hir::GenericBound::Trait(t, ..) => {
`
230
239
` t.trait_ref.trait_def_id() == Some(best_trait)
`
231
240
`}
`
232
241
` _ => false,
`
233
``
`-
},
`
234
``
`-
) {
`
``
242
`+
})
`
``
243
`+
{
`
235
244
`` // The type param already has a bound for trait_name
, we just need to
``
236
245
`// change the associated item.
`
237
246
` err.sugg = Some(errors::AssocItemNotFoundSugg::SimilarInOtherTrait {
`
`@@ -242,48 +251,60 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
`
242
251
`return self.dcx().emit_err(err);
`
243
252
`}
`
244
253
``
245
``
`-
let mut err = self.dcx().create_err(err);
`
246
``
`-
if suggest_constraining_type_param(
`
247
``
`-
tcx,
`
248
``
`-
generics,
`
249
``
`-
&mut err,
`
250
``
`-
&ty_param_name,
`
251
``
`-
&trait_name,
`
252
``
`-
None,
`
253
``
`-
None,
`
254
``
`-
) && suggested_name != assoc_name.name
`
``
254
`+
let trait_args = &ty::GenericArgs::identity_for_item(tcx, best_trait)[1..];
`
``
255
`+
let mut trait_ref = trait_name.clone();
`
``
256
`+
let applicability = if let [arg, args @ ..] = trait_args {
`
``
257
`+
use std::fmt::Write;
`
``
258
`+
write!(trait_ref, "</* {arg}").unwrap();
`
``
259
`+
args.iter().try_for_each(|arg| write!(trait_ref, ", {arg}")).unwrap();
`
``
260
`+
trait_ref += " */>";
`
``
261
`+
Applicability::HasPlaceholders
`
``
262
`+
} else {
`
``
263
`+
Applicability::MaybeIncorrect
`
``
264
`+
};
`
``
265
+
``
266
`+
let identically_named = suggested_name == assoc_name.name;
`
``
267
+
``
268
`+
if let DefKind::TyAlias = tcx.def_kind(item_def_id)
`
``
269
`+
&& !tcx.type_alias_is_lazy(item_def_id)
`
255
270
`{
`
256
``
`-
// We suggested constraining a type parameter, but the associated item on it
`
257
``
`-
// was also not an exact match, so we also suggest changing it.
`
258
``
`-
err.span_suggestion_verbose(
`
259
``
`-
assoc_name.span,
`
260
``
`-
fluent::hir_analysis_assoc_item_not_found_similar_in_other_trait_with_bound_sugg,
`
``
271
`+
err.sugg = Some(errors::AssocItemNotFoundSugg::SimilarInOtherTraitQPath {
`
``
272
`+
lo: ty_param_span.shrink_to_lo(),
`
``
273
`+
mi: ty_param_span.shrink_to_hi(),
`
``
274
`+
hi: (!identically_named).then_some(assoc_name.span),
`
``
275
`+
trait_ref,
`
``
276
`+
identically_named,
`
261
277
` suggested_name,
`
262
``
`-
Applicability::MaybeIncorrect,
`
263
``
`-
);
`
``
278
`+
applicability,
`
``
279
`+
});
`
``
280
`+
} else {
`
``
281
`+
let mut err = self.dcx().create_err(err);
`
``
282
`+
if suggest_constraining_type_param(
`
``
283
`+
tcx, generics, &mut err, &qself_str, &trait_ref, None, None,
`
``
284
`+
) && !identically_named
`
``
285
`+
{
`
``
286
`+
// We suggested constraining a type parameter, but the associated item on it
`
``
287
`+
// was also not an exact match, so we also suggest changing it.
`
``
288
`+
err.span_suggestion_verbose(
`
``
289
`+
assoc_name.span,
`
``
290
`+
fluent::hir_analysis_assoc_item_not_found_similar_in_other_trait_with_bound_sugg,
`
``
291
`+
suggested_name,
`
``
292
`+
Applicability::MaybeIncorrect,
`
``
293
`+
);
`
``
294
`+
}
`
``
295
`+
return err.emit();
`
264
296
`}
`
265
``
`-
return err.emit();
`
266
297
`}
`
267
298
`return self.dcx().emit_err(err);
`
268
299
`}
`
269
300
`}
`
270
301
``
271
302
`// If we still couldn't find any associated item, and only one associated item exists,
`
272
``
`-
// suggests using it.
`
``
303
`+
// suggest using it.
`
273
304
`if let [candidate_name] = all_candidate_names.as_slice() {
`
274
``
`` -
// This should still compile, except on #![feature(associated_type_defaults)]
``
275
``
`` -
// where it could suggests type A = Self::A
, thus recursing infinitely.
``
276
``
`-
let applicability =
`
277
``
`-
if assoc_kind == ty::AssocKind::Type && tcx.features().associated_type_defaults {
`
278
``
`-
Applicability::Unspecified
`
279
``
`-
} else {
`
280
``
`-
Applicability::MaybeIncorrect
`
281
``
`-
};
`
282
``
-
283
305
` err.sugg = Some(errors::AssocItemNotFoundSugg::Other {
`
284
306
`span: assoc_name.span,
`
285
``
`-
applicability,
`
286
``
`-
ty_param_name,
`
``
307
`+
qself: &qself_str,
`
287
308
`assoc_kind: assoc_kind_str,
`
288
309
`suggested_name: *candidate_name,
`
289
310
`});
`
`@@ -349,10 +370,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
`
349
370
``
350
371
`self.dcx().emit_err(errors::AssocKindMismatch {
`
351
372
` span,
`
352
``
`-
expected: super::assoc_kind_str(expected),
`
353
``
`-
got: super::assoc_kind_str(got),
`
``
373
`+
expected: assoc_kind_str(expected),
`
``
374
`+
got: assoc_kind_str(got),
`
354
375
` expected_because_label,
`
355
``
`-
assoc_kind: super::assoc_kind_str(assoc_item.kind),
`
``
376
`+
assoc_kind: assoc_kind_str(assoc_item.kind),
`
356
377
`def_span: tcx.def_span(assoc_item.def_id),
`
357
378
` bound_on_assoc_const_label,
`
358
379
` wrap_in_braces_sugg,
`
`@@ -746,7 +767,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
`
746
767
`if let ([], [bound]) = (&potential_assoc_types[..], &trait_bounds) {
`
747
768
`let grandparent = tcx.parent_hir_node(tcx.parent_hir_id(bound.trait_ref.hir_ref_id));
`
748
769
` in_expr_or_pat = match grandparent {
`
749
``
`-
Node::Expr() | Node::Pat() => true,
`
``
770
`+
hir::Node::Expr() | hir::Node::Pat() => true,
`
750
771
` _ => false,
`
751
772
`};
`
752
773
`match bound.trait_ref.path.segments {
`
`@@ -1612,3 +1633,11 @@ fn generics_args_err_extend<'a>(
`
1612
1633
` _ => {}
`
1613
1634
`}
`
1614
1635
`}
`
``
1636
+
``
1637
`+
pub(super) fn assoc_kind_str(kind: ty::AssocKind) -> &'static str {
`
``
1638
`+
match kind {
`
``
1639
`+
ty::AssocKind::Fn => "function",
`
``
1640
`+
ty::AssocKind::Const => "constant",
`
``
1641
`+
ty::AssocKind::Type => "type",
`
``
1642
`+
}
`
``
1643
`+
}
`