mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 23:04:33 +00:00
parent
caa64e5b5e
commit
1b341fe8a1
@ -24,14 +24,20 @@ use rustc_hir as hir;
|
|||||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||||
use rustc_hir::intravisit::{self, Visitor};
|
use rustc_hir::intravisit::{self, Visitor};
|
||||||
use rustc_hir::{GenericParamKind, Node};
|
use rustc_hir::{GenericParamKind, Node};
|
||||||
|
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||||
|
use rustc_infer::infer::TyCtxtInferExt;
|
||||||
use rustc_middle::hir::nested_filter;
|
use rustc_middle::hir::nested_filter;
|
||||||
use rustc_middle::ty::query::Providers;
|
use rustc_middle::ty::query::Providers;
|
||||||
use rustc_middle::ty::util::{Discr, IntTypeExt};
|
use rustc_middle::ty::util::{Discr, IntTypeExt};
|
||||||
use rustc_middle::ty::{self, AdtKind, Const, IsSuggestable, ToPredicate, Ty, TyCtxt};
|
use rustc_middle::ty::{
|
||||||
|
self, AdtKind, Const, IsSuggestable, ToPredicate, Ty, TyCtxt, TypeVisitable,
|
||||||
|
};
|
||||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
use rustc_target::spec::abi;
|
use rustc_target::spec::abi;
|
||||||
|
use rustc_trait_selection::infer::InferCtxtExt;
|
||||||
use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName;
|
use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName;
|
||||||
|
use rustc_trait_selection::traits::ObligationCtxt;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
|
||||||
mod generics_of;
|
mod generics_of;
|
||||||
@ -1224,7 +1230,17 @@ fn infer_return_ty_for_fn_sig<'tcx>(
|
|||||||
// to prevent the user from getting a papercut while trying to use the unique closure
|
// to prevent the user from getting a papercut while trying to use the unique closure
|
||||||
// syntax (e.g. `[closure@src/lib.rs:2:5: 2:9]`).
|
// syntax (e.g. `[closure@src/lib.rs:2:5: 2:9]`).
|
||||||
diag.help("consider using an `Fn`, `FnMut`, or `FnOnce` trait bound");
|
diag.help("consider using an `Fn`, `FnMut`, or `FnOnce` trait bound");
|
||||||
diag.note("for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html");
|
diag.note(
|
||||||
|
"for more information on `Fn` traits and closure types, see \
|
||||||
|
https://doc.rust-lang.org/book/ch13-01-closures.html",
|
||||||
|
);
|
||||||
|
} else if let Some(i_ty) = suggest_impl_iterator(tcx, ret_ty, ty.span, hir_id, def_id) {
|
||||||
|
diag.span_suggestion(
|
||||||
|
ty.span,
|
||||||
|
"replace with an appropriate return type",
|
||||||
|
format!("impl Iterator<Item = {}>", i_ty),
|
||||||
|
Applicability::MachineApplicable,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
diag.emit();
|
diag.emit();
|
||||||
|
|
||||||
@ -1242,6 +1258,52 @@ fn infer_return_ty_for_fn_sig<'tcx>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn suggest_impl_iterator<'tcx>(
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
ret_ty: Ty<'tcx>,
|
||||||
|
span: Span,
|
||||||
|
hir_id: hir::HirId,
|
||||||
|
def_id: LocalDefId,
|
||||||
|
) -> Option<Ty<'tcx>> {
|
||||||
|
let Some(iter_trait) = tcx.get_diagnostic_item(sym::Iterator) else { return None; };
|
||||||
|
let Some(iterator_item) = tcx.get_diagnostic_item(sym::IteratorItem) else { return None; };
|
||||||
|
if !tcx
|
||||||
|
.infer_ctxt()
|
||||||
|
.build()
|
||||||
|
.type_implements_trait(iter_trait, [ret_ty], tcx.param_env(iter_trait))
|
||||||
|
.must_apply_modulo_regions()
|
||||||
|
{
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let infcx = tcx.infer_ctxt().build();
|
||||||
|
let ocx = ObligationCtxt::new_in_snapshot(&infcx);
|
||||||
|
// Find the type of `Iterator::Item`.
|
||||||
|
let origin = TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span };
|
||||||
|
let ty_var = infcx.next_ty_var(origin);
|
||||||
|
let projection = ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::Projection(
|
||||||
|
ty::ProjectionPredicate {
|
||||||
|
projection_ty: tcx.mk_alias_ty(iterator_item, tcx.mk_substs([ret_ty.into()].iter())),
|
||||||
|
term: ty_var.into(),
|
||||||
|
},
|
||||||
|
)));
|
||||||
|
// Add `<ret_ty as Iterator>::Item = _` obligation.
|
||||||
|
ocx.register_obligation(crate::traits::Obligation::misc(
|
||||||
|
tcx,
|
||||||
|
span,
|
||||||
|
hir_id,
|
||||||
|
tcx.param_env(def_id),
|
||||||
|
projection,
|
||||||
|
));
|
||||||
|
if ocx.select_where_possible().is_empty()
|
||||||
|
&& let item_ty = infcx.resolve_vars_if_possible(ty_var)
|
||||||
|
&& !item_ty.references_error()
|
||||||
|
&& !item_ty.has_placeholders()
|
||||||
|
{
|
||||||
|
return Some(item_ty);
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::TraitRef<'_>> {
|
fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::TraitRef<'_>> {
|
||||||
let icx = ItemCtxt::new(tcx, def_id);
|
let icx = ItemCtxt::new(tcx, def_id);
|
||||||
let item = tcx.hir().expect_item(def_id.expect_local());
|
let item = tcx.hir().expect_item(def_id.expect_local());
|
||||||
|
@ -213,6 +213,7 @@ symbols! {
|
|||||||
Is,
|
Is,
|
||||||
ItemContext,
|
ItemContext,
|
||||||
Iterator,
|
Iterator,
|
||||||
|
IteratorItem,
|
||||||
Layout,
|
Layout,
|
||||||
Left,
|
Left,
|
||||||
LinkedList,
|
LinkedList,
|
||||||
|
@ -66,6 +66,7 @@ fn _assert_is_object_safe(_: &dyn Iterator<Item = ()>) {}
|
|||||||
#[must_use = "iterators are lazy and do nothing unless consumed"]
|
#[must_use = "iterators are lazy and do nothing unless consumed"]
|
||||||
pub trait Iterator {
|
pub trait Iterator {
|
||||||
/// The type of the elements being iterated over.
|
/// The type of the elements being iterated over.
|
||||||
|
#[rustc_diagnostic_item = "IteratorItem"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
type Item;
|
type Item;
|
||||||
|
|
||||||
|
@ -220,3 +220,11 @@ fn value() -> Option<&'static _> {
|
|||||||
|
|
||||||
const _: Option<_> = map(value);
|
const _: Option<_> = map(value);
|
||||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants
|
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants
|
||||||
|
|
||||||
|
fn evens_squared(n: usize) -> _ {
|
||||||
|
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types
|
||||||
|
(1..n).filter(|x| x % 2 == 0).map(|x| x * x)
|
||||||
|
}
|
||||||
|
|
||||||
|
const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x);
|
||||||
|
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants
|
||||||
|
@ -428,6 +428,27 @@ LL | const _: Option<_> = map(value);
|
|||||||
| not allowed in type signatures
|
| not allowed in type signatures
|
||||||
| help: replace with the correct type: `Option<u8>`
|
| help: replace with the correct type: `Option<u8>`
|
||||||
|
|
||||||
|
error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
|
||||||
|
--> $DIR/typeck_type_placeholder_item.rs:224:31
|
||||||
|
|
|
||||||
|
LL | fn evens_squared(n: usize) -> _ {
|
||||||
|
| ^
|
||||||
|
| |
|
||||||
|
| not allowed in type signatures
|
||||||
|
| help: replace with an appropriate return type: `impl Iterator<Item = usize>`
|
||||||
|
|
||||||
|
error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
|
||||||
|
--> $DIR/typeck_type_placeholder_item.rs:229:10
|
||||||
|
|
|
||||||
|
LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x);
|
||||||
|
| ^ not allowed in type signatures
|
||||||
|
|
|
||||||
|
note: however, the inferred type `Map<Filter<std::ops::Range<i32>, [closure@$DIR/typeck_type_placeholder_item.rs:229:29: 229:32]>, [closure@$DIR/typeck_type_placeholder_item.rs:229:49: 229:52]>` cannot be named
|
||||||
|
--> $DIR/typeck_type_placeholder_item.rs:229:14
|
||||||
|
|
|
||||||
|
LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
|
error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
|
||||||
--> $DIR/typeck_type_placeholder_item.rs:140:31
|
--> $DIR/typeck_type_placeholder_item.rs:140:31
|
||||||
|
|
|
|
||||||
@ -636,7 +657,7 @@ LL | const D: _ = 42;
|
|||||||
| not allowed in type signatures
|
| not allowed in type signatures
|
||||||
| help: replace with the correct type: `i32`
|
| help: replace with the correct type: `i32`
|
||||||
|
|
||||||
error: aborting due to 69 previous errors
|
error: aborting due to 71 previous errors
|
||||||
|
|
||||||
Some errors have detailed explanations: E0121, E0282, E0403.
|
Some errors have detailed explanations: E0121, E0282, E0403.
|
||||||
For more information about an error, try `rustc --explain E0121`.
|
For more information about an error, try `rustc --explain E0121`.
|
||||||
|
Loading…
Reference in New Issue
Block a user