diff options
| author | kadmin <julianknodt@gmail.com> | 2021-04-24 21:41:57 +0000 |
|---|---|---|
| committer | kadmin <julianknodt@gmail.com> | 2021-07-25 07:28:51 +0000 |
| commit | 417b098cfc493a9b803b4ffbf6b74fc4f8e76f3d (patch) | |
| tree | 613cc0e82fa1f34794abc8c6795c8cbdac57c1c3 | |
| parent | 71a6c7c80398143a67e27b01412f4b2ec12bde8b (diff) | |
| download | rust-417b098cfc493a9b803b4ffbf6b74fc4f8e76f3d.tar.gz rust-417b098cfc493a9b803b4ffbf6b74fc4f8e76f3d.zip | |
Add generic arg infer
28 files changed, 270 insertions, 94 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index f851725058d..5bffc94364d 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -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), } } } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index d4caba92416..c7a477fedc6 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -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, - ); - - // 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(); - - // 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 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 }); + 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. + + 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, + ); + + 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 }); + } } } + _ => {} } GenericArg::Type(self.lower_ty_direct(&ty, itctx)) } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index cacf1aeacd4..140219287b1 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -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, diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index c08f1f53218..dc54c55341e 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -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>, diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 5c1739b1ab9..d47bef4379c 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -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("_"), }, ); } diff --git a/compiler/rustc_middle/src/hir/map/collector.rs b/compiler/rustc_middle/src/hir/map/collector.rs index 8ffd98326f1..75dff288d78 100644 --- a/compiler/rustc_middle/src/hir/map/collector.rs +++ b/compiler/rustc_middle/src/hir/map/collector.rs @@ -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)); diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index ecd370b2404..c1f2b767e78 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -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"), diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 0908b6a1763..0395082fa65 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -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" diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index d969f50c1d9..f4bdaffe3f7 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -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) { diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index ca7cdc4caf5..26e2efc2552 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -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; + } } } diff --git a/compiler/rustc_typeck/src/astconv/generics.rs b/compiler/rustc_typeck/src/astconv/generics.rs index 456f2a908a8..a227d2f2337 100644 --- a/compiler/rustc_typeck/src/astconv/generics.rs +++ b/compiler/rustc_typeck/src/astconv/generics.rs @@ -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<_>>(); diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index f55e274ef8e..d80eb26f6c2 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -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, diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index 865e4ccc0b6..3a88fc5587a 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -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!(), } } diff --git a/compiler/rustc_typeck/src/check/method/confirm.rs b/compiler/rustc_typeck/src/check/method/confirm.rs index 75299bae5dd..3224fe362cb 100644 --- a/compiler/rustc_typeck/src/check/method/confirm.rs +++ b/compiler/rustc_typeck/src/check/method/confirm.rs @@ -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!(), } } diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 46b3ec5cf40..0b3fe82605c 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -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 diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 1a2852dc6c7..27c2f6cc87e 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -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), diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 2fd2d14bcab..da883d8057d 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -2007,6 +2007,7 @@ crate enum GenericArg { Lifetime(Lifetime), Type(Type), Const(Constant), + Infer, } #[derive(Clone, PartialEq, Eq, Debug, Hash)] diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 08499cef33e..cd74006530b 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -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), }) } } diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index bf8db79416b..f3eeea6c6ae 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -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, } } } diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs index 6d9a5cb515a..38ba87322c2 100644 --- a/src/rustdoc-json-types/lib.rs +++ b/src/rustdoc-json-types/lib.rs @@ -127,6 +127,7 @@ pub enum GenericArg { Lifetime(String), Type(Type), Const(Constant), + Infer, } #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] diff --git a/src/test/ui/const-generics/issues/issue-62878.full.stderr b/src/test/ui/const-generics/issues/issue-62878.full.stderr index 6e6aa196633..08f6454fa2d 100644 --- a/src/test/ui/const-generics/issues/issue-62878.full.stderr +++ b/src/test/ui/const-generics/issues/issue-62878.full.stderr @@ -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`. diff --git a/src/test/ui/const-generics/issues/issue-62878.rs b/src/test/ui/const-generics/issues/issue-62878.rs index a70606c4a7d..fae57b37773 100644 --- a/src/test/ui/const-generics/issues/issue-62878.rs +++ b/src/test/ui/const-generics/issues/issue-62878.rs @@ -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 } diff --git a/src/test/ui/const-generics/min_const_generics/inferred_const.rs b/src/test/ui/const-generics/min_const_generics/inferred_const.rs index dcd069ce3b0..f5800d10971 100644 --- a/src/test/ui/const-generics/min_const_generics/inferred_const.rs +++ b/src/test/ui/const-generics/min_const_generics/inferred_const.rs @@ -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]); } diff --git a/src/test/ui/const-generics/min_const_generics/inferred_const.stderr b/src/test/ui/const-generics/min_const_generics/inferred_const.stderr deleted file mode 100644 index e17105b2aa9..00000000000 --- a/src/test/ui/const-generics/min_const_generics/inferred_const.stderr +++ /dev/null @@ -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`. diff --git a/src/test/ui/parser/issue-14303-fncall.rs b/src/test/ui/parser/issue-14303-fncall.rs index 46ece84d69e..1757baec70f 100644 --- a/src/test/ui/parser/issue-14303-fncall.rs +++ b/src/test/ui/parser/issue-14303-fncall.rs @@ -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() {} diff --git a/src/test/ui/parser/issue-14303-fncall.stderr b/src/test/ui/parser/issue-14303-fncall.stderr index cdda0d001c7..a039eca0bfd 100644 --- a/src/test/ui/parser/issue-14303-fncall.stderr +++ b/src/test/ui/parser/issue-14303-fncall.stderr @@ -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>>>(); diff --git a/src/test/ui/privacy/associated-item-privacy-trait.stderr b/src/test/ui/privacy/associated-item-privacy-trait.stderr index 3a42415e474..1b6e27fa169 100644 --- a/src/test/ui/privacy/associated-item-privacy-trait.stderr +++ b/src/test/ui/privacy/associated-item-privacy-trait.stderr @@ -274,17 +274,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 | LL | let _: <Priv as PubTr<_>>::AssocTy; @@ -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 diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index a21ad42c061..63737955f09 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -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(), } } } |
