Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add more context to E0599 errors #69255

Merged
merged 17 commits into from
Feb 29, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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[..],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh, these are unpleasant variant names.

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 @@ -160,7 +159,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