1
Fork 0

Add generic arg infer

This commit is contained in:
kadmin 2021-04-24 21:41:57 +00:00
parent 71a6c7c803
commit 417b098cfc
28 changed files with 265 additions and 89 deletions

View file

@ -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(&param)) => {
match (arg, &param.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<_>>();

View file

@ -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,

View file

@ -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!(),
}
}

View file

@ -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!(),
}
}

View file

@ -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