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
``