1
Fork 0

Make selfless dyn AstConv methods into toplevel functions

This commit is contained in:
Maybe Waffle 2023-01-11 19:07:03 +00:00
parent 89f1555824
commit d642781708
4 changed files with 610 additions and 619 deletions

View file

@ -1,6 +1,6 @@
use super::IsMethodCall; use super::IsMethodCall;
use crate::astconv::{ use crate::astconv::{
AstConv, CreateSubstsForGenericArgsCtxt, ExplicitLateBound, GenericArgCountMismatch, CreateSubstsForGenericArgsCtxt, ExplicitLateBound, GenericArgCountMismatch,
GenericArgCountResult, GenericArgPosition, GenericArgCountResult, GenericArgPosition,
}; };
use crate::errors::AssocTypeBindingNotAllowed; use crate::errors::AssocTypeBindingNotAllowed;
@ -18,16 +18,15 @@ use rustc_session::lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS;
use rustc_span::{symbol::kw, Span}; use rustc_span::{symbol::kw, Span};
use smallvec::SmallVec; use smallvec::SmallVec;
impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// Report an error that a generic argument did not match the generic parameter that was
/// Report an error that a generic argument did not match the generic parameter that was /// expected.
/// expected. fn generic_arg_mismatch_err(
fn generic_arg_mismatch_err(
tcx: TyCtxt<'_>, tcx: TyCtxt<'_>,
arg: &GenericArg<'_>, arg: &GenericArg<'_>,
param: &GenericParamDef, param: &GenericParamDef,
possible_ordering_error: bool, possible_ordering_error: bool,
help: Option<&str>, help: Option<&str>,
) { ) {
let sess = tcx.sess; let sess = tcx.sess;
let mut err = struct_span_err!( let mut err = struct_span_err!(
sess, sess,
@ -42,9 +41,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
if matches!(arg, GenericArg::Type(hir::Ty { kind: hir::TyKind::Infer, .. })) { if matches!(arg, GenericArg::Type(hir::Ty { kind: hir::TyKind::Infer, .. })) {
err.help("const arguments cannot yet be inferred with `_`"); err.help("const arguments cannot yet be inferred with `_`");
if sess.is_nightly_build() { if sess.is_nightly_build() {
err.help( err.help("add `#![feature(generic_arg_infer)]` to the crate attributes to enable");
"add `#![feature(generic_arg_infer)]` to the crate attributes to enable",
);
} }
} }
} }
@ -73,9 +70,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
) => match path.res { ) => match path.res {
Res::Err => { Res::Err => {
add_braces_suggestion(arg, &mut err); add_braces_suggestion(arg, &mut err);
err.set_primary_message( err.set_primary_message("unresolved item provided when a constant was expected")
"unresolved item provided when a constant was expected",
)
.emit(); .emit();
return; return;
} }
@ -115,14 +110,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
} }
(GenericArg::Const(cnst), GenericParamDefKind::Type { .. }) => { (GenericArg::Const(cnst), GenericParamDefKind::Type { .. }) => {
let body = tcx.hir().body(cnst.value.body); let body = tcx.hir().body(cnst.value.body);
if let rustc_hir::ExprKind::Path(rustc_hir::QPath::Resolved(_, path)) = if let rustc_hir::ExprKind::Path(rustc_hir::QPath::Resolved(_, path)) = body.value.kind
body.value.kind
{ {
if let Res::Def(DefKind::Fn { .. }, id) = path.res { if let Res::Def(DefKind::Fn { .. }, id) = path.res {
err.help(&format!( err.help(&format!("`{}` is a function item, not a type", tcx.item_name(id)));
"`{}` is a function item, not a type",
tcx.item_name(id)
));
err.help("function item types cannot be named directly"); err.help("function item types cannot be named directly");
} }
} }
@ -147,38 +138,38 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
} }
err.emit(); err.emit();
} }
/// Creates the relevant generic argument substitutions /// Creates the relevant generic argument substitutions
/// corresponding to a set of generic parameters. This is a /// corresponding to a set of generic parameters. This is a
/// rather complex function. Let us try to explain the role /// rather complex function. Let us try to explain the role
/// of each of its parameters: /// of each of its parameters:
/// ///
/// To start, we are given the `def_id` of the thing we are /// To start, we are given the `def_id` of the thing we are
/// creating the substitutions for, and a partial set of /// creating the substitutions for, and a partial set of
/// substitutions `parent_substs`. In general, the substitutions /// substitutions `parent_substs`. In general, the substitutions
/// for an item begin with substitutions for all the "parents" of /// for an item begin with substitutions for all the "parents" of
/// that item -- e.g., for a method it might include the /// that item -- e.g., for a method it might include the
/// parameters from the impl. /// parameters from the impl.
/// ///
/// Therefore, the method begins by walking down these parents, /// Therefore, the method begins by walking down these parents,
/// starting with the outermost parent and proceed inwards until /// starting with the outermost parent and proceed inwards until
/// it reaches `def_id`. For each parent `P`, it will check `parent_substs` /// it reaches `def_id`. For each parent `P`, it will check `parent_substs`
/// first to see if the parent's substitutions are listed in there. If so, /// first to see if the parent's substitutions are listed in there. If so,
/// we can append those and move on. Otherwise, it invokes the /// we can append those and move on. Otherwise, it invokes the
/// three callback functions: /// three callback functions:
/// ///
/// - `args_for_def_id`: given the `DefId` `P`, supplies back the /// - `args_for_def_id`: given the `DefId` `P`, supplies back the
/// generic arguments that were given to that parent from within /// generic arguments that were given to that parent from within
/// the path; so e.g., if you have `<T as Foo>::Bar`, the `DefId` /// the path; so e.g., if you have `<T as Foo>::Bar`, the `DefId`
/// might refer to the trait `Foo`, and the arguments might be /// might refer to the trait `Foo`, and the arguments might be
/// `[T]`. The boolean value indicates whether to infer values /// `[T]`. The boolean value indicates whether to infer values
/// for arguments whose values were not explicitly provided. /// for arguments whose values were not explicitly provided.
/// - `provided_kind`: given the generic parameter and the value from `args_for_def_id`, /// - `provided_kind`: given the generic parameter and the value from `args_for_def_id`,
/// instantiate a `GenericArg`. /// instantiate a `GenericArg`.
/// - `inferred_kind`: if no parameter was provided, and inference is enabled, then /// - `inferred_kind`: if no parameter was provided, and inference is enabled, then
/// creates a suitable inference variable. /// creates a suitable inference variable.
pub fn create_substs_for_generic_args<'a>( pub fn create_substs_for_generic_args<'tcx, 'a>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
def_id: DefId, def_id: DefId,
parent_substs: &[subst::GenericArg<'tcx>], parent_substs: &[subst::GenericArg<'tcx>],
@ -186,7 +177,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
self_ty: Option<Ty<'tcx>>, self_ty: Option<Ty<'tcx>>,
arg_count: &GenericArgCountResult, arg_count: &GenericArgCountResult,
ctx: &mut impl CreateSubstsForGenericArgsCtxt<'a, 'tcx>, ctx: &mut impl CreateSubstsForGenericArgsCtxt<'a, 'tcx>,
) -> SubstsRef<'tcx> { ) -> SubstsRef<'tcx> {
// Collect the segments of the path; we need to substitute arguments // Collect the segments of the path; we need to substitute arguments
// for parameters throughout the entire path (wherever there are // for parameters throughout the entire path (wherever there are
// generic parameters). // generic parameters).
@ -305,7 +296,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
) = param_types_present.into_iter().unzip(); ) = param_types_present.into_iter().unzip();
param_types_present.dedup(); param_types_present.dedup();
Self::generic_arg_mismatch_err( generic_arg_mismatch_err(
tcx, tcx,
arg, arg,
param, param,
@ -361,7 +352,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
assert_eq!(kind, "lifetime"); assert_eq!(kind, "lifetime");
let (provided_arg, param) = let (provided_arg, param) =
force_infer_lt.expect("lifetimes ought to have been inferred"); force_infer_lt.expect("lifetimes ought to have been inferred");
Self::generic_arg_mismatch_err(tcx, provided_arg, param, false, None); generic_arg_mismatch_err(tcx, provided_arg, param, false, None);
} }
break; break;
@ -380,18 +371,18 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
} }
tcx.intern_substs(&substs) tcx.intern_substs(&substs)
} }
/// Checks that the correct number of generic arguments have been provided. /// Checks that the correct number of generic arguments have been provided.
/// Used specifically for function calls. /// Used specifically for function calls.
pub fn check_generic_arg_count_for_call( pub fn check_generic_arg_count_for_call(
tcx: TyCtxt<'_>, tcx: TyCtxt<'_>,
span: Span, span: Span,
def_id: DefId, def_id: DefId,
generics: &ty::Generics, generics: &ty::Generics,
seg: &hir::PathSegment<'_>, seg: &hir::PathSegment<'_>,
is_method_call: IsMethodCall, is_method_call: IsMethodCall,
) -> GenericArgCountResult { ) -> GenericArgCountResult {
let empty_args = hir::GenericArgs::none(); let empty_args = hir::GenericArgs::none();
let gen_args = seg.args.unwrap_or(&empty_args); let gen_args = seg.args.unwrap_or(&empty_args);
let gen_pos = if is_method_call == IsMethodCall::Yes { let gen_pos = if is_method_call == IsMethodCall::Yes {
@ -401,7 +392,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}; };
let has_self = generics.parent.is_none() && generics.has_self; let has_self = generics.parent.is_none() && generics.has_self;
Self::check_generic_arg_count( check_generic_arg_count(
tcx, tcx,
span, span,
def_id, def_id,
@ -412,12 +403,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
has_self, has_self,
seg.infer_args, 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.
/// This is used both for datatypes and function calls. /// This is used both for datatypes and function calls.
#[instrument(skip(tcx, gen_pos), level = "debug")] #[instrument(skip(tcx, gen_pos), level = "debug")]
pub(crate) fn check_generic_arg_count( pub(crate) fn check_generic_arg_count(
tcx: TyCtxt<'_>, tcx: TyCtxt<'_>,
span: Span, span: Span,
def_id: DefId, def_id: DefId,
@ -427,7 +418,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
gen_pos: GenericArgPosition, gen_pos: GenericArgPosition,
has_self: bool, has_self: bool,
infer_args: bool, infer_args: bool,
) -> GenericArgCountResult { ) -> GenericArgCountResult {
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();
@ -436,26 +427,22 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let synth_type_param_count = gen_params let synth_type_param_count = gen_params
.params .params
.iter() .iter()
.filter(|param| { .filter(|param| matches!(param.kind, ty::GenericParamDefKind::Type { synthetic: true, .. }))
matches!(param.kind, ty::GenericParamDefKind::Type { synthetic: true, .. })
})
.count(); .count();
let named_type_param_count = let named_type_param_count = param_counts.types - has_self as usize - synth_type_param_count;
param_counts.types - has_self as usize - synth_type_param_count;
let infer_lifetimes = let infer_lifetimes =
(gen_pos != GenericArgPosition::Type || infer_args) && !gen_args.has_lifetime_params(); (gen_pos != GenericArgPosition::Type || infer_args) && !gen_args.has_lifetime_params();
if gen_pos != GenericArgPosition::Type && let Some(b) = gen_args.bindings.first() { if gen_pos != GenericArgPosition::Type && let Some(b) = gen_args.bindings.first() {
Self::prohibit_assoc_ty_binding(tcx, b.span); prohibit_assoc_ty_binding(tcx, b.span);
} }
let explicit_late_bound = let explicit_late_bound =
Self::prohibit_explicit_late_bound_lifetimes(tcx, gen_params, gen_args, gen_pos); prohibit_explicit_late_bound_lifetimes(tcx, gen_params, gen_args, gen_pos);
let mut invalid_args = vec![]; let mut invalid_args = vec![];
let mut check_lifetime_args = let mut check_lifetime_args = |min_expected_args: usize,
|min_expected_args: usize,
max_expected_args: usize, max_expected_args: usize,
provided_args: usize, provided_args: usize,
late_bounds_ignore: bool| { late_bounds_ignore: bool| {
@ -469,17 +456,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
if provided_args > max_expected_args { if provided_args > max_expected_args {
invalid_args.extend( invalid_args.extend(
gen_args.args[max_expected_args..provided_args] gen_args.args[max_expected_args..provided_args].iter().map(|arg| arg.span()),
.iter()
.map(|arg| arg.span()),
); );
}; };
let gen_args_info = if provided_args > min_expected_args { let gen_args_info = if provided_args > min_expected_args {
invalid_args.extend( invalid_args.extend(
gen_args.args[min_expected_args..provided_args] gen_args.args[min_expected_args..provided_args].iter().map(|arg| arg.span()),
.iter()
.map(|arg| arg.span()),
); );
let num_redundant_args = provided_args - min_expected_args; let num_redundant_args = provided_args - min_expected_args;
GenericArgsInfo::ExcessLifetimes { num_redundant_args } GenericArgsInfo::ExcessLifetimes { num_redundant_args }
@ -601,25 +584,25 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
GenericArgCountResult { GenericArgCountResult {
explicit_late_bound, explicit_late_bound,
correct: lifetimes_correct.and(args_correct).map_err(|reported| { correct: lifetimes_correct
GenericArgCountMismatch { reported: Some(reported), invalid_args } .and(args_correct)
}), .map_err(|reported| GenericArgCountMismatch { reported: Some(reported), invalid_args }),
}
} }
}
/// Emits an error regarding forbidden type binding associations /// Emits an error regarding forbidden type binding associations
pub fn prohibit_assoc_ty_binding(tcx: TyCtxt<'_>, span: Span) { pub fn prohibit_assoc_ty_binding(tcx: TyCtxt<'_>, span: Span) {
tcx.sess.emit_err(AssocTypeBindingNotAllowed { span }); tcx.sess.emit_err(AssocTypeBindingNotAllowed { span });
} }
/// Prohibits explicit lifetime arguments if late-bound lifetime parameters /// Prohibits explicit lifetime arguments if late-bound lifetime parameters
/// are present. This is used both for datatypes and function calls. /// are present. This is used both for datatypes and function calls.
pub(crate) fn prohibit_explicit_late_bound_lifetimes( pub(crate) fn prohibit_explicit_late_bound_lifetimes(
tcx: TyCtxt<'_>, tcx: TyCtxt<'_>,
def: &ty::Generics, def: &ty::Generics,
args: &hir::GenericArgs<'_>, args: &hir::GenericArgs<'_>,
position: GenericArgPosition, position: GenericArgPosition,
) -> ExplicitLateBound { ) -> ExplicitLateBound {
let param_counts = def.own_counts(); let param_counts = def.own_counts();
let infer_lifetimes = position != GenericArgPosition::Type && !args.has_lifetime_params(); let infer_lifetimes = position != GenericArgPosition::Type && !args.has_lifetime_params();
@ -655,5 +638,4 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
} else { } else {
ExplicitLateBound::No ExplicitLateBound::No
} }
}
} }

View file

@ -3,8 +3,11 @@
//! instance of `AstConv`. //! instance of `AstConv`.
mod errors; mod errors;
mod generics; pub mod generics;
use crate::astconv::generics::{
check_generic_arg_count, create_substs_for_generic_args, prohibit_assoc_ty_binding,
};
use crate::bounds::Bounds; use crate::bounds::Bounds;
use crate::collect::HirPlaceholderCollector; use crate::collect::HirPlaceholderCollector;
use crate::errors::{ use crate::errors::{
@ -286,7 +289,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
ty::BoundConstness::NotConst, ty::BoundConstness::NotConst,
); );
if let Some(b) = item_segment.args().bindings.first() { if let Some(b) = item_segment.args().bindings.first() {
Self::prohibit_assoc_ty_binding(self.tcx(), b.span); prohibit_assoc_ty_binding(self.tcx(), b.span);
} }
substs substs
@ -356,7 +359,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
assert!(self_ty.is_none()); assert!(self_ty.is_none());
} }
let arg_count = Self::check_generic_arg_count( let arg_count = check_generic_arg_count(
tcx, tcx,
span, span,
def_id, def_id,
@ -531,7 +534,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
inferred_params: vec![], inferred_params: vec![],
infer_args, infer_args,
}; };
let substs = Self::create_substs_for_generic_args( let substs = create_substs_for_generic_args(
tcx, tcx,
def_id, def_id,
parent_substs, parent_substs,
@ -617,7 +620,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
); );
if let Some(b) = item_segment.args().bindings.first() { if let Some(b) = item_segment.args().bindings.first() {
Self::prohibit_assoc_ty_binding(self.tcx(), b.span); prohibit_assoc_ty_binding(self.tcx(), b.span);
} }
args args
@ -811,7 +814,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
constness, constness,
); );
if let Some(b) = trait_segment.args().bindings.first() { if let Some(b) = trait_segment.args().bindings.first() {
Self::prohibit_assoc_ty_binding(self.tcx(), b.span); prohibit_assoc_ty_binding(self.tcx(), b.span);
} }
self.tcx().mk_trait_ref(trait_def_id, substs) self.tcx().mk_trait_ref(trait_def_id, substs)
} }
@ -2308,7 +2311,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
for segment in segments { for segment in segments {
// Only emit the first error to avoid overloading the user with error messages. // Only emit the first error to avoid overloading the user with error messages.
if let Some(b) = segment.args().bindings.first() { if let Some(b) = segment.args().bindings.first() {
Self::prohibit_assoc_ty_binding(self.tcx(), b.span); prohibit_assoc_ty_binding(self.tcx(), b.span);
return true; return true;
} }
} }

