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: For example:
```compile_fail,E0284 ```compile_fail,E0284
fn foo() -> Result<bool, ()> { fn main() {
let results = [Ok(true), Ok(false), Err(())].iter().cloned(); let n: u32 = 1;
let v: Vec<bool> = results.collect()?; let mut d: u64 = 2;
// Do things with v... d = d + n.into();
Ok(true)
} }
``` ```
Here we have an iterator `results` over `Result<bool, ()>`. Here we have an addition of `d` and `n.into()`. Hence, `n.into()` can return
Hence, `results.collect()` can return any type implementing any type `T` where `u64: Add<T>`. On the other hand, the `into` method can
`FromIterator<Result<bool, ()>>`. On the other hand, the rteurn any type where `u32: Into<T>`.
`?` operator can accept any type implementing `Try`.
The author of this code probably wants `collect()` to return a The author of this code probably wants `into()` to return a `u64`, but the
`Result<Vec<bool>, ()>`, but the compiler can't be sure compiler can't be sure that there isn't another type `T` where both
that there isn't another type `T` implementing both `Try` and `u32: Into<T>` and `u64: Add<T>`.
`FromIterator<Result<bool, ()>>` in scope such that
`T::Ok == Vec<bool>`. Hence, this code is ambiguous and an error
is returned.
To resolve this error, use a concrete type for the intermediate expression: To resolve this error, use a concrete type for the intermediate expression:
``` ```
fn foo() -> Result<bool, ()> { fn main() {
let results = [Ok(true), Ok(false), Err(())].iter().cloned(); let n: u32 = 1;
let v = { let mut d: u64 = 2;
let temp: Result<Vec<bool>, ()> = results.collect(); let m: u64 = n.into();
temp? d = d + m;
};
// Do things with v...
Ok(true)
} }
``` ```

View File

