Auto merge of #83484 - JulianKnodt:infer, r=oli-obk,lcnr
Add hir::GenericArg::Infer In order to extend inference to consts, make an Infer type on hir::GenericArg.
This commit is contained in:
commit
fd853c00e2
44 changed files with 519 additions and 103 deletions
|
@ -336,6 +336,9 @@ pub enum ParamKindOrd {
|
||||||
// is active. Specifically, if it's only `min_const_generics`, it will still require
|
// is active. Specifically, if it's only `min_const_generics`, it will still require
|
||||||
// ordering consts after types.
|
// ordering consts after types.
|
||||||
Const { unordered: bool },
|
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,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Ord for ParamKindOrd {
|
impl Ord for ParamKindOrd {
|
||||||
|
@ -343,7 +346,7 @@ impl Ord for ParamKindOrd {
|
||||||
use ParamKindOrd::*;
|
use ParamKindOrd::*;
|
||||||
let to_int = |v| match v {
|
let to_int = |v| match v {
|
||||||
Lifetime => 0,
|
Lifetime => 0,
|
||||||
Type | Const { unordered: true } => 1,
|
Infer | Type | Const { unordered: true } => 1,
|
||||||
// technically both consts should be ordered equally,
|
// technically both consts should be ordered equally,
|
||||||
// but only one is ever encountered at a time, so this is
|
// but only one is ever encountered at a time, so this is
|
||||||
// fine.
|
// fine.
|
||||||
|
@ -371,6 +374,7 @@ impl fmt::Display for ParamKindOrd {
|
||||||
ParamKindOrd::Lifetime => "lifetime".fmt(f),
|
ParamKindOrd::Lifetime => "lifetime".fmt(f),
|
||||||
ParamKindOrd::Type => "type".fmt(f),
|
ParamKindOrd::Type => "type".fmt(f),
|
||||||
ParamKindOrd::Const { .. } => "const".fmt(f),
|
ParamKindOrd::Const { .. } => "const".fmt(f),
|
||||||
|
ParamKindOrd::Infer => "infer".fmt(f),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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::def_id::{DefId, DefIdMap, DefPathHash, LocalDefId, CRATE_DEF_ID};
|
||||||
use rustc_hir::definitions::{DefKey, DefPathData, Definitions};
|
use rustc_hir::definitions::{DefKey, DefPathData, Definitions};
|
||||||
use rustc_hir::intravisit;
|
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_index::vec::{Idx, IndexVec};
|
||||||
use rustc_session::lint::builtin::{BARE_TRAIT_OBJECTS, MISSING_ABI};
|
use rustc_session::lint::builtin::{BARE_TRAIT_OBJECTS, MISSING_ABI};
|
||||||
use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer};
|
use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer};
|
||||||
|
@ -1243,48 +1243,59 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
match arg {
|
match arg {
|
||||||
ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(<)),
|
ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(<)),
|
||||||
ast::GenericArg::Type(ty) => {
|
ast::GenericArg::Type(ty) => {
|
||||||
// We parse const arguments as path types as we cannot distinguish them during
|
match ty.kind {
|
||||||
// parsing. We try to resolve that ambiguity by attempting resolution in both the
|
TyKind::Infer if self.sess.features_untracked().generic_arg_infer => {
|
||||||
// type and value namespaces. If we resolved the path in the value namespace, we
|
let hir_id = self.lower_node_id(ty.id);
|
||||||
// transform it into a generic const argument.
|
return GenericArg::Infer(hir::InferArg {
|
||||||
if let TyKind::Path(ref qself, ref path) = ty.kind {
|
hir_id,
|
||||||
if let Some(partial_res) = self.resolver.get_partial_res(ty.id) {
|
span: ty.span,
|
||||||
let res = partial_res.base_res();
|
kind: InferKind::Type,
|
||||||
if !res.matches_ns(Namespace::TypeNS) {
|
});
|
||||||
debug!(
|
}
|
||||||
"lower_generic_arg: Lowering type argument as const argument: {:?}",
|
// We parse const arguments as path types as we cannot distinguish them during
|
||||||
ty,
|
// 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 parent_def_id = self.current_hir_id_owner.0;
|
||||||
let node_id = self.resolver.next_node_id();
|
let node_id = self.resolver.next_node_id();
|
||||||
|
|
||||||
// Add a definition for the in-band const def.
|
// Add a definition for the in-band const def.
|
||||||
self.resolver.create_def(
|
self.resolver.create_def(
|
||||||
parent_def_id,
|
parent_def_id,
|
||||||
node_id,
|
node_id,
|
||||||
DefPathData::AnonConst,
|
DefPathData::AnonConst,
|
||||||
ExpnId::root(),
|
ExpnId::root(),
|
||||||
ty.span,
|
ty.span,
|
||||||
);
|
);
|
||||||
|
|
||||||
let path_expr = Expr {
|
let path_expr = Expr {
|
||||||
id: ty.id,
|
id: ty.id,
|
||||||
kind: ExprKind::Path(qself.clone(), path.clone()),
|
kind: ExprKind::Path(qself.clone(), path.clone()),
|
||||||
span: ty.span,
|
span: ty.span,
|
||||||
attrs: AttrVec::new(),
|
attrs: AttrVec::new(),
|
||||||
tokens: None,
|
tokens: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let ct = self.with_new_scopes(|this| hir::AnonConst {
|
let ct = self.with_new_scopes(|this| hir::AnonConst {
|
||||||
hir_id: this.lower_node_id(node_id),
|
hir_id: this.lower_node_id(node_id),
|
||||||
body: this.lower_const_body(path_expr.span, Some(&path_expr)),
|
body: this.lower_const_body(path_expr.span, Some(&path_expr)),
|
||||||
});
|
});
|
||||||
return GenericArg::Const(ConstArg { value: ct, span: ty.span });
|
return GenericArg::Const(ConstArg { value: ct, span: ty.span });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
GenericArg::Type(self.lower_ty_direct(&ty, itctx))
|
GenericArg::Type(self.lower_ty_direct(&ty, itctx))
|
||||||
}
|
}
|
||||||
|
|
|
@ -680,6 +680,9 @@ declare_features! (
|
||||||
/// Allows `cfg(target_abi = "...")`.
|
/// Allows `cfg(target_abi = "...")`.
|
||||||
(active, cfg_target_abi, "1.55.0", Some(80970), None),
|
(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
|
// feature-group-end: actual feature gates
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
|
|
|
@ -254,11 +254,38 @@ pub struct ConstArg {
|
||||||
pub span: Span,
|
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,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InferArg {
|
||||||
|
pub fn to_ty(&self) -> Ty<'_> {
|
||||||
|
Ty { kind: TyKind::Infer, span: self.span, hir_id: self.hir_id }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, HashStable_Generic)]
|
#[derive(Debug, HashStable_Generic)]
|
||||||
pub enum GenericArg<'hir> {
|
pub enum GenericArg<'hir> {
|
||||||
Lifetime(Lifetime),
|
Lifetime(Lifetime),
|
||||||
Type(Ty<'hir>),
|
Type(Ty<'hir>),
|
||||||
Const(ConstArg),
|
Const(ConstArg),
|
||||||
|
Infer(InferArg),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GenericArg<'_> {
|
impl GenericArg<'_> {
|
||||||
|
@ -267,6 +294,7 @@ impl GenericArg<'_> {
|
||||||
GenericArg::Lifetime(l) => l.span,
|
GenericArg::Lifetime(l) => l.span,
|
||||||
GenericArg::Type(t) => t.span,
|
GenericArg::Type(t) => t.span,
|
||||||
GenericArg::Const(c) => c.span,
|
GenericArg::Const(c) => c.span,
|
||||||
|
GenericArg::Infer(i) => i.span,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,6 +303,7 @@ impl GenericArg<'_> {
|
||||||
GenericArg::Lifetime(l) => l.hir_id,
|
GenericArg::Lifetime(l) => l.hir_id,
|
||||||
GenericArg::Type(t) => t.hir_id,
|
GenericArg::Type(t) => t.hir_id,
|
||||||
GenericArg::Const(c) => c.value.hir_id,
|
GenericArg::Const(c) => c.value.hir_id,
|
||||||
|
GenericArg::Infer(i) => i.hir_id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,6 +320,7 @@ impl GenericArg<'_> {
|
||||||
GenericArg::Lifetime(_) => "lifetime",
|
GenericArg::Lifetime(_) => "lifetime",
|
||||||
GenericArg::Type(_) => "type",
|
GenericArg::Type(_) => "type",
|
||||||
GenericArg::Const(_) => "constant",
|
GenericArg::Const(_) => "constant",
|
||||||
|
GenericArg::Infer(_) => "inferred",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -301,6 +331,7 @@ impl GenericArg<'_> {
|
||||||
GenericArg::Const(_) => {
|
GenericArg::Const(_) => {
|
||||||
ast::ParamKindOrd::Const { unordered: feats.unordered_const_ty_params() }
|
ast::ParamKindOrd::Const { unordered: feats.unordered_const_ty_params() }
|
||||||
}
|
}
|
||||||
|
GenericArg::Infer(_) => ast::ParamKindOrd::Infer,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -342,27 +373,36 @@ impl GenericArgs<'_> {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
GenericArg::Const(_) => {}
|
GenericArg::Const(_) => {}
|
||||||
|
GenericArg::Infer(_) => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
panic!("GenericArgs::inputs: not a `Fn(T) -> U`");
|
panic!("GenericArgs::inputs: not a `Fn(T) -> U`");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn own_counts(&self) -> GenericParamCount {
|
#[inline]
|
||||||
// We could cache this as a property of `GenericParamCount`, but
|
pub fn has_type_params(&self) -> bool {
|
||||||
// the aim is to refactor this away entirely eventually and the
|
self.args.iter().any(|arg| matches!(arg, GenericArg::Type(_)))
|
||||||
// presence of this method will be a constant reminder.
|
}
|
||||||
let mut own_counts: GenericParamCount = Default::default();
|
|
||||||
|
|
||||||
for arg in self.args {
|
#[inline]
|
||||||
match arg {
|
pub fn num_type_params(&self) -> usize {
|
||||||
GenericArg::Lifetime(_) => own_counts.lifetimes += 1,
|
self.args.iter().filter(|arg| matches!(arg, GenericArg::Type(_))).count()
|
||||||
GenericArg::Type(_) => own_counts.types += 1,
|
}
|
||||||
GenericArg::Const(_) => own_counts.consts += 1,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
own_counts
|
#[inline]
|
||||||
|
pub fn num_lifetime_params(&self) -> usize {
|
||||||
|
self.args.iter().filter(|arg| matches!(arg, GenericArg::Lifetime(_))).count()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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.
|
/// The span encompassing the text inside the surrounding brackets.
|
||||||
|
@ -485,6 +525,7 @@ pub struct GenericParamCount {
|
||||||
pub lifetimes: usize,
|
pub lifetimes: usize,
|
||||||
pub types: usize,
|
pub types: usize,
|
||||||
pub consts: usize,
|
pub consts: usize,
|
||||||
|
pub infer: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents lifetimes and type parameters attached to a declaration
|
/// Represents lifetimes and type parameters attached to a declaration
|
||||||
|
@ -3130,6 +3171,8 @@ pub enum Node<'hir> {
|
||||||
Visibility(&'hir Visibility<'hir>),
|
Visibility(&'hir Visibility<'hir>),
|
||||||
|
|
||||||
Crate(&'hir Mod<'hir>),
|
Crate(&'hir Mod<'hir>),
|
||||||
|
|
||||||
|
Infer(&'hir InferArg),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'hir> Node<'hir> {
|
impl<'hir> Node<'hir> {
|
||||||
|
@ -3198,6 +3241,7 @@ impl<'hir> Node<'hir> {
|
||||||
| Node::Local(Local { hir_id, .. })
|
| Node::Local(Local { hir_id, .. })
|
||||||
| Node::Lifetime(Lifetime { hir_id, .. })
|
| Node::Lifetime(Lifetime { hir_id, .. })
|
||||||
| Node::Param(Param { hir_id, .. })
|
| Node::Param(Param { hir_id, .. })
|
||||||
|
| Node::Infer(InferArg { hir_id, .. })
|
||||||
| Node::GenericParam(GenericParam { hir_id, .. }) => Some(*hir_id),
|
| Node::GenericParam(GenericParam { hir_id, .. }) => Some(*hir_id),
|
||||||
Node::TraitRef(TraitRef { hir_ref_id, .. }) => Some(*hir_ref_id),
|
Node::TraitRef(TraitRef { hir_ref_id, .. }) => Some(*hir_ref_id),
|
||||||
Node::PathSegment(PathSegment { hir_id, .. }) => *hir_id,
|
Node::PathSegment(PathSegment { hir_id, .. }) => *hir_id,
|
||||||
|
|
|
@ -436,11 +436,15 @@ pub trait Visitor<'v>: Sized {
|
||||||
fn visit_label(&mut self, label: &'v Label) {
|
fn visit_label(&mut self, label: &'v Label) {
|
||||||
walk_label(self, label)
|
walk_label(self, label)
|
||||||
}
|
}
|
||||||
|
fn visit_infer(&mut self, inf: &'v InferArg) {
|
||||||
|
walk_inf(self, inf);
|
||||||
|
}
|
||||||
fn visit_generic_arg(&mut self, generic_arg: &'v GenericArg<'v>) {
|
fn visit_generic_arg(&mut self, generic_arg: &'v GenericArg<'v>) {
|
||||||
match generic_arg {
|
match generic_arg {
|
||||||
GenericArg::Lifetime(lt) => self.visit_lifetime(lt),
|
GenericArg::Lifetime(lt) => self.visit_lifetime(lt),
|
||||||
GenericArg::Type(ty) => self.visit_ty(ty),
|
GenericArg::Type(ty) => self.visit_ty(ty),
|
||||||
GenericArg::Const(ct) => self.visit_anon_const(&ct.value),
|
GenericArg::Const(ct) => self.visit_anon_const(&ct.value),
|
||||||
|
GenericArg::Infer(inf) => self.visit_infer(inf),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn visit_lifetime(&mut self, lifetime: &'v Lifetime) {
|
fn visit_lifetime(&mut self, lifetime: &'v Lifetime) {
|
||||||
|
@ -747,6 +751,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>>(
|
pub fn walk_qpath<'v, V: Visitor<'v>>(
|
||||||
visitor: &mut V,
|
visitor: &mut V,
|
||||||
qpath: &'v QPath<'v>,
|
qpath: &'v QPath<'v>,
|
||||||
|
|
|
@ -103,6 +103,7 @@ impl<'a> State<'a> {
|
||||||
Node::TraitRef(a) => self.print_trait_ref(&a),
|
Node::TraitRef(a) => self.print_trait_ref(&a),
|
||||||
Node::Binding(a) | Node::Pat(a) => self.print_pat(&a),
|
Node::Binding(a) | Node::Pat(a) => self.print_pat(&a),
|
||||||
Node::Arm(a) => self.print_arm(&a),
|
Node::Arm(a) => self.print_arm(&a),
|
||||||
|
Node::Infer(_) => self.s.word("_"),
|
||||||
Node::Block(a) => {
|
Node::Block(a) => {
|
||||||
// Containing cbox, will be closed by print-block at `}`.
|
// Containing cbox, will be closed by print-block at `}`.
|
||||||
self.cbox(INDENT_UNIT);
|
self.cbox(INDENT_UNIT);
|
||||||
|
@ -437,14 +438,14 @@ impl<'a> State<'a> {
|
||||||
self.print_anon_const(e);
|
self.print_anon_const(e);
|
||||||
self.s.word(")");
|
self.s.word(")");
|
||||||
}
|
}
|
||||||
hir::TyKind::Infer => {
|
|
||||||
self.s.word("_");
|
|
||||||
}
|
|
||||||
hir::TyKind::Err => {
|
hir::TyKind::Err => {
|
||||||
self.popen();
|
self.popen();
|
||||||
self.s.word("/*ERROR*/");
|
self.s.word("/*ERROR*/");
|
||||||
self.pclose();
|
self.pclose();
|
||||||
}
|
}
|
||||||
|
hir::TyKind::Infer => {
|
||||||
|
self.s.word("_");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self.end()
|
self.end()
|
||||||
}
|
}
|
||||||
|
@ -1851,6 +1852,7 @@ impl<'a> State<'a> {
|
||||||
GenericArg::Lifetime(_) => {}
|
GenericArg::Lifetime(_) => {}
|
||||||
GenericArg::Type(ty) => s.print_type(ty),
|
GenericArg::Type(ty) => s.print_type(ty),
|
||||||
GenericArg::Const(ct) => s.print_anon_const(&ct.value),
|
GenericArg::Const(ct) => s.print_anon_const(&ct.value),
|
||||||
|
GenericArg::Infer(_inf) => s.word("_"),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -244,6 +244,11 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
|
||||||
hir_visit::walk_ty(self, t);
|
hir_visit::walk_ty(self, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_infer(&mut self, inf: &'tcx hir::InferArg) {
|
||||||
|
lint_callback!(self, check_infer, inf);
|
||||||
|
hir_visit::walk_inf(self, inf);
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_name(&mut self, sp: Span, name: Symbol) {
|
fn visit_name(&mut self, sp: Span, name: Symbol) {
|
||||||
lint_callback!(self, check_name, sp, name);
|
lint_callback!(self, check_name, sp, name);
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,7 @@ macro_rules! late_lint_methods {
|
||||||
fn check_expr(a: &$hir hir::Expr<$hir>);
|
fn check_expr(a: &$hir hir::Expr<$hir>);
|
||||||
fn check_expr_post(a: &$hir hir::Expr<$hir>);
|
fn check_expr_post(a: &$hir hir::Expr<$hir>);
|
||||||
fn check_ty(a: &$hir hir::Ty<$hir>);
|
fn check_ty(a: &$hir hir::Ty<$hir>);
|
||||||
|
fn check_infer(a: &$hir hir::InferArg);
|
||||||
fn check_generic_arg(a: &$hir hir::GenericArg<$hir>);
|
fn check_generic_arg(a: &$hir hir::GenericArg<$hir>);
|
||||||
fn check_generic_param(a: &$hir hir::GenericParam<$hir>);
|
fn check_generic_param(a: &$hir hir::GenericParam<$hir>);
|
||||||
fn check_generics(a: &$hir hir::Generics<$hir>);
|
fn check_generics(a: &$hir hir::Generics<$hir>);
|
||||||
|
|
|
@ -336,6 +336,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>) {
|
fn visit_trait_ref(&mut self, tr: &'hir TraitRef<'hir>) {
|
||||||
self.insert(tr.path.span, tr.hir_ref_id, Node::TraitRef(tr));
|
self.insert(tr.path.span, tr.hir_ref_id, Node::TraitRef(tr));
|
||||||
|
|
||||||
|
|
|
@ -276,6 +276,7 @@ impl<'hir> Map<'hir> {
|
||||||
Node::Stmt(_)
|
Node::Stmt(_)
|
||||||
| Node::PathSegment(_)
|
| Node::PathSegment(_)
|
||||||
| Node::Ty(_)
|
| Node::Ty(_)
|
||||||
|
| Node::Infer(_)
|
||||||
| Node::TraitRef(_)
|
| Node::TraitRef(_)
|
||||||
| Node::Pat(_)
|
| Node::Pat(_)
|
||||||
| Node::Binding(_)
|
| Node::Binding(_)
|
||||||
|
@ -871,6 +872,7 @@ impl<'hir> Map<'hir> {
|
||||||
node: VisibilityKind::Restricted { ref path, .. },
|
node: VisibilityKind::Restricted { ref path, .. },
|
||||||
..
|
..
|
||||||
}) => path.span,
|
}) => path.span,
|
||||||
|
Node::Infer(i) => i.span,
|
||||||
Node::Visibility(v) => bug!("unexpected Visibility {:?}", v),
|
Node::Visibility(v) => bug!("unexpected Visibility {:?}", v),
|
||||||
Node::Local(local) => local.span,
|
Node::Local(local) => local.span,
|
||||||
Node::MacroDef(macro_def) => macro_def.span,
|
Node::MacroDef(macro_def) => macro_def.span,
|
||||||
|
@ -1118,6 +1120,7 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId) -> String {
|
||||||
Some(Node::Param(_)) => node_str("param"),
|
Some(Node::Param(_)) => node_str("param"),
|
||||||
Some(Node::Arm(_)) => node_str("arm"),
|
Some(Node::Arm(_)) => node_str("arm"),
|
||||||
Some(Node::Block(_)) => node_str("block"),
|
Some(Node::Block(_)) => node_str("block"),
|
||||||
|
Some(Node::Infer(_)) => node_str("infer"),
|
||||||
Some(Node::Local(_)) => node_str("local"),
|
Some(Node::Local(_)) => node_str("local"),
|
||||||
Some(Node::Ctor(..)) => format!("ctor {}{}", path_str(), id_str),
|
Some(Node::Ctor(..)) => format!("ctor {}{}", path_str(), id_str),
|
||||||
Some(Node::Lifetime(_)) => node_str("lifetime"),
|
Some(Node::Lifetime(_)) => node_str("lifetime"),
|
||||||
|
|
|
@ -1188,6 +1188,14 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
|
||||||
self.maybe_typeck_results = old_maybe_typeck_results;
|
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.visit_infer(inf),
|
||||||
|
hir::GenericArg::Lifetime(_) | hir::GenericArg::Const(_) => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_ty(&mut self, hir_ty: &'tcx hir::Ty<'tcx>) {
|
fn visit_ty(&mut self, hir_ty: &'tcx hir::Ty<'tcx>) {
|
||||||
self.span = hir_ty.span;
|
self.span = hir_ty.span;
|
||||||
if let Some(typeck_results) = self.maybe_typeck_results {
|
if let Some(typeck_results) = self.maybe_typeck_results {
|
||||||
|
@ -1207,6 +1215,30 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
|
||||||
intravisit::walk_ty(self, hir_ty);
|
intravisit::walk_ty(self, hir_ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_infer(&mut self, inf: &'tcx hir::InferArg) {
|
||||||
|
self.span = inf.span;
|
||||||
|
if let Some(typeck_results) = self.maybe_typeck_results {
|
||||||
|
if let Some(ty) = typeck_results.node_type_opt(inf.hir_id) {
|
||||||
|
if self.visit(ty).is_break() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
intravisit::walk_inf(self, inf);
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_trait_ref(&mut self, trait_ref: &'tcx hir::TraitRef<'tcx>) {
|
fn visit_trait_ref(&mut self, trait_ref: &'tcx hir::TraitRef<'tcx>) {
|
||||||
self.span = trait_ref.path.span;
|
self.span = trait_ref.path.span;
|
||||||
if self.maybe_typeck_results.is_none() {
|
if self.maybe_typeck_results.is_none() {
|
||||||
|
@ -1443,6 +1475,14 @@ impl<'a, 'b, 'tcx, 'v> Visitor<'v> for ObsoleteCheckTypeForPrivatenessVisitor<'a
|
||||||
NestedVisitorMap::None
|
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<'_>) {
|
fn visit_ty(&mut self, ty: &hir::Ty<'_>) {
|
||||||
if let hir::TyKind::Path(hir::QPath::Resolved(_, ref path)) = ty.kind {
|
if let hir::TyKind::Path(hir::QPath::Resolved(_, ref path)) = ty.kind {
|
||||||
if self.inner.path_is_private_type(path) {
|
if self.inner.path_is_private_type(path) {
|
||||||
|
|
|
@ -2550,6 +2550,12 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||||
GenericArg::Const(ct) => {
|
GenericArg::Const(ct) => {
|
||||||
self.visit_anon_const(&ct.value);
|
self.visit_anon_const(&ct.value);
|
||||||
}
|
}
|
||||||
|
GenericArg::Infer(inf) => {
|
||||||
|
self.visit_id(inf.hir_id);
|
||||||
|
if inf.kind.is_type() {
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -622,6 +622,7 @@ symbols! {
|
||||||
generator,
|
generator,
|
||||||
generator_state,
|
generator_state,
|
||||||
generators,
|
generators,
|
||||||
|
generic_arg_infer,
|
||||||
generic_associated_types,
|
generic_associated_types,
|
||||||
generic_param_attrs,
|
generic_param_attrs,
|
||||||
get_context,
|
get_context,
|
||||||
|
|
|
@ -39,8 +39,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
);
|
);
|
||||||
|
|
||||||
if let GenericParamDefKind::Const { .. } = param.kind {
|
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, .. })) {
|
||||||
err.help("const arguments cannot yet be inferred with `_`");
|
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",
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,14 +254,22 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
(Some(&arg), Some(¶m)) => {
|
(Some(&arg), Some(¶m)) => {
|
||||||
match (arg, ¶m.kind, arg_count.explicit_late_bound) {
|
match (arg, ¶m.kind, arg_count.explicit_late_bound) {
|
||||||
(GenericArg::Lifetime(_), GenericParamDefKind::Lifetime, _)
|
(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));
|
substs.push(ctx.provided_kind(param, arg));
|
||||||
args.next();
|
args.next();
|
||||||
params.next();
|
params.next();
|
||||||
}
|
}
|
||||||
(
|
(
|
||||||
GenericArg::Type(_) | GenericArg::Const(_),
|
GenericArg::Infer(_) | GenericArg::Type(_) | GenericArg::Const(_),
|
||||||
GenericParamDefKind::Lifetime,
|
GenericParamDefKind::Lifetime,
|
||||||
_,
|
_,
|
||||||
) => {
|
) => {
|
||||||
|
@ -325,6 +338,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
.features()
|
.features()
|
||||||
.unordered_const_ty_params(),
|
.unordered_const_ty_params(),
|
||||||
},
|
},
|
||||||
|
GenericArg::Infer(_) => ParamKindOrd::Infer,
|
||||||
}),
|
}),
|
||||||
Some(&format!(
|
Some(&format!(
|
||||||
"reorder the arguments: {}: `<{}>`",
|
"reorder the arguments: {}: `<{}>`",
|
||||||
|
@ -446,8 +460,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
let default_counts = gen_params.own_defaults();
|
let default_counts = gen_params.own_defaults();
|
||||||
let param_counts = gen_params.own_counts();
|
let param_counts = gen_params.own_counts();
|
||||||
let named_type_param_count = param_counts.types - has_self as usize;
|
let named_type_param_count = param_counts.types - has_self as usize;
|
||||||
let arg_counts = gen_args.own_counts();
|
let infer_lifetimes =
|
||||||
let infer_lifetimes = gen_pos != GenericArgPosition::Type && arg_counts.lifetimes == 0;
|
gen_pos != GenericArgPosition::Type && !gen_args.has_lifetime_params();
|
||||||
|
|
||||||
if gen_pos != GenericArgPosition::Type && !gen_args.bindings.is_empty() {
|
if gen_pos != GenericArgPosition::Type && !gen_args.bindings.is_empty() {
|
||||||
Self::prohibit_assoc_ty_binding(tcx, gen_args.bindings[0].span);
|
Self::prohibit_assoc_ty_binding(tcx, gen_args.bindings[0].span);
|
||||||
|
@ -505,7 +519,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
|
|
||||||
let min_expected_lifetime_args = if infer_lifetimes { 0 } else { param_counts.lifetimes };
|
let min_expected_lifetime_args = if infer_lifetimes { 0 } else { param_counts.lifetimes };
|
||||||
let max_expected_lifetime_args = 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(
|
let lifetimes_correct = check_lifetime_args(
|
||||||
min_expected_lifetime_args,
|
min_expected_lifetime_args,
|
||||||
|
@ -576,14 +590,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
- default_counts.consts
|
- default_counts.consts
|
||||||
};
|
};
|
||||||
debug!("expected_min: {:?}", expected_min);
|
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(
|
check_types_and_consts(
|
||||||
expected_min,
|
expected_min,
|
||||||
param_counts.consts + named_type_param_count,
|
param_counts.consts + named_type_param_count,
|
||||||
arg_counts.consts + arg_counts.types,
|
gen_args.num_generic_params(),
|
||||||
param_counts.lifetimes + has_self as usize,
|
param_counts.lifetimes + has_self as usize,
|
||||||
arg_counts.lifetimes,
|
gen_args.num_lifetime_params(),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -622,7 +636,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
.args
|
.args
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|arg| match arg {
|
.filter_map(|arg| match arg {
|
||||||
GenericArg::Type(_) | GenericArg::Const(_) => Some(arg.span()),
|
GenericArg::Infer(_) | GenericArg::Type(_) | GenericArg::Const(_) => {
|
||||||
|
Some(arg.span())
|
||||||
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
@ -659,8 +675,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
position: GenericArgPosition,
|
position: GenericArgPosition,
|
||||||
) -> ExplicitLateBound {
|
) -> ExplicitLateBound {
|
||||||
let param_counts = def.own_counts();
|
let param_counts = def.own_counts();
|
||||||
let arg_counts = args.own_counts();
|
let infer_lifetimes = position != GenericArgPosition::Type && !args.has_lifetime_params();
|
||||||
let infer_lifetimes = position != GenericArgPosition::Type && arg_counts.lifetimes == 0;
|
|
||||||
|
|
||||||
if infer_lifetimes {
|
if infer_lifetimes {
|
||||||
return ExplicitLateBound::No;
|
return ExplicitLateBound::No;
|
||||||
|
@ -673,7 +688,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
let span = args.args[0].span();
|
let span = args.args[0].span();
|
||||||
|
|
||||||
if position == GenericArgPosition::Value
|
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);
|
let mut err = tcx.sess.struct_span_err(span, msg);
|
||||||
err.span_note(span_late, note);
|
err.span_note(span_late, note);
|
||||||
|
|
|
@ -461,6 +461,43 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
)
|
)
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
(&GenericParamDefKind::Const { has_default }, hir::GenericArg::Infer(inf)) => {
|
||||||
|
if has_default {
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(
|
||||||
|
&GenericParamDefKind::Type { has_default, .. },
|
||||||
|
hir::GenericArg::Infer(inf),
|
||||||
|
) => {
|
||||||
|
if has_default {
|
||||||
|
tcx.check_optional_stability(
|
||||||
|
param.def_id,
|
||||||
|
Some(arg.id()),
|
||||||
|
arg.span(),
|
||||||
|
None,
|
||||||
|
|_, _| {
|
||||||
|
// 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!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1930,6 +1967,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
has_err = true;
|
has_err = true;
|
||||||
(ct.span, "const")
|
(ct.span, "const")
|
||||||
}
|
}
|
||||||
|
hir::GenericArg::Infer(inf) => {
|
||||||
|
if err_for_ty {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
has_err = true;
|
||||||
|
err_for_ty = true;
|
||||||
|
(inf.span, "generic")
|
||||||
|
}
|
||||||
};
|
};
|
||||||
let mut err = struct_span_err!(
|
let mut err = struct_span_err!(
|
||||||
self.tcx().sess,
|
self.tcx().sess,
|
||||||
|
|
|
@ -581,6 +581,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn node_ty_opt(&self, id: hir::HirId) -> Option<Ty<'tcx>> {
|
||||||
|
match self.typeck_results.borrow().node_types().get(id) {
|
||||||
|
Some(&t) => Some(t),
|
||||||
|
None if self.is_tainted_by_errors() => Some(self.tcx.ty_error()),
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Registers an obligation for checking later, during regionck, that `arg` is well-formed.
|
/// Registers an obligation for checking later, during regionck, that `arg` is well-formed.
|
||||||
pub fn register_wf_obligation(
|
pub fn register_wf_obligation(
|
||||||
&self,
|
&self,
|
||||||
|
@ -1471,6 +1479,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
|
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
|
||||||
self.fcx.const_arg_to_const(&ct.value, param.def_id).into()
|
self.fcx.const_arg_to_const(&ct.value, param.def_id).into()
|
||||||
}
|
}
|
||||||
|
(GenericParamDefKind::Type { .. }, GenericArg::Infer(inf)) => {
|
||||||
|
self.fcx.ty_infer(Some(param), inf.span).into()
|
||||||
|
}
|
||||||
|
(GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => {
|
||||||
|
let tcx = self.fcx.tcx();
|
||||||
|
self.fcx.ct_infer(tcx.type_of(param.def_id), Some(param), inf.span).into()
|
||||||
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -366,6 +366,13 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
||||||
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
|
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
|
||||||
self.cfcx.const_arg_to_const(&ct.value, param.def_id).into()
|
self.cfcx.const_arg_to_const(&ct.value, param.def_id).into()
|
||||||
}
|
}
|
||||||
|
(GenericParamDefKind::Type { .. }, GenericArg::Infer(inf)) => {
|
||||||
|
self.cfcx.ty_infer(Some(param), inf.span).into()
|
||||||
|
}
|
||||||
|
(GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => {
|
||||||
|
let tcx = self.cfcx.tcx();
|
||||||
|
self.cfcx.ct_infer(tcx.type_of(param.def_id), Some(param), inf.span).into()
|
||||||
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -331,6 +331,15 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> {
|
||||||
let ty = self.resolve(ty, &hir_ty.span);
|
let ty = self.resolve(ty, &hir_ty.span);
|
||||||
self.write_ty_to_typeck_results(hir_ty.hir_id, ty);
|
self.write_ty_to_typeck_results(hir_ty.hir_id, ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_infer(&mut self, inf: &'tcx hir::InferArg) {
|
||||||
|
intravisit::walk_inf(self, inf);
|
||||||
|
// Ignore cases where the inference is a const.
|
||||||
|
if let Some(ty) = self.fcx.node_ty_opt(inf.hir_id) {
|
||||||
|
let ty = self.resolve(ty, &inf.span);
|
||||||
|
self.write_ty_to_typeck_results(inf.hir_id, ty);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
|
impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
|
||||||
|
|
|
@ -129,6 +129,16 @@ impl<'v> Visitor<'v> for PlaceholderHirTyCollector {
|
||||||
}
|
}
|
||||||
intravisit::walk_ty(self, t)
|
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);
|
||||||
|
intravisit::walk_inf(self, inf);
|
||||||
|
}
|
||||||
|
hir::GenericArg::Type(t) => self.visit_ty(t),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CollectItemTypesVisitor<'tcx> {
|
struct CollectItemTypesVisitor<'tcx> {
|
||||||
|
@ -1714,13 +1724,11 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn are_suggestable_generic_args(generic_args: &[hir::GenericArg<'_>]) -> bool {
|
fn are_suggestable_generic_args(generic_args: &[hir::GenericArg<'_>]) -> bool {
|
||||||
generic_args
|
generic_args.iter().any(|arg| match arg {
|
||||||
.iter()
|
hir::GenericArg::Type(ty) => is_suggestable_infer_ty(ty),
|
||||||
.filter_map(|arg| match arg {
|
hir::GenericArg::Infer(_) => true,
|
||||||
hir::GenericArg::Type(ty) => Some(ty),
|
_ => false,
|
||||||
_ => None,
|
})
|
||||||
})
|
|
||||||
.any(is_suggestable_infer_ty)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether `ty` is a type with `_` placeholders that can be inferred. Used in diagnostics only to
|
/// Whether `ty` is a type with `_` placeholders that can be inferred. Used in diagnostics only to
|
||||||
|
|
|
@ -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`.
|
/// 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> {
|
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::*;
|
use hir::*;
|
||||||
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
|
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
|
||||||
|
|
||||||
|
|
|
@ -1768,6 +1768,7 @@ impl Clean<GenericArgs> for hir::GenericArgs<'_> {
|
||||||
hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()),
|
hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()),
|
||||||
hir::GenericArg::Type(ty) => GenericArg::Type(ty.clean(cx)),
|
hir::GenericArg::Type(ty) => GenericArg::Type(ty.clean(cx)),
|
||||||
hir::GenericArg::Const(ct) => GenericArg::Const(ct.clean(cx)),
|
hir::GenericArg::Const(ct) => GenericArg::Const(ct.clean(cx)),
|
||||||
|
hir::GenericArg::Infer(_inf) => GenericArg::Infer,
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
bindings: self.bindings.clean(cx),
|
bindings: self.bindings.clean(cx),
|
||||||
|
|
|
@ -2007,6 +2007,7 @@ crate enum GenericArg {
|
||||||
Lifetime(Lifetime),
|
Lifetime(Lifetime),
|
||||||
Type(Type),
|
Type(Type),
|
||||||
Const(Constant),
|
Const(Constant),
|
||||||
|
Infer,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
||||||
|
|
|
@ -1424,6 +1424,7 @@ impl clean::GenericArg {
|
||||||
clean::GenericArg::Lifetime(lt) => fmt::Display::fmt(<.print(), f),
|
clean::GenericArg::Lifetime(lt) => fmt::Display::fmt(<.print(), f),
|
||||||
clean::GenericArg::Type(ty) => fmt::Display::fmt(&ty.print(cx), 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::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()),
|
Lifetime(l) => GenericArg::Lifetime(l.0.to_string()),
|
||||||
Type(t) => GenericArg::Type(t.into_tcx(tcx)),
|
Type(t) => GenericArg::Type(t.into_tcx(tcx)),
|
||||||
Const(c) => GenericArg::Const(c.into_tcx(tcx)),
|
Const(c) => GenericArg::Const(c.into_tcx(tcx)),
|
||||||
|
Infer => GenericArg::Infer,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,6 +127,7 @@ pub enum GenericArg {
|
||||||
Lifetime(String),
|
Lifetime(String),
|
||||||
Type(Type),
|
Type(Type),
|
||||||
Const(Constant),
|
Const(Constant),
|
||||||
|
Infer,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
#[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]>() {}
|
LL | fn foo<const N: usize, const A: [u8; N]>() {}
|
||||||
| ^ the type must not depend on the parameter `N`
|
| ^ the type must not depend on the parameter `N`
|
||||||
|
|
||||||
error[E0747]: type provided when a constant was expected
|
error: constant expression depends on a generic parameter
|
||||||
--> $DIR/issue-62878.rs:10:11
|
--> $DIR/issue-62878.rs:10:14
|
||||||
|
|
|
|
||||||
LL | foo::<_, {[1]}>();
|
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
|
error[E0308]: mismatched types
|
||||||
--> $DIR/issue-62878.rs:10:15
|
--> $DIR/issue-62878.rs:10:15
|
||||||
|
@ -20,5 +20,5 @@ LL | foo::<_, {[1]}>();
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
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`.
|
For more information about an error, try `rustc --explain E0308`.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// revisions: full min
|
// revisions: full min
|
||||||
#![cfg_attr(full, feature(const_generics))]
|
#![cfg_attr(full, feature(const_generics, generic_arg_infer))]
|
||||||
#![cfg_attr(full, allow(incomplete_features))]
|
#![cfg_attr(full, allow(incomplete_features))]
|
||||||
|
|
||||||
fn foo<const N: usize, const A: [u8; N]>() {}
|
fn foo<const N: usize, const A: [u8; N]>() {}
|
||||||
|
@ -8,6 +8,6 @@ fn foo<const N: usize, const A: [u8; N]>() {}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
foo::<_, {[1]}>();
|
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,9 @@
|
||||||
#![feature(min_const_generics)]
|
#![feature(generic_arg_infer)]
|
||||||
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]
|
[0; K]
|
||||||
}
|
}
|
||||||
fn main() {
|
fn main() {
|
||||||
let a = foo::<_, 2>([0, 1, 2]);
|
let _a = foo::<_, 2>([0, 1, 2]);
|
||||||
//~^ ERROR type provided when a constant was expected
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
error[E0747]: type provided when a constant was expected
|
error[E0747]: type provided when a constant was expected
|
||||||
--> $DIR/inferred_const.rs:6:19
|
--> $DIR/feature-gate-generic_arg_infer.rs:11:20
|
||||||
|
|
|
|
||||||
LL | let a = foo::<_, 2>([0, 1, 2]);
|
LL | let _x = foo::<_>([1,2]);
|
||||||
| ^
|
| ^
|
||||||
|
|
|
|
||||||
= help: const arguments cannot yet be inferred with `_`
|
= help: const arguments cannot yet be inferred with `_`
|
||||||
|
= help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
13
src/test/ui/feature-gates/feature-gate-generic_arg_infer.rs
Normal file
13
src/test/ui/feature-gates/feature-gate-generic_arg_infer.rs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
// [feature] run-pass
|
||||||
|
// revisions: normal feature
|
||||||
|
|
||||||
|
#![cfg_attr(feature, feature(generic_arg_infer))]
|
||||||
|
|
||||||
|
fn foo<const N: usize>(_: [u8; N]) -> [u8; N] {
|
||||||
|
[0; N]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let _x = foo::<_>([1,2]);
|
||||||
|
//[normal]~^ ERROR: type provided when a constant was expected
|
||||||
|
}
|
24
src/test/ui/inference/infer-arg-test.rs
Normal file
24
src/test/ui/inference/infer-arg-test.rs
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#![feature(generic_arg_infer)]
|
||||||
|
|
||||||
|
struct All<'a, T, const N: usize> {
|
||||||
|
v: &'a T,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct BadInfer<_>;
|
||||||
|
//~^ ERROR expected identifier
|
||||||
|
//~| ERROR parameter `_` is never used
|
||||||
|
|
||||||
|
fn all_fn<'a, T, const N: usize>() {}
|
||||||
|
|
||||||
|
fn bad_infer_fn<_>() {}
|
||||||
|
//~^ ERROR expected identifier
|
||||||
|
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let a: All<_, _, _>;
|
||||||
|
all_fn();
|
||||||
|
let v: [u8; _];
|
||||||
|
//~^ ERROR in expressions
|
||||||
|
let v: [u8; 10] = [0; _];
|
||||||
|
//~^ ERROR in expressions
|
||||||
|
}
|
36
src/test/ui/inference/infer-arg-test.stderr
Normal file
36
src/test/ui/inference/infer-arg-test.stderr
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
error: expected identifier, found reserved identifier `_`
|
||||||
|
--> $DIR/infer-arg-test.rs:7:17
|
||||||
|
|
|
||||||
|
LL | struct BadInfer<_>;
|
||||||
|
| ^ expected identifier, found reserved identifier
|
||||||
|
|
||||||
|
error: expected identifier, found reserved identifier `_`
|
||||||
|
--> $DIR/infer-arg-test.rs:13:17
|
||||||
|
|
|
||||||
|
LL | fn bad_infer_fn<_>() {}
|
||||||
|
| ^ expected identifier, found reserved identifier
|
||||||
|
|
||||||
|
error: in expressions, `_` can only be used on the left-hand side of an assignment
|
||||||
|
--> $DIR/infer-arg-test.rs:20:15
|
||||||
|
|
|
||||||
|
LL | let v: [u8; _];
|
||||||
|
| ^ `_` not allowed here
|
||||||
|
|
||||||
|
error: in expressions, `_` can only be used on the left-hand side of an assignment
|
||||||
|
--> $DIR/infer-arg-test.rs:22:25
|
||||||
|
|
|
||||||
|
LL | let v: [u8; 10] = [0; _];
|
||||||
|
| ^ `_` not allowed here
|
||||||
|
|
||||||
|
error[E0392]: parameter `_` is never used
|
||||||
|
--> $DIR/infer-arg-test.rs:7:17
|
||||||
|
|
|
||||||
|
LL | struct BadInfer<_>;
|
||||||
|
| ^ unused parameter
|
||||||
|
|
|
||||||
|
= help: consider removing `_`, referring to it in a field, or using a marker such as `PhantomData`
|
||||||
|
= help: if you intended `_` to be a const parameter, use `const _: usize` instead
|
||||||
|
|
||||||
|
error: aborting due to 5 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0392`.
|
35
src/test/ui/object-lifetime-default-inferred.rs
Normal file
35
src/test/ui/object-lifetime-default-inferred.rs
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
// run-pass
|
||||||
|
// Test that even with prior inferred parameters, object lifetimes of objects after are still
|
||||||
|
// valid.
|
||||||
|
|
||||||
|
// pretty-expanded FIXME #23616
|
||||||
|
|
||||||
|
#![allow(dead_code)]
|
||||||
|
#![feature(generic_arg_infer)]
|
||||||
|
|
||||||
|
trait Test {
|
||||||
|
fn foo(&self) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Foo;
|
||||||
|
impl Test for Foo {}
|
||||||
|
|
||||||
|
struct SomeStruct<'a> {
|
||||||
|
t: &'a dyn Test,
|
||||||
|
u: &'a (dyn Test+'a),
|
||||||
|
}
|
||||||
|
|
||||||
|
fn a<'a, const N: usize>(_: [u8; N], t: &'a (dyn Test+'a), mut ss: SomeStruct<'a>) {
|
||||||
|
ss.t = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn b<'a, T>(_: T, t: &'a (dyn Test+'a), mut ss: SomeStruct<'a>) {
|
||||||
|
ss.u = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// Inside a function body, we can just infer both
|
||||||
|
// lifetimes, to allow &'tmp (Display+'static).
|
||||||
|
a::<_>([], &Foo as &dyn Test, SomeStruct{t:&Foo,u:&Foo});
|
||||||
|
b::<_>(0u8, &Foo as &dyn Test, SomeStruct{t:&Foo,u:&Foo});
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0747]: type provided when a lifetime was expected
|
error[E0747]: type provided when a lifetime was expected
|
||||||
--> $DIR/issue-14303-fncall.rs:13:26
|
--> $DIR/issue-14303-fncall.rs:16:26
|
||||||
|
|
|
|
||||||
LL | .collect::<Vec<S<_, 'a>>>();
|
LL | .collect::<Vec<S<_, 'a>>>();
|
||||||
| ^
|
| ^
|
9
src/test/ui/parser/issue-14303-fncall.generic_arg.stderr
Normal file
9
src/test/ui/parser/issue-14303-fncall.generic_arg.stderr
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
error[E0747]: inferred provided when a lifetime was expected
|
||||||
|
--> $DIR/issue-14303-fncall.rs:16:26
|
||||||
|
|
|
||||||
|
LL | .collect::<Vec<S<_, 'a>>>();
|
||||||
|
| ^
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0747`.
|
|
@ -1,6 +1,9 @@
|
||||||
// can't run rustfix because it doesn't handle multipart suggestions correctly
|
// revisions: full generic_arg
|
||||||
// compile-flags: -Zborrowck=mir
|
// compile-flags: -Zborrowck=mir
|
||||||
|
// can't run rustfix because it doesn't handle multipart suggestions correctly
|
||||||
// we need the above to avoid ast borrowck failure in recovered code
|
// we need the above to avoid ast borrowck failure in recovered code
|
||||||
|
#![cfg_attr(generic_arg, feature(generic_arg_infer))]
|
||||||
|
|
||||||
|
|
||||||
struct S<'a, T> {
|
struct S<'a, T> {
|
||||||
a: &'a T,
|
a: &'a T,
|
||||||
|
@ -11,7 +14,8 @@ fn foo<'a, 'b>(start: &'a usize, end: &'a usize) {
|
||||||
let _x = (*start..*end)
|
let _x = (*start..*end)
|
||||||
.map(|x| S { a: start, b: end })
|
.map(|x| S { a: start, b: end })
|
||||||
.collect::<Vec<S<_, 'a>>>();
|
.collect::<Vec<S<_, 'a>>>();
|
||||||
//~^ ERROR type provided when a lifetime was expected
|
//[generic_arg]~^ ERROR inferred provided when a lifetime was expected
|
||||||
|
//[full]~^^ ERROR type provided when a lifetime was expected
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0282]: type annotations needed for `Option<_>`
|
error[E0282]: type annotations needed for `Option<_>`
|
||||||
--> $DIR/issue-42234-unknown-receiver-type.rs:7:7
|
--> $DIR/issue-42234-unknown-receiver-type.rs:10:7
|
||||||
|
|
|
|
||||||
LL | let x: Option<_> = None;
|
LL | let x: Option<_> = None;
|
||||||
| - consider giving `x` the explicit type `Option<_>`, where the type parameter `T` is specified
|
| - consider giving `x` the explicit type `Option<_>`, where the type parameter `T` is specified
|
||||||
|
@ -9,7 +9,7 @@ LL | x.unwrap().method_that_could_exist_on_some_type();
|
||||||
= note: type must be known at this point
|
= note: type must be known at this point
|
||||||
|
|
||||||
error[E0282]: type annotations needed
|
error[E0282]: type annotations needed
|
||||||
--> $DIR/issue-42234-unknown-receiver-type.rs:13:10
|
--> $DIR/issue-42234-unknown-receiver-type.rs:16:10
|
||||||
|
|
|
|
||||||
LL | .sum::<_>()
|
LL | .sum::<_>()
|
||||||
| ^^^ cannot infer type
|
| ^^^ cannot infer type
|
|
@ -0,0 +1,21 @@
|
||||||
|
error[E0282]: type annotations needed for `Option<_>`
|
||||||
|
--> $DIR/issue-42234-unknown-receiver-type.rs:10:7
|
||||||
|
|
|
||||||
|
LL | let x: Option<_> = None;
|
||||||
|
| - consider giving `x` the explicit type `Option<_>`, where the type parameter `T` is specified
|
||||||
|
LL | x.unwrap().method_that_could_exist_on_some_type();
|
||||||
|
| ^^^^^^ cannot infer type for type parameter `T`
|
||||||
|
|
|
||||||
|
= note: type must be known at this point
|
||||||
|
|
||||||
|
error[E0282]: type annotations needed
|
||||||
|
--> $DIR/issue-42234-unknown-receiver-type.rs:16:16
|
||||||
|
|
|
||||||
|
LL | .sum::<_>()
|
||||||
|
| ^ cannot infer type for type parameter `S` declared on the associated function `sum`
|
||||||
|
|
|
||||||
|
= note: type must be known at this point
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0282`.
|
|
@ -1,3 +1,6 @@
|
||||||
|
// revisions: full generic_arg
|
||||||
|
#![cfg_attr(generic_arg, feature(generic_arg_infer))]
|
||||||
|
|
||||||
// When the type of a method call's receiver is unknown, the span should point
|
// When the type of a method call's receiver is unknown, the span should point
|
||||||
// to the receiver (and not the entire call, as was previously the case before
|
// to the receiver (and not the entire call, as was previously the case before
|
||||||
// the fix of which this tests).
|
// the fix of which this tests).
|
||||||
|
|
|
@ -5,7 +5,7 @@ use std::collections::BTreeMap;
|
||||||
|
|
||||||
use rustc_errors::DiagnosticBuilder;
|
use rustc_errors::DiagnosticBuilder;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::intravisit::{walk_body, walk_expr, walk_ty, NestedVisitorMap, Visitor};
|
use rustc_hir::intravisit::{walk_body, walk_expr, walk_ty, walk_inf, NestedVisitorMap, Visitor};
|
||||||
use rustc_hir::{Body, Expr, ExprKind, GenericArg, Item, ItemKind, QPath, TyKind};
|
use rustc_hir::{Body, Expr, ExprKind, GenericArg, Item, ItemKind, QPath, TyKind};
|
||||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||||
use rustc_middle::hir::map::Map;
|
use rustc_middle::hir::map::Map;
|
||||||
|
@ -295,6 +295,14 @@ impl<'a, 'tcx> Visitor<'tcx> for ImplicitHasherTypeVisitor<'a, 'tcx> {
|
||||||
walk_ty(self, t);
|
walk_ty(self, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_infer(&mut self, inf: &'tcx hir::InferArg) {
|
||||||
|
if let Some(target) = ImplicitHasherType::new(self.cx, &inf.to_ty()) {
|
||||||
|
self.found.push(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
walk_inf(self, inf);
|
||||||
|
}
|
||||||
|
|
||||||
fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
|
fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
|
||||||
NestedVisitorMap::None
|
NestedVisitorMap::None
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use clippy_utils::diagnostics::span_lint;
|
use clippy_utils::diagnostics::span_lint;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::intravisit::{walk_ty, NestedVisitorMap, Visitor};
|
use rustc_hir::intravisit::{walk_ty, walk_inf, NestedVisitorMap, Visitor};
|
||||||
use rustc_hir::{GenericParamKind, TyKind};
|
use rustc_hir::{GenericParamKind, TyKind};
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
use rustc_middle::hir::map::Map;
|
use rustc_middle::hir::map::Map;
|
||||||
|
@ -39,6 +39,11 @@ struct TypeComplexityVisitor {
|
||||||
impl<'tcx> Visitor<'tcx> for TypeComplexityVisitor {
|
impl<'tcx> Visitor<'tcx> for TypeComplexityVisitor {
|
||||||
type Map = Map<'tcx>;
|
type Map = Map<'tcx>;
|
||||||
|
|
||||||
|
fn visit_infer(&mut self, inf: &'tcx hir::InferArg) {
|
||||||
|
self.score += 1;
|
||||||
|
walk_inf(self, inf);
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_ty(&mut self, ty: &'tcx hir::Ty<'_>) {
|
fn visit_ty(&mut self, ty: &'tcx hir::Ty<'_>) {
|
||||||
let (add_score, sub_nest) = match ty.kind {
|
let (add_score, sub_nest) = match ty.kind {
|
||||||
// _, &x and *x have only small overhead; don't mess with nesting level
|
// _, &x and *x have only small overhead; don't mess with nesting level
|
||||||
|
|
|
@ -8,8 +8,9 @@ use rustc_hir::{
|
||||||
self as hir,
|
self as hir,
|
||||||
def::{CtorOf, DefKind, Res},
|
def::{CtorOf, DefKind, Res},
|
||||||
def_id::LocalDefId,
|
def_id::LocalDefId,
|
||||||
intravisit::{walk_ty, NestedVisitorMap, Visitor},
|
intravisit::{walk_ty, walk_inf, NestedVisitorMap, Visitor},
|
||||||
Expr, ExprKind, FnRetTy, FnSig, GenericArg, HirId, Impl, ImplItemKind, Item, ItemKind, Path, QPath, TyKind,
|
Expr, ExprKind, FnRetTy, FnSig, GenericArg, HirId, Impl, ImplItemKind, Item, ItemKind, Path,
|
||||||
|
QPath, TyKind,
|
||||||
};
|
};
|
||||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||||
use rustc_middle::hir::map::Map;
|
use rustc_middle::hir::map::Map;
|
||||||
|
@ -263,6 +264,11 @@ struct SkipTyCollector {
|
||||||
impl<'tcx> Visitor<'tcx> for SkipTyCollector {
|
impl<'tcx> Visitor<'tcx> for SkipTyCollector {
|
||||||
type Map = Map<'tcx>;
|
type Map = Map<'tcx>;
|
||||||
|
|
||||||
|
fn visit_infer(&mut self, inf: &hir::InferArg) {
|
||||||
|
self.types_to_skip.push(inf.hir_id);
|
||||||
|
|
||||||
|
walk_inf(self, inf)
|
||||||
|
}
|
||||||
fn visit_ty(&mut self, hir_ty: &hir::Ty<'_>) {
|
fn visit_ty(&mut self, hir_ty: &hir::Ty<'_>) {
|
||||||
self.types_to_skip.push(hir_ty.hir_id);
|
self.types_to_skip.push(hir_ty.hir_id);
|
||||||
|
|
||||||
|
|
|
@ -288,6 +288,8 @@ impl HirEqInterExpr<'_, '_, '_> {
|
||||||
(GenericArg::Const(l), GenericArg::Const(r)) => self.eq_body(l.value.body, r.value.body),
|
(GenericArg::Const(l), GenericArg::Const(r)) => self.eq_body(l.value.body, r.value.body),
|
||||||
(GenericArg::Lifetime(l_lt), GenericArg::Lifetime(r_lt)) => Self::eq_lifetime(l_lt, r_lt),
|
(GenericArg::Lifetime(l_lt), GenericArg::Lifetime(r_lt)) => Self::eq_lifetime(l_lt, r_lt),
|
||||||
(GenericArg::Type(l_ty), GenericArg::Type(r_ty)) => self.eq_ty(l_ty, r_ty),
|
(GenericArg::Type(l_ty), GenericArg::Type(r_ty)) => self.eq_ty(l_ty, r_ty),
|
||||||
|
(GenericArg::Infer(l_inf), GenericArg::Infer(r_inf)) =>
|
||||||
|
self.eq_ty(&l_inf.to_ty(), &r_inf.to_ty()),
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -885,7 +887,11 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
||||||
|
|
||||||
pub fn hash_ty(&mut self, ty: &Ty<'_>) {
|
pub fn hash_ty(&mut self, ty: &Ty<'_>) {
|
||||||
std::mem::discriminant(&ty.kind).hash(&mut self.s);
|
std::mem::discriminant(&ty.kind).hash(&mut self.s);
|
||||||
match ty.kind {
|
self.hash_tykind(&ty.kind);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn hash_tykind(&mut self, ty: &TyKind<'_>) {
|
||||||
|
match ty {
|
||||||
TyKind::Slice(ty) => {
|
TyKind::Slice(ty) => {
|
||||||
self.hash_ty(ty);
|
self.hash_ty(ty);
|
||||||
},
|
},
|
||||||
|
@ -898,7 +904,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
||||||
mut_ty.mutbl.hash(&mut self.s);
|
mut_ty.mutbl.hash(&mut self.s);
|
||||||
},
|
},
|
||||||
TyKind::Rptr(lifetime, ref mut_ty) => {
|
TyKind::Rptr(lifetime, ref mut_ty) => {
|
||||||
self.hash_lifetime(lifetime);
|
self.hash_lifetime(*lifetime);
|
||||||
self.hash_ty(mut_ty.ty);
|
self.hash_ty(mut_ty.ty);
|
||||||
mut_ty.mutbl.hash(&mut self.s);
|
mut_ty.mutbl.hash(&mut self.s);
|
||||||
},
|
},
|
||||||
|
@ -918,7 +924,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
||||||
bfn.decl.c_variadic.hash(&mut self.s);
|
bfn.decl.c_variadic.hash(&mut self.s);
|
||||||
},
|
},
|
||||||
TyKind::Tup(ty_list) => {
|
TyKind::Tup(ty_list) => {
|
||||||
for ty in ty_list {
|
for ty in *ty_list {
|
||||||
self.hash_ty(ty);
|
self.hash_ty(ty);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -927,7 +933,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
||||||
self.hash_generic_args(arg_list);
|
self.hash_generic_args(arg_list);
|
||||||
},
|
},
|
||||||
TyKind::TraitObject(_, lifetime, _) => {
|
TyKind::TraitObject(_, lifetime, _) => {
|
||||||
self.hash_lifetime(lifetime);
|
self.hash_lifetime(*lifetime);
|
||||||
},
|
},
|
||||||
TyKind::Typeof(anon_const) => {
|
TyKind::Typeof(anon_const) => {
|
||||||
self.hash_body(anon_const.body);
|
self.hash_body(anon_const.body);
|
||||||
|
@ -949,6 +955,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
||||||
GenericArg::Lifetime(l) => self.hash_lifetime(l),
|
GenericArg::Lifetime(l) => self.hash_lifetime(l),
|
||||||
GenericArg::Type(ref ty) => self.hash_ty(ty),
|
GenericArg::Type(ref ty) => self.hash_ty(ty),
|
||||||
GenericArg::Const(ref ca) => self.hash_body(ca.value.body),
|
GenericArg::Const(ref ca) => self.hash_body(ca.value.body),
|
||||||
|
GenericArg::Infer(ref inf) => self.hash_ty(&inf.to_ty()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -180,7 +180,7 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Per https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/infer/at/struct.At.html#method.normalize
|
// FIXME: Per https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/infer/at/struct.At.html#method.normalize
|
||||||
// this function can be removed once the `normalizie` method does not panic when normalization does
|
// this function can be removed once the `normalize` method does not panic when normalization does
|
||||||
// not succeed
|
// not succeed
|
||||||
/// Checks if `Ty` is normalizable. This function is useful
|
/// Checks if `Ty` is normalizable. This function is useful
|
||||||
/// to avoid crashes on `layout_of`.
|
/// to avoid crashes on `layout_of`.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue