Skip to content

Commit 5761e6c

Browse files
committed
Resolve assoc item bindings by namespace
If a const is expected, resolve a const. If a type is expected, resolve a type. Don't try to resolve a type first falling back to consts.
1 parent dd6126e commit 5761e6c

26 files changed

+597
-415
lines changed

compiler/rustc_hir_analysis/messages.ftl

+22-9
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,28 @@
1+
hir_analysis_ambiguous_assoc_item = ambiguous associated {$assoc_kind} `{$assoc_name}` in bounds of `{$ty_param_name}`
2+
.label = ambiguous associated {$assoc_kind} `{$assoc_name}`
3+
14
hir_analysis_ambiguous_lifetime_bound =
25
ambiguous lifetime bound, explicit lifetime bound required
36
4-
hir_analysis_assoc_bound_on_const = expected associated type, found {$descr}
5-
.note = trait bounds not allowed on {$descr}
7+
hir_analysis_assoc_item_not_found = associated {$assoc_kind} `{$assoc_name}` not found for `{$ty_param_name}`
8+
9+
hir_analysis_assoc_item_not_found_found_in_other_trait_label = there is {$identically_named ->
10+
[true] an
11+
*[false] a similarly named
12+
} associated {$assoc_kind} `{$suggested_name}` in the trait `{$trait_name}`
13+
hir_analysis_assoc_item_not_found_label = associated {$assoc_kind} `{$assoc_name}` not found
14+
hir_analysis_assoc_item_not_found_other_sugg = `{$ty_param_name}` has the following associated {$assoc_kind}
15+
hir_analysis_assoc_item_not_found_similar_in_other_trait_sugg = change the associated {$assoc_kind} name to use `{$suggested_name}` from `{$trait_name}`
16+
hir_analysis_assoc_item_not_found_similar_in_other_trait_with_bound_sugg = and also change the associated {$assoc_kind} name
17+
hir_analysis_assoc_item_not_found_similar_sugg = there is an associated {$assoc_kind} with a similar name
18+
19+
hir_analysis_assoc_kind_mismatch = expected {$expected}, found {$got}
20+
.label = unexpected {$got}
21+
.expected_because_label = expected a {$expected} because of this associated {$expected}
22+
.note = the associated {$assoc_kind} is defined here
23+
.bound_on_assoc_const_label = bounds are not allowed on associated constants
24+
25+
hir_analysis_assoc_kind_mismatch_wrap_in_braces_sugg = consider adding braces here
626
727
hir_analysis_assoc_type_binding_not_allowed =
828
associated type bindings are not allowed here
@@ -280,10 +300,6 @@ hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is no
280300
281301
hir_analysis_requires_note = the `{$trait_name}` impl for `{$ty}` requires that `{$error_predicate}`
282302
283-
hir_analysis_return_type_notation_conflicting_bound =
284-
ambiguous associated function `{$assoc_name}` for `{$ty_name}`
285-
.note = `{$assoc_name}` is declared in two supertraits: `{$first_bound}` and `{$second_bound}`
286-
287303
hir_analysis_return_type_notation_equality_bound =
288304
return type notation is not allowed to use type equality
289305
@@ -294,9 +310,6 @@ hir_analysis_return_type_notation_illegal_param_type =
294310
return type notation is not allowed for functions that have type parameters
295311
.label = type parameter declared here
296312
297-
hir_analysis_return_type_notation_missing_method =
298-
cannot find associated function `{$assoc_name}` for `{$ty_name}`
299-
300313
hir_analysis_return_type_notation_on_non_rpitit =
301314
return type notation used on function that is not `async` and does not return `impl Trait`
302315
.note = function returns `{$ty}`, which is not compatible with associated type return bounds

compiler/rustc_hir_analysis/src/astconv/bounds.rs

+34-100
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@ use rustc_errors::struct_span_err;
33
use rustc_hir as hir;
44
use rustc_hir::def::{DefKind, Res};
55
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};
87
use rustc_span::symbol::Ident;
98
use rustc_span::{ErrorGuaranteed, Span};
109
use rustc_trait_selection::traits;
@@ -256,64 +255,49 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
256255

257256
let tcx = self.tcx();
258257

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
269265
} 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(
278270
trait_ref.def_id(),
279-
ty::AssocKind::Type,
271+
assoc_kind,
280272
binding.item_name,
281273
) {
282-
// Simple case: X is defined in the current trait.
274+
// Simple case: The assoc item is defined in the current trait.
283275
trait_ref
284276
} else {
285277
// 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(
288280
|| traits::supertraits(tcx, trait_ref),
289281
trait_ref.skip_binder().print_only_trait_name(),
290282
None,
283+
assoc_kind,
291284
binding.item_name,
292285
path_span,
293-
match binding.kind {
294-
ConvertedBindingKind::Equality(term) => Some(term),
295-
_ => None,
296-
},
286+
Some(&binding),
297287
)?
298288
};
299289

300290
let (assoc_ident, def_scope) =
301291
tcx.adjust_ident_and_get_scope(binding.item_name, candidate.def_id(), hir_ref_id);
302292

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");
317301

318302
if !assoc_item.visibility(tcx).is_accessible_from(def_scope, tcx) {
319303
tcx.sess
@@ -340,7 +324,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
340324
.or_insert(binding.span);
341325
}
342326

343-
let projection_ty = if return_type_notation {
327+
let projection_ty = if let ty::AssocKind::Fn = assoc_kind {
344328
let mut emitted_bad_param_err = false;
345329
// If we have an method return type bound, then we need to substitute
346330
// the method's early bound params with suitable late-bound params.
@@ -467,7 +451,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
467451
let late_bound_in_trait_ref =
468452
tcx.collect_constrained_late_bound_regions(&projection_ty);
469453
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));
471455
debug!(?late_bound_in_trait_ref);
472456
debug!(?late_bound_in_ty);
473457

@@ -492,77 +476,27 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
492476
}
493477
}
494478

495-
let assoc_item_def_id = projection_ty.skip_binder().def_id;
496-
let def_kind = tcx.def_kind(assoc_item_def_id);
497479
match binding.kind {
498-
ConvertedBindingKind::Equality(..) if return_type_notation => {
480+
ConvertedBindingKind::Equality(..) if let ty::AssocKind::Fn = assoc_kind => {
499481
return Err(self.tcx().sess.emit_err(
500482
crate::errors::ReturnTypeNotationEqualityBound { span: binding.span },
501483
));
502484
}
503-
ConvertedBindingKind::Equality(mut term) => {
485+
ConvertedBindingKind::Equality(term) => {
504486
// "Desugar" a constraint like `T: Iterator<Item = u32>` this to
505487
// the "projection predicate" for:
506488
//
507489
// `<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-
}
549490
bounds.push_projection_bound(
550491
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+
}),
553496
binding.span,
554497
);
555498
}
556499
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-
}
566500
// "Desugar" a constraint like `T: Iterator<Item: Debug>` to
567501
//
568502
// `<T as Iterator>::Item: Debug`

0 commit comments

Comments
 (0)