mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-26 22:53:28 +00:00
Add generic arg infer
This commit is contained in:
parent
71a6c7c803
commit
417b098cfc
@ -336,6 +336,7 @@ pub enum ParamKindOrd {
|
||||
// is active. Specifically, if it's only `min_const_generics`, it will still require
|
||||
// ordering consts after types.
|
||||
Const { unordered: bool },
|
||||
Infer,
|
||||
}
|
||||
|
||||
impl Ord for ParamKindOrd {
|
||||
@ -343,7 +344,7 @@ impl Ord for ParamKindOrd {
|
||||
use ParamKindOrd::*;
|
||||
let to_int = |v| match v {
|
||||
Lifetime => 0,
|
||||
Type | Const { unordered: true } => 1,
|
||||
Infer | Type | Const { unordered: true } => 1,
|
||||
// technically both consts should be ordered equally,
|
||||
// but only one is ever encountered at a time, so this is
|
||||
// fine.
|
||||
@ -371,6 +372,7 @@ impl fmt::Display for ParamKindOrd {
|
||||
ParamKindOrd::Lifetime => "lifetime".fmt(f),
|
||||
ParamKindOrd::Type => "type".fmt(f),
|
||||
ParamKindOrd::Const { .. } => "const".fmt(f),
|
||||
ParamKindOrd::Infer => "infer".fmt(f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1218,48 +1218,55 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
match arg {
|
||||
ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(<)),
|
||||
ast::GenericArg::Type(ty) => {
|
||||
// We parse const arguments as path types as we cannot distinguish them during
|
||||
// parsing. We try to resolve that ambiguity by attempting resolution in both the
|
||||
// type and value namespaces. If we resolved the path in the value namespace, we
|
||||
// transform it into a generic const argument.
|
||||
if let TyKind::Path(ref qself, ref path) = ty.kind {
|
||||
if let Some(partial_res) = self.resolver.get_partial_res(ty.id) {
|
||||
let res = partial_res.base_res();
|
||||
if !res.matches_ns(Namespace::TypeNS) {
|
||||
debug!(
|
||||
"lower_generic_arg: Lowering type argument as const argument: {:?}",
|
||||
ty,
|
||||
);
|
||||
match ty.kind {
|
||||
TyKind::Infer => {
|
||||
let hir_id = self.lower_node_id(ty.id);
|
||||
return GenericArg::Infer(hir::InferArg { hir_id, span: ty.span });
|
||||
}
|
||||
// We parse const arguments as path types as we cannot distinguish them during
|
||||
// parsing. We try to resolve that ambiguity by attempting resolution in both the
|
||||
// type and value namespaces. If we resolved the path in the value namespace, we
|
||||
// transform it into a generic const argument.
|
||||
TyKind::Path(ref qself, ref path) => {
|
||||
if let Some(partial_res) = self.resolver.get_partial_res(ty.id) {
|
||||
let res = partial_res.base_res();
|
||||
if !res.matches_ns(Namespace::TypeNS) {
|
||||
debug!(
|
||||
"lower_generic_arg: Lowering type argument as const argument: {:?}",
|
||||
ty,
|
||||
);
|
||||
|
||||
// Construct a AnonConst where the expr is the "ty"'s path.
|
||||
// Construct a AnonConst where the expr is the "ty"'s path.
|
||||
|
||||
let parent_def_id = self.current_hir_id_owner.0;
|
||||
let node_id = self.resolver.next_node_id();
|
||||
let parent_def_id = self.current_hir_id_owner.0;
|
||||
let node_id = self.resolver.next_node_id();
|
||||
|
||||
// Add a definition for the in-band const def.
|
||||
self.resolver.create_def(
|
||||
parent_def_id,
|
||||
node_id,
|
||||
DefPathData::AnonConst,
|
||||
ExpnId::root(),
|
||||
ty.span,
|
||||
);
|
||||
// Add a definition for the in-band const def.
|
||||
self.resolver.create_def(
|
||||
parent_def_id,
|
||||
node_id,
|
||||
DefPathData::AnonConst,
|
||||
ExpnId::root(),
|
||||
ty.span,
|
||||
);
|
||||
|
||||
let path_expr = Expr {
|
||||
id: ty.id,
|
||||
kind: ExprKind::Path(qself.clone(), path.clone()),
|
||||
span: ty.span,
|
||||
attrs: AttrVec::new(),
|
||||
tokens: None,
|
||||
};
|
||||
let path_expr = Expr {
|
||||
id: ty.id,
|
||||
kind: ExprKind::Path(qself.clone(), path.clone()),
|
||||
span: ty.span,
|
||||
attrs: AttrVec::new(),
|
||||
tokens: None,
|
||||
};
|
||||
|
||||
let ct = self.with_new_scopes(|this| hir::AnonConst {
|
||||
hir_id: this.lower_node_id(node_id),
|
||||
body: this.lower_const_body(path_expr.span, Some(&path_expr)),
|
||||
});
|
||||
return GenericArg::Const(ConstArg { value: ct, span: ty.span });
|
||||
let ct = self.with_new_scopes(|this| hir::AnonConst {
|
||||
hir_id: this.lower_node_id(node_id),
|
||||
body: this.lower_const_body(path_expr.span, Some(&path_expr)),
|
||||
});
|
||||
return GenericArg::Const(ConstArg { value: ct, span: ty.span });
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
GenericArg::Type(self.lower_ty_direct(&ty, itctx))
|
||||
}
|
||||
|
@ -253,11 +253,24 @@ pub struct ConstArg {
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Encodable, Debug, HashStable_Generic)]
|
||||
pub struct InferArg {
|
||||
pub hir_id: HirId,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
impl InferArg {
|
||||
pub fn to_ty(&self) -> Ty<'_> {
|
||||
Ty { kind: TyKind::Infer, span: self.span, hir_id: self.hir_id }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, HashStable_Generic)]
|
||||
pub enum GenericArg<'hir> {
|
||||
Lifetime(Lifetime),
|
||||
Type(Ty<'hir>),
|
||||
Const(ConstArg),
|
||||
Infer(InferArg),
|
||||
}
|
||||
|
||||
impl GenericArg<'_> {
|
||||
@ -266,6 +279,7 @@ impl GenericArg<'_> {
|
||||
GenericArg::Lifetime(l) => l.span,
|
||||
GenericArg::Type(t) => t.span,
|
||||
GenericArg::Const(c) => c.span,
|
||||
GenericArg::Infer(i) => i.span,
|
||||
}
|
||||
}
|
||||
|
||||
@ -274,6 +288,7 @@ impl GenericArg<'_> {
|
||||
GenericArg::Lifetime(l) => l.hir_id,
|
||||
GenericArg::Type(t) => t.hir_id,
|
||||
GenericArg::Const(c) => c.value.hir_id,
|
||||
GenericArg::Infer(i) => i.hir_id,
|
||||
}
|
||||
}
|
||||
|
||||
@ -290,6 +305,7 @@ impl GenericArg<'_> {
|
||||
GenericArg::Lifetime(_) => "lifetime",
|
||||
GenericArg::Type(_) => "type",
|
||||
GenericArg::Const(_) => "constant",
|
||||
GenericArg::Infer(_) => "inferred",
|
||||
}
|
||||
}
|
||||
|
||||
@ -300,6 +316,7 @@ impl GenericArg<'_> {
|
||||
GenericArg::Const(_) => {
|
||||
ast::ParamKindOrd::Const { unordered: feats.unordered_const_ty_params() }
|
||||
}
|
||||
GenericArg::Infer(_) => ast::ParamKindOrd::Infer,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -341,6 +358,7 @@ impl GenericArgs<'_> {
|
||||
break;
|
||||
}
|
||||
GenericArg::Const(_) => {}
|
||||
GenericArg::Infer(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -358,6 +376,7 @@ impl GenericArgs<'_> {
|
||||
GenericArg::Lifetime(_) => own_counts.lifetimes += 1,
|
||||
GenericArg::Type(_) => own_counts.types += 1,
|
||||
GenericArg::Const(_) => own_counts.consts += 1,
|
||||
GenericArg::Infer(_) => own_counts.infer += 1,
|
||||
};
|
||||
}
|
||||
|
||||
@ -484,6 +503,7 @@ pub struct GenericParamCount {
|
||||
pub lifetimes: usize,
|
||||
pub types: usize,
|
||||
pub consts: usize,
|
||||
pub infer: usize,
|
||||
}
|
||||
|
||||
/// Represents lifetimes and type parameters attached to a declaration
|
||||
@ -2987,6 +3007,8 @@ pub enum Node<'hir> {
|
||||
Visibility(&'hir Visibility<'hir>),
|
||||
|
||||
Crate(&'hir Mod<'hir>),
|
||||
|
||||
Infer(&'hir InferArg),
|
||||
}
|
||||
|
||||
impl<'hir> Node<'hir> {
|
||||
@ -3055,6 +3077,7 @@ impl<'hir> Node<'hir> {
|
||||
| Node::Local(Local { hir_id, .. })
|
||||
| Node::Lifetime(Lifetime { hir_id, .. })
|
||||
| Node::Param(Param { hir_id, .. })
|
||||
| Node::Infer(InferArg { hir_id, .. })
|
||||
| Node::GenericParam(GenericParam { hir_id, .. }) => Some(*hir_id),
|
||||
Node::TraitRef(TraitRef { hir_ref_id, .. }) => Some(*hir_ref_id),
|
||||
Node::PathSegment(PathSegment { hir_id, .. }) => *hir_id,
|
||||
|
@ -436,13 +436,22 @@ pub trait Visitor<'v>: Sized {
|
||||
fn visit_label(&mut self, label: &'v Label) {
|
||||
walk_label(self, label)
|
||||
}
|
||||
fn visit_infer(&mut self, inf: &'v InferArg) {
|
||||
self.visit_id(inf.hir_id);
|
||||
}
|
||||
fn visit_generic_arg(&mut self, generic_arg: &'v GenericArg<'v>) {
|
||||
match generic_arg {
|
||||
GenericArg::Lifetime(lt) => self.visit_lifetime(lt),
|
||||
GenericArg::Type(ty) => self.visit_ty(ty),
|
||||
GenericArg::Const(ct) => self.visit_anon_const(&ct.value),
|
||||
GenericArg::Infer(inf) => self.visit_infer(inf),
|
||||
}
|
||||
}
|
||||
/*
|
||||
fn tcx(&self) -> Option<&TyCtxt<'tcx>> {
|
||||
None
|
||||
}
|
||||
*/
|
||||
fn visit_lifetime(&mut self, lifetime: &'v Lifetime) {
|
||||
walk_lifetime(self, lifetime)
|
||||
}
|
||||
@ -746,6 +755,10 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn walk_inf<'v, V: Visitor<'v>>(visitor: &mut V, inf: &'v InferArg) {
|
||||
visitor.visit_id(inf.hir_id);
|
||||
}
|
||||
|
||||
pub fn walk_qpath<'v, V: Visitor<'v>>(
|
||||
visitor: &mut V,
|
||||
qpath: &'v QPath<'v>,
|
||||
|
@ -103,6 +103,7 @@ impl<'a> State<'a> {
|
||||
Node::TraitRef(a) => self.print_trait_ref(&a),
|
||||
Node::Binding(a) | Node::Pat(a) => self.print_pat(&a),
|
||||
Node::Arm(a) => self.print_arm(&a),
|
||||
Node::Infer(_) => self.print_string("_", ast::StrStyle::Cooked),
|
||||
Node::Block(a) => {
|
||||
// Containing cbox, will be closed by print-block at `}`.
|
||||
self.cbox(INDENT_UNIT);
|
||||
@ -437,14 +438,14 @@ impl<'a> State<'a> {
|
||||
self.print_anon_const(e);
|
||||
self.s.word(")");
|
||||
}
|
||||
hir::TyKind::Infer => {
|
||||
self.s.word("_");
|
||||
}
|
||||
hir::TyKind::Err => {
|
||||
self.popen();
|
||||
self.s.word("/*ERROR*/");
|
||||
self.pclose();
|
||||
}
|
||||
hir::TyKind::Infer => {
|
||||
self.s.word("_");
|
||||
}
|
||||
}
|
||||
self.end()
|
||||
}
|
||||
@ -1851,6 +1852,7 @@ impl<'a> State<'a> {
|
||||
GenericArg::Lifetime(_) => {}
|
||||
GenericArg::Type(ty) => s.print_type(ty),
|
||||
GenericArg::Const(ct) => s.print_anon_const(&ct.value),
|
||||
GenericArg::Infer(_inf) => s.word("_"),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -404,6 +404,14 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
|
||||
});
|
||||
}
|
||||
|
||||
fn visit_infer(&mut self, inf: &'hir InferArg) {
|
||||
self.insert(inf.span, inf.hir_id, Node::Infer(inf));
|
||||
|
||||
self.with_parent(inf.hir_id, |this| {
|
||||
intravisit::walk_inf(this, inf);
|
||||
});
|
||||
}
|
||||
|
||||
fn visit_trait_ref(&mut self, tr: &'hir TraitRef<'hir>) {
|
||||
self.insert(tr.path.span, tr.hir_ref_id, Node::TraitRef(tr));
|
||||
|
||||
|
@ -272,6 +272,7 @@ impl<'hir> Map<'hir> {
|
||||
GenericParamKind::Type { .. } => DefKind::TyParam,
|
||||
GenericParamKind::Const { .. } => DefKind::ConstParam,
|
||||
},
|
||||
Node::Infer(_) => todo!(),
|
||||
Node::Crate(_) => DefKind::Mod,
|
||||
Node::Stmt(_)
|
||||
| Node::PathSegment(_)
|
||||
@ -882,6 +883,7 @@ impl<'hir> Map<'hir> {
|
||||
node: VisibilityKind::Restricted { ref path, .. },
|
||||
..
|
||||
}) => path.span,
|
||||
Node::Infer(i) => i.span,
|
||||
Node::Visibility(v) => bug!("unexpected Visibility {:?}", v),
|
||||
Node::Local(local) => local.span,
|
||||
Node::MacroDef(macro_def) => macro_def.span,
|
||||
@ -1129,6 +1131,7 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId) -> String {
|
||||
Some(Node::Param(_)) => node_str("param"),
|
||||
Some(Node::Arm(_)) => node_str("arm"),
|
||||
Some(Node::Block(_)) => node_str("block"),
|
||||
Some(Node::Infer(_)) => node_str("infer"),
|
||||
Some(Node::Local(_)) => node_str("local"),
|
||||
Some(Node::Ctor(..)) => format!("ctor {}{}", path_str(), id_str),
|
||||
Some(Node::Lifetime(_)) => node_str("lifetime"),
|
||||
|
@ -133,6 +133,11 @@ rustc_queries! {
|
||||
cache_on_disk_if { key.is_local() }
|
||||
}
|
||||
|
||||
query generic_arg_for_infer_arg(key: DefId) -> hir::GenericArg<'tcx> {
|
||||
desc { |tcx| "computes concrete type for inference, `{}`", tcx.def_path_str(key) }
|
||||
storage(ArenaCacheSelector<'tcx>)
|
||||
}
|
||||
|
||||
/// Maps from the `DefId` of an item (trait/struct/enum/fn) to the
|
||||
/// predicates (where-clauses) that must be proven true in order
|
||||
/// to reference it. This is almost always the "predicates query"
|
||||
|
@ -1188,6 +1188,23 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
|
||||
self.maybe_typeck_results = old_maybe_typeck_results;
|
||||
}
|
||||
|
||||
fn visit_generic_arg(&mut self, generic_arg: &'tcx hir::GenericArg<'tcx>) {
|
||||
match generic_arg {
|
||||
hir::GenericArg::Type(t) => self.visit_ty(t),
|
||||
hir::GenericArg::Infer(inf) => {
|
||||
self.span = inf.span;
|
||||
let parent_hir_id = self.tcx.hir().get_parent_node(inf.hir_id);
|
||||
if let Some(typeck_results) = self.maybe_typeck_results {
|
||||
let node_substs = typeck_results.node_substs(parent_hir_id);
|
||||
for ty in node_substs.types() {
|
||||
self.visit(ty);
|
||||
}
|
||||
}
|
||||
}
|
||||
hir::GenericArg::Lifetime(_) | hir::GenericArg::Const(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, hir_ty: &'tcx hir::Ty<'tcx>) {
|
||||
self.span = hir_ty.span;
|
||||
if let Some(typeck_results) = self.maybe_typeck_results {
|
||||
@ -1443,6 +1460,14 @@ impl<'a, 'b, 'tcx, 'v> Visitor<'v> for ObsoleteCheckTypeForPrivatenessVisitor<'a
|
||||
NestedVisitorMap::None
|
||||
}
|
||||
|
||||
fn visit_generic_arg(&mut self, generic_arg: &'v hir::GenericArg<'v>) {
|
||||
match generic_arg {
|
||||
hir::GenericArg::Type(t) => self.visit_ty(t),
|
||||
hir::GenericArg::Infer(inf) => self.visit_ty(&inf.to_ty()),
|
||||
hir::GenericArg::Lifetime(_) | hir::GenericArg::Const(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, ty: &hir::Ty<'_>) {
|
||||
if let hir::TyKind::Path(hir::QPath::Resolved(_, ref path)) = ty.kind {
|
||||
if self.inner.path_is_private_type(path) {
|
||||
|
@ -2557,6 +2557,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||
GenericArg::Const(ct) => {
|
||||
self.visit_anon_const(&ct.value);
|
||||
}
|
||||
GenericArg::Infer(inf) => {
|
||||
self.visit_id(inf.hir_id);
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -1768,6 +1768,7 @@ impl Clean<GenericArgs> for hir::GenericArgs<'_> {
|
||||
hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()),
|
||||
hir::GenericArg::Type(ty) => GenericArg::Type(ty.clean(cx)),
|
||||
hir::GenericArg::Const(ct) => GenericArg::Const(ct.clean(cx)),
|
||||
hir::GenericArg::Infer(_inf) => GenericArg::Infer,
|
||||
})
|
||||
.collect(),
|
||||
bindings: self.bindings.clean(cx),
|
||||
|
@ -2007,6 +2007,7 @@ crate enum GenericArg {
|
||||
Lifetime(Lifetime),
|
||||
Type(Type),
|
||||
Const(Constant),
|
||||
Infer,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
||||
|
@ -1424,6 +1424,7 @@ impl clean::GenericArg {
|
||||
clean::GenericArg::Lifetime(lt) => fmt::Display::fmt(<.print(), f),
|
||||
clean::GenericArg::Type(ty) => fmt::Display::fmt(&ty.print(cx), f),
|
||||
clean::GenericArg::Const(ct) => fmt::Display::fmt(&ct.print(cx.tcx()), f),
|
||||
clean::GenericArg::Infer => fmt::Display::fmt("_", f),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -140,6 +140,7 @@ impl FromWithTcx<clean::GenericArg> for GenericArg {
|
||||
Lifetime(l) => GenericArg::Lifetime(l.0.to_string()),
|
||||
Type(t) => GenericArg::Type(t.into_tcx(tcx)),
|
||||
Const(c) => GenericArg::Const(c.into_tcx(tcx)),
|
||||
Infer => GenericArg::Infer,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -127,6 +127,7 @@ pub enum GenericArg {
|
||||
Lifetime(String),
|
||||
Type(Type),
|
||||
Const(Constant),
|
||||
Infer,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
|
@ -4,13 +4,13 @@ error[E0770]: the type of const parameters must not depend on other generic para
|
||||
LL | fn foo<const N: usize, const A: [u8; N]>() {}
|
||||
| ^ the type must not depend on the parameter `N`
|
||||
|
||||
error[E0747]: type provided when a constant was expected
|
||||
--> $DIR/issue-62878.rs:10:11
|
||||
error: constant expression depends on a generic parameter
|
||||
--> $DIR/issue-62878.rs:10:14
|
||||
|
|
||||
LL | foo::<_, {[1]}>();
|
||||
| ^
|
||||
| ^^^^^
|
||||
|
|
||||
= help: const arguments cannot yet be inferred with `_`
|
||||
= note: this may fail depending on what value the parameter takes
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-62878.rs:10:15
|
||||
@ -20,5 +20,5 @@ LL | foo::<_, {[1]}>();
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0308, E0747, E0770.
|
||||
Some errors have detailed explanations: E0308, E0770.
|
||||
For more information about an error, try `rustc --explain E0308`.
|
||||
|
@ -8,6 +8,6 @@ fn foo<const N: usize, const A: [u8; N]>() {}
|
||||
|
||||
fn main() {
|
||||
foo::<_, {[1]}>();
|
||||
//[full]~^ ERROR type provided when a constant was expected
|
||||
//[full]~| ERROR mismatched types
|
||||
//[full]~^ ERROR mismatched types
|
||||
//[full]~| ERROR constant expression
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
#![feature(min_const_generics)]
|
||||
fn foo<const N: usize, const K: usize>(data: [u32; N]) -> [u32; K] {
|
||||
// run-pass
|
||||
|
||||
fn foo<const N: usize, const K: usize>(_data: [u32; N]) -> [u32; K] {
|
||||
[0; K]
|
||||
}
|
||||
fn main() {
|
||||
let a = foo::<_, 2>([0, 1, 2]);
|
||||
//~^ ERROR type provided when a constant was expected
|
||||
let _a = foo::<_, 2>([0, 1, 2]);
|
||||
}
|
||||
|
@ -1,11 +0,0 @@
|
||||
error[E0747]: type provided when a constant was expected
|
||||
--> $DIR/inferred_const.rs:6:19
|
||||
|
|
||||
LL | let a = foo::<_, 2>([0, 1, 2]);
|
||||
| ^
|
||||
|
|
||||
= help: const arguments cannot yet be inferred with `_`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0747`.
|
@ -11,7 +11,7 @@ fn foo<'a, 'b>(start: &'a usize, end: &'a usize) {
|
||||
let _x = (*start..*end)
|
||||
.map(|x| S { a: start, b: end })
|
||||
.collect::<Vec<S<_, 'a>>>();
|
||||
//~^ ERROR type provided when a lifetime was expected
|
||||
//~^ ERROR inferred provided when a lifetime was expected
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0747]: type provided when a lifetime was expected
|
||||
error[E0747]: inferred provided when a lifetime was expected
|
||||
--> $DIR/issue-14303-fncall.rs:13:26
|
||||
|
|
||||
LL | .collect::<Vec<S<_, 'a>>>();
|
||||
|
@ -273,17 +273,6 @@ LL | priv_parent_substs::mac!();
|
||||
|
|
||||
= note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: type `priv_parent_substs::Priv` is private
|
||||
--> $DIR/associated-item-privacy-trait.rs:117:30
|
||||
|
|
||||
LL | let _: <Pub as PubTr<_>>::AssocTy;
|
||||
| ^ private type
|
||||
...
|
||||
LL | priv_parent_substs::mac!();
|
||||
| --------------------------- in this macro invocation
|
||||
|
|
||||
= note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: type `priv_parent_substs::Priv` is private
|
||||
--> $DIR/associated-item-privacy-trait.rs:119:17
|
||||
|
|
||||
@ -328,5 +317,5 @@ LL | priv_parent_substs::mac!();
|
||||
|
|
||||
= note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 30 previous errors
|
||||
error: aborting due to 29 previous errors
|
||||
|
||||
|
@ -885,7 +885,15 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
||||
|
||||
pub fn hash_ty(&mut self, ty: &Ty<'_>) {
|
||||
std::mem::discriminant(&ty.kind).hash(&mut self.s);
|
||||
match ty.kind {
|
||||
self.hash_tykind(&ty.kind);
|
||||
}
|
||||
|
||||
pub fn hash_infer(&mut self) {
|
||||
"_".hash(&mut self.s);
|
||||
}
|
||||
|
||||
pub fn hash_tykind(&mut self, ty: &TyKind<'_>) {
|
||||
match ty {
|
||||
TyKind::Slice(ty) => {
|
||||
self.hash_ty(ty);
|
||||
},
|
||||
@ -949,6 +957,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
||||
GenericArg::Lifetime(l) => self.hash_lifetime(l),
|
||||
GenericArg::Type(ref ty) => self.hash_ty(ty),
|
||||
GenericArg::Const(ref ca) => self.hash_body(ca.value.body),
|
||||
GenericArg::Infer(ref _inf) => self.hash_infer(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user