Fix tools
This commit is contained in:
parent
042464f75a
commit
0dda4154bd
@ -5,37 +5,29 @@ as the `collect` method for `Iterator`s.
|
||||
For example:
|
||||
|
||||
```compile_fail,E0284
|
||||
fn foo() -> Result<bool, ()> {
|
||||
let results = [Ok(true), Ok(false), Err(())].iter().cloned();
|
||||
let v: Vec<bool> = results.collect()?;
|
||||
// Do things with v...
|
||||
Ok(true)
|
||||
fn main() {
|
||||
let n: u32 = 1;
|
||||
let mut d: u64 = 2;
|
||||
d = d + n.into();
|
||||
}
|
||||
```
|
||||
|
||||
Here we have an iterator `results` over `Result<bool, ()>`.
|
||||
Hence, `results.collect()` can return any type implementing
|
||||
`FromIterator<Result<bool, ()>>`. On the other hand, the
|
||||
`?` operator can accept any type implementing `Try`.
|
||||
Here we have an addition of `d` and `n.into()`. Hence, `n.into()` can return
|
||||
any type `T` where `u64: Add<T>`. On the other hand, the `into` method can
|
||||
rteurn any type where `u32: Into<T>`.
|
||||
|
||||
The author of this code probably wants `collect()` to return a
|
||||
`Result<Vec<bool>, ()>`, but the compiler can't be sure
|
||||
that there isn't another type `T` implementing both `Try` and
|
||||
`FromIterator<Result<bool, ()>>` in scope such that
|
||||
`T::Ok == Vec<bool>`. Hence, this code is ambiguous and an error
|
||||
is returned.
|
||||
The author of this code probably wants `into()` to return a `u64`, but the
|
||||
compiler can't be sure that there isn't another type `T` where both
|
||||
`u32: Into<T>` and `u64: Add<T>`.
|
||||
|
||||
To resolve this error, use a concrete type for the intermediate expression:
|
||||
|
||||
```
|
||||
fn foo() -> Result<bool, ()> {
|
||||
let results = [Ok(true), Ok(false), Err(())].iter().cloned();
|
||||
let v = {
|
||||
let temp: Result<Vec<bool>, ()> = results.collect();
|
||||
temp?
|
||||
};
|
||||
// Do things with v...
|
||||
Ok(true)
|
||||
fn main() {
|
||||
let n: u32 = 1;
|
||||
let mut d: u64 = 2;
|
||||
let m: u64 = n.into();
|
||||
d = d + m;
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -21,7 +21,7 @@ use rustc_middle::bug;
|
||||
use rustc_middle::middle::resolve_lifetime as rl;
|
||||
use rustc_middle::middle::stability;
|
||||
use rustc_middle::ty::fold::TypeFolder;
|
||||
use rustc_middle::ty::subst::InternalSubsts;
|
||||
use rustc_middle::ty::subst::{InternalSubsts, Subst};
|
||||
use rustc_middle::ty::{self, AdtKind, Lift, Ty, TyCtxt};
|
||||
use rustc_mir::const_eval::{is_const_fn, is_min_const_fn, is_unstable_const_fn};
|
||||
use rustc_span::hygiene::MacroKind;
|
||||
@ -1268,13 +1268,10 @@ impl Clean<Item> for ty::AssocItem {
|
||||
ty::AssocKind::Type => {
|
||||
let my_name = self.ident.name.clean(cx);
|
||||
|
||||
if let ty::TraitContainer(did) = self.container {
|
||||
// When loading a cross-crate associated type, the bounds for this type
|
||||
// are actually located on the trait/impl itself, so we need to load
|
||||
// all of the generics from there and then look for bounds that are
|
||||
// applied to this associated type in question.
|
||||
let predicates = cx.tcx.explicit_predicates_of(did);
|
||||
let generics = (cx.tcx.generics_of(did), predicates).clean(cx);
|
||||
if let ty::TraitContainer(_) = self.container {
|
||||
let bounds = cx.tcx.explicit_item_bounds(self.def_id);
|
||||
let predicates = ty::GenericPredicates { parent: None, predicates: bounds };
|
||||
let generics = (cx.tcx.generics_of(self.def_id), predicates).clean(cx);
|
||||
let mut bounds = generics
|
||||
.where_predicates
|
||||
.iter()
|
||||
@ -1678,19 +1675,22 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
|
||||
|
||||
ty::Opaque(def_id, substs) => {
|
||||
// Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
|
||||
// by looking up the projections associated with the def_id.
|
||||
let predicates_of = cx.tcx.explicit_predicates_of(def_id);
|
||||
// by looking up the bounds associated with the def_id.
|
||||
let substs = cx.tcx.lift(&substs).expect("Opaque lift failed");
|
||||
let bounds = predicates_of.instantiate(cx.tcx, substs);
|
||||
let bounds = cx
|
||||
.tcx
|
||||
.explicit_item_bounds(def_id)
|
||||
.iter()
|
||||
.map(|(bound, _)| bound.subst(cx.tcx, substs))
|
||||
.collect::<Vec<_>>();
|
||||
let mut regions = vec![];
|
||||
let mut has_sized = false;
|
||||
let mut bounds = bounds
|
||||
.predicates
|
||||
.iter()
|
||||
.filter_map(|predicate| {
|
||||
.filter_map(|bound| {
|
||||
// Note: The substs of opaque types can contain unbound variables,
|
||||
// meaning that we have to use `ignore_quantifiers_with_unbound_vars` here.
|
||||
let trait_ref = match predicate.bound_atom(cx.tcx).skip_binder() {
|
||||
let trait_ref = match bound.bound_atom(cx.tcx).skip_binder() {
|
||||
ty::PredicateAtom::Trait(tr, _constness) => {
|
||||
ty::Binder::bind(tr.trait_ref)
|
||||
}
|
||||
@ -1711,11 +1711,10 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
|
||||
}
|
||||
|
||||
let bounds: Vec<_> = bounds
|
||||
.predicates
|
||||
.iter()
|
||||
.filter_map(|pred| {
|
||||
.filter_map(|bound| {
|
||||
if let ty::PredicateAtom::Projection(proj) =
|
||||
pred.bound_atom(cx.tcx).skip_binder()
|
||||
bound.bound_atom(cx.tcx).skip_binder()
|
||||
{
|
||||
if proj.projection_ty.trait_ref(cx.tcx)
|
||||
== trait_ref.skip_binder()
|
||||
@ -2067,13 +2066,10 @@ impl Clean<Item> for doctree::OpaqueTy<'_> {
|
||||
visibility: self.vis.clean(cx),
|
||||
stability: cx.stability(self.id).clean(cx),
|
||||
deprecation: cx.deprecation(self.id).clean(cx),
|
||||
inner: OpaqueTyItem(
|
||||
OpaqueTy {
|
||||
bounds: self.opaque_ty.bounds.clean(cx),
|
||||
generics: self.opaque_ty.generics.clean(cx),
|
||||
},
|
||||
false,
|
||||
),
|
||||
inner: OpaqueTyItem(OpaqueTy {
|
||||
bounds: self.opaque_ty.bounds.clean(cx),
|
||||
generics: self.opaque_ty.generics.clean(cx),
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -252,7 +252,7 @@ pub enum ItemEnum {
|
||||
FunctionItem(Function),
|
||||
ModuleItem(Module),
|
||||
TypedefItem(Typedef, bool /* is associated type */),
|
||||
OpaqueTyItem(OpaqueTy, bool /* is associated type */),
|
||||
OpaqueTyItem(OpaqueTy),
|
||||
StaticItem(Static),
|
||||
ConstantItem(Constant),
|
||||
TraitItem(Trait),
|
||||
|
@ -1709,7 +1709,7 @@ fn print_item(cx: &Context, item: &clean::Item, buf: &mut Buffer, cache: &Cache)
|
||||
clean::ConstantItem(ref c) => item_constant(buf, cx, item, c),
|
||||
clean::ForeignTypeItem => item_foreign_type(buf, cx, item, cache),
|
||||
clean::KeywordItem(_) => item_keyword(buf, cx, item),
|
||||
clean::OpaqueTyItem(ref e, _) => item_opaque_ty(buf, cx, item, e, cache),
|
||||
clean::OpaqueTyItem(ref e) => item_opaque_ty(buf, cx, item, e, cache),
|
||||
clean::TraitAliasItem(ref ta) => item_trait_alias(buf, cx, item, ta, cache),
|
||||
_ => {
|
||||
// We don't generate pages for any other type.
|
||||
|
@ -3,6 +3,7 @@ use rustc_hir::intravisit::FnKind;
|
||||
use rustc_hir::{Body, FnDecl, HirId};
|
||||
use rustc_infer::infer::TyCtxtInferExt;
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::ty::subst::Subst;
|
||||
use rustc_middle::ty::{Opaque, PredicateAtom::Trait};
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
use rustc_span::{sym, Span};
|
||||
@ -62,9 +63,10 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend {
|
||||
}
|
||||
let ret_ty = utils::return_ty(cx, hir_id);
|
||||
if let Opaque(id, subst) = *ret_ty.kind() {
|
||||
let preds = cx.tcx.predicates_of(id).instantiate(cx.tcx, subst);
|
||||
let preds = cx.tcx.explicit_item_bounds(id);
|
||||
let mut is_future = false;
|
||||
for p in preds.predicates {
|
||||
for &(p, _span) in preds {
|
||||
let p = p.subst(cx.tcx, subst);
|
||||
if let Some(trait_ref) = p.to_opt_poly_trait_ref() {
|
||||
if Some(trait_ref.def_id()) == cx.tcx.lang_items().future_trait() {
|
||||
is_future = true;
|
||||
@ -90,8 +92,13 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend {
|
||||
|db| {
|
||||
cx.tcx.infer_ctxt().enter(|infcx| {
|
||||
for FulfillmentError { obligation, .. } in send_errors {
|
||||
infcx.maybe_note_obligation_cause_for_async_await(db, &obligation);
|
||||
if let Trait(trait_pred, _) = obligation.predicate.skip_binders() {
|
||||
infcx.maybe_note_obligation_cause_for_async_await(
|
||||
db,
|
||||
&obligation,
|
||||
);
|
||||
if let Trait(trait_pred, _) =
|
||||
obligation.predicate.skip_binders()
|
||||
{
|
||||
db.note(&format!(
|
||||
"`{}` doesn't implement `{}`",
|
||||
trait_pred.self_ty(),
|
||||
|
@ -1667,8 +1667,10 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
|
||||
// if return type is impl trait, check the associated types
|
||||
if let ty::Opaque(def_id, _) = *ret_ty.kind() {
|
||||
// one of the associated types must be Self
|
||||
for &(predicate, _span) in cx.tcx.predicates_of(def_id).predicates {
|
||||
if let ty::PredicateAtom::Projection(projection_predicate) = predicate.skip_binders() {
|
||||
for &(predicate, _span) in cx.tcx.explicit_item_bounds(def_id) {
|
||||
if let ty::PredicateAtom::Projection(projection_predicate) =
|
||||
predicate.skip_binders()
|
||||
{
|
||||
// walk the associated type and check for Self
|
||||
if contains_ty(projection_predicate.ty, self_ty) {
|
||||
return;
|
||||
|
@ -1285,9 +1285,10 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
|
||||
},
|
||||
ty::Tuple(ref substs) => substs.types().any(|ty| is_must_use_ty(cx, ty)),
|
||||
ty::Opaque(ref def_id, _) => {
|
||||
for (predicate, _) in cx.tcx.predicates_of(*def_id).predicates {
|
||||
for (predicate, _) in cx.tcx.explicit_item_bounds(*def_id) {
|
||||
if let ty::PredicateAtom::Trait(trait_predicate, _) = predicate.skip_binders() {
|
||||
if must_use_attr(&cx.tcx.get_attrs(trait_predicate.trait_ref.def_id)).is_some() {
|
||||
if must_use_attr(&cx.tcx.get_attrs(trait_predicate.trait_ref.def_id)).is_some()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user