Skip to content

Commit

Permalink
Auto merge of #69255 - estebank:e0599-details, r=varkor
Browse files Browse the repository at this point in the history
Add more context to E0599 errors

Point at the intermediary unfulfilled trait bounds.

Fix #52523, fix #61661, cc #36513, fix #68131, fix #64417, fix #61768, cc #57457, cc #9082, fix #57994, cc #64934, cc #65149.
  • Loading branch information
bors committed Feb 29, 2020
2 parents 5703b7a + 2fb35ad commit 55aee8d
Show file tree
Hide file tree
Showing 44 changed files with 635 additions and 158 deletions.
14 changes: 14 additions & 0 deletions src/librustc/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,20 @@ impl<'tcx, N> Vtable<'tcx, N> {
}
}

pub fn borrow_nested_obligations(&self) -> &[N] {
match &self {
VtableImpl(i) => &i.nested[..],
VtableParam(n) => &n[..],
VtableBuiltin(i) => &i.nested[..],
VtableAutoImpl(d) => &d.nested[..],
VtableClosure(c) => &c.nested[..],
VtableGenerator(c) => &c.nested[..],
VtableObject(d) => &d.nested[..],
VtableFnPointer(d) => &d.nested[..],
VtableTraitAlias(d) => &d.nested[..],
}
}

