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

librustc error_reporting.rs cleanup. #39977

Merged
merged 8 commits into from
Feb 28, 2017
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
100 changes: 18 additions & 82 deletions src/librustc/traits/error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ use super::{
SelectionContext,
SelectionError,
ObjectSafetyViolation,
MethodViolationCode,
};

use fmt_macros::{Parser, Piece, Position};
Expand Down Expand Up @@ -267,8 +266,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {

let span = obligation.cause.span;
let mut report = None;
for item in self.tcx.get_attrs(def_id).iter() {
if item.check_name("rustc_on_unimplemented") {
if let Some(item) = self.tcx
.get_attrs(def_id)
.into_iter()
.filter(|a| a.check_name("rustc_on_unimplemented"))
.next()
{
let err_sp = item.meta().span.substitute_dummy(span);
let trait_str = self.tcx.item_path_str(trait_ref.def_id);
if let Some(istring) = item.value_str() {
Expand Down Expand Up @@ -321,8 +324,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
eg `#[rustc_on_unimplemented = \"foo\"]`",
trait_str);
}
break;
}
}
report
}
Expand Down Expand Up @@ -359,34 +360,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
}

fn report_similar_impl_candidates(&self,
trait_ref: ty::PolyTraitRef<'tcx>,
impl_candidates: Vec<ty::TraitRef<'tcx>>,
err: &mut DiagnosticBuilder)
{
Copy link
Member

Choose a reason for hiding this comment

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

Was all of this duplicated from find_similar_impl_candidates? 😆

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeeeppppppp

let simp = fast_reject::simplify_type(self.tcx,
trait_ref.skip_binder().self_ty(),
true);
let mut impl_candidates = Vec::new();
let trait_def = self.tcx.lookup_trait_def(trait_ref.def_id());

match simp {
Some(simp) => trait_def.for_each_impl(self.tcx, |def_id| {
let imp = self.tcx.impl_trait_ref(def_id).unwrap();
let imp_simp = fast_reject::simplify_type(self.tcx,
imp.self_ty(),
true);
if let Some(imp_simp) = imp_simp {
if simp != imp_simp {
return;
}
}
impl_candidates.push(imp);
}),
None => trait_def.for_each_impl(self.tcx, |def_id| {
impl_candidates.push(
self.tcx.impl_trait_ref(def_id).unwrap());
})
};

if impl_candidates.is_empty() {
return;
}
Expand Down Expand Up @@ -525,24 +501,20 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
lint_id)
.emit();
return;
} else {
}
match obligation.predicate {
ty::Predicate::Trait(ref trait_predicate) => {
let trait_predicate =
self.resolve_type_vars_if_possible(trait_predicate);

if self.tcx.sess.has_errors() && trait_predicate.references_error() {
return;
} else {
let trait_ref = trait_predicate.to_poly_trait_ref();
let (post_message, pre_message) = match self.get_parent_trait_ref(
&obligation.cause.code)
{
Some(t) => {
(format!(" in `{}`", t), format!("within `{}`, ", t))
}
None => (String::new(), String::new()),
};
let trait_ref = trait_predicate.to_poly_trait_ref();
let (post_message, pre_message) =
self.get_parent_trait_ref(&obligation.cause.code)
.map(|t| (format!(" in `{}`", t), format!("within `{}`, ", t)))
.unwrap_or((String::new(), String::new()));
let mut err = struct_span_err!(
self.tcx.sess,
span,
Expand Down Expand Up @@ -578,15 +550,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
} else {
// If we can't show anything useful, try to find
// similar impls.
let impl_candidates =
self.find_similar_impl_candidates(trait_ref);
if impl_candidates.len() > 0 {
self.report_similar_impl_candidates(trait_ref, &mut err);
}
let impl_candidates = self.find_similar_impl_candidates(trait_ref);
self.report_similar_impl_candidates(impl_candidates, &mut err);
}
err
}
}

ty::Predicate::Equate(ref predicate) => {
let predicate = self.resolve_type_vars_if_possible(predicate);
Expand Down Expand Up @@ -648,7 +616,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
}
}
}
}

