Fix tools

This commit is contained in:
Matthew Jasper 2020-06-30 22:41:57 +01:00
parent 042464f75a
commit 0dda4154bd
7 changed files with 55 additions and 57 deletions

View File

@ -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;
}
```

View File

@ -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),
}),
}
}
}

View File

@ -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),

View File

@ -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.

View File

@ -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(),

View File

@ -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;

View File

@ -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;
}
}