Skip to content

Commit

Permalink
Rollup merge of #122527 - fmease:clean-up-hir-ty-lowering, r=compiler…
Browse files Browse the repository at this point in the history
…-errors

Clean up AstConv

Split off from #120926 to make it only contain the renaming & (doc) comment updates.
Any changes other than that which have accumulated over time are now part of this PR.
Let's be disciplined ;) Inspired by #120926 (comment).

---

* Remove `hir_trait_to_predicates`
  * Unused since #113671
* Inline `create_args_for_ast_trait_ref`
  * Only had a single call site
  * Having it as a separate method didn't gain us anything
* Use an if-let guard somewhere to avoid unwrapping
* Avoid explicit trait object lifetimes
  * More legible, stylistic-only (the updated code is 100% semantically identical)
  * Use explicitly elided lifetimes in impl headers, they get elaborated to distinct lifetimes
  * Make use of [object lifetime defaulting](https://doc.rust-lang.org/reference/lifetime-elision.html#default-trait-object-lifetimes) for a trait object type inside of a reference type somewhere
* Use preexisting dedicated method `ItemCtxt::to_ty` over `<dyn AstConv<'_>>::ast_ty_to_ty`
* Use preexisting dedicated method `AstConv::astconv` over explicit coercions
* Simplify the function signature of `create_args_for_ast_path` and of `check_generic_arg_count`
  * In both cases redundant information was passed rendering the call sites verbose and confusing
  * No perf impact (tested in [#120926](#120926))
* Move diagnostic method `report_ambiguous_associated_type` from `astconv` to `astconv::errors`
  * The submodule `errors` exists specifically for that purpose
  * Use it to keep the main module clean & short
  • Loading branch information
matthiaskrgr committed Mar 15, 2024
2 parents c588677 + 5beda81 commit e1b25d9
Show file tree
Hide file tree
Showing 8 changed files with 142 additions and 208 deletions.
114 changes: 113 additions & 1 deletion compiler/rustc_hir_analysis/src/astconv/errors.rs
Expand Up @@ -22,7 +22,7 @@ use rustc_span::symbol::{sym, Ident};
use rustc_span::{Span, Symbol, DUMMY_SP};
use rustc_trait_selection::traits::object_safety_violations_for_assoc_item;

impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
impl<'tcx> dyn AstConv<'tcx> + '_ {
/// On missing type parameters, emit an E0393 error and provide a structured suggestion using
/// the type parameter's name as a placeholder.
pub(crate) fn complain_about_missing_type_params(
Expand Down Expand Up @@ -349,6 +349,118 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
})
}

pub(super) fn report_ambiguous_associated_type(
&self,
span: Span,
types: &[String],
traits: &[String],
name: Symbol,
) -> ErrorGuaranteed {
let mut err =
struct_span_code_err!(self.tcx().dcx(), span, E0223, "ambiguous associated type");
if self
.tcx()
.resolutions(())
.confused_type_with_std_module
.keys()
.any(|full_span| full_span.contains(span))
{
err.span_suggestion_verbose(
span.shrink_to_lo(),
"you are looking for the module in `std`, not the primitive type",
"std::",
Applicability::MachineApplicable,
);
} else {
let mut types = types.to_vec();
types.sort();
let mut traits = traits.to_vec();
traits.sort();
match (&types[..], &traits[..]) {
([], []) => {
err.span_suggestion_verbose(
span,
format!(
"if there were a type named `Type` that implements a trait named \
`Trait` with associated type `{name}`, you could use the \
fully-qualified path",
),
format!("<Type as Trait>::{name}"),
Applicability::HasPlaceholders,
);
}
([], [trait_str]) => {
err.span_suggestion_verbose(
span,
format!(
"if there were a type named `Example` that implemented `{trait_str}`, \
you could use the fully-qualified path",
),
format!("<Example as {trait_str}>::{name}"),
Applicability::HasPlaceholders,
);
}
([], traits) => {
err.span_suggestions(
span,
format!(
"if there were a type named `Example` that implemented one of the \
traits with associated type `{name}`, you could use the \
fully-qualified path",
),
traits
.iter()
.map(|trait_str| format!("<Example as {trait_str}>::{name}"))
.collect::<Vec<_>>(),
Applicability::HasPlaceholders,
);
}
([type_str], []) => {
err.span_suggestion_verbose(
span,
format!(
"if there were a trait named `Example` with associated type `{name}` \
implemented for `{type_str}`, you could use the fully-qualified path",
),
format!("<{type_str} as Example>::{name}"),
Applicability::HasPlaceholders,
);
}
(types, []) => {
err.span_suggestions(
span,
format!(
"if there were a trait named `Example` with associated type `{name}` \
implemented for one of the types, you could use the fully-qualified \
path",
),
types
.into_iter()
.map(|type_str| format!("<{type_str} as Example>::{name}")),
Applicability::HasPlaceholders,
);
}
(types, traits) => {
let mut suggestions = vec![];
for type_str in types {
for trait_str in traits {
suggestions.push(format!("<{type_str} as {trait_str}>::{name}"));
}
}
err.span_suggestions(
span,
"use fully-qualified syntax",
suggestions,
Applicability::MachineApplicable,
);
}
}
}
let reported = err.emit();
self.set_tainted_by_errors(reported);
reported
}

pub(crate) fn complain_about_ambiguous_inherent_assoc_type(
&self,
name: Ident,
Expand Down
12 changes: 4 additions & 8 deletions compiler/rustc_hir_analysis/src/astconv/generics.rs
Expand Up @@ -409,15 +409,12 @@ pub fn check_generic_arg_count_for_call(
seg: &hir::PathSegment<'_>,
is_method_call: IsMethodCall,
) -> GenericArgCountResult {
let empty_args = hir::GenericArgs::none();
let gen_args = seg.args.unwrap_or(&empty_args);
let gen_pos = match is_method_call {
IsMethodCall::Yes => GenericArgPosition::MethodCall,
IsMethodCall::No => GenericArgPosition::Value,
};
let has_self = generics.parent.is_none() && generics.has_self;

check_generic_arg_count(tcx, def_id, seg, generics, gen_args, gen_pos, has_self, seg.infer_args)
check_generic_arg_count(tcx, def_id, seg, generics, gen_pos, has_self)
}

/// Checks that the correct number of generic arguments have been provided.
Expand All @@ -428,11 +425,10 @@ pub(crate) fn check_generic_arg_count(
def_id: DefId,
seg: &hir::PathSegment<'_>,
gen_params: &ty::Generics,
gen_args: &hir::GenericArgs<'_>,
gen_pos: GenericArgPosition,
has_self: bool,
infer_args: bool,
) -> GenericArgCountResult {
let gen_args = seg.args();
let default_counts = gen_params.own_defaults();
let param_counts = gen_params.own_counts();

Expand All @@ -453,7 +449,7 @@ pub(crate) fn check_generic_arg_count(
.count();
let named_const_param_count = param_counts.consts - synth_const_param_count;
let infer_lifetimes =
(gen_pos != GenericArgPosition::Type || infer_args) && !gen_args.has_lifetime_params();
(gen_pos != GenericArgPosition::Type || seg.infer_args) && !gen_args.has_lifetime_params();

if gen_pos != GenericArgPosition::Type
&& let Some(b) = gen_args.bindings.first()
Expand Down Expand Up @@ -586,7 +582,7 @@ pub(crate) fn check_generic_arg_count(
};

let args_correct = {
let expected_min = if infer_args {
let expected_min = if seg.infer_args {
0
} else {
param_counts.consts + named_type_param_count
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/astconv/lint.rs
Expand Up @@ -8,7 +8,7 @@ use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamNa

use super::AstConv;

impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
impl<'tcx> dyn AstConv<'tcx> + '_ {
/// Make sure that we are in the condition to suggest the blanket implementation.
pub(super) fn maybe_lint_blanket_trait_impl<G: EmissionGuarantee>(
&self,
Expand Down

0 comments on commit e1b25d9

Please sign in to comment.