Skip to content

Commit 5004096

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 8d1b59a commit 5004096

28 files changed

+417
-324
lines changed

compiler/rustc_hir_analysis/messages.ftl

+15-7
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,24 @@
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
47
hir_analysis_assoc_bound_on_const = expected associated type, found {$descr}
58
.note = trait bounds not allowed on {$descr}
69
10+
hir_analysis_assoc_item_not_found = associated {$assoc_kind} `{$assoc_name}` not found for `{$ty_param_name}`
11+
12+
hir_analysis_assoc_item_not_found_found_in_other_trait_label = there is {$identically_named ->
13+
[true] an
14+
*[false] a similarly named
15+
} associated {$assoc_kind} `{$suggested_name}` in the trait `{$trait_name}`
16+
hir_analysis_assoc_item_not_found_label = associated {$assoc_kind} `{$assoc_name}` not found
17+
hir_analysis_assoc_item_not_found_other_sugg = `{$ty_param_name}` has the following associated {$assoc_kind}
18+
hir_analysis_assoc_item_not_found_similar_in_other_trait_sugg = change the associated {$assoc_kind} name to use `{$suggested_name}` from `{$trait_name}`
19+
hir_analysis_assoc_item_not_found_similar_in_other_trait_with_bound_sugg = and also change the associated {$assoc_kind} name
20+
hir_analysis_assoc_item_not_found_similar_sugg = there is an associated {$assoc_kind} with a similar name
21+
722
hir_analysis_assoc_type_binding_not_allowed =
823
associated type bindings are not allowed here
924
.label = associated type not allowed here
@@ -284,10 +299,6 @@ hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is no
284299
285300
hir_analysis_requires_note = the `{$trait_name}` impl for `{$ty}` requires that `{$error_predicate}`
286301
287-
hir_analysis_return_type_notation_conflicting_bound =
288-
ambiguous associated function `{$assoc_name}` for `{$ty_name}`
289-
.note = `{$assoc_name}` is declared in two supertraits: `{$first_bound}` and `{$second_bound}`
290-
291302
hir_analysis_return_type_notation_equality_bound =
292303
return type notation is not allowed to use type equality
293304
@@ -298,9 +309,6 @@ hir_analysis_return_type_notation_illegal_param_type =
298309
return type notation is not allowed for functions that have type parameters
299310
.label = type parameter declared here
300311
301-
hir_analysis_return_type_notation_missing_method =
302-
cannot find associated function `{$assoc_name}` for `{$ty_name}`
303-
304312
hir_analysis_return_type_notation_on_non_rpitit =
305313
return type notation used on function that is not `async` and does not return `impl Trait`
306314
.note = function returns `{$ty}`, which is not compatible with associated type return bounds

compiler/rustc_hir_analysis/src/astconv/bounds.rs

+27-40
Original file line numberDiff line numberDiff line change
@@ -256,44 +256,35 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
256256

257257
let tcx = self.tcx();
258258

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
259+
let assoc_kind =
260+
if binding.gen_args.parenthesized == hir::GenericArgsParentheses::ReturnTypeNotation {
261+
ty::AssocKind::Fn
262+
} else if let ConvertedBindingKind::Equality(term) = binding.kind
263+
&& let ty::TermKind::Const(_) = term.unpack()
264+
{
265+
ty::AssocKind::Const
269266
} 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(
267+
ty::AssocKind::Type
268+
};
269+
270+
let candidate = if self.trait_defines_associated_item_named(
278271
trait_ref.def_id(),
279-
ty::AssocKind::Type,
272+
assoc_kind,
280273
binding.item_name,
281274
) {
282-
// Simple case: X is defined in the current trait.
275+
// Simple case: The assoc item is defined in the current trait.
283276
trait_ref
284277
} else {
285278
// Otherwise, we have to walk through the supertraits to find
286-
// those that do.
287-
self.one_bound_for_assoc_type(
279+
// those that do contain it.
280+
self.one_bound_for_assoc_item(
288281
|| traits::supertraits(tcx, trait_ref),
289282
trait_ref.skip_binder().print_only_trait_name(),
290283
None,
284+
assoc_kind,
291285
binding.item_name,
292286
path_span,
293-
match binding.kind {
294-
ConvertedBindingKind::Equality(term) => Some(term),
295-
_ => None,
296-
},
287+
Some(&binding.kind),
297288
)?
298289
};
299290

@@ -302,18 +293,11 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
302293

303294
// We have already adjusted the item name above, so compare with `ident.normalize_to_macros_2_0()` instead
304295
// 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");
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.
@@ -495,7 +479,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
495479
let assoc_item_def_id = projection_ty.skip_binder().def_id;
496480
let def_kind = tcx.def_kind(assoc_item_def_id);
497481
match binding.kind {
498-
ConvertedBindingKind::Equality(..) if return_type_notation => {
482+
ConvertedBindingKind::Equality(..) if let ty::AssocKind::Fn = assoc_kind => {
499483
return Err(self.tcx().sess.emit_err(
500484
crate::errors::ReturnTypeNotationEqualityBound { span: binding.span },
501485
));
@@ -505,6 +489,9 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
505489
// the "projection predicate" for:
506490
//
507491
// `<T as Iterator>::Item = u32`
492+
// FIXME(fmease): This is no longer reachable since we no longer fall back to
493+
// consts from types above. Ideally, we would start a second "probe" here
494+
// where AssocKind is not fixed and then provide a nice error message.
508495
match (def_kind, term.unpack()) {
509496
(DefKind::AssocTy, ty::TermKind::Ty(_))
510497
| (DefKind::AssocConst, ty::TermKind::Const(_)) => (),

0 commit comments

Comments
 (0)