Add generic arg infer
This commit is contained in:
parent
71a6c7c803
commit
417b098cfc
28 changed files with 265 additions and 89 deletions
|
@ -18,6 +18,23 @@ use rustc_session::lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS;
|
|||
use rustc_span::{symbol::kw, MultiSpan, Span};
|
||||
use smallvec::SmallVec;
|
||||
|
||||
/*
|
||||
pub fn generic_arg_for_infer_arg<'tcx>(tcx: TyCtxt<'tcx>, did: LocalDefId) -> GenericArg<'tcx> {
|
||||
todo!()
|
||||
let hir_id = tcx.hir().local_def_id_to_hir_id(did);
|
||||
let arg = match tcx.hir().get(hir_id) {
|
||||
hir::Node::GenericParam(hir::GenericParam {
|
||||
kind: hir::GenericParamKind::Const { ty: _, default: _ },
|
||||
..
|
||||
}) => todo!(),
|
||||
_ => bug!("Expected GenericParam for generic_arg_for_infer_arg"),
|
||||
};
|
||||
|
||||
assert!(!matches!(arg, GenericArg::Infer(_)));
|
||||
arg
|
||||
}
|
||||
*/
|
||||
|
||||
impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
/// Report an error that a generic argument did not match the generic parameter that was
|
||||
/// expected.
|
||||
|
@ -39,7 +56,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
);
|
||||
|
||||
if let GenericParamDefKind::Const { .. } = param.kind {
|
||||
if let GenericArg::Type(hir::Ty { kind: hir::TyKind::Infer, .. }) = arg {
|
||||
if matches!(
|
||||
arg,
|
||||
GenericArg::Type(hir::Ty { kind: hir::TyKind::Infer, .. }) | GenericArg::Infer(_)
|
||||
) {
|
||||
err.help("const arguments cannot yet be inferred with `_`");
|
||||
}
|
||||
}
|
||||
|
@ -249,14 +269,22 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
(Some(&arg), Some(¶m)) => {
|
||||
match (arg, ¶m.kind, arg_count.explicit_late_bound) {
|
||||
(GenericArg::Lifetime(_), GenericParamDefKind::Lifetime, _)
|
||||
| (GenericArg::Type(_), GenericParamDefKind::Type { .. }, _)
|
||||
| (GenericArg::Const(_), GenericParamDefKind::Const { .. }, _) => {
|
||||
| (
|
||||
GenericArg::Type(_) | GenericArg::Infer(_),
|
||||
GenericParamDefKind::Type { .. },
|
||||
_,
|
||||
)
|
||||
| (
|
||||
GenericArg::Const(_) | GenericArg::Infer(_),
|
||||
GenericParamDefKind::Const { .. },
|
||||
_,
|
||||
) => {
|
||||
substs.push(ctx.provided_kind(param, arg));
|
||||
args.next();
|
||||
params.next();
|
||||
}
|
||||
(
|
||||
GenericArg::Type(_) | GenericArg::Const(_),
|
||||
GenericArg::Infer(_) | GenericArg::Type(_) | GenericArg::Const(_),
|
||||
GenericParamDefKind::Lifetime,
|
||||
_,
|
||||
) => {
|
||||
|
@ -325,6 +353,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
.features()
|
||||
.unordered_const_ty_params(),
|
||||
},
|
||||
GenericArg::Infer(_) => ParamKindOrd::Infer,
|
||||
}),
|
||||
Some(&format!(
|
||||
"reorder the arguments: {}: `<{}>`",
|
||||
|
@ -581,7 +610,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
check_types_and_consts(
|
||||
expected_min,
|
||||
param_counts.consts + named_type_param_count,
|
||||
arg_counts.consts + arg_counts.types,
|
||||
arg_counts.consts + arg_counts.types + arg_counts.infer,
|
||||
param_counts.lifetimes + has_self as usize,
|
||||
arg_counts.lifetimes,
|
||||
)
|
||||
|
@ -622,7 +651,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
.args
|
||||
.iter()
|
||||
.filter_map(|arg| match arg {
|
||||
GenericArg::Type(_) | GenericArg::Const(_) => Some(arg.span()),
|
||||
GenericArg::Infer(_) | GenericArg::Type(_) | GenericArg::Const(_) => {
|
||||
Some(arg.span())
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
|
|
@ -461,6 +461,40 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
)
|
||||
.into()
|
||||
}
|
||||
(&GenericParamDefKind::Const { has_default }, hir::GenericArg::Infer(inf)) => {
|
||||
if has_default {
|
||||
// FIXME(const_generics): Actually infer parameter here?
|
||||
tcx.const_param_default(param.def_id).into()
|
||||
} else {
|
||||
self.inferred_params.push(inf.span);
|
||||
tcx.ty_error().into()
|
||||
}
|
||||
}
|
||||
(
|
||||
&GenericParamDefKind::Type { has_default, .. },
|
||||
hir::GenericArg::Infer(inf),
|
||||
) => {
|
||||
if has_default {
|
||||
tcx.check_optional_stability(
|
||||
param.def_id,
|
||||
Some(arg.id()),
|
||||
arg.span(),
|
||||
|_, _| {
|
||||
// Default generic parameters may not be marked
|
||||
// with stability attributes, i.e. when the
|
||||
// default parameter was defined at the same time
|
||||
// as the rest of the type. As such, we ignore missing
|
||||
// stability attributes.
|
||||
},
|
||||
);
|
||||
}
|
||||
if self.astconv.allow_ty_infer() {
|
||||
self.astconv.ast_ty_to_ty(&inf.to_ty()).into()
|
||||
} else {
|
||||
self.inferred_params.push(inf.span);
|
||||
tcx.ty_error().into()
|
||||
}
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
@ -1922,6 +1956,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
has_err = true;
|
||||
(ct.span, "const")
|
||||
}
|
||||
hir::GenericArg::Infer(inf) => {
|
||||
if err_for_ty {
|
||||
continue;
|
||||
}
|
||||
has_err = true;
|
||||
err_for_ty = true;
|
||||
(inf.span, "inferred")
|
||||
}
|
||||
};
|
||||
let mut err = struct_span_err!(
|
||||
self.tcx().sess,
|
||||
|
|
|
@ -1471,6 +1471,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
|
||||
self.fcx.const_arg_to_const(&ct.value, param.def_id).into()
|
||||
}
|
||||
(GenericParamDefKind::Type { .. }, GenericArg::Infer(inf)) => {
|
||||
self.fcx.to_ty(&inf.to_ty()).into()
|
||||
}
|
||||
(GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => {
|
||||
self.fcx.var_for_def(inf.span, param)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -366,6 +366,12 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
|||
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
|
||||
self.cfcx.const_arg_to_const(&ct.value, param.def_id).into()
|
||||
}
|
||||
(GenericParamDefKind::Type { .. }, GenericArg::Infer(inf)) => {
|
||||
self.cfcx.to_ty(&inf.to_ty()).into()
|
||||
}
|
||||
(GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => {
|
||||
self.cfcx.var_for_def(inf.span, param)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -129,6 +129,15 @@ impl<'v> Visitor<'v> for PlaceholderHirTyCollector {
|
|||
}
|
||||
intravisit::walk_ty(self, t)
|
||||
}
|
||||
fn visit_generic_arg(&mut self, generic_arg: &'v hir::GenericArg<'v>) {
|
||||
match generic_arg {
|
||||
hir::GenericArg::Infer(inf) => {
|
||||
self.0.push(inf.span);
|
||||
}
|
||||
hir::GenericArg::Type(t) => self.visit_ty(t),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct CollectItemTypesVisitor<'tcx> {
|
||||
|
@ -1714,13 +1723,11 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
|
|||
}
|
||||
|
||||
fn are_suggestable_generic_args(generic_args: &[hir::GenericArg<'_>]) -> bool {
|
||||
generic_args
|
||||
.iter()
|
||||
.filter_map(|arg| match arg {
|
||||
hir::GenericArg::Type(ty) => Some(ty),
|
||||
_ => None,
|
||||
})
|
||||
.any(is_suggestable_infer_ty)
|
||||
generic_args.iter().any(|arg| match arg {
|
||||
hir::GenericArg::Type(ty) => is_suggestable_infer_ty(ty),
|
||||
hir::GenericArg::Infer(_) => true,
|
||||
_ => false,
|
||||
})
|
||||
}
|
||||
|
||||
/// Whether `ty` is a type with `_` placeholders that can be inferred. Used in diagnostics only to
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue