Resolve assoc item bindings by namespace · rust-lang/rust@55559d9 (original) (raw)

`@@ -3,8 +3,7 @@ use rustc_errors::struct_span_err;

`

3

3

`use rustc_hir as hir;

`

4

4

`use rustc_hir::def::{DefKind, Res};

`

5

5

`use rustc_hir::def_id::{DefId, LocalDefId};

`

6

``

`-

use rustc_lint_defs::Applicability;

`

7

``

`-

use rustc_middle::ty::{self as ty, Ty, TypeVisitableExt};

`

``

6

`+

use rustc_middle::ty::{self as ty, Ty};

`

8

7

`use rustc_span::symbol::Ident;

`

9

8

`use rustc_span::{ErrorGuaranteed, Span};

`

10

9

`use rustc_trait_selection::traits;

`

`@@ -256,64 +255,49 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {

`

256

255

``

257

256

`let tcx = self.tcx();

`

258

257

``

259

``

`-

let return_type_notation =

`

260

``

`-

binding.gen_args.parenthesized == hir::GenericArgsParentheses::ReturnTypeNotation;

`

261

``

-

262

``

`-

let candidate = if return_type_notation {

`

263

``

`-

if self.trait_defines_associated_item_named(

`

264

``

`-

trait_ref.def_id(),

`

265

``

`-

ty::AssocKind::Fn,

`

266

``

`-

binding.item_name,

`

267

``

`-

) {

`

268

``

`-

trait_ref

`

``

258

`+

let assoc_kind =

`

``

259

`+

if binding.gen_args.parenthesized == hir::GenericArgsParentheses::ReturnTypeNotation {

`

``

260

`+

ty::AssocKind::Fn

`

``

261

`+

} else if let ConvertedBindingKind::Equality(term) = binding.kind

`

``

262

`+

&& let ty::TermKind::Const(_) = term.node.unpack()

`

``

263

`+

{

`

``

264

`+

ty::AssocKind::Const

`

269

265

`} else {

`

270

``

`-

self.one_bound_for_assoc_method(

`

271

``

`-

traits::supertraits(tcx, trait_ref),

`

272

``

`-

trait_ref.print_only_trait_path(),

`

273

``

`-

binding.item_name,

`

274

``

`-

path_span,

`

275

``

`-

)?

`

276

``

`-

}

`

277

``

`-

} else if self.trait_defines_associated_item_named(

`

``

266

`+

ty::AssocKind::Type

`

``

267

`+

};

`

``

268

+

``

269

`+

let candidate = if self.trait_defines_associated_item_named(

`

278

270

` trait_ref.def_id(),

`

279

``

`-

ty::AssocKind::Type,

`

``

271

`+

assoc_kind,

`

280

272

` binding.item_name,

`

281

273

`) {

`

282

``

`-

// Simple case: X is defined in the current trait.

`

``

274

`+

// Simple case: The assoc item is defined in the current trait.

`

283

275

` trait_ref

`

284

276

`} else {

`

285

277

`// Otherwise, we have to walk through the supertraits to find

`

286

``

`-

// those that do.

`

287

``

`-

self.one_bound_for_assoc_type(

`

``

278

`+

// one that does define it.

`

``

279

`+

self.one_bound_for_assoc_item(

`

288

280

` || traits::supertraits(tcx, trait_ref),

`

289

281

` trait_ref.skip_binder().print_only_trait_name(),

`

290

282

`None,

`

``

283

`+

assoc_kind,

`

291

284

` binding.item_name,

`

292

285

` path_span,

`

293

``

`-

match binding.kind {

`

294

``

`-

ConvertedBindingKind::Equality(term) => Some(term),

`

295

``

`-

_ => None,

`

296

``

`-

},

`

``

286

`+

Some(&binding),

`

297

287

`)?

`

298

288

`};

`

299

289

``

300

290

`let (assoc_ident, def_scope) =

`

301

291

` tcx.adjust_ident_and_get_scope(binding.item_name, candidate.def_id(), hir_ref_id);

`

302

292

``

303

``

`` -

// We have already adjusted the item name above, so compare with ident.normalize_to_macros_2_0() instead

``

304

``

`` -

// of calling filter_by_name_and_kind.

``

305

``

`-

let find_item_of_kind = |kind| {

`

306

``

`-

tcx.associated_items(candidate.def_id())

`

307

``

`-

.filter_by_name_unhygienic(assoc_ident.name)

`

308

``

`-

.find(|i| i.kind == kind && i.ident(tcx).normalize_to_macros_2_0() == assoc_ident)

`

309

``

`-

};

`

310

``

`-

let assoc_item = if return_type_notation {

`

311

``

`-

find_item_of_kind(ty::AssocKind::Fn)

`

312

``

`-

} else {

`

313

``

`-

find_item_of_kind(ty::AssocKind::Type)

`

314

``

`-

.or_else(|| find_item_of_kind(ty::AssocKind::Const))

`

315

``

`-

}

`

316

``

`-

.expect("missing associated type");

`

``

293

`` +

// We have already adjusted the item name above, so compare with .normalize_to_macros_2_0()

``

``

294

`` +

// instead of calling filter_by_name_and_kind which would needlessly normalize the

``

``

295

`` +

// assoc_ident again and again.

``

``

296

`+

let assoc_item = tcx

`

``

297

`+

.associated_items(candidate.def_id())

`

``

298

`+

.filter_by_name_unhygienic(assoc_ident.name)

`

``

299

`+

.find(|i| i.kind == assoc_kind && i.ident(tcx).normalize_to_macros_2_0() == assoc_ident)

`

``

300

`+

.expect("missing associated item");

`

317

301

``

318

302

