]> git.proxmox.com Git - rustc.git/blobdiff - src/librustc_typeck/check/wfcheck.rs
New upstream version 1.41.1+dfsg1
[rustc.git] / src / librustc_typeck / check / wfcheck.rs
index 49b33ad466834ebd3c0daa209e7d5d5873dbdd5f..20b6b01de57b2555ee26a7da116c826b11b9d1b3 100644 (file)
@@ -2,23 +2,24 @@ use crate::check::{Inherited, FnCtxt};
 use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter};
 
 use crate::hir::def_id::DefId;
-use rustc::traits::{self, ObligationCauseCode};
+use rustc::traits::{self, ObligationCause, ObligationCauseCode};
 use rustc::ty::{self, Ty, TyCtxt, GenericParamDefKind, TypeFoldable, ToPredicate};
 use rustc::ty::subst::{Subst, InternalSubsts};
 use rustc::util::nodemap::{FxHashSet, FxHashMap};
-use rustc::mir::interpret::ConstValue;
 use rustc::middle::lang_items;
 use rustc::infer::opaque_types::may_define_opaque_type;
 
 use syntax::ast;
-use syntax::feature_gate::{self, GateIssue};
+use syntax::feature_gate;
 use syntax_pos::Span;
 use syntax::symbol::sym;
-use errors::{DiagnosticBuilder, DiagnosticId};
+use errors::DiagnosticBuilder;
 
 use rustc::hir::itemlikevisit::ParItemLikeVisitor;
 use rustc::hir;
 
+use rustc_error_codes::*;
+
 /// Helper type of a temporary returned by `.for_item(...)`.
 /// This is necessary because we can't write the following bound:
 ///
@@ -190,7 +191,7 @@ fn check_associated_item(
     tcx: TyCtxt<'_>,
     item_id: hir::HirId,
     span: Span,
-    sig_if_method: Option<&hir::MethodSig>,
+    sig_if_method: Option<&hir::FnSig>,
 ) {
     debug!("check_associated_item: {:?}", item_id);
 
@@ -536,7 +537,7 @@ fn check_where_clauses<'tcx, 'fcx>(
             }
 
             fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool {
-                if let ConstValue::Param(param) = c.val {
+                if let ty::ConstKind::Param(param) = c.val {
                     self.params.insert(param.index);
                 }
                 c.super_visit_with(self)
@@ -705,7 +706,7 @@ fn check_opaque_types<'fcx, 'tcx>(
                                 }
 
                                 ty::subst::GenericArgKind::Const(ct) => match ct.val {
-                                    ConstValue::Param(_) => {}
+                                    ty::ConstKind::Param(_) => {}
                                     _ => {
                                         tcx.sess
                                             .struct_span_err(
@@ -783,7 +784,7 @@ const HELP_FOR_SELF_TYPE: &str =
 
 fn check_method_receiver<'fcx, 'tcx>(
     fcx: &FnCtxt<'fcx, 'tcx>,
-    method_sig: &hir::MethodSig,
+    fn_sig: &hir::FnSig,
     method: &ty::AssocItem,
     self_ty: Ty<'tcx>,
 ) {
@@ -794,7 +795,7 @@ fn check_method_receiver<'fcx, 'tcx>(
         return;
     }
 
-    let span = method_sig.decl.inputs[0].span;
+    let span = fn_sig.decl.inputs[0].span;
 
     let sig = fcx.tcx.fn_sig(method.def_id);
     let sig = fcx.normalize_associated_types_in(span, &sig);
@@ -829,13 +830,13 @@ fn check_method_receiver<'fcx, 'tcx>(
                     &fcx.tcx.sess.parse_sess,
                     sym::arbitrary_self_types,
                     span,
-                    GateIssue::Language,
                     &format!(
                         "`{}` cannot be used as the type of `self` without \
                             the `arbitrary_self_types` feature",
                         receiver_ty,
                     ),
-                ).help(HELP_FOR_SELF_TYPE)
+                )
+                .help(HELP_FOR_SELF_TYPE)
                 .emit();
             } else {
                 // Report error; would not have worked with `arbitrary_self_types`.
@@ -846,12 +847,13 @@ fn check_method_receiver<'fcx, 'tcx>(
 }
 
 fn e0307(fcx: &FnCtxt<'fcx, 'tcx>, span: Span, receiver_ty: Ty<'_>) {
-    fcx.tcx.sess.diagnostic().struct_span_err(
+    struct_span_err!(
+        fcx.tcx.sess.diagnostic(),
         span,
-        &format!("invalid `self` parameter type: {:?}", receiver_ty)
+        E0307,
+        "invalid `self` parameter type: {:?}", receiver_ty,
     ).note("type of `self` must be `Self` or a type that dereferences to it")
     .help(HELP_FOR_SELF_TYPE)
-    .code(DiagnosticId::Error("E0307".into()))
     .emit();
 }
 
@@ -893,6 +895,11 @@ fn receiver_is_valid<'fcx, 'tcx>(
     // The first type is `receiver_ty`, which we know its not equal to `self_ty`; skip it.
     autoderef.next();
 
+    let receiver_trait_def_id = fcx.tcx.require_lang_item(
+        lang_items::ReceiverTraitLangItem,
+        None,
+    );
+
     // Keep dereferencing `receiver_ty` until we get to `self_ty`.
     loop {
         if let Some((potential_self_ty, _)) = autoderef.next() {
@@ -909,51 +916,63 @@ fn receiver_is_valid<'fcx, 'tcx>(
                 }
 
                 break
+            } else {
+                // Without `feature(arbitrary_self_types)`, we require that each step in the
+                // deref chain implement `receiver`
+                if !arbitrary_self_types_enabled
+                    && !receiver_is_implemented(
+                        fcx,
+                        receiver_trait_def_id,
+                        cause.clone(),
+                        potential_self_ty,
+                    )
+                {
+                    return false
+                }
             }
         } else {
             debug!("receiver_is_valid: type `{:?}` does not deref to `{:?}`",
                 receiver_ty, self_ty);
             // If he receiver already has errors reported due to it, consider it valid to avoid
-            // unecessary errors (#58712).
+            // unnecessary errors (#58712).
             return receiver_ty.references_error();
         }
-
-        // Without the `arbitrary_self_types` feature, `receiver_ty` must directly deref to
-        // `self_ty`. Enforce this by only doing one iteration of the loop.
-        if !arbitrary_self_types_enabled {
-            return false
-        }
     }
 
     // Without `feature(arbitrary_self_types)`, we require that `receiver_ty` implements `Receiver`.
-    if !arbitrary_self_types_enabled {
-        let trait_def_id = match fcx.tcx.lang_items().receiver_trait() {
-            Some(did) => did,
-            None => {
-                debug!("receiver_is_valid: missing Receiver trait");
-                return false
-            }
-        };
+    if !arbitrary_self_types_enabled
+        && !receiver_is_implemented(fcx, receiver_trait_def_id, cause.clone(), receiver_ty)
+    {
+        return false
+    }
 
-        let trait_ref = ty::TraitRef{
-            def_id: trait_def_id,
-            substs: fcx.tcx.mk_substs_trait(receiver_ty, &[]),
-        };
+    true
+}
 
-        let obligation = traits::Obligation::new(
-            cause,
-            fcx.param_env,
-            trait_ref.to_predicate()
-        );
+fn receiver_is_implemented(
+    fcx: &FnCtxt<'_, 'tcx>,
+    receiver_trait_def_id: DefId,
+    cause: ObligationCause<'tcx>,
+    receiver_ty: Ty<'tcx>,
+) -> bool {
+    let trait_ref = ty::TraitRef{
+        def_id: receiver_trait_def_id,
+        substs: fcx.tcx.mk_substs_trait(receiver_ty, &[]),
+    };
 
-        if !fcx.predicate_must_hold_modulo_regions(&obligation) {
-            debug!("receiver_is_valid: type `{:?}` does not implement `Receiver` trait",
-                receiver_ty);
-            return false
-        }
-    }
+    let obligation = traits::Obligation::new(
+        cause,
+        fcx.param_env,
+        trait_ref.to_predicate()
+    );
 
-    true
+    if fcx.predicate_must_hold_modulo_regions(&obligation) {
+        true
+    } else {
+        debug!("receiver_is_implemented: type `{:?}` does not implement `Receiver` trait",
+            receiver_ty);
+        false
+    }
 }
 
 fn check_variances_for_type_defn<'tcx>(