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

`+

}

`