`if !assoc_item.visibility(tcx).is_accessible_from(def_scope, tcx) {

`

319

303

` tcx.sess

`

`@@ -340,7 +324,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {

`

340

324

`.or_insert(binding.span);

`

341

325

`}

`

342

326

``

343

``

`-

let projection_ty = if return_type_notation {

`

``

327

`+

let projection_ty = if let ty::AssocKind::Fn = assoc_kind {

`

344

328

`let mut emitted_bad_param_err = false;

`

345

329

`// If we have an method return type bound, then we need to substitute

`

346

330

`// the method's early bound params with suitable late-bound params.

`

`@@ -467,7 +451,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {

`

467

451

`let late_bound_in_trait_ref =

`

468

452

` tcx.collect_constrained_late_bound_regions(&projection_ty);

`

469

453

`let late_bound_in_ty =

`

470

``

`-

tcx.collect_referenced_late_bound_regions(&trait_ref.rebind(ty));

`

``

454

`+

tcx.collect_referenced_late_bound_regions(&trait_ref.rebind(ty.node));

`

471

455

`debug!(?late_bound_in_trait_ref);

`

472

456

`debug!(?late_bound_in_ty);

`

473

457

``

`@@ -492,77 +476,27 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {

`

492

476

`}

`

493

477

`}

`

494

478

``

495

``

`-

let assoc_item_def_id = projection_ty.skip_binder().def_id;

`

496

``

`-

let def_kind = tcx.def_kind(assoc_item_def_id);

`

497

479

`match binding.kind {

`

498

``

`-

ConvertedBindingKind::Equality(..) if return_type_notation => {

`

``

480

`+

ConvertedBindingKind::Equality(..) if let ty::AssocKind::Fn = assoc_kind => {

`

499

481

`return Err(self.tcx().sess.emit_err(

`

500

482

`crate::errors::ReturnTypeNotationEqualityBound { span: binding.span },

`

501

483

`));

`

502

484

`}

`

503

``

`-

ConvertedBindingKind::Equality(mut term) => {

`

``

485

`+

ConvertedBindingKind::Equality(term) => {

`

504

486

`` // "Desugar" a constraint like T: Iterator<Item = u32> this to

``

505

487

`// the "projection predicate" for:

`

506

488

`//

`

507

489

`` // <T as Iterator>::Item = u32

``

508

``

`-

match (def_kind, term.unpack()) {

`

509

``

`-

(DefKind::AssocTy, ty::TermKind::Ty(_))

`

510

``

`-

| (DefKind::AssocConst, ty::TermKind::Const(_)) => (),

`

511

``

`-

(_, _) => {

`

512

``

`-

let got = if let Some(_) = term.ty() { "type" } else { "constant" };

`

513

``

`-

let expected = tcx.def_descr(assoc_item_def_id);

`

514

``

`-

let mut err = tcx.sess.struct_span_err(

`

515

``

`-

binding.span,

`

516

``

`-

format!("expected {expected} bound, found {got}"),

`

517

``

`-

);

`

518

``

`-

err.span_note(

`

519

``

`-

tcx.def_span(assoc_item_def_id),

`

520

``

`-

format!("{expected} defined here"),

`

521

``

`-

);

`

522

``

-

523

``

`-

if let DefKind::AssocConst = def_kind

`

524

``

`-

&& let Some(t) = term.ty()

`

525

``

`-

&& (t.is_enum() || t.references_error())

`

526

``

`-

&& tcx.features().associated_const_equality

`

527

``

`-

{

`

528

``

`-

err.span_suggestion(

`

529

``

`-

binding.span,

`

530

``

`-

"if equating a const, try wrapping with braces",

`

531

``

`-

format!("{} = {{ const }}", binding.item_name),

`

532

``

`-

Applicability::HasPlaceholders,

`

533

``

`-

);

`

534

``

`-

}

`

535

``

`-

let reported = err.emit();

`

536

``

`-

term = match def_kind {

`

537

``

`-

DefKind::AssocTy => Ty::new_error(tcx, reported).into(),

`

538

``

`-

DefKind::AssocConst => ty::Const::new_error(

`

539

``

`-

tcx,

`

540

``

`-

reported,

`

541

``

`-

tcx.type_of(assoc_item_def_id)

`

542

``

`-

.instantiate(tcx, projection_ty.skip_binder().args),

`

543

``

`-

)

`

544

``

`-

.into(),

`

545

``

`-

_ => unreachable!(),

`

546

``

`-

};

`

547

``

`-

}

`

548

``

`-

}

`

549

490

` bounds.push_projection_bound(

`

550

491

` tcx,

`

551

``

`-

projection_ty

`

552

``

`-

.map_bound(|projection_ty| ty::ProjectionPredicate { projection_ty, term }),

`

``

492

`+

projection_ty.map_bound(|projection_ty| ty::ProjectionPredicate {

`

``

493

`+

projection_ty,

`

``

494

`+

term: term.node,

`

``

495

`+

}),

`

553

496

` binding.span,

`

554

497

`);

`

555

498

`}

`

556

499

`ConvertedBindingKind::Constraint(ast_bounds) => {

`

557

``

`-

match def_kind {

`

558

``

`-

DefKind::AssocTy => {}

`

559

``

`-

_ => {

`

560

``

`-

return Err(tcx.sess.emit_err(errors::AssocBoundOnConst {

`

561

``

`-

span: assoc_ident.span,

`

562

``

`-

descr: tcx.def_descr(assoc_item_def_id),

`

563

``

`-

}));

`

564

``

`-

}

`

565

``

`-

}

`

566

500

`` // "Desugar" a constraint like T: Iterator<Item: Debug> to

``

567

501

`//

`

568

502

`` // <T as Iterator>::Item: Debug

``