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:
///
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);
}
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)
}
ty::subst::GenericArgKind::Const(ct) => match ct.val {
- ConstValue::Param(_) => {}
+ ty::ConstKind::Param(_) => {}
_ => {
tcx.sess
.struct_span_err(
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>,
) {
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);
&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`.
}
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();
}
// 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() {
}
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>(