From 5beda81b71509175f1661361a56eb8306b730639 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Fri, 15 Mar 2024 02:19:29 +0100 Subject: [PATCH] Clean up AstConv --- .../rustc_hir_analysis/src/astconv/errors.rs | 114 +++++++++++- .../src/astconv/generics.rs | 12 +- .../rustc_hir_analysis/src/astconv/lint.rs | 2 +- .../rustc_hir_analysis/src/astconv/mod.rs | 176 ++---------------- .../src/astconv/object_safety.rs | 2 +- .../rustc_hir_analysis/src/collect/type_of.rs | 3 +- compiler/rustc_hir_analysis/src/lib.rs | 37 +--- compiler/rustc_hir_typeck/src/closure.rs | 4 +- 8 files changed, 142 insertions(+), 208 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs index 6caba6ff23e52..37fbf45235a86 100644 --- a/compiler/rustc_hir_analysis/src/astconv/errors.rs +++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs @@ -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( @@ -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!("::{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!("::{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!("::{name}")) + .collect::>(), + 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, diff --git a/compiler/rustc_hir_analysis/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs index 63afa4f7e82d2..428eea2f686e9 100644 --- a/compiler/rustc_hir_analysis/src/astconv/generics.rs +++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs @@ -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. @@ -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(); @@ -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() @@ -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 diff --git a/compiler/rustc_hir_analysis/src/astconv/lint.rs b/compiler/rustc_hir_analysis/src/astconv/lint.rs index fb5f3426cea6a..b421a33ba294b 100644 --- a/compiler/rustc_hir_analysis/src/astconv/lint.rs +++ b/compiler/rustc_hir_analysis/src/astconv/lint.rs @@ -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( &self, diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 25df76359a88e..401dd76a9f914 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -214,7 +214,7 @@ pub trait CreateInstantiationsForGenericArgsCtxt<'a, 'tcx> { ) -> ty::GenericArg<'tcx>; } -impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { +impl<'tcx> dyn AstConv<'tcx> + '_ { #[instrument(level = "debug", skip(self), ret)] pub fn ast_region_to_region( &self, @@ -284,8 +284,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { def_id, &[], item_segment, - item_segment.args(), - item_segment.infer_args, None, ty::BoundConstness::NotConst, ); @@ -330,14 +328,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// type itself: `['a]`. The returned `GenericArgsRef` concatenates these two /// lists: `[Vec, u8, 'a]`. #[instrument(level = "debug", skip(self, span), ret)] - fn create_args_for_ast_path<'a>( + fn create_args_for_ast_path( &self, span: Span, def_id: DefId, parent_args: &[ty::GenericArg<'tcx>], - seg: &hir::PathSegment<'_>, - generic_args: &'a hir::GenericArgs<'tcx>, - infer_args: bool, + segment: &hir::PathSegment<'tcx>, self_ty: Option>, constness: ty::BoundConstness, ) -> (GenericArgsRef<'tcx>, GenericArgCountResult) { @@ -365,12 +361,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let mut arg_count = check_generic_arg_count( tcx, def_id, - seg, + segment, generics, - generic_args, GenericArgPosition::Type, self_ty.is_some(), - infer_args, ); if let Err(err) = &arg_count.correct @@ -388,7 +382,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } struct InstantiationsForAstPathCtxt<'a, 'tcx> { - astconv: &'a (dyn AstConv<'tcx> + 'a), + astconv: &'a dyn AstConv<'tcx>, def_id: DefId, generic_args: &'a GenericArgs<'tcx>, span: Span, @@ -547,9 +541,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { astconv: self, def_id, span, - generic_args, + generic_args: segment.args(), inferred_params: vec![], - infer_args, + infer_args: segment.infer_args, }; if let ty::BoundConstness::Const | ty::BoundConstness::ConstIfConst = constness && generics.has_self @@ -592,8 +586,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { item_def_id, parent_args, item_segment, - item_segment.args(), - item_segment.infer_args, None, ty::BoundConstness::NotConst, ); @@ -661,7 +653,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ) -> GenericArgCountResult { let trait_def_id = trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise()); 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.complain_about_internal_fn_trait(span, trait_def_id, trait_segment, false); @@ -671,8 +662,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { trait_def_id, &[], trait_segment, - args, - trait_segment.infer_args, Some(self_ty), constness, ); @@ -690,7 +679,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { bounds.push_trait_bound(tcx, poly_trait_ref, span, polarity); 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, // since we should have emitten an error for them earlier, and they will // not be well-formed! @@ -729,12 +718,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // FIXME(effects) move all host param things in astconv to hir lowering constness: ty::BoundConstness, ) -> 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, trait_def_id, - self_ty, + &[], trait_segment, - is_impl, + Some(self_ty), constness, ); if let Some(b) = trait_segment.args().bindings.first() { @@ -743,30 +734,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { 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( &self, trait_def_id: DefId, @@ -801,115 +768,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } - 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!("::{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!("::{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!("::{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 // 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 @@ -2471,8 +2329,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { def_id, &[], &hir::PathSegment::invalid(), - &GenericArgs::none(), - true, None, ty::BoundConstness::NotConst, ); @@ -2552,9 +2408,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { pub fn ty_of_arg(&self, ty: &hir::Ty<'tcx>, expected_ty: Option>) -> Ty<'tcx> { match ty.kind { - hir::TyKind::Infer if expected_ty.is_some() => { - self.record_ty(ty.hir_id, expected_ty.unwrap(), ty.span); - expected_ty.unwrap() + hir::TyKind::Infer if let Some(expected_ty) = expected_ty => { + self.record_ty(ty.hir_id, expected_ty, ty.span); + expected_ty } _ => self.ast_ty_to_ty(ty), } diff --git a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs index b9543c7a29b2a..d97728c33035d 100644 --- a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs +++ b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs @@ -17,7 +17,7 @@ use smallvec::{smallvec, SmallVec}; use super::AstConv; -impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { +impl<'tcx> dyn AstConv<'tcx> + '_ { pub(super) fn conv_object_ty_poly_trait_ref( &self, span: Span, diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 598dba922d0c4..fd86f2dd1b16c 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -108,8 +108,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { .unwrap() .0 .def_id; - let item_ctxt = &ItemCtxt::new(tcx, item_def_id) as &dyn crate::astconv::AstConv<'_>; - let ty = item_ctxt.ast_ty_to_ty(hir_ty); + let ty = ItemCtxt::new(tcx, item_def_id).to_ty(hir_ty); // 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 diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index b1b36ade50801..e5307f57a2f4d 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -99,19 +99,16 @@ pub mod structured_errors; mod variance; use rustc_hir as hir; +use rustc_hir::def::DefKind; use rustc_middle::middle; use rustc_middle::query::Providers; -use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::ty::{Ty, TyCtxt}; use rustc_middle::util; 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_trait_selection::traits; -use astconv::{AstConv, OnlySelfBounds}; -use bounds::Bounds; -use rustc_hir::def::DefKind; - rustc_fluent_macro::fluent_messages! { "../messages.ftl" } fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi, span: Span) { @@ -200,31 +197,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 // scope. This is derived from the enclosing item-like thing. 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); - 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 + collect::ItemCtxt::new(tcx, env_def_id.def_id).to_ty(hir_ty) } diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index c17af666eb9fe..4bea4bb3e8262 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -780,7 +780,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { decl: &hir::FnDecl<'tcx>, closure_kind: hir::ClosureKind, ) -> ty::PolyFnSig<'tcx> { - let astconv: &dyn AstConv<'_> = self; + let astconv = self.astconv(); trace!("decl = {:#?}", decl); debug!(?closure_kind); @@ -985,7 +985,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { decl: &hir::FnDecl<'tcx>, guar: ErrorGuaranteed, ) -> ty::PolyFnSig<'tcx> { - let astconv: &dyn AstConv<'_> = self; + let astconv = self.astconv(); let err_ty = Ty::new_error(self.tcx, guar); let supplied_arguments = decl.inputs.iter().map(|a| {