OutputTypeParameterMismatch(ref expected_trait_ref, ref actual_trait_ref, ref e) => {
let expected_trait_ref = self.resolve_type_vars_if_possible(&*expected_trait_ref);
Expand Down Expand Up @@ -713,38 +680,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
if !reported_violations.insert(violation.clone()) {
continue;
}
let buf;
let note = match violation {
ObjectSafetyViolation::SizedSelf => {
"the trait cannot require that `Self : Sized`"
}

ObjectSafetyViolation::SupertraitSelf => {
"the trait cannot use `Self` as a type parameter \
in the supertrait listing"
}

ObjectSafetyViolation::Method(name,
MethodViolationCode::StaticMethod) => {
buf = format!("method `{}` has no receiver", name);
&buf
}

ObjectSafetyViolation::Method(name,
MethodViolationCode::ReferencesSelf) => {
buf = format!("method `{}` references the `Self` type \
in its arguments or return type",
name);
&buf
}

ObjectSafetyViolation::Method(name,
MethodViolationCode::Generic) => {
buf = format!("method `{}` has generic type parameters", name);
&buf
}
};
err.note(note);
err.note(&violation.error_msg());
}
err
}
Expand Down Expand Up @@ -774,7 +710,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
let trait_ref = data.to_poly_trait_ref();
let self_ty = trait_ref.self_ty();
if predicate.references_error() {
} else {
return;
}
// Typically, this ambiguity should only happen if
// there are unresolved type inference variables
// (otherwise it would suggest a coherence
Expand Down Expand Up @@ -816,7 +753,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
}
}
}
}

ty::Predicate::WellFormed(ty) => {
// Same hacky approach as above to avoid deluging user
Expand Down
20 changes: 20 additions & 0 deletions src/librustc/traits/object_safety.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use hir::def_id::DefId;
use traits;
use ty::{self, Ty, TyCtxt, TypeFoldable};
use ty::subst::Substs;
use std::borrow::Cow;
use syntax::ast;

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
Expand All @@ -38,6 +39,25 @@ pub enum ObjectSafetyViolation {
Method(ast::Name, MethodViolationCode),
}

impl ObjectSafetyViolation {
pub fn error_msg(&self) -> Cow<'static, str> {
match *self {
ObjectSafetyViolation::SizedSelf =>
"the trait cannot require that `Self : Sized`".into(),
ObjectSafetyViolation::SupertraitSelf =>
"the trait cannot use `Self` as a type parameter \
in the supertrait listing".into(),
ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod) =>
format!("method `{}` has no receiver", name).into(),
ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelf) =>
format!("method `{}` references the `Self` type \
in its arguments or return type", name).into(),
ObjectSafetyViolation::Method(name, MethodViolationCode::Generic) =>
format!("method `{}` has generic type parameters", name).into(),
}
}
}

/// Reasons a method might not be object-safe.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum MethodViolationCode {
Expand Down
18 changes: 0 additions & 18 deletions src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1086,24 +1086,6 @@ impl<'tcx> InstantiatedPredicates<'tcx> {
}
}

impl<'tcx> TraitRef<'tcx> {
pub fn new(def_id: DefId, substs: &'tcx Substs<'tcx>) -> TraitRef<'tcx> {
TraitRef { def_id: def_id, substs: substs }
}

pub fn self_ty(&self) -> Ty<'tcx> {
self.substs.type_at(0)
}

pub fn input_types<'a>(&'a self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> + 'a {
// Select only the "input types" from a trait-reference. For
// now this is all the types that appear in the
// trait-reference, but it should eventually exclude
// associated types.
self.substs.types()
}
}

/// When type checking, we use the `ParameterEnvironment` to track
/// details about the type/lifetime parameters that are in scope.
/// It primarily stores the bounds information.
Expand Down
18 changes: 18 additions & 0 deletions src/librustc/ty/sty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,24 @@ pub struct TraitRef<'tcx> {
pub substs: &'tcx Substs<'tcx>,
}

impl<'tcx> TraitRef<'tcx> {
pub fn new(def_id: DefId, substs: &'tcx Substs<'tcx>) -> TraitRef<'tcx> {
TraitRef { def_id: def_id, substs: substs }
}

pub fn self_ty(&self) -> Ty<'tcx> {
self.substs.type_at(0)
}

pub fn input_types<'a>(&'a self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> + 'a {
// Select only the "input types" from a trait-reference. For
// now this is all the types that appear in the
// trait-reference, but it should eventually exclude
// associated types.
self.substs.types()
}
}

pub type PolyTraitRef<'tcx> = Binder<TraitRef<'tcx>>;

impl<'tcx> PolyTraitRef<'tcx> {
Expand Down