View file

@ -10,6 +10,9 @@ use rustc_hir::def::{CtorOf, DefKind, Res};
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItem; use rustc_hir::lang_items::LangItem;
use rustc_hir::{ExprKind, GenericArg, Node, QPath}; use rustc_hir::{ExprKind, GenericArg, Node, QPath};
use rustc_hir_analysis::astconv::generics::{
check_generic_arg_count_for_call, create_substs_for_generic_args,
};
use rustc_hir_analysis::astconv::{ use rustc_hir_analysis::astconv::{
AstConv, CreateSubstsForGenericArgsCtxt, ExplicitLateBound, GenericArgCountMismatch, AstConv, CreateSubstsForGenericArgsCtxt, ExplicitLateBound, GenericArgCountMismatch,
GenericArgCountResult, IsMethodCall, PathSeg, GenericArgCountResult, IsMethodCall, PathSeg,
@ -1067,7 +1070,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// parameter internally, but we don't allow users to specify the // parameter internally, but we don't allow users to specify the
// parameter's value explicitly, so we have to do some error- // parameter's value explicitly, so we have to do some error-
// checking here. // checking here.
let arg_count = <dyn AstConv<'_>>::check_generic_arg_count_for_call( let arg_count = check_generic_arg_count_for_call(
tcx, tcx,
span, span,
def_id, def_id,
@ -1233,7 +1236,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} }
let substs_raw = self_ctor_substs.unwrap_or_else(|| { let substs_raw = self_ctor_substs.unwrap_or_else(|| {
<dyn AstConv<'_>>::create_substs_for_generic_args( create_substs_for_generic_args(
tcx, tcx,
def_id, def_id,
&[], &[],

View file

@ -4,6 +4,9 @@ use crate::{callee, FnCtxt};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::GenericArg; use rustc_hir::GenericArg;
use rustc_hir_analysis::astconv::generics::{
check_generic_arg_count_for_call, create_substs_for_generic_args,
};
use rustc_hir_analysis::astconv::{AstConv, CreateSubstsForGenericArgsCtxt, IsMethodCall}; use rustc_hir_analysis::astconv::{AstConv, CreateSubstsForGenericArgsCtxt, IsMethodCall};
use rustc_infer::infer::{self, InferOk}; use rustc_infer::infer::{self, InferOk};
use rustc_middle::traits::{ObligationCauseCode, UnifyReceiverContext}; use rustc_middle::traits::{ObligationCauseCode, UnifyReceiverContext};
@ -331,7 +334,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
// variables. // variables.
let generics = self.tcx.generics_of(pick.item.def_id); let generics = self.tcx.generics_of(pick.item.def_id);
let arg_count_correct = <dyn AstConv<'_>>::check_generic_arg_count_for_call( let arg_count_correct = check_generic_arg_count_for_call(
self.tcx, self.tcx,
self.span, self.span,
pick.item.def_id, pick.item.def_id,
@ -398,7 +401,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
} }
} }
let substs = <dyn AstConv<'_>>::create_substs_for_generic_args( let substs = create_substs_for_generic_args(
self.tcx, self.tcx,
pick.item.def_id, pick.item.def_id,
parent_substs, parent_substs,