diff options
| author | kadmin <julianknodt@gmail.com> | 2021-05-06 15:33:44 +0000 |
|---|---|---|
| committer | kadmin <julianknodt@gmail.com> | 2021-07-26 21:15:18 +0000 |
| commit | 8759f00c73641d44b3ab7a2290e3c58168d3e30f (patch) | |
| tree | b2d4cdbbaa0b84be96c03e068d0f1fa6539d4ec7 /compiler | |
| parent | 3605675bb1b4f1fb65f80585ded2b62aea15bf2c (diff) | |
| download | rust-8759f00c73641d44b3ab7a2290e3c58168d3e30f.tar.gz rust-8759f00c73641d44b3ab7a2290e3c58168d3e30f.zip | |
Actually infer args in visitors
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_ast/src/ast.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_ast_lowering/src/lib.rs | 10 | ||||
| -rw-r--r-- | compiler/rustc_feature/src/active.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_hir/src/hir.rs | 49 | ||||
| -rw-r--r-- | compiler/rustc_hir_pretty/src/lib.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_privacy/src/lib.rs | 7 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/late/lifetimes.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_span/src/symbol.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_typeck/src/astconv/generics.rs | 27 | ||||
| -rw-r--r-- | compiler/rustc_typeck/src/astconv/mod.rs | 6 | ||||
| -rw-r--r-- | compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs | 5 | ||||
| -rw-r--r-- | compiler/rustc_typeck/src/check/method/confirm.rs | 5 | ||||
| -rw-r--r-- | compiler/rustc_typeck/src/collect/type_of.rs | 3 |
13 files changed, 86 insertions, 38 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 5bffc94364d..8cab83707dc 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -336,6 +336,8 @@ 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` is not actually constructed directly from the AST, but is implicitly constructed + // during HIR lowering, and `ParamKindOrd` will implicitly order inferred variables last. Infer, } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index c7a477fedc6..a19a2fbbe74 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -51,7 +51,7 @@ use rustc_hir::def::{DefKind, Namespace, PartialRes, PerNS, Res}; use rustc_hir::def_id::{DefId, DefIdMap, DefPathHash, LocalDefId, CRATE_DEF_ID}; use rustc_hir::definitions::{DefKey, DefPathData, Definitions}; use rustc_hir::intravisit; -use rustc_hir::{ConstArg, GenericArg, ParamName}; +use rustc_hir::{ConstArg, GenericArg, InferKind, ParamName}; use rustc_index::vec::{Idx, IndexVec}; use rustc_session::lint::builtin::{BARE_TRAIT_OBJECTS, MISSING_ABI}; use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer}; @@ -1219,9 +1219,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(<)), ast::GenericArg::Type(ty) => { match ty.kind { - TyKind::Infer => { + TyKind::Infer if self.sess.features_untracked().generic_arg_infer => { let hir_id = self.lower_node_id(ty.id); - return GenericArg::Infer(hir::InferArg { hir_id, span: ty.span }); + return GenericArg::Infer(hir::InferArg { + hir_id, + span: ty.span, + kind: InferKind::Type, + }); } // 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 diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index a3e40daf6bf..46bf49d640f 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -684,6 +684,9 @@ declare_features! ( /// Allows `cfg(target_abi = "...")`. (active, cfg_target_abi, "1.55.0", Some(80970), None), + /// Infer generic args for both consts and types. + (active, generic_arg_infer, "1.55.0", Some(85077), None), + // ------------------------------------------------------------------------- // feature-group-end: actual feature gates // ------------------------------------------------------------------------- diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 140219287b1..4914280f5c8 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -253,9 +253,23 @@ pub struct ConstArg { pub span: Span, } +#[derive(Copy, Clone, Encodable, Debug, HashStable_Generic)] +pub enum InferKind { + Const, + Type, +} + +impl InferKind { + #[inline] + pub fn is_type(self) -> bool { + matches!(self, InferKind::Type) + } +} + #[derive(Encodable, Debug, HashStable_Generic)] pub struct InferArg { pub hir_id: HirId, + pub kind: InferKind, pub span: Span, } @@ -365,22 +379,29 @@ impl GenericArgs<'_> { panic!("GenericArgs::inputs: not a `Fn(T) -> U`"); } - pub fn own_counts(&self) -> GenericParamCount { - // We could cache this as a property of `GenericParamCount`, but - // the aim is to refactor this away entirely eventually and the - // presence of this method will be a constant reminder. - let mut own_counts: GenericParamCount = Default::default(); + #[inline] + pub fn has_type_params(&self) -> bool { + self.args.iter().any(|arg| matches!(arg, GenericArg::Type(_))) + } - for arg in self.args { - match arg { - GenericArg::Lifetime(_) => own_counts.lifetimes += 1, - GenericArg::Type(_) => own_counts.types += 1, - GenericArg::Const(_) => own_counts.consts += 1, - GenericArg::Infer(_) => own_counts.infer += 1, - }; - } + #[inline] + pub fn num_type_params(&self) -> usize { + self.args.iter().filter(|arg| matches!(arg, GenericArg::Type(_))).count() + } + + #[inline] + pub fn num_lifetime_params(&self) -> usize { + self.args.iter().filter(|arg| matches!(arg, GenericArg::Lifetime(_))).count() + } - own_counts + #[inline] + pub fn has_lifetime_params(&self) -> bool { + self.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_))) + } + + #[inline] + pub fn num_generic_params(&self) -> usize { + self.args.iter().filter(|arg| !matches!(arg, GenericArg::Lifetime(_))).count() } /// The span encompassing the text inside the surrounding brackets. diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index d47bef4379c..94dd2116e16 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -103,7 +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::Infer(_) => self.s.word("_"), Node::Block(a) => { // Containing cbox, will be closed by print-block at `}`. self.cbox(INDENT_UNIT); diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index e77bda7d4ab..cd91ecdf2ba 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -1224,6 +1224,13 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { } } } else { + let local_id = self.tcx.hir().local_def_id(inf.hir_id); + if let Some(did) = self.tcx.opt_const_param_of(local_id) { + if self.visit_def_id(did, "inferred", &"").is_break() { + return; + } + } + // FIXME see above note for same issue. if self.visit(rustc_typeck::hir_ty_to_ty(self.tcx, &inf.to_ty())).is_break() { return; diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 26e2efc2552..bf6d5542f62 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -2559,7 +2559,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } GenericArg::Infer(inf) => { self.visit_id(inf.hir_id); - i += 1; + if inf.kind.is_type() { + i += 1; + } } } } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index c0f63f40853..536ebdef426 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -622,6 +622,7 @@ symbols! { generator, generator_state, generators, + generic_arg_infer, generic_associated_types, generic_param_attrs, get_context, diff --git a/compiler/rustc_typeck/src/astconv/generics.rs b/compiler/rustc_typeck/src/astconv/generics.rs index dd15d2d65b9..eb6265dec89 100644 --- a/compiler/rustc_typeck/src/astconv/generics.rs +++ b/compiler/rustc_typeck/src/astconv/generics.rs @@ -39,11 +39,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ); if let GenericParamDefKind::Const { .. } = param.kind { - if matches!( - arg, - GenericArg::Type(hir::Ty { kind: hir::TyKind::Infer, .. }) | GenericArg::Infer(_) - ) { + if matches!(arg, GenericArg::Type(hir::Ty { kind: hir::TyKind::Infer, .. })) { err.help("const arguments cannot yet be inferred with `_`"); + if sess.is_nightly_build() { + err.help( + "add `#![feature(generic_arg_infer)]` to the crate attributes to enable", + ); + } } } @@ -458,8 +460,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let default_counts = gen_params.own_defaults(); let param_counts = gen_params.own_counts(); let named_type_param_count = param_counts.types - has_self as usize; - let arg_counts = gen_args.own_counts(); - let infer_lifetimes = gen_pos != GenericArgPosition::Type && arg_counts.lifetimes == 0; + let infer_lifetimes = + gen_pos != GenericArgPosition::Type && !gen_args.has_lifetime_params(); if gen_pos != GenericArgPosition::Type && !gen_args.bindings.is_empty() { Self::prohibit_assoc_ty_binding(tcx, gen_args.bindings[0].span); @@ -517,7 +519,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let min_expected_lifetime_args = if infer_lifetimes { 0 } else { param_counts.lifetimes }; let max_expected_lifetime_args = param_counts.lifetimes; - let num_provided_lifetime_args = arg_counts.lifetimes; + let num_provided_lifetime_args = gen_args.num_lifetime_params(); let lifetimes_correct = check_lifetime_args( min_expected_lifetime_args, @@ -588,14 +590,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { - default_counts.consts }; debug!("expected_min: {:?}", expected_min); - debug!("arg_counts.lifetimes: {:?}", arg_counts.lifetimes); + debug!("arg_counts.lifetimes: {:?}", gen_args.num_lifetime_params()); check_types_and_consts( expected_min, param_counts.consts + named_type_param_count, - arg_counts.consts + arg_counts.types + arg_counts.infer, + gen_args.num_generic_params(), param_counts.lifetimes + has_self as usize, - arg_counts.lifetimes, + gen_args.num_lifetime_params(), ) }; @@ -673,8 +675,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { position: GenericArgPosition, ) -> ExplicitLateBound { let param_counts = def.own_counts(); - let arg_counts = args.own_counts(); - let infer_lifetimes = position != GenericArgPosition::Type && arg_counts.lifetimes == 0; + let infer_lifetimes = position != GenericArgPosition::Type && !args.has_lifetime_params(); if infer_lifetimes { return ExplicitLateBound::No; @@ -687,7 +688,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let span = args.args[0].span(); if position == GenericArgPosition::Value - && arg_counts.lifetimes != param_counts.lifetimes + && args.num_lifetime_params() != param_counts.lifetimes { let mut err = tcx.sess.struct_span_err(span, msg); err.span_note(span_late, note); diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 58ad086f225..03c4c5dfa0c 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -463,8 +463,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } (&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 if self.astconv.allow_ty_infer() { + // FIXME(const_generics): Actually infer parameter here? + todo!() } else { self.inferred_params.push(inf.span); tcx.ty_error().into() @@ -1963,7 +1965,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } has_err = true; err_for_ty = true; - (inf.span, "inferred") + (inf.span, "generic") } }; let mut err = struct_span_err!( diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index 310517339cd..f5776ae7cf6 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -1480,10 +1480,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { 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() + self.fcx.ty_infer(Some(param), inf.span).into() } (GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => { - self.fcx.var_for_def(inf.span, param) + let tcx = self.fcx.tcx(); + self.fcx.ct_infer(tcx.type_of(param.def_id), Some(param), inf.span).into() } _ => unreachable!(), } diff --git a/compiler/rustc_typeck/src/check/method/confirm.rs b/compiler/rustc_typeck/src/check/method/confirm.rs index 3224fe362cb..3aceaba882d 100644 --- a/compiler/rustc_typeck/src/check/method/confirm.rs +++ b/compiler/rustc_typeck/src/check/method/confirm.rs @@ -367,10 +367,11 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { 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() + self.cfcx.ty_infer(Some(param), inf.span).into() } (GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => { - self.cfcx.var_for_def(inf.span, param) + let tcx = self.cfcx.tcx(); + self.cfcx.ct_infer(tcx.type_of(param.def_id), Some(param), inf.span).into() } _ => unreachable!(), } diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index 50e4ba4fe6c..96b3fa9aa01 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -20,6 +20,9 @@ use super::{bad_placeholder_type, is_suggestable_infer_ty}; /// /// This should be called using the query `tcx.opt_const_param_of`. pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<DefId> { + // FIXME(generic_arg_infer): allow for returning DefIds of inference of + // GenericArg::Infer below. This may require a change where GenericArg::Infer has some flag + // for const or type. use hir::*; let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); |
