Actually infer args in visitors
This commit is contained in:
parent
3605675bb1
commit
8759f00c73
30 changed files with 257 additions and 97 deletions
|
@ -336,6 +336,8 @@ 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,
|
Infer,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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};
|
||||||
|
@ -1219,9 +1219,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
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) => {
|
||||||
match ty.kind {
|
match ty.kind {
|
||||||
TyKind::Infer => {
|
TyKind::Infer if self.sess.features_untracked().generic_arg_infer => {
|
||||||
let hir_id = self.lower_node_id(ty.id);
|
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
|
// 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
|
// parsing. We try to resolve that ambiguity by attempting resolution in both the
|
||||||
|
|
|
@ -684,6 +684,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
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
|
|
|
@ -253,9 +253,23 @@ 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)]
|
#[derive(Encodable, Debug, HashStable_Generic)]
|
||||||
pub struct InferArg {
|
pub struct InferArg {
|
||||||
pub hir_id: HirId,
|
pub hir_id: HirId,
|
||||||
|
pub kind: InferKind,
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -365,22 +379,29 @@ impl GenericArgs<'_> {
|
||||||
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,
|
|
||||||
GenericArg::Infer(_) => own_counts.infer += 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.
|
||||||
|
|
|
@ -103,7 +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.print_string("_", ast::StrStyle::Cooked),
|
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);
|
||||||
|
|
|
@ -1224,6 +1224,13 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} 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.
|
// FIXME see above note for same issue.
|
||||||
if self.visit(rustc_typeck::hir_ty_to_ty(self.tcx, &inf.to_ty())).is_break() {
|
if self.visit(rustc_typeck::hir_ty_to_ty(self.tcx, &inf.to_ty())).is_break() {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -2559,7 +2559,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
GenericArg::Infer(inf) => {
|
GenericArg::Infer(inf) => {
|
||||||
self.visit_id(inf.hir_id);
|
self.visit_id(inf.hir_id);
|
||||||
i += 1;
|
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,11 +39,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
);
|
);
|
||||||
|
|
||||||
if let GenericParamDefKind::Const { .. } = param.kind {
|
if let GenericParamDefKind::Const { .. } = param.kind {
|
||||||
if matches!(
|
if matches!(arg, GenericArg::Type(hir::Ty { kind: hir::TyKind::Infer, .. })) {
|
||||||
arg,
|
|
||||||
GenericArg::Type(hir::Ty { kind: hir::TyKind::Infer, .. }) | GenericArg::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",
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -458,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);
|
||||||
|
@ -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 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,
|
||||||
|
@ -588,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 + arg_counts.infer,
|
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(),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -673,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;
|
||||||
|
@ -687,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);
|
||||||
|
|
|
@ -463,8 +463,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
}
|
}
|
||||||
(&GenericParamDefKind::Const { has_default }, hir::GenericArg::Infer(inf)) => {
|
(&GenericParamDefKind::Const { has_default }, hir::GenericArg::Infer(inf)) => {
|
||||||
if has_default {
|
if has_default {
|
||||||
// FIXME(const_generics): Actually infer parameter here?
|
|
||||||
tcx.const_param_default(param.def_id).into()
|
tcx.const_param_default(param.def_id).into()
|
||||||
|
} else if self.astconv.allow_ty_infer() {
|
||||||
|
// FIXME(const_generics): Actually infer parameter here?
|
||||||
|
todo!()
|
||||||
} else {
|
} else {
|
||||||
self.inferred_params.push(inf.span);
|
self.inferred_params.push(inf.span);
|
||||||
tcx.ty_error().into()
|
tcx.ty_error().into()
|
||||||
|
@ -1963,7 +1965,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
}
|
}
|
||||||
has_err = true;
|
has_err = true;
|
||||||
err_for_ty = true;
|
err_for_ty = true;
|
||||||
(inf.span, "inferred")
|
(inf.span, "generic")
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let mut err = struct_span_err!(
|
let mut err = struct_span_err!(
|
||||||
|
|
|
@ -1480,10 +1480,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
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)) => {
|
(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)) => {
|
(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!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
|
|
|
@ -367,10 +367,11 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
||||||
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)) => {
|
(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)) => {
|
(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!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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]>() {}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#![feature(generic_arg_infer)]
|
||||||
// run-pass
|
// run-pass
|
||||||
|
|
||||||
fn foo<const N: usize, const K: usize>(_data: [u32; N]) -> [u32; K] {
|
fn foo<const N: usize, const K: usize>(_data: [u32; N]) -> [u32; K] {
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
error[E0747]: type provided when a constant was expected
|
||||||
|
--> $DIR/feature-gate-generic_arg_infer.rs:11:20
|
||||||
|
|
|
||||||
|
LL | let _x = foo::<_>([1,2]);
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
= 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
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0747`.
|
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});
|
||||||
|
}
|
9
src/test/ui/parser/issue-14303-fncall.full.stderr
Normal file
9
src/test/ui/parser/issue-14303-fncall.full.stderr
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
error[E0747]: type 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,5 +1,5 @@
|
||||||
error[E0747]: inferred provided when a lifetime was expected
|
error[E0747]: inferred 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>>>();
|
||||||
| ^
|
| ^
|
|
@ -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 inferred 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() {}
|
||||||
|
|
|
@ -282,7 +282,7 @@ LL | let _: <Pub as PubTr<_>>::AssocTy;
|
||||||
LL | priv_parent_substs::mac!();
|
LL | priv_parent_substs::mac!();
|
||||||
| --------------------------- in this macro invocation
|
| --------------------------- in this macro invocation
|
||||||
|
|
|
|
||||||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
= 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
|
error: type `priv_parent_substs::Priv` is private
|
||||||
--> $DIR/associated-item-privacy-trait.rs:119:17
|
--> $DIR/associated-item-privacy-trait.rs:119:17
|
||||||
|
|
|
@ -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).
|
||||||
|
|
|
@ -9,7 +9,7 @@ use rustc_hir::{
|
||||||
def::{CtorOf, DefKind, Res},
|
def::{CtorOf, DefKind, Res},
|
||||||
def_id::LocalDefId,
|
def_id::LocalDefId,
|
||||||
intravisit::{walk_ty, walk_inf, NestedVisitorMap, Visitor},
|
intravisit::{walk_ty, walk_inf, NestedVisitorMap, Visitor},
|
||||||
Expr, ExprKind, FnRetTy, FnSig, GenericArg, HirId, Impl, ImplItemKind, Item, ItemKind, Node, Path, PathSegment,
|
Expr, ExprKind, FnRetTy, FnSig, GenericArg, HirId, Impl, ImplItemKind, Item, ItemKind, Path,
|
||||||
QPath, TyKind,
|
QPath, TyKind,
|
||||||
};
|
};
|
||||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||||
|
@ -280,52 +280,6 @@ impl<'tcx> Visitor<'tcx> for SkipTyCollector {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
<<<<<<< HEAD
|
|
||||||
=======
|
|
||||||
struct LintTyCollector<'a, 'tcx> {
|
|
||||||
cx: &'a LateContext<'tcx>,
|
|
||||||
self_ty: Ty<'tcx>,
|
|
||||||
types_to_lint: Vec<HirId>,
|
|
||||||
types_to_skip: Vec<HirId>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, 'tcx> Visitor<'tcx> for LintTyCollector<'a, 'tcx> {
|
|
||||||
type Map = Map<'tcx>;
|
|
||||||
|
|
||||||
fn visit_ty(&mut self, hir_ty: &'tcx hir::Ty<'_>) {
|
|
||||||
if_chain! {
|
|
||||||
if let Some(ty) = self.cx.typeck_results().node_type_opt(hir_ty.hir_id);
|
|
||||||
if should_lint_ty(hir_ty, ty, self.self_ty);
|
|
||||||
then {
|
|
||||||
self.types_to_lint.push(hir_ty.hir_id);
|
|
||||||
} else {
|
|
||||||
self.types_to_skip.push(hir_ty.hir_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
walk_ty(self, hir_ty);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_infer(&mut self, inf: &'tcx hir::InferArg) {
|
|
||||||
if_chain! {
|
|
||||||
if let Some(ty) = self.cx.typeck_results().node_type_opt(inf.hir_id);
|
|
||||||
if should_lint_ty(&inf.to_ty(), ty, self.self_ty);
|
|
||||||
then {
|
|
||||||
self.types_to_lint.push(inf.hir_id);
|
|
||||||
} else {
|
|
||||||
self.types_to_skip.push(inf.hir_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
walk_inf(self, inf)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
|
|
||||||
NestedVisitorMap::None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
>>>>>>> Add inferred args to typeck
|
|
||||||
fn span_lint(cx: &LateContext<'_>, span: Span) {
|
fn span_lint(cx: &LateContext<'_>, span: Span) {
|
||||||
span_lint_and_sugg(
|
span_lint_and_sugg(
|
||||||
cx,
|
cx,
|
||||||
|
|
|
@ -904,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);
|
||||||
},
|
},
|
||||||
|
@ -924,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);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -933,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);
|
||||||
|
|
|
@ -46,13 +46,13 @@ error: transmute from a pointer type (`*const i32`) to a reference type (`&issue
|
||||||
--> $DIR/transmute_ptr_to_ref.rs:32:32
|
--> $DIR/transmute_ptr_to_ref.rs:32:32
|
||||||
|
|
|
|
||||||
LL | let _: &Foo<u8> = unsafe { std::mem::transmute::<_, &Foo<_>>(raw) };
|
LL | let _: &Foo<u8> = unsafe { std::mem::transmute::<_, &Foo<_>>(raw) };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(raw as *const issue1231::Foo<u8>)`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(raw as *const Foo<_>)`
|
||||||
|
|
||||||
error: transmute from a pointer type (`*const i32`) to a reference type (`&issue1231::Foo<&u8>`)
|
error: transmute from a pointer type (`*const i32`) to a reference type (`&issue1231::Foo<&u8>`)
|
||||||
--> $DIR/transmute_ptr_to_ref.rs:34:33
|
--> $DIR/transmute_ptr_to_ref.rs:34:33
|
||||||
|
|
|
|
||||||
LL | let _: &Foo<&u8> = unsafe { std::mem::transmute::<_, &Foo<&_>>(raw) };
|
LL | let _: &Foo<&u8> = unsafe { std::mem::transmute::<_, &Foo<&_>>(raw) };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(raw as *const issue1231::Foo<&u8>)`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(raw as *const Foo<&_>)`
|
||||||
|
|
||||||
error: transmute from a pointer type (`*const i32`) to a reference type (`&u8`)
|
error: transmute from a pointer type (`*const i32`) to a reference type (`&u8`)
|
||||||
--> $DIR/transmute_ptr_to_ref.rs:38:14
|
--> $DIR/transmute_ptr_to_ref.rs:38:14
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue