Rollup merge of #122527 - fmease:clean-up-hir-ty-lowering, r=compiler-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 https://github.com/rust-lang/rust/pull/120926#issuecomment-1997984483. --- * 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](https://github.com/rust-lang/rust/pull/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
This commit is contained in:
commit
277df5e176
@ -22,7 +22,7 @@
|
|||||||
use rustc_span::{Span, Symbol, DUMMY_SP};
|
use rustc_span::{Span, Symbol, DUMMY_SP};
|
||||||
use rustc_trait_selection::traits::object_safety_violations_for_assoc_item;
|
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
|
/// On missing type parameters, emit an E0393 error and provide a structured suggestion using
|
||||||
/// the type parameter's name as a placeholder.
|
/// the type parameter's name as a placeholder.
|
||||||
pub(crate) fn complain_about_missing_type_params(
|
pub(crate) fn complain_about_missing_type_params(
|
||||||
@ -349,6 +349,118 @@ fn complain_about_assoc_kind_mismatch(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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(
|
pub(crate) fn complain_about_ambiguous_inherent_assoc_type(
|
||||||
&self,
|
&self,
|
||||||
name: Ident,
|
name: Ident,
|
||||||
|
@ -409,15 +409,12 @@ pub fn check_generic_arg_count_for_call(
|
|||||||
seg: &hir::PathSegment<'_>,
|
seg: &hir::PathSegment<'_>,
|
||||||
is_method_call: IsMethodCall,
|
is_method_call: IsMethodCall,
|
||||||
) -> GenericArgCountResult {
|
) -> GenericArgCountResult {
|
||||||
let empty_args = hir::GenericArgs::none();
|
|
||||||
let gen_args = seg.args.unwrap_or(&empty_args);
|
|
||||||
let gen_pos = match is_method_call {
|
let gen_pos = match is_method_call {
|
||||||
IsMethodCall::Yes => GenericArgPosition::MethodCall,
|
IsMethodCall::Yes => GenericArgPosition::MethodCall,
|
||||||
IsMethodCall::No => GenericArgPosition::Value,
|
IsMethodCall::No => GenericArgPosition::Value,
|
||||||
};
|
};
|
||||||
let has_self = generics.parent.is_none() && generics.has_self;
|
let has_self = generics.parent.is_none() && generics.has_self;
|
||||||
|
check_generic_arg_count(tcx, def_id, seg, generics, gen_pos, has_self)
|
||||||
check_generic_arg_count(tcx, def_id, seg, generics, gen_args, gen_pos, has_self, seg.infer_args)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks that the correct number of generic arguments have been provided.
|
/// Checks that the correct number of generic arguments have been provided.
|
||||||
@ -428,11 +425,10 @@ pub(crate) fn check_generic_arg_count(
|
|||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
seg: &hir::PathSegment<'_>,
|
seg: &hir::PathSegment<'_>,
|
||||||
gen_params: &ty::Generics,
|
gen_params: &ty::Generics,
|
||||||
gen_args: &hir::GenericArgs<'_>,
|
|
||||||
gen_pos: GenericArgPosition,
|
gen_pos: GenericArgPosition,
|
||||||
has_self: bool,
|
has_self: bool,
|
||||||
infer_args: bool,
|
|
||||||
) -> GenericArgCountResult {
|
) -> GenericArgCountResult {
|
||||||
|
let gen_args = seg.args();
|
||||||
let default_counts = gen_params.own_defaults();
|
let default_counts = gen_params.own_defaults();
|
||||||
let param_counts = gen_params.own_counts();
|
let param_counts = gen_params.own_counts();
|
||||||
|
|
||||||
@ -453,7 +449,7 @@ pub(crate) fn check_generic_arg_count(
|
|||||||
.count();
|
.count();
|
||||||
let named_const_param_count = param_counts.consts - synth_const_param_count;
|
let named_const_param_count = param_counts.consts - synth_const_param_count;
|
||||||
let infer_lifetimes =
|
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
|
if gen_pos != GenericArgPosition::Type
|
||||||
&& let Some(b) = gen_args.bindings.first()
|
&& let Some(b) = gen_args.bindings.first()
|
||||||
@ -586,7 +582,7 @@ pub(crate) fn check_generic_arg_count(
|
|||||||
};
|
};
|
||||||
|
|
||||||
let args_correct = {
|
let args_correct = {
|
||||||
let expected_min = if infer_args {
|
let expected_min = if seg.infer_args {
|
||||||
0
|
0
|
||||||
} else {
|
} else {
|
||||||
param_counts.consts + named_type_param_count
|
param_counts.consts + named_type_param_count
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
use super::AstConv;
|
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.
|
/// Make sure that we are in the condition to suggest the blanket implementation.
|
||||||
pub(super) fn maybe_lint_blanket_trait_impl<G: EmissionGuarantee>(
|
pub(super) fn maybe_lint_blanket_trait_impl<G: EmissionGuarantee>(
|
||||||
&self,
|
&self,
|
||||||
|
@ -214,7 +214,7 @@ fn inferred_kind(
|
|||||||
) -> ty::GenericArg<'tcx>;
|
) -> ty::GenericArg<'tcx>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
impl<'tcx> dyn AstConv<'tcx> + '_ {
|
||||||
#[instrument(level = "debug", skip(self), ret)]
|
#[instrument(level = "debug", skip(self), ret)]
|
||||||
pub fn ast_region_to_region(
|
pub fn ast_region_to_region(
|
||||||
&self,
|
&self,
|
||||||
@ -284,8 +284,6 @@ pub fn ast_path_args_for_ty(
|
|||||||
def_id,
|
def_id,
|
||||||
&[],
|
&[],
|
||||||
item_segment,
|
item_segment,
|
||||||
item_segment.args(),
|
|
||||||
item_segment.infer_args,
|
|
||||||
None,
|
None,
|
||||||
ty::BoundConstness::NotConst,
|
ty::BoundConstness::NotConst,
|
||||||
);
|
);
|
||||||
@ -330,14 +328,12 @@ pub fn ast_path_args_for_ty(
|
|||||||
/// type itself: `['a]`. The returned `GenericArgsRef` concatenates these two
|
/// type itself: `['a]`. The returned `GenericArgsRef` concatenates these two
|
||||||
/// lists: `[Vec<u8>, u8, 'a]`.
|
/// lists: `[Vec<u8>, u8, 'a]`.
|
||||||
#[instrument(level = "debug", skip(self, span), ret)]
|
#[instrument(level = "debug", skip(self, span), ret)]
|
||||||
fn create_args_for_ast_path<'a>(
|
fn create_args_for_ast_path(
|
||||||
&self,
|
&self,
|
||||||
span: Span,
|
span: Span,
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
parent_args: &[ty::GenericArg<'tcx>],
|
parent_args: &[ty::GenericArg<'tcx>],
|
||||||
seg: &hir::PathSegment<'_>,
|
segment: &hir::PathSegment<'tcx>,
|
||||||
generic_args: &'a hir::GenericArgs<'tcx>,
|
|
||||||
infer_args: bool,
|
|
||||||
self_ty: Option<Ty<'tcx>>,
|
self_ty: Option<Ty<'tcx>>,
|
||||||
constness: ty::BoundConstness,
|
constness: ty::BoundConstness,
|
||||||
) -> (GenericArgsRef<'tcx>, GenericArgCountResult) {
|
) -> (GenericArgsRef<'tcx>, GenericArgCountResult) {
|
||||||
@ -365,12 +361,10 @@ fn create_args_for_ast_path<'a>(
|
|||||||
let mut arg_count = check_generic_arg_count(
|
let mut arg_count = check_generic_arg_count(
|
||||||
tcx,
|
tcx,
|
||||||
def_id,
|
def_id,
|
||||||
seg,
|
segment,
|
||||||
generics,
|
generics,
|
||||||
generic_args,
|
|
||||||
GenericArgPosition::Type,
|
GenericArgPosition::Type,
|
||||||
self_ty.is_some(),
|
self_ty.is_some(),
|
||||||
infer_args,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Err(err) = &arg_count.correct
|
if let Err(err) = &arg_count.correct
|
||||||
@ -388,7 +382,7 @@ fn create_args_for_ast_path<'a>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct InstantiationsForAstPathCtxt<'a, 'tcx> {
|
struct InstantiationsForAstPathCtxt<'a, 'tcx> {
|
||||||
astconv: &'a (dyn AstConv<'tcx> + 'a),
|
astconv: &'a dyn AstConv<'tcx>,
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
generic_args: &'a GenericArgs<'tcx>,
|
generic_args: &'a GenericArgs<'tcx>,
|
||||||
span: Span,
|
span: Span,
|
||||||
@ -547,9 +541,9 @@ fn inferred_kind(
|
|||||||
astconv: self,
|
astconv: self,
|
||||||
def_id,
|
def_id,
|
||||||
span,
|
span,
|
||||||
generic_args,
|
generic_args: segment.args(),
|
||||||
inferred_params: vec![],
|
inferred_params: vec![],
|
||||||
infer_args,
|
infer_args: segment.infer_args,
|
||||||
};
|
};
|
||||||
if let ty::BoundConstness::Const | ty::BoundConstness::ConstIfConst = constness
|
if let ty::BoundConstness::Const | ty::BoundConstness::ConstIfConst = constness
|
||||||
&& generics.has_self
|
&& generics.has_self
|
||||||
@ -592,8 +586,6 @@ pub fn create_args_for_associated_item(
|
|||||||
item_def_id,
|
item_def_id,
|
||||||
parent_args,
|
parent_args,
|
||||||
item_segment,
|
item_segment,
|
||||||
item_segment.args(),
|
|
||||||
item_segment.infer_args,
|
|
||||||
None,
|
None,
|
||||||
ty::BoundConstness::NotConst,
|
ty::BoundConstness::NotConst,
|
||||||
);
|
);
|
||||||
@ -661,7 +653,6 @@ pub(crate) fn instantiate_poly_trait_ref(
|
|||||||
) -> GenericArgCountResult {
|
) -> GenericArgCountResult {
|
||||||
let trait_def_id = trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise());
|
let trait_def_id = trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise());
|
||||||
let trait_segment = trait_ref.path.segments.last().unwrap();
|
let trait_segment = trait_ref.path.segments.last().unwrap();
|
||||||
let args = trait_segment.args();
|
|
||||||
|
|
||||||
self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1.iter(), |_| {});
|
self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1.iter(), |_| {});
|
||||||
self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment, false);
|
self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment, false);
|
||||||
@ -671,8 +662,6 @@ pub(crate) fn instantiate_poly_trait_ref(
|
|||||||
trait_def_id,
|
trait_def_id,
|
||||||
&[],
|
&[],
|
||||||
trait_segment,
|
trait_segment,
|
||||||
args,
|
|
||||||
trait_segment.infer_args,
|
|
||||||
Some(self_ty),
|
Some(self_ty),
|
||||||
constness,
|
constness,
|
||||||
);
|
);
|
||||||
@ -690,7 +679,7 @@ pub(crate) fn instantiate_poly_trait_ref(
|
|||||||
bounds.push_trait_bound(tcx, poly_trait_ref, span, polarity);
|
bounds.push_trait_bound(tcx, poly_trait_ref, span, polarity);
|
||||||
|
|
||||||
let mut dup_bindings = FxIndexMap::default();
|
let mut dup_bindings = FxIndexMap::default();
|
||||||
for binding in args.bindings {
|
for binding in trait_segment.args().bindings {
|
||||||
// Don't register additional associated type bounds for negative bounds,
|
// Don't register additional associated type bounds for negative bounds,
|
||||||
// since we should have emitten an error for them earlier, and they will
|
// since we should have emitten an error for them earlier, and they will
|
||||||
// not be well-formed!
|
// not be well-formed!
|
||||||
@ -729,12 +718,14 @@ fn ast_path_to_mono_trait_ref(
|
|||||||
// FIXME(effects) move all host param things in astconv to hir lowering
|
// FIXME(effects) move all host param things in astconv to hir lowering
|
||||||
constness: ty::BoundConstness,
|
constness: ty::BoundConstness,
|
||||||
) -> ty::TraitRef<'tcx> {
|
) -> ty::TraitRef<'tcx> {
|
||||||
let (generic_args, _) = self.create_args_for_ast_trait_ref(
|
self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment, is_impl);
|
||||||
|
|
||||||
|
let (generic_args, _) = self.create_args_for_ast_path(
|
||||||
span,
|
span,
|
||||||
trait_def_id,
|
trait_def_id,
|
||||||
self_ty,
|
&[],
|
||||||
trait_segment,
|
trait_segment,
|
||||||
is_impl,
|
Some(self_ty),
|
||||||
constness,
|
constness,
|
||||||
);
|
);
|
||||||
if let Some(b) = trait_segment.args().bindings.first() {
|
if let Some(b) = trait_segment.args().bindings.first() {
|
||||||
@ -743,30 +734,6 @@ fn ast_path_to_mono_trait_ref(
|
|||||||
ty::TraitRef::new(self.tcx(), trait_def_id, generic_args)
|
ty::TraitRef::new(self.tcx(), trait_def_id, generic_args)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self, span))]
|
|
||||||
fn create_args_for_ast_trait_ref<'a>(
|
|
||||||
&self,
|
|
||||||
span: Span,
|
|
||||||
trait_def_id: DefId,
|
|
||||||
self_ty: Ty<'tcx>,
|
|
||||||
trait_segment: &'a hir::PathSegment<'tcx>,
|
|
||||||
is_impl: bool,
|
|
||||||
constness: ty::BoundConstness,
|
|
||||||
) -> (GenericArgsRef<'tcx>, GenericArgCountResult) {
|
|
||||||
self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment, is_impl);
|
|
||||||
|
|
||||||
self.create_args_for_ast_path(
|
|
||||||
span,
|
|
||||||
trait_def_id,
|
|
||||||
&[],
|
|
||||||
trait_segment,
|
|
||||||
trait_segment.args(),
|
|
||||||
trait_segment.infer_args,
|
|
||||||
Some(self_ty),
|
|
||||||
constness,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn trait_defines_associated_item_named(
|
fn trait_defines_associated_item_named(
|
||||||
&self,
|
&self,
|
||||||
trait_def_id: DefId,
|
trait_def_id: DefId,
|
||||||
@ -801,115 +768,6 @@ fn ast_path_to_ty(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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}")),
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
// Search for a bound on a type parameter which includes the associated item
|
// Search for a bound on a type parameter which includes the associated item
|
||||||
// given by `assoc_name`. `ty_param_def_id` is the `DefId` of the type parameter
|
// given by `assoc_name`. `ty_param_def_id` is the `DefId` of the type parameter
|
||||||
// This function will fail if there are no suitable bounds or there is
|
// This function will fail if there are no suitable bounds or there is
|
||||||
@ -2471,8 +2329,6 @@ fn ast_ty_to_ty_inner(
|
|||||||
def_id,
|
def_id,
|
||||||
&[],
|
&[],
|
||||||
&hir::PathSegment::invalid(),
|
&hir::PathSegment::invalid(),
|
||||||
&GenericArgs::none(),
|
|
||||||
true,
|
|
||||||
None,
|
None,
|
||||||
ty::BoundConstness::NotConst,
|
ty::BoundConstness::NotConst,
|
||||||
);
|
);
|
||||||
@ -2552,9 +2408,9 @@ fn impl_trait_ty_to_ty(
|
|||||||
|
|
||||||
pub fn ty_of_arg(&self, ty: &hir::Ty<'tcx>, expected_ty: Option<Ty<'tcx>>) -> Ty<'tcx> {
|
pub fn ty_of_arg(&self, ty: &hir::Ty<'tcx>, expected_ty: Option<Ty<'tcx>>) -> Ty<'tcx> {
|
||||||
match ty.kind {
|
match ty.kind {
|
||||||
hir::TyKind::Infer if expected_ty.is_some() => {
|
hir::TyKind::Infer if let Some(expected_ty) = expected_ty => {
|
||||||
self.record_ty(ty.hir_id, expected_ty.unwrap(), ty.span);
|
self.record_ty(ty.hir_id, expected_ty, ty.span);
|
||||||
expected_ty.unwrap()
|
expected_ty
|
||||||
}
|
}
|
||||||
_ => self.ast_ty_to_ty(ty),
|
_ => self.ast_ty_to_ty(ty),
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
use super::AstConv;
|
use super::AstConv;
|
||||||
|
|
||||||
impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
impl<'tcx> dyn AstConv<'tcx> + '_ {
|
||||||
pub(super) fn conv_object_ty_poly_trait_ref(
|
pub(super) fn conv_object_ty_poly_trait_ref(
|
||||||
&self,
|
&self,
|
||||||
span: Span,
|
span: Span,
|
||||||
|
@ -108,8 +108,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.0
|
.0
|
||||||
.def_id;
|
.def_id;
|
||||||
let item_ctxt = &ItemCtxt::new(tcx, item_def_id) as &dyn crate::astconv::AstConv<'_>;
|
let ty = ItemCtxt::new(tcx, item_def_id).to_ty(hir_ty);
|
||||||
let ty = item_ctxt.ast_ty_to_ty(hir_ty);
|
|
||||||
|
|
||||||
// Iterate through the generics of the projection to find the one that corresponds to
|
// Iterate through the generics of the projection to find the one that corresponds to
|
||||||
// the def_id that this query was called with. We filter to only type and const args here
|
// the def_id that this query was called with. We filter to only type and const args here
|
||||||
|
@ -100,19 +100,16 @@
|
|||||||
|
|
||||||
use rustc_errors::ErrorGuaranteed;
|
use rustc_errors::ErrorGuaranteed;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_middle::middle;
|
use rustc_middle::middle;
|
||||||
use rustc_middle::query::Providers;
|
use rustc_middle::query::Providers;
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
use rustc_middle::ty::{Ty, TyCtxt};
|
||||||
use rustc_middle::util;
|
use rustc_middle::util;
|
||||||
use rustc_session::parse::feature_err;
|
use rustc_session::parse::feature_err;
|
||||||
use rustc_span::{symbol::sym, Span, DUMMY_SP};
|
use rustc_span::{symbol::sym, Span};
|
||||||
use rustc_target::spec::abi::Abi;
|
use rustc_target::spec::abi::Abi;
|
||||||
use rustc_trait_selection::traits;
|
use rustc_trait_selection::traits;
|
||||||
|
|
||||||
use astconv::{AstConv, OnlySelfBounds};
|
|
||||||
use bounds::Bounds;
|
|
||||||
use rustc_hir::def::DefKind;
|
|
||||||
|
|
||||||
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
|
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
|
||||||
|
|
||||||
fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi, span: Span) {
|
fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi, span: Span) {
|
||||||
@ -222,31 +219,5 @@ pub fn hir_ty_to_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx>
|
|||||||
// def-ID that will be used to determine the traits/predicates in
|
// def-ID that will be used to determine the traits/predicates in
|
||||||
// scope. This is derived from the enclosing item-like thing.
|
// scope. This is derived from the enclosing item-like thing.
|
||||||
let env_def_id = tcx.hir().get_parent_item(hir_ty.hir_id);
|
let env_def_id = tcx.hir().get_parent_item(hir_ty.hir_id);
|
||||||
let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.def_id);
|
collect::ItemCtxt::new(tcx, env_def_id.def_id).to_ty(hir_ty)
|
||||||
item_cx.astconv().ast_ty_to_ty(hir_ty)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn hir_trait_to_predicates<'tcx>(
|
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
hir_trait: &hir::TraitRef<'tcx>,
|
|
||||||
self_ty: Ty<'tcx>,
|
|
||||||
) -> Bounds<'tcx> {
|
|
||||||
// In case there are any projections, etc., find the "environment"
|
|
||||||
// def-ID that will be used to determine the traits/predicates in
|
|
||||||
// scope. This is derived from the enclosing item-like thing.
|
|
||||||
let env_def_id = tcx.hir().get_parent_item(hir_trait.hir_ref_id);
|
|
||||||
let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.def_id);
|
|
||||||
let mut bounds = Bounds::default();
|
|
||||||
let _ = &item_cx.astconv().instantiate_poly_trait_ref(
|
|
||||||
hir_trait,
|
|
||||||
DUMMY_SP,
|
|
||||||
ty::BoundConstness::NotConst,
|
|
||||||
ty::ImplPolarity::Positive,
|
|
||||||
self_ty,
|
|
||||||
&mut bounds,
|
|
||||||
true,
|
|
||||||
OnlySelfBounds(false),
|
|
||||||
);
|
|
||||||
|
|
||||||
bounds
|
|
||||||
}
|
}
|
||||||
|
@ -780,7 +780,7 @@ fn supplied_sig_of_closure(
|
|||||||
decl: &hir::FnDecl<'tcx>,
|
decl: &hir::FnDecl<'tcx>,
|
||||||
closure_kind: hir::ClosureKind,
|
closure_kind: hir::ClosureKind,
|
||||||
) -> ty::PolyFnSig<'tcx> {
|
) -> ty::PolyFnSig<'tcx> {
|
||||||
let astconv: &dyn AstConv<'_> = self;
|
let astconv = self.astconv();
|
||||||
|
|
||||||
trace!("decl = {:#?}", decl);
|
trace!("decl = {:#?}", decl);
|
||||||
debug!(?closure_kind);
|
debug!(?closure_kind);
|
||||||
@ -985,7 +985,7 @@ fn error_sig_of_closure(
|
|||||||
decl: &hir::FnDecl<'tcx>,
|
decl: &hir::FnDecl<'tcx>,
|
||||||
guar: ErrorGuaranteed,
|
guar: ErrorGuaranteed,
|
||||||
) -> ty::PolyFnSig<'tcx> {
|
) -> ty::PolyFnSig<'tcx> {
|
||||||
let astconv: &dyn AstConv<'_> = self;
|
let astconv = self.astconv();
|
||||||
let err_ty = Ty::new_error(self.tcx, guar);
|
let err_ty = Ty::new_error(self.tcx, guar);
|
||||||
|
|
||||||
let supplied_arguments = decl.inputs.iter().map(|a| {
|
let supplied_arguments = decl.inputs.iter().map(|a| {
|
||||||
|
Loading…
Reference in New Issue
Block a user