]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc/traits/error_reporting.rs
Rollup merge of #41249 - GuillaumeGomez:rustdoc-render, r=steveklabnik,frewsxcv
[rust.git] / src / librustc / traits / error_reporting.rs
index 931c77badad222009ee0e6da53af98e99d2b5ee1..f7a7d0e2071f210287dc4b4b6c575866146e1f21 100644 (file)
@@ -39,6 +39,7 @@
 use ty::fast_reject;
 use ty::fold::TypeFolder;
 use ty::subst::Subst;
+use ty::SubtypePredicate;
 use util::nodemap::{FxHashMap, FxHashSet};
 
 use syntax_pos::{DUMMY_SP, Span};
@@ -68,6 +69,19 @@ struct FindLocalByTypeVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
     found_pattern: Option<&'a Pat>,
 }
 
+impl<'a, 'gcx, 'tcx> FindLocalByTypeVisitor<'a, 'gcx, 'tcx> {
+    fn is_match(&self, ty: Ty<'tcx>) -> bool {
+        ty == *self.target_ty || match (&ty.sty, &self.target_ty.sty) {
+            (&ty::TyInfer(ty::TyVar(a_vid)), &ty::TyInfer(ty::TyVar(b_vid))) =>
+                self.infcx.type_variables
+                          .borrow_mut()
+                          .sub_unified(a_vid, b_vid),
+
+            _ => false,
+        }
+    }
+}
+
 impl<'a, 'gcx, 'tcx> Visitor<'a> for FindLocalByTypeVisitor<'a, 'gcx, 'tcx> {
     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'a> {
         NestedVisitorMap::None
@@ -76,7 +90,7 @@ fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'a> {
     fn visit_local(&mut self, local: &'a Local) {
         if let Some(&ty) = self.infcx.tables.borrow().node_types.get(&local.id) {
             let ty = self.infcx.resolve_type_vars_if_possible(&ty);
-            let is_match = ty.walk().any(|t| t == *self.target_ty);
+            let is_match = ty.walk().any(|t| self.is_match(t));
 
             if is_match && self.found_pattern.is_none() {
                 self.found_pattern = Some(&*local.pat);
@@ -112,6 +126,13 @@ fn report_fulfillment_error(&self,
             FulfillmentErrorCode::CodeAmbiguity => {
                 self.maybe_report_ambiguity(&error.obligation);
             }
+            FulfillmentErrorCode::CodeSubtypeError(ref expected_found, ref err) => {
+                self.report_mismatched_types(&error.obligation.cause,
+                                             expected_found.expected,
+                                             expected_found.found,
+                                             err.clone())
+                    .emit();
+            }
         }
     }
 
@@ -555,6 +576,13 @@ pub fn report_selection_error(&self,
                         err
                     }
 
+                    ty::Predicate::Subtype(ref predicate) => {
+                        // Errors for Subtype predicates show up as
+                        // `FulfillmentErrorCode::CodeSubtypeError`,
+                        // not selection error.
+                        span_bug!(span, "subtype requirement gave wrong error: `{:?}`", predicate)
+                    }
+
                     ty::Predicate::Equate(ref predicate) => {
                         let predicate = self.resolve_type_vars_if_possible(predicate);
                         let err = self.equality_predicate(&obligation.cause,
@@ -761,6 +789,17 @@ fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>) {
                 }
             }
 
+            ty::Predicate::Subtype(ref data) => {
+                if data.references_error() || self.tcx.sess.has_errors() {
+                    // no need to overload user in such cases
+                } else {
+                    let &SubtypePredicate { a_is_expected: _, a, b } = data.skip_binder();
+                    // both must be type variables, or the other would've been instantiated
+                    assert!(a.is_ty_var() && b.is_ty_var());
+                    self.need_type_info(obligation, a);
+                }
+            }
+
             _ => {
                 if !self.tcx.sess.has_errors() {
                     let mut err = struct_span_err!(self.tcx.sess,