2014-12-06 16:39:25 +00:00
|
|
|
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
2014-12-17 19:16:28 +00:00
|
|
|
use super::{
|
|
|
|
FulfillmentError,
|
|
|
|
FulfillmentErrorCode,
|
|
|
|
MismatchedProjectionTypes,
|
2015-03-20 10:48:40 +00:00
|
|
|
Obligation,
|
2016-03-29 17:12:31 +00:00
|
|
|
ObligationCause,
|
2014-12-17 19:16:28 +00:00
|
|
|
ObligationCauseCode,
|
|
|
|
OutputTypeParameterMismatch,
|
2015-04-14 23:57:29 +00:00
|
|
|
TraitNotObjectSafe,
|
2014-12-17 19:16:28 +00:00
|
|
|
PredicateObligation,
|
2016-03-29 17:12:31 +00:00
|
|
|
SelectionContext,
|
2014-12-17 19:16:28 +00:00
|
|
|
SelectionError,
|
2015-04-14 23:57:29 +00:00
|
|
|
ObjectSafetyViolation,
|
2014-12-17 19:16:28 +00:00
|
|
|
};
|
2014-12-06 16:39:25 +00:00
|
|
|
|
2017-03-09 23:51:47 +00:00
|
|
|
use errors::DiagnosticBuilder;
|
2015-01-10 18:21:27 +00:00
|
|
|
use fmt_macros::{Parser, Piece, Position};
|
2017-04-11 21:37:40 +00:00
|
|
|
use hir::{self, intravisit, Local, Pat, Body};
|
2017-03-09 23:51:47 +00:00
|
|
|
use hir::intravisit::{Visitor, NestedVisitorMap};
|
|
|
|
use hir::map::NodeExpr;
|
2016-03-29 09:54:26 +00:00
|
|
|
use hir::def_id::DefId;
|
2016-11-07 18:25:06 +00:00
|
|
|
use infer::{self, InferCtxt};
|
2016-11-28 18:08:08 +00:00
|
|
|
use infer::type_variable::TypeVariableOrigin;
|
2016-10-12 20:38:58 +00:00
|
|
|
use rustc::lint::builtin::EXTRA_REQUIREMENT_IN_IMPL;
|
2017-03-09 23:51:47 +00:00
|
|
|
use std::fmt;
|
2017-04-11 21:37:40 +00:00
|
|
|
use syntax::ast::{self, NodeId};
|
|
|
|
use ty::{self, AdtKind, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable, TyInfer, TyVar};
|
2017-04-23 22:36:35 +00:00
|
|
|
use ty::error::{ExpectedFound, TypeError};
|
2016-03-22 15:30:57 +00:00
|
|
|
use ty::fast_reject;
|
2016-01-23 05:44:38 +00:00
|
|
|
use ty::fold::TypeFolder;
|
2016-08-17 03:32:00 +00:00
|
|
|
use ty::subst::Subst;
|
2017-03-10 02:47:09 +00:00
|
|
|
use ty::SubtypePredicate;
|
2016-11-08 03:02:55 +00:00
|
|
|
use util::nodemap::{FxHashMap, FxHashSet};
|
2015-09-24 23:40:57 +00:00
|
|
|
|
2016-11-28 18:08:08 +00:00
|
|
|
use syntax_pos::{DUMMY_SP, Span};
|
2017-03-09 23:51:47 +00:00
|
|
|
|
2014-12-06 16:39:25 +00:00
|
|
|
|
2015-09-24 16:58:00 +00:00
|
|
|
#[derive(Debug, PartialEq, Eq, Hash)]
|
|
|
|
pub struct TraitErrorKey<'tcx> {
|
|
|
|
span: Span,
|
|
|
|
predicate: ty::Predicate<'tcx>
|
|
|
|
}
|
|
|
|
|
2016-04-29 03:00:23 +00:00
|
|
|
impl<'a, 'gcx, 'tcx> TraitErrorKey<'tcx> {
|
|
|
|
fn from_error(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
|
2016-09-01 10:34:56 +00:00
|
|
|
e: &FulfillmentError<'tcx>) -> Self {
|
2015-09-24 16:58:00 +00:00
|
|
|
let predicate =
|
|
|
|
infcx.resolve_type_vars_if_possible(&e.obligation.predicate);
|
|
|
|
TraitErrorKey {
|
|
|
|
span: e.obligation.cause.span,
|
2016-09-01 10:34:56 +00:00
|
|
|
predicate: infcx.tcx.erase_regions(&predicate)
|
2015-09-24 16:58:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-24 15:19:36 +00:00
|
|
|
struct FindLocalByTypeVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
|
|
|
|
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
|
|
|
|
target_ty: &'a Ty<'tcx>,
|
2017-04-11 21:37:40 +00:00
|
|
|
hir_map: &'a hir::map::Map<'gcx>,
|
|
|
|
found_local_pattern: Option<&'gcx Pat>,
|
|
|
|
found_arg_pattern: Option<&'gcx Pat>,
|
2017-01-24 15:19:36 +00:00
|
|
|
}
|
|
|
|
|
generalize type variables too
When we are generalizing a super/sub-type, we have to replace type
variables with a fresh variable (and not just region variables). So if
we know that `Box<?T> <: ?U`, for example, we instantiate `?U` with
`Box<?V>` and then relate `Box<?T>` to `Box<?V>` (and hence require that
`?T <: ?V`).
This change has some complex interactions, however:
First, the occurs check must be updated to detect constraints like `?T
<: ?U` and `?U <: Box<?T>`. If we're not careful, we'll create a
never-ending sequence of new variables. To address this, we add a second
unification set into `type_variables` that tracks type variables related
through **either** equality **or** subtyping, and use that during the
occurs-check.
Second, the "fudge regions if ok" code was expecting no new type
variables to be created. It must be updated to create new type variables
outside of the probe. This is relatively straight-forward under the new
scheme, since type variables are now independent from one another, and
any relations are moderated by pending subtype obliations and so forth.
This part would be tricky to backport though.
cc #18653
cc #40951
2017-04-11 21:17:58 +00:00
|
|
|
impl<'a, 'gcx, 'tcx> FindLocalByTypeVisitor<'a, 'gcx, 'tcx> {
|
2017-04-11 21:37:40 +00:00
|
|
|
fn node_matches_type(&mut self, node_id: &'gcx NodeId) -> bool {
|
|
|
|
match self.infcx.tables.borrow().node_types.get(node_id) {
|
|
|
|
Some(&ty) => {
|
|
|
|
let ty = self.infcx.resolve_type_vars_if_possible(&ty);
|
|
|
|
ty.walk().any(|inner_ty| {
|
|
|
|
inner_ty == *self.target_ty || match (&inner_ty.sty, &self.target_ty.sty) {
|
|
|
|
(&TyInfer(TyVar(a_vid)), &TyInfer(TyVar(b_vid))) => {
|
|
|
|
self.infcx
|
|
|
|
.type_variables
|
|
|
|
.borrow_mut()
|
|
|
|
.sub_unified(a_vid, b_vid)
|
|
|
|
}
|
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
generalize type variables too
When we are generalizing a super/sub-type, we have to replace type
variables with a fresh variable (and not just region variables). So if
we know that `Box<?T> <: ?U`, for example, we instantiate `?U` with
`Box<?V>` and then relate `Box<?T>` to `Box<?V>` (and hence require that
`?T <: ?V`).
This change has some complex interactions, however:
First, the occurs check must be updated to detect constraints like `?T
<: ?U` and `?U <: Box<?T>`. If we're not careful, we'll create a
never-ending sequence of new variables. To address this, we add a second
unification set into `type_variables` that tracks type variables related
through **either** equality **or** subtyping, and use that during the
occurs-check.
Second, the "fudge regions if ok" code was expecting no new type
variables to be created. It must be updated to create new type variables
outside of the probe. This is relatively straight-forward under the new
scheme, since type variables are now independent from one another, and
any relations are moderated by pending subtype obliations and so forth.
This part would be tricky to backport though.
cc #18653
cc #40951
2017-04-11 21:17:58 +00:00
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-11 21:37:40 +00:00
|
|
|
impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindLocalByTypeVisitor<'a, 'gcx, 'tcx> {
|
|
|
|
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> {
|
|
|
|
NestedVisitorMap::OnlyBodies(&self.hir_map)
|
2017-01-24 15:19:36 +00:00
|
|
|
}
|
|
|
|
|
2017-04-11 21:37:40 +00:00
|
|
|
fn visit_local(&mut self, local: &'gcx Local) {
|
|
|
|
if self.found_local_pattern.is_none() && self.node_matches_type(&local.id) {
|
|
|
|
self.found_local_pattern = Some(&*local.pat);
|
|
|
|
}
|
|
|
|
intravisit::walk_local(self, local);
|
|
|
|
}
|
2017-01-24 15:19:36 +00:00
|
|
|
|
2017-04-11 21:37:40 +00:00
|
|
|
fn visit_body(&mut self, body: &'gcx Body) {
|
|
|
|
for argument in &body.arguments {
|
|
|
|
if self.found_arg_pattern.is_none() && self.node_matches_type(&argument.id) {
|
|
|
|
self.found_arg_pattern = Some(&*argument.pat);
|
2017-01-24 15:19:36 +00:00
|
|
|
}
|
|
|
|
}
|
2017-04-11 21:37:40 +00:00
|
|
|
intravisit::walk_body(self, body);
|
2017-01-24 15:19:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-29 03:00:23 +00:00
|
|
|
impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
2016-05-11 05:48:12 +00:00
|
|
|
pub fn report_fulfillment_errors(&self, errors: &Vec<FulfillmentError<'tcx>>) {
|
|
|
|
for error in errors {
|
2016-09-01 10:34:56 +00:00
|
|
|
self.report_fulfillment_error(error);
|
2016-05-11 05:48:12 +00:00
|
|
|
}
|
2014-12-06 16:39:25 +00:00
|
|
|
}
|
|
|
|
|
2016-05-11 05:48:12 +00:00
|
|
|
fn report_fulfillment_error(&self,
|
2016-09-01 10:34:56 +00:00
|
|
|
error: &FulfillmentError<'tcx>) {
|
|
|
|
let error_key = TraitErrorKey::from_error(self, error);
|
2016-05-11 05:48:12 +00:00
|
|
|
debug!("report_fulfillment_errors({:?}) - key={:?}",
|
|
|
|
error, error_key);
|
|
|
|
if !self.reported_trait_errors.borrow_mut().insert(error_key) {
|
|
|
|
debug!("report_fulfillment_errors: skipping duplicate");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
match error.code {
|
|
|
|
FulfillmentErrorCode::CodeSelectionError(ref e) => {
|
2016-09-01 10:34:56 +00:00
|
|
|
self.report_selection_error(&error.obligation, e);
|
2016-05-11 05:48:12 +00:00
|
|
|
}
|
|
|
|
FulfillmentErrorCode::CodeProjectionError(ref e) => {
|
2016-09-01 10:34:56 +00:00
|
|
|
self.report_projection_error(&error.obligation, e);
|
2016-05-11 05:48:12 +00:00
|
|
|
}
|
|
|
|
FulfillmentErrorCode::CodeAmbiguity => {
|
|
|
|
self.maybe_report_ambiguity(&error.obligation);
|
|
|
|
}
|
2017-03-10 02:47:09 +00:00
|
|
|
FulfillmentErrorCode::CodeSubtypeError(ref expected_found, ref err) => {
|
|
|
|
self.report_mismatched_types(&error.obligation.cause,
|
|
|
|
expected_found.expected,
|
|
|
|
expected_found.found,
|
|
|
|
err.clone())
|
|
|
|
.emit();
|
|
|
|
}
|
2014-12-06 16:39:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-11 05:48:12 +00:00
|
|
|
fn report_projection_error(&self,
|
|
|
|
obligation: &PredicateObligation<'tcx>,
|
2016-09-01 10:34:56 +00:00
|
|
|
error: &MismatchedProjectionTypes<'tcx>)
|
2016-05-11 05:48:12 +00:00
|
|
|
{
|
|
|
|
let predicate =
|
|
|
|
self.resolve_type_vars_if_possible(&obligation.predicate);
|
|
|
|
|
2016-07-20 23:13:14 +00:00
|
|
|
if predicate.references_error() {
|
|
|
|
return
|
|
|
|
}
|
2016-09-01 10:34:56 +00:00
|
|
|
|
2016-07-20 23:13:14 +00:00
|
|
|
self.probe(|_| {
|
|
|
|
let err_buf;
|
|
|
|
let mut err = &error.err;
|
|
|
|
let mut values = None;
|
|
|
|
|
|
|
|
// try to find the mismatched types to report the error with.
|
|
|
|
//
|
|
|
|
// this can fail if the problem was higher-ranked, in which
|
|
|
|
// cause I have no idea for a good error message.
|
|
|
|
if let ty::Predicate::Projection(ref data) = predicate {
|
|
|
|
let mut selcx = SelectionContext::new(self);
|
|
|
|
let (data, _) = self.replace_late_bound_regions_with_fresh_var(
|
2016-05-11 05:48:12 +00:00
|
|
|
obligation.cause.span,
|
2016-07-20 23:13:14 +00:00
|
|
|
infer::LateBoundRegionConversionTime::HigherRankedType,
|
|
|
|
data);
|
|
|
|
let normalized = super::normalize_projection_type(
|
|
|
|
&mut selcx,
|
2017-05-23 08:19:47 +00:00
|
|
|
obligation.param_env,
|
2016-07-20 23:13:14 +00:00
|
|
|
data.projection_ty,
|
|
|
|
obligation.cause.clone(),
|
|
|
|
0
|
|
|
|
);
|
2017-05-24 13:43:20 +00:00
|
|
|
if let Err(error) = self.at(&obligation.cause, obligation.param_env)
|
|
|
|
.eq(normalized.value, data.ty) {
|
2016-07-20 23:13:14 +00:00
|
|
|
values = Some(infer::ValuePairs::Types(ExpectedFound {
|
|
|
|
expected: normalized.value,
|
|
|
|
found: data.ty,
|
|
|
|
}));
|
|
|
|
err_buf = error;
|
|
|
|
err = &err_buf;
|
|
|
|
}
|
2016-05-11 05:48:12 +00:00
|
|
|
}
|
2016-07-20 23:13:14 +00:00
|
|
|
|
2016-07-21 17:12:30 +00:00
|
|
|
let mut diag = struct_span_err!(
|
2016-11-07 18:25:06 +00:00
|
|
|
self.tcx.sess, obligation.cause.span, E0271,
|
2016-07-21 17:12:30 +00:00
|
|
|
"type mismatch resolving `{}`", predicate
|
|
|
|
);
|
2016-11-07 18:25:06 +00:00
|
|
|
self.note_type_err(&mut diag, &obligation.cause, None, values, err);
|
2016-07-20 23:13:14 +00:00
|
|
|
self.note_obligation_cause(&mut diag, obligation);
|
|
|
|
diag.emit();
|
|
|
|
});
|
2014-12-17 19:16:28 +00:00
|
|
|
}
|
|
|
|
|
2016-05-17 18:55:34 +00:00
|
|
|
fn fuzzy_match_tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
|
|
|
|
/// returns the fuzzy category of a given type, or None
|
|
|
|
/// if the type can be equated to any type.
|
|
|
|
fn type_category<'tcx>(t: Ty<'tcx>) -> Option<u32> {
|
|
|
|
match t.sty {
|
|
|
|
ty::TyBool => Some(0),
|
|
|
|
ty::TyChar => Some(1),
|
|
|
|
ty::TyStr => Some(2),
|
2016-09-05 22:26:02 +00:00
|
|
|
ty::TyInt(..) | ty::TyUint(..) | ty::TyInfer(ty::IntVar(..)) => Some(3),
|
2016-05-17 18:55:34 +00:00
|
|
|
ty::TyFloat(..) | ty::TyInfer(ty::FloatVar(..)) => Some(4),
|
2017-01-21 14:40:31 +00:00
|
|
|
ty::TyRef(..) | ty::TyRawPtr(..) => Some(5),
|
2016-09-05 22:26:02 +00:00
|
|
|
ty::TyArray(..) | ty::TySlice(..) => Some(6),
|
|
|
|
ty::TyFnDef(..) | ty::TyFnPtr(..) => Some(7),
|
2016-11-16 16:21:49 +00:00
|
|
|
ty::TyDynamic(..) => Some(8),
|
2016-09-05 22:26:02 +00:00
|
|
|
ty::TyClosure(..) => Some(9),
|
|
|
|
ty::TyTuple(..) => Some(10),
|
|
|
|
ty::TyProjection(..) => Some(11),
|
|
|
|
ty::TyParam(..) => Some(12),
|
|
|
|
ty::TyAnon(..) => Some(13),
|
|
|
|
ty::TyNever => Some(14),
|
|
|
|
ty::TyAdt(adt, ..) => match adt.adt_kind() {
|
|
|
|
AdtKind::Struct => Some(15),
|
|
|
|
AdtKind::Union => Some(16),
|
|
|
|
AdtKind::Enum => Some(17),
|
|
|
|
},
|
2016-05-17 18:55:34 +00:00
|
|
|
ty::TyInfer(..) | ty::TyError => None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
match (type_category(a), type_category(b)) {
|
|
|
|
(Some(cat_a), Some(cat_b)) => match (&a.sty, &b.sty) {
|
2016-09-05 22:26:02 +00:00
|
|
|
(&ty::TyAdt(def_a, _), &ty::TyAdt(def_b, _)) => def_a == def_b,
|
2016-05-17 18:55:34 +00:00
|
|
|
_ => cat_a == cat_b
|
|
|
|
},
|
|
|
|
// infer and error can be equated to all types
|
|
|
|
_ => true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn impl_similar_to(&self,
|
|
|
|
trait_ref: ty::PolyTraitRef<'tcx>,
|
|
|
|
obligation: &PredicateObligation<'tcx>)
|
|
|
|
-> Option<DefId>
|
2016-05-14 06:01:57 +00:00
|
|
|
{
|
|
|
|
let tcx = self.tcx;
|
2017-05-23 08:19:47 +00:00
|
|
|
let param_env = obligation.param_env;
|
2016-05-17 18:55:34 +00:00
|
|
|
let trait_ref = tcx.erase_late_bound_regions(&trait_ref);
|
|
|
|
let trait_self_ty = trait_ref.self_ty();
|
2016-05-14 06:01:57 +00:00
|
|
|
|
2016-05-17 18:55:34 +00:00
|
|
|
let mut self_match_impls = vec![];
|
|
|
|
let mut fuzzy_match_impls = vec![];
|
2016-05-16 20:16:52 +00:00
|
|
|
|
2017-04-24 12:20:46 +00:00
|
|
|
self.tcx.trait_def(trait_ref.def_id)
|
2016-05-14 06:01:57 +00:00
|
|
|
.for_each_relevant_impl(self.tcx, trait_self_ty, |def_id| {
|
2016-08-08 20:39:49 +00:00
|
|
|
let impl_substs = self.fresh_substs_for_item(obligation.cause.span, def_id);
|
2016-05-17 18:55:34 +00:00
|
|
|
let impl_trait_ref = tcx
|
2016-05-14 06:01:57 +00:00
|
|
|
.impl_trait_ref(def_id)
|
|
|
|
.unwrap()
|
2016-08-17 00:56:18 +00:00
|
|
|
.subst(tcx, impl_substs);
|
2016-05-14 06:01:57 +00:00
|
|
|
|
2016-05-17 18:55:34 +00:00
|
|
|
let impl_self_ty = impl_trait_ref.self_ty();
|
2016-05-16 20:16:52 +00:00
|
|
|
|
2017-05-24 13:43:20 +00:00
|
|
|
if let Ok(..) = self.can_eq(param_env, trait_self_ty, impl_self_ty) {
|
2016-05-17 18:55:34 +00:00
|
|
|
self_match_impls.push(def_id);
|
|
|
|
|
2016-08-18 05:32:50 +00:00
|
|
|
if trait_ref.substs.types().skip(1)
|
|
|
|
.zip(impl_trait_ref.substs.types().skip(1))
|
2016-05-17 18:55:34 +00:00
|
|
|
.all(|(u,v)| self.fuzzy_match_tys(u, v))
|
|
|
|
{
|
|
|
|
fuzzy_match_impls.push(def_id);
|
|
|
|
}
|
2016-05-11 12:33:14 +00:00
|
|
|
}
|
2016-05-14 06:01:57 +00:00
|
|
|
});
|
2016-05-11 12:33:14 +00:00
|
|
|
|
2016-05-17 18:55:34 +00:00
|
|
|
let impl_def_id = if self_match_impls.len() == 1 {
|
|
|
|
self_match_impls[0]
|
|
|
|
} else if fuzzy_match_impls.len() == 1 {
|
|
|
|
fuzzy_match_impls[0]
|
2016-05-16 20:16:52 +00:00
|
|
|
} else {
|
2016-05-17 18:55:34 +00:00
|
|
|
return None
|
|
|
|
};
|
|
|
|
|
|
|
|
if tcx.has_attr(impl_def_id, "rustc_on_unimplemented") {
|
|
|
|
Some(impl_def_id)
|
|
|
|
} else {
|
|
|
|
None
|
2016-05-11 12:33:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-11 05:48:12 +00:00
|
|
|
fn on_unimplemented_note(&self,
|
|
|
|
trait_ref: ty::PolyTraitRef<'tcx>,
|
2016-05-11 12:33:14 +00:00
|
|
|
obligation: &PredicateObligation<'tcx>) -> Option<String> {
|
2016-05-17 18:55:34 +00:00
|
|
|
let def_id = self.impl_similar_to(trait_ref, obligation)
|
2016-05-14 06:01:57 +00:00
|
|
|
.unwrap_or(trait_ref.def_id());
|
2016-05-11 05:48:12 +00:00
|
|
|
let trait_ref = trait_ref.skip_binder();
|
2016-05-14 06:01:57 +00:00
|
|
|
|
2016-05-11 12:33:14 +00:00
|
|
|
let span = obligation.cause.span;
|
2016-05-11 05:48:12 +00:00
|
|
|
let mut report = None;
|
2017-02-19 22:02:10 +00:00
|
|
|
if let Some(item) = self.tcx
|
|
|
|
.get_attrs(def_id)
|
|
|
|
.into_iter()
|
|
|
|
.filter(|a| a.check_name("rustc_on_unimplemented"))
|
|
|
|
.next()
|
|
|
|
{
|
2017-03-03 09:23:59 +00:00
|
|
|
let err_sp = item.span.substitute_dummy(span);
|
2017-02-19 22:02:10 +00:00
|
|
|
let trait_str = self.tcx.item_path_str(trait_ref.def_id);
|
|
|
|
if let Some(istring) = item.value_str() {
|
|
|
|
let istring = &*istring.as_str();
|
2017-04-24 12:20:46 +00:00
|
|
|
let generics = self.tcx.generics_of(trait_ref.def_id);
|
2017-02-19 22:02:10 +00:00
|
|
|
let generic_map = generics.types.iter().map(|param| {
|
|
|
|
(param.name.as_str().to_string(),
|
|
|
|
trait_ref.substs.type_for_def(param).to_string())
|
|
|
|
}).collect::<FxHashMap<String, String>>();
|
|
|
|
let parser = Parser::new(istring);
|
|
|
|
let mut errored = false;
|
|
|
|
let err: String = parser.filter_map(|p| {
|
|
|
|
match p {
|
|
|
|
Piece::String(s) => Some(s),
|
|
|
|
Piece::NextArgument(a) => match a.position {
|
|
|
|
Position::ArgumentNamed(s) => match generic_map.get(s) {
|
|
|
|
Some(val) => Some(val),
|
|
|
|
None => {
|
|
|
|
span_err!(self.tcx.sess, err_sp, E0272,
|
2017-04-11 11:40:31 +00:00
|
|
|
"the #[rustc_on_unimplemented] attribute on trait \
|
|
|
|
definition for {} refers to non-existent type \
|
|
|
|
parameter {}",
|
|
|
|
trait_str, s);
|
2015-01-10 18:21:27 +00:00
|
|
|
errored = true;
|
|
|
|
None
|
|
|
|
}
|
2017-02-19 22:02:10 +00:00
|
|
|
},
|
|
|
|
_ => {
|
|
|
|
span_err!(self.tcx.sess, err_sp, E0273,
|
2017-04-11 11:40:31 +00:00
|
|
|
"the #[rustc_on_unimplemented] attribute on trait \
|
|
|
|
definition for {} must have named format arguments, eg \
|
|
|
|
`#[rustc_on_unimplemented = \"foo {{T}}\"]`",
|
|
|
|
trait_str);
|
2017-02-19 22:02:10 +00:00
|
|
|
errored = true;
|
|
|
|
None
|
2015-01-10 18:21:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-02-19 22:02:10 +00:00
|
|
|
}).collect();
|
|
|
|
// Report only if the format string checks out
|
|
|
|
if !errored {
|
|
|
|
report = Some(err);
|
2015-01-10 18:21:27 +00:00
|
|
|
}
|
2017-02-19 22:02:10 +00:00
|
|
|
} else {
|
|
|
|
span_err!(self.tcx.sess, err_sp, E0274,
|
|
|
|
"the #[rustc_on_unimplemented] attribute on \
|
|
|
|
trait definition for {} must have a value, \
|
|
|
|
eg `#[rustc_on_unimplemented = \"foo\"]`",
|
|
|
|
trait_str);
|
2015-01-10 18:21:27 +00:00
|
|
|
}
|
|
|
|
}
|
2016-05-11 05:48:12 +00:00
|
|
|
report
|
2015-01-11 19:03:20 +00:00
|
|
|
}
|
2015-01-10 18:21:27 +00:00
|
|
|
|
2016-05-11 12:33:14 +00:00
|
|
|
fn find_similar_impl_candidates(&self,
|
|
|
|
trait_ref: ty::PolyTraitRef<'tcx>)
|
|
|
|
-> Vec<ty::TraitRef<'tcx>>
|
|
|
|
{
|
|
|
|
let simp = fast_reject::simplify_type(self.tcx,
|
|
|
|
trait_ref.skip_binder().self_ty(),
|
|
|
|
true);
|
|
|
|
let mut impl_candidates = Vec::new();
|
2017-04-24 12:20:46 +00:00
|
|
|
let trait_def = self.tcx.trait_def(trait_ref.def_id());
|
2016-05-11 12:33:14 +00:00
|
|
|
|
|
|
|
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());
|
|
|
|
})
|
|
|
|
};
|
|
|
|
impl_candidates
|
|
|
|
}
|
|
|
|
|
2016-05-11 05:48:12 +00:00
|
|
|
fn report_similar_impl_candidates(&self,
|
2017-02-19 17:33:59 +00:00
|
|
|
impl_candidates: Vec<ty::TraitRef<'tcx>>,
|
2016-05-11 05:48:12 +00:00
|
|
|
err: &mut DiagnosticBuilder)
|
|
|
|
{
|
|
|
|
if impl_candidates.is_empty() {
|
|
|
|
return;
|
|
|
|
}
|
2016-03-16 22:15:31 +00:00
|
|
|
|
2017-02-14 04:32:05 +00:00
|
|
|
let end = if impl_candidates.len() <= 5 {
|
|
|
|
impl_candidates.len()
|
|
|
|
} else {
|
|
|
|
4
|
|
|
|
};
|
2017-01-13 19:40:44 +00:00
|
|
|
err.help(&format!("the following implementations were found:{}{}",
|
|
|
|
&impl_candidates[0..end].iter().map(|candidate| {
|
|
|
|
format!("\n {:?}", candidate)
|
|
|
|
}).collect::<String>(),
|
2017-02-14 04:32:05 +00:00
|
|
|
if impl_candidates.len() > 5 {
|
2017-01-13 19:40:44 +00:00
|
|
|
format!("\nand {} others", impl_candidates.len() - 4)
|
|
|
|
} else {
|
|
|
|
"".to_owned()
|
|
|
|
}
|
|
|
|
));
|
2016-04-05 20:19:29 +00:00
|
|
|
}
|
|
|
|
|
2016-05-11 05:48:12 +00:00
|
|
|
/// Reports that an overflow has occurred and halts compilation. We
|
|
|
|
/// halt compilation unconditionally because it is important that
|
|
|
|
/// overflows never be masked -- they basically represent computations
|
|
|
|
/// whose result could not be truly determined and thus we can't say
|
|
|
|
/// if the program type checks or not -- and they are unusual
|
|
|
|
/// occurrences in any case.
|
|
|
|
pub fn report_overflow_error<T>(&self,
|
|
|
|
obligation: &Obligation<'tcx, T>,
|
|
|
|
suggest_increasing_limit: bool) -> !
|
|
|
|
where T: fmt::Display + TypeFoldable<'tcx>
|
|
|
|
{
|
|
|
|
let predicate =
|
|
|
|
self.resolve_type_vars_if_possible(&obligation.predicate);
|
|
|
|
let mut err = struct_span_err!(self.tcx.sess, obligation.cause.span, E0275,
|
|
|
|
"overflow evaluating the requirement `{}`",
|
|
|
|
predicate);
|
2015-03-20 10:48:40 +00:00
|
|
|
|
2016-05-11 05:48:12 +00:00
|
|
|
if suggest_increasing_limit {
|
|
|
|
self.suggest_new_overflow_limit(&mut err);
|
|
|
|
}
|
2015-03-20 10:48:40 +00:00
|
|
|
|
2016-05-11 05:48:12 +00:00
|
|
|
self.note_obligation_cause(&mut err, obligation);
|
2015-03-20 10:48:40 +00:00
|
|
|
|
2016-05-11 05:48:12 +00:00
|
|
|
err.emit();
|
|
|
|
self.tcx.sess.abort_if_errors();
|
|
|
|
bug!();
|
|
|
|
}
|
2016-01-09 02:41:37 +00:00
|
|
|
|
2016-05-11 05:48:12 +00:00
|
|
|
/// Reports that a cycle was detected which led to overflow and halts
|
|
|
|
/// compilation. This is equivalent to `report_overflow_error` except
|
|
|
|
/// that we can give a more helpful error message (and, in particular,
|
|
|
|
/// we do not suggest increasing the overflow limit, which is not
|
|
|
|
/// going to help).
|
2016-05-05 09:31:45 +00:00
|
|
|
pub fn report_overflow_error_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> ! {
|
|
|
|
let cycle = self.resolve_type_vars_if_possible(&cycle.to_owned());
|
2016-05-07 21:52:45 +00:00
|
|
|
assert!(cycle.len() > 0);
|
2016-01-09 02:41:37 +00:00
|
|
|
|
2016-05-11 05:48:12 +00:00
|
|
|
debug!("report_overflow_error_cycle: cycle={:?}", cycle);
|
2016-01-09 02:41:37 +00:00
|
|
|
|
2016-05-11 05:48:12 +00:00
|
|
|
self.report_overflow_error(&cycle[0], false);
|
2016-01-09 02:41:37 +00:00
|
|
|
}
|
|
|
|
|
2016-10-05 14:17:14 +00:00
|
|
|
pub fn report_extra_impl_obligation(&self,
|
|
|
|
error_span: Span,
|
|
|
|
item_name: ast::Name,
|
|
|
|
_impl_item_def_id: DefId,
|
|
|
|
trait_item_def_id: DefId,
|
2016-10-12 20:38:58 +00:00
|
|
|
requirement: &fmt::Display,
|
|
|
|
lint_id: Option<ast::NodeId>) // (*)
|
2016-10-05 14:17:14 +00:00
|
|
|
-> DiagnosticBuilder<'tcx>
|
|
|
|
{
|
2016-10-12 20:38:58 +00:00
|
|
|
// (*) This parameter is temporary and used only for phasing
|
|
|
|
// in the bug fix to #18937. If it is `Some`, it has a kind of
|
|
|
|
// weird effect -- the diagnostic is reported as a lint, and
|
|
|
|
// the builder which is returned is marked as canceled.
|
|
|
|
|
2016-10-05 14:17:14 +00:00
|
|
|
let mut err =
|
|
|
|
struct_span_err!(self.tcx.sess,
|
|
|
|
error_span,
|
|
|
|
E0276,
|
|
|
|
"impl has stricter requirements than trait");
|
|
|
|
|
2017-01-26 00:41:06 +00:00
|
|
|
if let Some(trait_item_span) = self.tcx.hir.span_if_local(trait_item_def_id) {
|
2017-04-11 11:40:31 +00:00
|
|
|
let span = self.tcx.sess.codemap().def_span(trait_item_span);
|
2017-05-04 12:17:23 +00:00
|
|
|
err.span_label(span, format!("definition of `{}` from trait", item_name));
|
2016-10-05 14:17:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
err.span_label(
|
|
|
|
error_span,
|
2017-05-04 12:17:23 +00:00
|
|
|
format!("impl has extra requirement {}", requirement));
|
2016-10-05 14:17:14 +00:00
|
|
|
|
2016-10-12 20:38:58 +00:00
|
|
|
if let Some(node_id) = lint_id {
|
2016-10-13 16:09:05 +00:00
|
|
|
self.tcx.sess.add_lint_diagnostic(EXTRA_REQUIREMENT_IN_IMPL,
|
|
|
|
node_id,
|
|
|
|
(*err).clone());
|
2016-10-12 20:38:58 +00:00
|
|
|
err.cancel();
|
|
|
|
}
|
|
|
|
|
2016-10-05 14:17:14 +00:00
|
|
|
err
|
|
|
|
}
|
|
|
|
|
2016-12-12 22:51:40 +00:00
|
|
|
|
|
|
|
/// Get the parent trait chain start
|
|
|
|
fn get_parent_trait_ref(&self, code: &ObligationCauseCode<'tcx>) -> Option<String> {
|
|
|
|
match code {
|
|
|
|
&ObligationCauseCode::BuiltinDerivedObligation(ref data) => {
|
|
|
|
let parent_trait_ref = self.resolve_type_vars_if_possible(
|
|
|
|
&data.parent_trait_ref);
|
|
|
|
match self.get_parent_trait_ref(&data.parent_code) {
|
|
|
|
Some(t) => Some(t),
|
|
|
|
None => Some(format!("{}", parent_trait_ref.0.self_ty())),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-11 05:48:12 +00:00
|
|
|
pub fn report_selection_error(&self,
|
|
|
|
obligation: &PredicateObligation<'tcx>,
|
2016-09-01 10:34:56 +00:00
|
|
|
error: &SelectionError<'tcx>)
|
2016-05-11 05:48:12 +00:00
|
|
|
{
|
|
|
|
let span = obligation.cause.span;
|
2016-12-12 22:51:40 +00:00
|
|
|
|
2016-05-11 05:48:12 +00:00
|
|
|
let mut err = match *error {
|
|
|
|
SelectionError::Unimplemented => {
|
2016-10-05 14:17:14 +00:00
|
|
|
if let ObligationCauseCode::CompareImplMethodObligation {
|
2016-10-12 20:38:58 +00:00
|
|
|
item_name, impl_item_def_id, trait_item_def_id, lint_id
|
2016-10-05 14:17:14 +00:00
|
|
|
} = obligation.cause.code {
|
|
|
|
self.report_extra_impl_obligation(
|
|
|
|
span,
|
|
|
|
item_name,
|
|
|
|
impl_item_def_id,
|
|
|
|
trait_item_def_id,
|
2016-10-12 20:38:58 +00:00
|
|
|
&format!("`{}`", obligation.predicate),
|
|
|
|
lint_id)
|
2016-10-05 14:17:14 +00:00
|
|
|
.emit();
|
2016-05-11 05:48:12 +00:00
|
|
|
return;
|
2017-02-19 03:48:36 +00:00
|
|
|
}
|
|
|
|
match obligation.predicate {
|
|
|
|
ty::Predicate::Trait(ref trait_predicate) => {
|
|
|
|
let trait_predicate =
|
|
|
|
self.resolve_type_vars_if_possible(trait_predicate);
|
2015-08-07 14:28:51 +00:00
|
|
|
|
2017-02-19 03:48:36 +00:00
|
|
|
if self.tcx.sess.has_errors() && trait_predicate.references_error() {
|
|
|
|
return;
|
2017-02-19 15:46:43 +00:00
|
|
|
}
|
|
|
|
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,
|
|
|
|
E0277,
|
|
|
|
"the trait bound `{}` is not satisfied{}",
|
|
|
|
trait_ref.to_predicate(),
|
|
|
|
post_message);
|
|
|
|
|
2017-04-26 16:42:27 +00:00
|
|
|
let unimplemented_note = self.on_unimplemented_note(trait_ref, obligation);
|
|
|
|
if let Some(ref s) = unimplemented_note {
|
|
|
|
// If it has a custom "#[rustc_on_unimplemented]"
|
|
|
|
// error message, let's display it as the label!
|
|
|
|
err.span_label(span, s.as_str());
|
|
|
|
err.help(&format!("{}the trait `{}` is not implemented for `{}`",
|
|
|
|
pre_message,
|
|
|
|
trait_ref,
|
|
|
|
trait_ref.self_ty()));
|
|
|
|
} else {
|
|
|
|
err.span_label(span,
|
|
|
|
&*format!("{}the trait `{}` is not implemented for `{}`",
|
|
|
|
pre_message,
|
|
|
|
trait_ref,
|
|
|
|
trait_ref.self_ty()));
|
|
|
|
}
|
|
|
|
|
2017-02-19 15:46:43 +00:00
|
|
|
// Try to report a help message
|
|
|
|
if !trait_ref.has_infer_types() &&
|
2017-05-23 08:19:47 +00:00
|
|
|
self.predicate_can_apply(obligation.param_env, trait_ref) {
|
2017-02-19 15:46:43 +00:00
|
|
|
// If a where-clause may be useful, remind the
|
|
|
|
// user that they can add it.
|
|
|
|
//
|
|
|
|
// don't display an on-unimplemented note, as
|
|
|
|
// these notes will often be of the form
|
|
|
|
// "the type `T` can't be frobnicated"
|
|
|
|
// which is somewhat confusing.
|
|
|
|
err.help(&format!("consider adding a `where {}` bound",
|
|
|
|
trait_ref.to_predicate()));
|
2017-04-26 16:42:27 +00:00
|
|
|
} else if unimplemented_note.is_none() {
|
2017-04-10 21:17:49 +00:00
|
|
|
// Can't show anything else useful, try to find similar impls.
|
2017-02-19 17:33:59 +00:00
|
|
|
let impl_candidates = self.find_similar_impl_candidates(trait_ref);
|
|
|
|
self.report_similar_impl_candidates(impl_candidates, &mut err);
|
2016-01-21 09:57:21 +00:00
|
|
|
}
|
2017-04-10 21:17:49 +00:00
|
|
|
|
2017-02-19 15:46:43 +00:00
|
|
|
err
|
2017-02-19 03:48:36 +00:00
|
|
|
}
|
2016-01-21 09:57:21 +00:00
|
|
|
|
2017-03-10 02:47:09 +00:00
|
|
|
ty::Predicate::Subtype(ref predicate) => {
|
generalize type variables too
When we are generalizing a super/sub-type, we have to replace type
variables with a fresh variable (and not just region variables). So if
we know that `Box<?T> <: ?U`, for example, we instantiate `?U` with
`Box<?V>` and then relate `Box<?T>` to `Box<?V>` (and hence require that
`?T <: ?V`).
This change has some complex interactions, however:
First, the occurs check must be updated to detect constraints like `?T
<: ?U` and `?U <: Box<?T>`. If we're not careful, we'll create a
never-ending sequence of new variables. To address this, we add a second
unification set into `type_variables` that tracks type variables related
through **either** equality **or** subtyping, and use that during the
occurs-check.
Second, the "fudge regions if ok" code was expecting no new type
variables to be created. It must be updated to create new type variables
outside of the probe. This is relatively straight-forward under the new
scheme, since type variables are now independent from one another, and
any relations are moderated by pending subtype obliations and so forth.
This part would be tricky to backport though.
cc #18653
cc #40951
2017-04-11 21:17:58 +00:00
|
|
|
// Errors for Subtype predicates show up as
|
|
|
|
// `FulfillmentErrorCode::CodeSubtypeError`,
|
|
|
|
// not selection error.
|
|
|
|
span_bug!(span, "subtype requirement gave wrong error: `{:?}`", predicate)
|
2017-03-10 02:47:09 +00:00
|
|
|
}
|
|
|
|
|
2017-02-19 03:48:36 +00:00
|
|
|
ty::Predicate::Equate(ref predicate) => {
|
|
|
|
let predicate = self.resolve_type_vars_if_possible(predicate);
|
|
|
|
let err = self.equality_predicate(&obligation.cause,
|
2017-05-23 08:19:47 +00:00
|
|
|
obligation.param_env,
|
|
|
|
&predicate).err().unwrap();
|
2017-02-19 03:48:36 +00:00
|
|
|
struct_span_err!(self.tcx.sess, span, E0278,
|
|
|
|
"the requirement `{}` is not satisfied (`{}`)",
|
|
|
|
predicate, err)
|
|
|
|
}
|
2015-01-14 21:43:17 +00:00
|
|
|
|
2017-02-19 03:48:36 +00:00
|
|
|
ty::Predicate::RegionOutlives(ref predicate) => {
|
|
|
|
let predicate = self.resolve_type_vars_if_possible(predicate);
|
|
|
|
let err = self.region_outlives_predicate(&obligation.cause,
|
|
|
|
&predicate).err().unwrap();
|
|
|
|
struct_span_err!(self.tcx.sess, span, E0279,
|
|
|
|
"the requirement `{}` is not satisfied (`{}`)",
|
|
|
|
predicate, err)
|
|
|
|
}
|
2015-01-14 21:43:17 +00:00
|
|
|
|
2017-02-19 03:48:36 +00:00
|
|
|
ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => {
|
|
|
|
let predicate =
|
|
|
|
self.resolve_type_vars_if_possible(&obligation.predicate);
|
|
|
|
struct_span_err!(self.tcx.sess, span, E0280,
|
|
|
|
"the requirement `{}` is not satisfied",
|
|
|
|
predicate)
|
|
|
|
}
|
2015-08-07 14:28:51 +00:00
|
|
|
|
2017-02-19 03:48:36 +00:00
|
|
|
ty::Predicate::ObjectSafe(trait_def_id) => {
|
|
|
|
let violations = self.tcx.object_safety_violations(trait_def_id);
|
|
|
|
self.tcx.report_object_safety_error(span,
|
|
|
|
trait_def_id,
|
|
|
|
violations)
|
|
|
|
}
|
2015-08-07 14:28:51 +00:00
|
|
|
|
2017-02-19 03:48:36 +00:00
|
|
|
ty::Predicate::ClosureKind(closure_def_id, kind) => {
|
|
|
|
let found_kind = self.closure_kind(closure_def_id).unwrap();
|
|
|
|
let closure_span = self.tcx.hir.span_if_local(closure_def_id).unwrap();
|
|
|
|
let mut err = struct_span_err!(
|
|
|
|
self.tcx.sess, closure_span, E0525,
|
|
|
|
"expected a closure that implements the `{}` trait, \
|
|
|
|
but this closure only implements `{}`",
|
|
|
|
kind,
|
|
|
|
found_kind);
|
|
|
|
err.span_note(
|
|
|
|
obligation.cause.span,
|
|
|
|
&format!("the requirement to implement \
|
|
|
|
`{}` derives from here", kind));
|
|
|
|
err.emit();
|
|
|
|
return;
|
|
|
|
}
|
2016-04-06 07:20:59 +00:00
|
|
|
|
2017-02-19 03:48:36 +00:00
|
|
|
ty::Predicate::WellFormed(ty) => {
|
|
|
|
// WF predicates cannot themselves make
|
|
|
|
// errors. They can only block due to
|
|
|
|
// ambiguity; otherwise, they always
|
|
|
|
// degenerate into other obligations
|
|
|
|
// (which may fail).
|
|
|
|
span_bug!(span, "WF predicate not satisfied for {:?}", ty);
|
2016-05-01 06:59:28 +00:00
|
|
|
}
|
2014-12-06 16:39:25 +00:00
|
|
|
}
|
|
|
|
}
|
2015-01-14 21:43:17 +00:00
|
|
|
|
2016-05-11 05:48:12 +00:00
|
|
|
OutputTypeParameterMismatch(ref expected_trait_ref, ref actual_trait_ref, ref e) => {
|
|
|
|
let expected_trait_ref = self.resolve_type_vars_if_possible(&*expected_trait_ref);
|
|
|
|
let actual_trait_ref = self.resolve_type_vars_if_possible(&*actual_trait_ref);
|
|
|
|
if actual_trait_ref.self_ty().references_error() {
|
|
|
|
return;
|
|
|
|
}
|
2017-04-23 22:36:35 +00:00
|
|
|
let expected_trait_ty = expected_trait_ref.self_ty();
|
2017-04-24 00:54:32 +00:00
|
|
|
let found_span = expected_trait_ty.ty_to_def_id().and_then(|did| {
|
|
|
|
self.tcx.hir.span_if_local(did)
|
|
|
|
});
|
|
|
|
|
|
|
|
if let &TypeError::TupleSize(ref expected_found) = e {
|
|
|
|
// Expected `|x| { }`, found `|x, y| { }`
|
|
|
|
self.report_arg_count_mismatch(span,
|
|
|
|
found_span,
|
|
|
|
expected_found.expected,
|
|
|
|
expected_found.found,
|
|
|
|
expected_trait_ty.is_closure())
|
|
|
|
} else if let &TypeError::Sorts(ref expected_found) = e {
|
|
|
|
let expected = if let ty::TyTuple(tys, _) = expected_found.expected.sty {
|
|
|
|
tys.len()
|
2017-04-23 22:36:35 +00:00
|
|
|
} else {
|
2017-04-24 00:54:32 +00:00
|
|
|
1
|
|
|
|
};
|
|
|
|
let found = if let ty::TyTuple(tys, _) = expected_found.found.sty {
|
|
|
|
tys.len()
|
|
|
|
} else {
|
|
|
|
1
|
|
|
|
};
|
|
|
|
|
|
|
|
if expected != found {
|
|
|
|
// Expected `|| { }`, found `|x, y| { }`
|
|
|
|
// Expected `fn(x) -> ()`, found `|| { }`
|
|
|
|
self.report_arg_count_mismatch(span,
|
|
|
|
found_span,
|
|
|
|
expected,
|
|
|
|
found,
|
|
|
|
expected_trait_ty.is_closure())
|
|
|
|
} else {
|
|
|
|
self.report_type_argument_mismatch(span,
|
|
|
|
found_span,
|
|
|
|
expected_trait_ty,
|
|
|
|
expected_trait_ref,
|
|
|
|
actual_trait_ref,
|
|
|
|
e)
|
2017-04-23 22:36:35 +00:00
|
|
|
}
|
|
|
|
} else {
|
2017-04-24 00:54:32 +00:00
|
|
|
self.report_type_argument_mismatch(span,
|
|
|
|
found_span,
|
|
|
|
expected_trait_ty,
|
|
|
|
expected_trait_ref,
|
|
|
|
actual_trait_ref,
|
|
|
|
e)
|
2017-04-23 22:36:35 +00:00
|
|
|
}
|
2016-05-11 05:48:12 +00:00
|
|
|
}
|
2015-04-14 23:57:29 +00:00
|
|
|
|
2016-05-11 05:48:12 +00:00
|
|
|
TraitNotObjectSafe(did) => {
|
|
|
|
let violations = self.tcx.object_safety_violations(did);
|
2016-09-01 10:34:56 +00:00
|
|
|
self.tcx.report_object_safety_error(span, did,
|
|
|
|
violations)
|
2016-05-01 06:59:28 +00:00
|
|
|
}
|
2016-05-11 05:48:12 +00:00
|
|
|
};
|
|
|
|
self.note_obligation_cause(&mut err, obligation);
|
|
|
|
err.emit();
|
|
|
|
}
|
2017-04-24 00:54:32 +00:00
|
|
|
|
|
|
|
fn report_type_argument_mismatch(&self,
|
|
|
|
span: Span,
|
|
|
|
found_span: Option<Span>,
|
|
|
|
expected_ty: Ty<'tcx>,
|
|
|
|
expected_ref: ty::PolyTraitRef<'tcx>,
|
|
|
|
found_ref: ty::PolyTraitRef<'tcx>,
|
|
|
|
type_error: &TypeError<'tcx>)
|
|
|
|
-> DiagnosticBuilder<'tcx>
|
|
|
|
{
|
|
|
|
let mut err = struct_span_err!(self.tcx.sess, span, E0281,
|
|
|
|
"type mismatch: `{}` implements the trait `{}`, but the trait `{}` is required",
|
|
|
|
expected_ty,
|
|
|
|
expected_ref,
|
|
|
|
found_ref);
|
|
|
|
|
2017-05-04 12:17:23 +00:00
|
|
|
err.span_label(span, format!("{}", type_error));
|
2017-04-24 00:54:32 +00:00
|
|
|
|
|
|
|
if let Some(sp) = found_span {
|
2017-05-04 12:17:23 +00:00
|
|
|
err.span_label(span, format!("requires `{}`", found_ref));
|
|
|
|
err.span_label(sp, format!("implements `{}`", expected_ref));
|
2017-04-24 00:54:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
err
|
|
|
|
}
|
|
|
|
|
|
|
|
fn report_arg_count_mismatch(&self,
|
|
|
|
span: Span,
|
|
|
|
found_span: Option<Span>,
|
|
|
|
expected: usize,
|
|
|
|
found: usize,
|
|
|
|
is_closure: bool)
|
|
|
|
-> DiagnosticBuilder<'tcx>
|
|
|
|
{
|
|
|
|
let mut err = struct_span_err!(self.tcx.sess, span, E0593,
|
|
|
|
"{} takes {} argument{} but {} argument{} {} required",
|
|
|
|
if is_closure { "closure" } else { "function" },
|
|
|
|
found,
|
|
|
|
if found == 1 { "" } else { "s" },
|
|
|
|
expected,
|
|
|
|
if expected == 1 { "" } else { "s" },
|
|
|
|
if expected == 1 { "is" } else { "are" });
|
|
|
|
|
2017-05-04 12:17:23 +00:00
|
|
|
err.span_label(span, format!("expected {} that takes {} argument{}",
|
2017-04-24 00:54:32 +00:00
|
|
|
if is_closure { "closure" } else { "function" },
|
|
|
|
expected,
|
|
|
|
if expected == 1 { "" } else { "s" }));
|
|
|
|
if let Some(span) = found_span {
|
2017-05-04 12:17:23 +00:00
|
|
|
err.span_label(span, format!("takes {} argument{}",
|
2017-04-24 00:54:32 +00:00
|
|
|
found,
|
|
|
|
if found == 1 { "" } else { "s" }));
|
|
|
|
}
|
|
|
|
err
|
|
|
|
}
|
2016-03-16 22:15:31 +00:00
|
|
|
}
|
|
|
|
|
2016-04-29 03:00:23 +00:00
|
|
|
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
2016-05-11 05:48:12 +00:00
|
|
|
pub fn recursive_type_with_infinite_size_error(self,
|
|
|
|
type_def_id: DefId)
|
|
|
|
-> DiagnosticBuilder<'tcx>
|
|
|
|
{
|
|
|
|
assert!(type_def_id.is_local());
|
2017-01-26 00:41:06 +00:00
|
|
|
let span = self.hir.span_if_local(type_def_id).unwrap();
|
2017-04-11 11:40:31 +00:00
|
|
|
let span = self.sess.codemap().def_span(span);
|
2016-05-11 05:48:12 +00:00
|
|
|
let mut err = struct_span_err!(self.sess, span, E0072,
|
|
|
|
"recursive type `{}` has infinite size",
|
|
|
|
self.item_path_str(type_def_id));
|
2017-05-04 12:17:23 +00:00
|
|
|
err.span_label(span, "recursive type has infinite size");
|
2016-05-11 05:48:12 +00:00
|
|
|
err.help(&format!("insert indirection (e.g., a `Box`, `Rc`, or `&`) \
|
|
|
|
at some point to make `{}` representable",
|
|
|
|
self.item_path_str(type_def_id)));
|
|
|
|
err
|
|
|
|
}
|
2015-04-14 23:57:29 +00:00
|
|
|
|
2016-05-11 05:48:12 +00:00
|
|
|
pub fn report_object_safety_error(self,
|
|
|
|
span: Span,
|
|
|
|
trait_def_id: DefId,
|
|
|
|
violations: Vec<ObjectSafetyViolation>)
|
2016-09-01 10:34:56 +00:00
|
|
|
-> DiagnosticBuilder<'tcx>
|
2016-05-11 05:48:12 +00:00
|
|
|
{
|
2016-09-01 10:34:56 +00:00
|
|
|
let trait_str = self.item_path_str(trait_def_id);
|
2017-04-11 11:40:31 +00:00
|
|
|
let span = self.sess.codemap().def_span(span);
|
2016-09-01 10:34:56 +00:00
|
|
|
let mut err = struct_span_err!(
|
|
|
|
self.sess, span, E0038,
|
|
|
|
"the trait `{}` cannot be made into an object",
|
|
|
|
trait_str);
|
2017-05-04 12:17:23 +00:00
|
|
|
err.span_label(span, format!("the trait `{}` cannot be made into an object", trait_str));
|
2015-04-14 23:57:29 +00:00
|
|
|
|
2016-11-08 03:02:55 +00:00
|
|
|
let mut reported_violations = FxHashSet();
|
2016-05-11 05:48:12 +00:00
|
|
|
for violation in violations {
|
|
|
|
if !reported_violations.insert(violation.clone()) {
|
|
|
|
continue;
|
2015-08-07 14:28:51 +00:00
|
|
|
}
|
2017-02-19 18:00:25 +00:00
|
|
|
err.note(&violation.error_msg());
|
2015-04-14 23:57:29 +00:00
|
|
|
}
|
2016-05-11 05:48:12 +00:00
|
|
|
err
|
2014-12-06 16:39:25 +00:00
|
|
|
}
|
2016-03-16 22:15:31 +00:00
|
|
|
}
|
2014-12-06 16:39:25 +00:00
|
|
|
|
2016-04-29 03:00:23 +00:00
|
|
|
impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
2016-05-11 05:48:12 +00:00
|
|
|
fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>) {
|
|
|
|
// Unable to successfully determine, probably means
|
|
|
|
// insufficient type information, but could mean
|
|
|
|
// ambiguous impls. The latter *ought* to be a
|
|
|
|
// coherence violation, so we don't report it here.
|
|
|
|
|
|
|
|
let predicate = self.resolve_type_vars_if_possible(&obligation.predicate);
|
2017-04-11 21:37:40 +00:00
|
|
|
let body_id = hir::BodyId { node_id: obligation.cause.body_id };
|
|
|
|
let span = obligation.cause.span;
|
2016-05-11 05:48:12 +00:00
|
|
|
|
|
|
|
debug!("maybe_report_ambiguity(predicate={:?}, obligation={:?})",
|
|
|
|
predicate,
|
|
|
|
obligation);
|
|
|
|
|
|
|
|
// Ambiguity errors are often caused as fallout from earlier
|
|
|
|
// errors. So just ignore them if this infcx is tainted.
|
|
|
|
if self.is_tainted_by_errors() {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
match predicate {
|
|
|
|
ty::Predicate::Trait(ref data) => {
|
|
|
|
let trait_ref = data.to_poly_trait_ref();
|
|
|
|
let self_ty = trait_ref.self_ty();
|
2016-08-18 05:32:50 +00:00
|
|
|
if predicate.references_error() {
|
2017-02-19 18:12:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
// Typically, this ambiguity should only happen if
|
|
|
|
// there are unresolved type inference variables
|
|
|
|
// (otherwise it would suggest a coherence
|
|
|
|
// failure). But given #21974 that is not necessarily
|
|
|
|
// the case -- we can have multiple where clauses that
|
|
|
|
// are only distinguished by a region, which results
|
|
|
|
// in an ambiguity even when all types are fully
|
|
|
|
// known, since we don't dispatch based on region
|
|
|
|
// relationships.
|
|
|
|
|
|
|
|
// This is kind of a hack: it frequently happens that some earlier
|
|
|
|
// error prevents types from being fully inferred, and then we get
|
|
|
|
// a bunch of uninteresting errors saying something like "<generic
|
|
|
|
// #0> doesn't implement Sized". It may even be true that we
|
|
|
|
// could just skip over all checks where the self-ty is an
|
|
|
|
// inference variable, but I was afraid that there might be an
|
|
|
|
// inference variable created, registered as an obligation, and
|
|
|
|
// then never forced by writeback, and hence by skipping here we'd
|
|
|
|
// be ignoring the fact that we don't KNOW the type works
|
|
|
|
// out. Though even that would probably be harmless, given that
|
|
|
|
// we're only talking about builtin traits, which are known to be
|
|
|
|
// inhabited. But in any case I just threw in this check for
|
|
|
|
// has_errors() to be sure that compilation isn't happening
|
|
|
|
// anyway. In that case, why inundate the user.
|
|
|
|
if !self.tcx.sess.has_errors() {
|
|
|
|
if
|
|
|
|
self.tcx.lang_items.sized_trait()
|
|
|
|
.map_or(false, |sized_id| sized_id == trait_ref.def_id())
|
|
|
|
{
|
2017-04-11 21:37:40 +00:00
|
|
|
self.need_type_info(body_id, span, self_ty);
|
2017-02-19 18:12:18 +00:00
|
|
|
} else {
|
|
|
|
let mut err = struct_span_err!(self.tcx.sess,
|
2017-04-11 21:37:40 +00:00
|
|
|
span, E0283,
|
2017-02-19 18:12:18 +00:00
|
|
|
"type annotations required: \
|
|
|
|
cannot resolve `{}`",
|
|
|
|
predicate);
|
|
|
|
self.note_obligation_cause(&mut err, obligation);
|
|
|
|
err.emit();
|
2014-12-30 22:42:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-11 05:48:12 +00:00
|
|
|
ty::Predicate::WellFormed(ty) => {
|
|
|
|
// Same hacky approach as above to avoid deluging user
|
|
|
|
// with error messages.
|
|
|
|
if !ty.references_error() && !self.tcx.sess.has_errors() {
|
2017-04-11 21:37:40 +00:00
|
|
|
self.need_type_info(body_id, span, ty);
|
2016-05-11 05:48:12 +00:00
|
|
|
}
|
2015-08-07 14:28:51 +00:00
|
|
|
}
|
|
|
|
|
2017-03-10 02:47:09 +00:00
|
|
|
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();
|
generalize type variables too
When we are generalizing a super/sub-type, we have to replace type
variables with a fresh variable (and not just region variables). So if
we know that `Box<?T> <: ?U`, for example, we instantiate `?U` with
`Box<?V>` and then relate `Box<?T>` to `Box<?V>` (and hence require that
`?T <: ?V`).
This change has some complex interactions, however:
First, the occurs check must be updated to detect constraints like `?T
<: ?U` and `?U <: Box<?T>`. If we're not careful, we'll create a
never-ending sequence of new variables. To address this, we add a second
unification set into `type_variables` that tracks type variables related
through **either** equality **or** subtyping, and use that during the
occurs-check.
Second, the "fudge regions if ok" code was expecting no new type
variables to be created. It must be updated to create new type variables
outside of the probe. This is relatively straight-forward under the new
scheme, since type variables are now independent from one another, and
any relations are moderated by pending subtype obliations and so forth.
This part would be tricky to backport though.
cc #18653
cc #40951
2017-04-11 21:17:58 +00:00
|
|
|
// both must be type variables, or the other would've been instantiated
|
|
|
|
assert!(a.is_ty_var() && b.is_ty_var());
|
2017-04-11 21:37:40 +00:00
|
|
|
self.need_type_info(hir::BodyId { node_id: obligation.cause.body_id },
|
|
|
|
obligation.cause.span,
|
|
|
|
a);
|
2017-03-10 02:47:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-11 05:48:12 +00:00
|
|
|
_ => {
|
|
|
|
if !self.tcx.sess.has_errors() {
|
|
|
|
let mut err = struct_span_err!(self.tcx.sess,
|
|
|
|
obligation.cause.span, E0284,
|
|
|
|
"type annotations required: \
|
|
|
|
cannot resolve `{}`",
|
|
|
|
predicate);
|
|
|
|
self.note_obligation_cause(&mut err, obligation);
|
|
|
|
err.emit();
|
|
|
|
}
|
2014-12-06 16:39:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-11 05:48:12 +00:00
|
|
|
/// Returns whether the trait predicate may apply for *some* assignment
|
|
|
|
/// to the type parameters.
|
2017-05-23 08:19:47 +00:00
|
|
|
fn predicate_can_apply(&self,
|
|
|
|
param_env: ty::ParamEnv<'tcx>,
|
|
|
|
pred: ty::PolyTraitRef<'tcx>)
|
|
|
|
-> bool {
|
2016-05-11 05:48:12 +00:00
|
|
|
struct ParamToVarFolder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
|
|
|
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
|
2016-11-08 03:02:55 +00:00
|
|
|
var_map: FxHashMap<Ty<'tcx>, Ty<'tcx>>
|
2016-05-11 05:48:12 +00:00
|
|
|
}
|
2016-03-29 17:12:31 +00:00
|
|
|
|
2016-05-11 05:48:12 +00:00
|
|
|
impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for ParamToVarFolder<'a, 'gcx, 'tcx> {
|
|
|
|
fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.infcx.tcx }
|
2016-03-29 17:12:31 +00:00
|
|
|
|
2016-05-11 05:48:12 +00:00
|
|
|
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
2016-11-28 18:08:08 +00:00
|
|
|
if let ty::TyParam(ty::ParamTy {name, ..}) = ty.sty {
|
2016-05-11 05:48:12 +00:00
|
|
|
let infcx = self.infcx;
|
2016-11-28 18:08:08 +00:00
|
|
|
self.var_map.entry(ty).or_insert_with(||
|
|
|
|
infcx.next_ty_var(
|
|
|
|
TypeVariableOrigin::TypeParameterDefinition(DUMMY_SP, name)))
|
2016-05-11 05:48:12 +00:00
|
|
|
} else {
|
|
|
|
ty.super_fold_with(self)
|
|
|
|
}
|
2016-03-29 17:12:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-11 05:48:12 +00:00
|
|
|
self.probe(|_| {
|
|
|
|
let mut selcx = SelectionContext::new(self);
|
2016-03-29 17:12:31 +00:00
|
|
|
|
2016-05-11 05:48:12 +00:00
|
|
|
let cleaned_pred = pred.fold_with(&mut ParamToVarFolder {
|
|
|
|
infcx: self,
|
2016-11-08 03:02:55 +00:00
|
|
|
var_map: FxHashMap()
|
2016-05-11 05:48:12 +00:00
|
|
|
});
|
2016-03-29 17:12:31 +00:00
|
|
|
|
2016-05-11 05:48:12 +00:00
|
|
|
let cleaned_pred = super::project::normalize(
|
|
|
|
&mut selcx,
|
2017-05-23 08:19:47 +00:00
|
|
|
param_env,
|
2016-05-11 05:48:12 +00:00
|
|
|
ObligationCause::dummy(),
|
|
|
|
&cleaned_pred
|
|
|
|
).value;
|
2016-03-29 17:12:31 +00:00
|
|
|
|
2016-05-11 05:48:12 +00:00
|
|
|
let obligation = Obligation::new(
|
|
|
|
ObligationCause::dummy(),
|
2017-05-23 08:19:47 +00:00
|
|
|
param_env,
|
2016-05-11 05:48:12 +00:00
|
|
|
cleaned_pred.to_predicate()
|
|
|
|
);
|
2016-03-29 17:12:31 +00:00
|
|
|
|
2016-05-11 05:48:12 +00:00
|
|
|
selcx.evaluate_obligation(&obligation)
|
|
|
|
})
|
|
|
|
}
|
2016-03-29 17:12:31 +00:00
|
|
|
|
2017-01-25 06:26:39 +00:00
|
|
|
fn extract_type_name(&self, ty: &'a Ty<'tcx>) -> String {
|
|
|
|
if let ty::TyInfer(ty::TyVar(ty_vid)) = (*ty).sty {
|
|
|
|
let ty_vars = self.type_variables.borrow();
|
|
|
|
if let TypeVariableOrigin::TypeParameterDefinition(_, name) =
|
|
|
|
*ty_vars.var_origin(ty_vid) {
|
|
|
|
name.to_string()
|
|
|
|
} else {
|
|
|
|
ty.to_string()
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ty.to_string()
|
|
|
|
}
|
|
|
|
}
|
2016-03-29 17:12:31 +00:00
|
|
|
|
2017-04-11 21:37:40 +00:00
|
|
|
pub fn need_type_info(&self, body_id: hir::BodyId, span: Span, ty: Ty<'tcx>) {
|
2016-11-28 18:08:29 +00:00
|
|
|
let ty = self.resolve_type_vars_if_possible(&ty);
|
2017-01-25 06:26:39 +00:00
|
|
|
let name = self.extract_type_name(&ty);
|
2017-01-24 15:19:36 +00:00
|
|
|
|
2017-04-11 21:37:40 +00:00
|
|
|
let mut err_span = span;
|
|
|
|
let mut labels = vec![(span, format!("cannot infer type for `{}`", name))];
|
2017-01-24 15:19:36 +00:00
|
|
|
|
|
|
|
let mut local_visitor = FindLocalByTypeVisitor {
|
|
|
|
infcx: &self,
|
|
|
|
target_ty: &ty,
|
2017-04-11 21:37:40 +00:00
|
|
|
hir_map: &self.tcx.hir,
|
|
|
|
found_local_pattern: None,
|
|
|
|
found_arg_pattern: None,
|
2017-01-24 15:19:36 +00:00
|
|
|
};
|
|
|
|
|
2017-03-09 23:51:47 +00:00
|
|
|
// #40294: cause.body_id can also be a fn declaration.
|
|
|
|
// Currently, if it's anything other than NodeExpr, we just ignore it
|
2017-04-11 21:37:40 +00:00
|
|
|
match self.tcx.hir.find(body_id.node_id) {
|
2017-03-09 23:51:47 +00:00
|
|
|
Some(NodeExpr(expr)) => local_visitor.visit_expr(expr),
|
|
|
|
_ => ()
|
|
|
|
}
|
2017-01-24 15:19:36 +00:00
|
|
|
|
2017-04-11 21:37:40 +00:00
|
|
|
if let Some(pattern) = local_visitor.found_arg_pattern {
|
|
|
|
err_span = pattern.span;
|
|
|
|
// We don't want to show the default label for closures.
|
|
|
|
//
|
|
|
|
// So, before clearing, the output would look something like this:
|
|
|
|
// ```
|
|
|
|
// let x = |_| { };
|
|
|
|
// - ^^^^ cannot infer type for `[_; 0]`
|
|
|
|
// |
|
|
|
|
// consider giving this closure parameter a type
|
|
|
|
// ```
|
|
|
|
//
|
|
|
|
// After clearing, it looks something like this:
|
|
|
|
// ```
|
|
|
|
// let x = |_| { };
|
|
|
|
// ^ consider giving this closure parameter a type
|
|
|
|
// ```
|
|
|
|
labels.clear();
|
|
|
|
labels.push((pattern.span, format!("consider giving this closure parameter a type")));
|
|
|
|
}
|
|
|
|
|
|
|
|
if let Some(pattern) = local_visitor.found_local_pattern {
|
2017-01-25 06:26:39 +00:00
|
|
|
if let Some(simple_name) = pattern.simple_name() {
|
2017-04-11 21:37:40 +00:00
|
|
|
labels.push((pattern.span, format!("consider giving `{}` a type", simple_name)));
|
2016-11-28 18:08:29 +00:00
|
|
|
} else {
|
2017-04-18 18:42:55 +00:00
|
|
|
labels.push((pattern.span, format!("consider giving the pattern a type")));
|
2016-11-28 18:08:29 +00:00
|
|
|
}
|
2017-01-24 15:19:36 +00:00
|
|
|
}
|
2016-11-28 18:08:29 +00:00
|
|
|
|
2017-04-11 21:37:40 +00:00
|
|
|
let mut err = struct_span_err!(self.tcx.sess,
|
|
|
|
err_span,
|
|
|
|
E0282,
|
|
|
|
"type annotations needed");
|
|
|
|
|
|
|
|
for (target_span, label_message) in labels {
|
2017-05-04 12:17:23 +00:00
|
|
|
err.span_label(target_span, label_message);
|
2017-04-11 21:37:40 +00:00
|
|
|
}
|
|
|
|
|
2016-11-28 18:08:29 +00:00
|
|
|
err.emit();
|
2016-05-11 05:48:12 +00:00
|
|
|
}
|
2015-08-07 14:28:51 +00:00
|
|
|
|
2016-05-11 05:48:12 +00:00
|
|
|
fn note_obligation_cause<T>(&self,
|
|
|
|
err: &mut DiagnosticBuilder,
|
|
|
|
obligation: &Obligation<'tcx, T>)
|
|
|
|
where T: fmt::Display
|
|
|
|
{
|
|
|
|
self.note_obligation_cause_code(err,
|
|
|
|
&obligation.predicate,
|
|
|
|
&obligation.cause.code);
|
|
|
|
}
|
2014-12-06 16:39:25 +00:00
|
|
|
|
2016-05-11 05:48:12 +00:00
|
|
|
fn note_obligation_cause_code<T>(&self,
|
|
|
|
err: &mut DiagnosticBuilder,
|
|
|
|
predicate: &T,
|
|
|
|
cause_code: &ObligationCauseCode<'tcx>)
|
|
|
|
where T: fmt::Display
|
|
|
|
{
|
|
|
|
let tcx = self.tcx;
|
|
|
|
match *cause_code {
|
2016-11-07 18:25:06 +00:00
|
|
|
ObligationCauseCode::ExprAssignable |
|
|
|
|
ObligationCauseCode::MatchExpressionArm { .. } |
|
|
|
|
ObligationCauseCode::IfExpression |
|
|
|
|
ObligationCauseCode::IfExpressionWithNoElse |
|
|
|
|
ObligationCauseCode::EquatePredicate |
|
|
|
|
ObligationCauseCode::MainFunctionType |
|
|
|
|
ObligationCauseCode::StartFunctionType |
|
|
|
|
ObligationCauseCode::IntrinsicType |
|
|
|
|
ObligationCauseCode::MethodReceiver |
|
2017-03-17 13:37:18 +00:00
|
|
|
ObligationCauseCode::ReturnNoExpression |
|
2016-11-07 18:25:06 +00:00
|
|
|
ObligationCauseCode::MiscObligation => {
|
|
|
|
}
|
2016-05-11 05:48:12 +00:00
|
|
|
ObligationCauseCode::SliceOrArrayElem => {
|
|
|
|
err.note("slice and array elements must have `Sized` type");
|
|
|
|
}
|
|
|
|
ObligationCauseCode::TupleElem => {
|
|
|
|
err.note("tuple elements must have `Sized` type");
|
|
|
|
}
|
|
|
|
ObligationCauseCode::ProjectionWf(data) => {
|
|
|
|
err.note(&format!("required so that the projection `{}` is well-formed",
|
|
|
|
data));
|
|
|
|
}
|
|
|
|
ObligationCauseCode::ReferenceOutlivesReferent(ref_ty) => {
|
|
|
|
err.note(&format!("required so that reference `{}` does not outlive its referent",
|
|
|
|
ref_ty));
|
|
|
|
}
|
2016-10-14 14:09:59 +00:00
|
|
|
ObligationCauseCode::ObjectTypeBound(object_ty, region) => {
|
|
|
|
err.note(&format!("required so that the lifetime bound of `{}` for `{}` \
|
|
|
|
is satisfied",
|
|
|
|
region, object_ty));
|
|
|
|
}
|
2016-05-11 05:48:12 +00:00
|
|
|
ObligationCauseCode::ItemObligation(item_def_id) => {
|
|
|
|
let item_name = tcx.item_path_str(item_def_id);
|
|
|
|
err.note(&format!("required by `{}`", item_name));
|
|
|
|
}
|
|
|
|
ObligationCauseCode::ObjectCastObligation(object_ty) => {
|
|
|
|
err.note(&format!("required for the cast to the object type `{}`",
|
|
|
|
self.ty_to_string(object_ty)));
|
|
|
|
}
|
|
|
|
ObligationCauseCode::RepeatVec => {
|
|
|
|
err.note("the `Copy` trait is required because the \
|
|
|
|
repeated element will be copied");
|
|
|
|
}
|
|
|
|
ObligationCauseCode::VariableType(_) => {
|
|
|
|
err.note("all local variables must have a statically known size");
|
|
|
|
}
|
|
|
|
ObligationCauseCode::ReturnType => {
|
|
|
|
err.note("the return type of a function must have a \
|
|
|
|
statically known size");
|
|
|
|
}
|
|
|
|
ObligationCauseCode::AssignmentLhsSized => {
|
|
|
|
err.note("the left-hand-side of an assignment must have a statically known size");
|
|
|
|
}
|
|
|
|
ObligationCauseCode::StructInitializerSized => {
|
|
|
|
err.note("structs must have a statically known size to be initialized");
|
|
|
|
}
|
|
|
|
ObligationCauseCode::FieldSized => {
|
2016-10-12 10:40:48 +00:00
|
|
|
err.note("only the last field of a struct may have a dynamically sized type");
|
2016-05-11 05:48:12 +00:00
|
|
|
}
|
2016-06-24 00:20:37 +00:00
|
|
|
ObligationCauseCode::ConstSized => {
|
|
|
|
err.note("constant expressions must have a statically known size");
|
|
|
|
}
|
2016-05-11 05:48:12 +00:00
|
|
|
ObligationCauseCode::SharedStatic => {
|
|
|
|
err.note("shared static variables must have a type that implements `Sync`");
|
|
|
|
}
|
|
|
|
ObligationCauseCode::BuiltinDerivedObligation(ref data) => {
|
|
|
|
let parent_trait_ref = self.resolve_type_vars_if_possible(&data.parent_trait_ref);
|
|
|
|
err.note(&format!("required because it appears within the type `{}`",
|
|
|
|
parent_trait_ref.0.self_ty()));
|
|
|
|
let parent_predicate = parent_trait_ref.to_predicate();
|
|
|
|
self.note_obligation_cause_code(err,
|
|
|
|
&parent_predicate,
|
|
|
|
&data.parent_code);
|
|
|
|
}
|
|
|
|
ObligationCauseCode::ImplDerivedObligation(ref data) => {
|
|
|
|
let parent_trait_ref = self.resolve_type_vars_if_possible(&data.parent_trait_ref);
|
|
|
|
err.note(
|
|
|
|
&format!("required because of the requirements on the impl of `{}` for `{}`",
|
|
|
|
parent_trait_ref,
|
|
|
|
parent_trait_ref.0.self_ty()));
|
|
|
|
let parent_predicate = parent_trait_ref.to_predicate();
|
|
|
|
self.note_obligation_cause_code(err,
|
|
|
|
&parent_predicate,
|
|
|
|
&data.parent_code);
|
|
|
|
}
|
2016-10-05 14:17:14 +00:00
|
|
|
ObligationCauseCode::CompareImplMethodObligation { .. } => {
|
2016-05-11 05:48:12 +00:00
|
|
|
err.note(
|
|
|
|
&format!("the requirement `{}` appears on the impl method \
|
|
|
|
but not on the corresponding trait method",
|
|
|
|
predicate));
|
|
|
|
}
|
2015-01-14 21:43:17 +00:00
|
|
|
}
|
2014-12-06 16:39:25 +00:00
|
|
|
}
|
2014-12-17 19:16:28 +00:00
|
|
|
|
2016-05-11 05:48:12 +00:00
|
|
|
fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder) {
|
|
|
|
let current_limit = self.tcx.sess.recursion_limit.get();
|
|
|
|
let suggested_limit = current_limit * 2;
|
2017-02-28 18:18:54 +00:00
|
|
|
err.help(&format!(
|
2016-05-11 05:48:12 +00:00
|
|
|
"consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate",
|
|
|
|
suggested_limit));
|
|
|
|
}
|
2016-03-16 22:15:31 +00:00
|
|
|
}
|
2017-04-10 21:17:49 +00:00
|
|
|
|