@ -21,7 +21,7 @@ use rustc_middle::bug;
use rustc_middle::middle::resolve_lifetime as rl; use rustc_middle::middle::resolve_lifetime as rl;
use rustc_middle::middle::stability; use rustc_middle::middle::stability;
use rustc_middle::ty::fold::TypeFolder; 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_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_mir::const_eval::{is_const_fn, is_min_const_fn, is_unstable_const_fn};
use rustc_span::hygiene::MacroKind; use rustc_span::hygiene::MacroKind;
@ -1268,13 +1268,10 @@ impl Clean<Item> for ty::AssocItem {
ty::AssocKind::Type => { ty::AssocKind::Type => {
let my_name = self.ident.name.clean(cx); let my_name = self.ident.name.clean(cx);
if let ty::TraitContainer(did) = self.container { if let ty::TraitContainer(_) = self.container {
// When loading a cross-crate associated type, the bounds for this type let bounds = cx.tcx.explicit_item_bounds(self.def_id);
// are actually located on the trait/impl itself, so we need to load let predicates = ty::GenericPredicates { parent: None, predicates: bounds };
// all of the generics from there and then look for bounds that are let generics = (cx.tcx.generics_of(self.def_id), predicates).clean(cx);
// 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);
let mut bounds = generics let mut bounds = generics
.where_predicates .where_predicates
.iter() .iter()
@ -1678,19 +1675,22 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
ty::Opaque(def_id, substs) => { ty::Opaque(def_id, substs) => {
// Grab the "TraitA + TraitB" from `impl TraitA + TraitB`, // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
// by looking up the projections associated with the def_id. // by looking up the bounds associated with the def_id.
let predicates_of = cx.tcx.explicit_predicates_of(def_id);
let substs = cx.tcx.lift(&substs).expect("Opaque lift failed"); 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 regions = vec![];
let mut has_sized = false; let mut has_sized = false;
let mut bounds = bounds let mut bounds = bounds
.predicates
.iter() .iter()
.filter_map(|predicate| { .filter_map(|bound| {
// Note: The substs of opaque types can contain unbound variables, // Note: The substs of opaque types can contain unbound variables,
// meaning that we have to use `ignore_quantifiers_with_unbound_vars` here. // 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::PredicateAtom::Trait(tr, _constness) => {
ty::Binder::bind(tr.trait_ref) ty::Binder::bind(tr.trait_ref)
} }
@ -1711,11 +1711,10 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
} }
let bounds: Vec<_> = bounds let bounds: Vec<_> = bounds
.predicates
.iter() .iter()
.filter_map(|pred| { .filter_map(|bound| {
if let ty::PredicateAtom::Projection(proj) = 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) if proj.projection_ty.trait_ref(cx.tcx)
== trait_ref.skip_binder() == trait_ref.skip_binder()
@ -2067,13 +2066,10 @@ impl Clean<Item> for doctree::OpaqueTy<'_> {
visibility: self.vis.clean(cx), visibility: self.vis.clean(cx),
stability: cx.stability(self.id).clean(cx), stability: cx.stability(self.id).clean(cx),
deprecation: cx.deprecation(self.id).clean(cx), deprecation: cx.deprecation(self.id).clean(cx),
inner: OpaqueTyItem( inner: OpaqueTyItem(OpaqueTy {
OpaqueTy { bounds: self.opaque_ty.bounds.clean(cx),
bounds: self.opaque_ty.bounds.clean(cx), generics: self.opaque_ty.generics.clean(cx),
generics: self.opaque_ty.generics.clean(cx), }),
},
false,
),
} }
} }
} }

View File

@ -252,7 +252,7 @@ pub enum ItemEnum {
FunctionItem(Function), FunctionItem(Function),
ModuleItem(Module), ModuleItem(Module),
TypedefItem(Typedef, bool /* is associated type */), TypedefItem(Typedef, bool /* is associated type */),
OpaqueTyItem(OpaqueTy, bool /* is associated type */), OpaqueTyItem(OpaqueTy),
StaticItem(Static), StaticItem(Static),
ConstantItem(Constant), ConstantItem(Constant),
TraitItem(Trait), 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::ConstantItem(ref c) => item_constant(buf, cx, item, c),
clean::ForeignTypeItem => item_foreign_type(buf, cx, item, cache), clean::ForeignTypeItem => item_foreign_type(buf, cx, item, cache),
clean::KeywordItem(_) => item_keyword(buf, cx, item), 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), clean::TraitAliasItem(ref ta) => item_trait_alias(buf, cx, item, ta, cache),
_ => { _ => {
// We don't generate pages for any other type. // 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_hir::{Body, FnDecl, HirId};
use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::infer::TyCtxtInferExt;
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::subst::Subst;
use rustc_middle::ty::{Opaque, PredicateAtom::Trait}; use rustc_middle::ty::{Opaque, PredicateAtom::Trait};
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::{sym, Span}; use rustc_span::{sym, Span};
@ -62,9 +63,10 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend {
} }
let ret_ty = utils::return_ty(cx, hir_id); let ret_ty = utils::return_ty(cx, hir_id);
if let Opaque(id, subst) = *ret_ty.kind() { 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; 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 let Some(trait_ref) = p.to_opt_poly_trait_ref() {
if Some(trait_ref.def_id()) == cx.tcx.lang_items().future_trait() { if Some(trait_ref.def_id()) == cx.tcx.lang_items().future_trait() {
is_future = true; is_future = true;
@ -90,8 +92,13 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend {
|db| { |db| {
cx.tcx.infer_ctxt().enter(|infcx| { cx.tcx.infer_ctxt().enter(|infcx| {
for FulfillmentError { obligation, .. } in send_errors { for FulfillmentError { obligation, .. } in send_errors {
infcx.maybe_note_obligation_cause_for_async_await(db, &obligation); infcx.maybe_note_obligation_cause_for_async_await(
if let Trait(trait_pred, _) = obligation.predicate.skip_binders() { db,
&obligation,
);
if let Trait(trait_pred, _) =
obligation.predicate.skip_binders()
{
db.note(&format!( db.note(&format!(
"`{}` doesn't implement `{}`", "`{}` doesn't implement `{}`",
trait_pred.self_ty(), 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 return type is impl trait, check the associated types
if let ty::Opaque(def_id, _) = *ret_ty.kind() { if let ty::Opaque(def_id, _) = *ret_ty.kind() {
// one of the associated types must be Self // one of the associated types must be Self
for &(predicate, _span) in cx.tcx.predicates_of(def_id).predicates { for &(predicate, _span) in cx.tcx.explicit_item_bounds(def_id) {
if let ty::PredicateAtom::Projection(projection_predicate) = predicate.skip_binders() { if let ty::PredicateAtom::Projection(projection_predicate) =
predicate.skip_binders()
{
// walk the associated type and check for Self // walk the associated type and check for Self
if contains_ty(projection_predicate.ty, self_ty) { if contains_ty(projection_predicate.ty, self_ty) {
return; 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::Tuple(ref substs) => substs.types().any(|ty| is_must_use_ty(cx, ty)),
ty::Opaque(ref def_id, _) => { 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 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; return true;
} }
} }