pub fn map<M, F>(self, f: F) -> Vtable<'tcx, M>
where
F: FnMut(N) -> M,
Expand Down
3 changes: 1 addition & 2 deletions src/librustc_infer/infer/error_reporting/note.rs
Original file line number Diff line number Diff line change
Expand Up @@ -645,8 +645,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
self.tcx.sess,
span,
E0491,
"in type `{}`, reference has a longer lifetime \
than the data it references",
"in type `{}`, reference has a longer lifetime than the data it references",
self.ty_to_string(ty)
);
note_and_explain_region(
Expand Down
6 changes: 4 additions & 2 deletions src/librustc_parse/parser/generics.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use super::Parser;

use rustc_errors::PResult;
use rustc_span::source_map::DUMMY_SP;
use rustc_span::symbol::{kw, sym};
use syntax::ast::{self, Attribute, GenericBounds, GenericParam, GenericParamKind, WhereClause};
use syntax::token;
Expand Down Expand Up @@ -157,7 +156,10 @@ impl<'a> Parser<'a> {
};
Ok(ast::Generics {
params,
where_clause: WhereClause { predicates: Vec::new(), span: DUMMY_SP },
where_clause: WhereClause {
predicates: Vec::new(),
span: self.prev_span.shrink_to_hi(),
},
span,
})
}
Expand Down
6 changes: 3 additions & 3 deletions src/librustc_typeck/check/method/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use crate::check::FnCtxt;
use rustc::ty::subst::Subst;
use rustc::ty::subst::{InternalSubsts, SubstsRef};
use rustc::ty::GenericParamDefKind;
use rustc::ty::{self, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TypeFoldable, WithConstness};
use rustc::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TypeFoldable, WithConstness};
use rustc_data_structures::sync::Lrc;
use rustc_errors::{Applicability, DiagnosticBuilder};
use rustc_hir as hir;
Expand Down Expand Up @@ -67,7 +67,7 @@ pub enum MethodError<'tcx> {
// could lead to matches if satisfied, and a list of not-in-scope traits which may work.
pub struct NoMatchData<'tcx> {
pub static_candidates: Vec<CandidateSource>,
pub unsatisfied_predicates: Vec<TraitRef<'tcx>>,
pub unsatisfied_predicates: Vec<(ty::Predicate<'tcx>, Option<ty::Predicate<'tcx>>)>,
pub out_of_scope_traits: Vec<DefId>,
pub lev_candidate: Option<ty::AssocItem>,
pub mode: probe::Mode,
Expand All @@ -76,7 +76,7 @@ pub struct NoMatchData<'tcx> {
impl<'tcx> NoMatchData<'tcx> {
pub fn new(
static_candidates: Vec<CandidateSource>,
unsatisfied_predicates: Vec<TraitRef<'tcx>>,
unsatisfied_predicates: Vec<(ty::Predicate<'tcx>, Option<ty::Predicate<'tcx>>)>,
out_of_scope_traits: Vec<DefId>,
lev_candidate: Option<ty::AssocItem>,
mode: probe::Mode,
Expand Down
65 changes: 46 additions & 19 deletions src/librustc_typeck/check/method/probe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ use rustc::session::config::nightly_options;
use rustc::ty::subst::{InternalSubsts, Subst, SubstsRef};
use rustc::ty::GenericParamDefKind;
use rustc::ty::{
self, ParamEnvAnd, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt, TypeFoldable,
WithConstness,
self, ParamEnvAnd, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness,
};
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::sync::Lrc;
Expand Down Expand Up @@ -78,7 +77,7 @@ struct ProbeContext<'a, 'tcx> {

/// Collects near misses when trait bounds for type parameters are unsatisfied and is only used
/// for error reporting
unsatisfied_predicates: Vec<TraitRef<'tcx>>,
unsatisfied_predicates: Vec<(ty::Predicate<'tcx>, Option<ty::Predicate<'tcx>>)>,

is_suggestion: IsSuggestion,
}
Expand Down Expand Up @@ -1224,7 +1223,10 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
&self,
self_ty: Ty<'tcx>,
probes: ProbesIter,
possibly_unsatisfied_predicates: &mut Vec<TraitRef<'tcx>>,
possibly_unsatisfied_predicates: &mut Vec<(
ty::Predicate<'tcx>,
Option<ty::Predicate<'tcx>>,
)>,
unstable_candidates: Option<&mut Vec<(&'b Candidate<'tcx>, Symbol)>>,
) -> Option<PickResult<'tcx>>
where
Expand Down Expand Up @@ -1343,7 +1345,10 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
&self,
self_ty: Ty<'tcx>,
probe: &Candidate<'tcx>,
possibly_unsatisfied_predicates: &mut Vec<TraitRef<'tcx>>,
possibly_unsatisfied_predicates: &mut Vec<(
ty::Predicate<'tcx>,
Option<ty::Predicate<'tcx>>,
)>,
) -> ProbeResult {
debug!("consider_probe: self_ty={:?} probe={:?}", self_ty, probe);

Expand Down Expand Up @@ -1398,21 +1403,45 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
let predicate = trait_ref.without_const().to_predicate();
let obligation = traits::Obligation::new(cause, self.param_env, predicate);
if !self.predicate_may_hold(&obligation) {
if self.probe(|_| self.select_trait_candidate(trait_ref).is_err()) {
if self.probe(|_| {
match self.select_trait_candidate(trait_ref) {
Err(_) => return true,
Ok(Some(vtable))
if !vtable.borrow_nested_obligations().is_empty() =>
{
for obligation in vtable.borrow_nested_obligations() {
// Determine exactly which obligation wasn't met, so
// that we can give more context in the error.
if !self.predicate_may_hold(&obligation) {
result = ProbeResult::NoMatch;
let o = self.resolve_vars_if_possible(obligation);
let predicate =
self.resolve_vars_if_possible(&predicate);
let p = if predicate == o.predicate {
// Avoid "`MyStruct: Foo` which is required by
// `MyStruct: Foo`" in E0599.
None
} else {
Some(predicate)
};
possibly_unsatisfied_predicates.push((o.predicate, p));
}
}
}
_ => {
// Some nested subobligation of this predicate
// failed.
result = ProbeResult::NoMatch;
let predicate = self.resolve_vars_if_possible(&predicate);
possibly_unsatisfied_predicates.push((predicate, None));
}
}
false
}) {
// This candidate's primary obligation doesn't even
// select - don't bother registering anything in
// `potentially_unsatisfied_predicates`.
return ProbeResult::NoMatch;
} else {
// Some nested subobligation of this predicate
// failed.
//
// FIXME: try to find the exact nested subobligation
// and point at it rather than reporting the entire
// trait-ref?
result = ProbeResult::NoMatch;
let trait_ref = self.resolve_vars_if_possible(&trait_ref);
possibly_unsatisfied_predicates.push(trait_ref);
}
}
vec![]
Expand All @@ -1429,9 +1458,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
let o = self.resolve_vars_if_possible(&o);
if !self.predicate_may_hold(&o) {
result = ProbeResult::NoMatch;
if let &ty::Predicate::Trait(ref pred, _) = &o.predicate {
possibly_unsatisfied_predicates.push(pred.skip_binder().trait_ref);
}
possibly_unsatisfied_predicates.push((o.predicate, None));
}
}

Expand Down
Loading

0 comments on commit 55aee8d

Please sign in to comment.