Auto merge of #30389 - nikomatsakis:rfc1214-error, r=arielb1
Make RFC 1214 warnings into errors, and rip out the "warn or err" associated machinery. Future such attempts should go through lints anyhow. There is a fair amount of fallout in the compile-fail tests, as WF checking now occurs earlier in the process. r? @arielb1
This commit is contained in:
commit
5dd29cc310
@ -577,11 +577,6 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
// where the error was detected. But that span is not readily
|
||||
// accessible.
|
||||
|
||||
let is_warning = match origin {
|
||||
infer::RFC1214Subregion(_) => true,
|
||||
_ => false,
|
||||
};
|
||||
|
||||
let labeled_user_string = match bound_kind {
|
||||
GenericKind::Param(ref p) =>
|
||||
format!("the parameter type `{}`", p),
|
||||
@ -592,8 +587,8 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
match sub {
|
||||
ty::ReFree(ty::FreeRegion {bound_region: ty::BrNamed(..), ..}) => {
|
||||
// Does the required lifetime have a nice name we can print?
|
||||
span_err_or_warn!(
|
||||
is_warning, self.tcx.sess, origin.span(), E0309,
|
||||
span_err!(
|
||||
self.tcx.sess, origin.span(), E0309,
|
||||
"{} may not live long enough", labeled_user_string);
|
||||
self.tcx.sess.fileline_help(
|
||||
origin.span(),
|
||||
@ -605,8 +600,8 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
|
||||
ty::ReStatic => {
|
||||
// Does the required lifetime have a nice name we can print?
|
||||
span_err_or_warn!(
|
||||
is_warning, self.tcx.sess, origin.span(), E0310,
|
||||
span_err!(
|
||||
self.tcx.sess, origin.span(), E0310,
|
||||
"{} may not live long enough", labeled_user_string);
|
||||
self.tcx.sess.fileline_help(
|
||||
origin.span(),
|
||||
@ -617,8 +612,8 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
|
||||
_ => {
|
||||
// If not, be less specific.
|
||||
span_err_or_warn!(
|
||||
is_warning, self.tcx.sess, origin.span(), E0311,
|
||||
span_err!(
|
||||
self.tcx.sess, origin.span(), E0311,
|
||||
"{} may not live long enough",
|
||||
labeled_user_string);
|
||||
self.tcx.sess.fileline_help(
|
||||
@ -633,10 +628,6 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
if is_warning {
|
||||
self.tcx.sess.note_rfc_1214(origin.span());
|
||||
}
|
||||
|
||||
self.note_region_origin(&origin);
|
||||
}
|
||||
|
||||
@ -645,13 +636,6 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
sub: Region,
|
||||
sup: Region) {
|
||||
match origin {
|
||||
infer::RFC1214Subregion(ref suborigin) => {
|
||||
// Ideally, this would be a warning, but it doesn't
|
||||
// seem to come up in practice, since the changes from
|
||||
// RFC1214 mostly trigger errors in type definitions
|
||||
// that don't wind up coming down this path.
|
||||
self.report_concrete_failure((**suborigin).clone(), sub, sup);
|
||||
}
|
||||
infer::Subtype(trace) => {
|
||||
let terr = TypeError::RegionsDoesNotOutlive(sup, sub);
|
||||
self.report_and_explain_type_error(trace, &terr);
|
||||
@ -1598,9 +1582,6 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
|
||||
fn note_region_origin(&self, origin: &SubregionOrigin<'tcx>) {
|
||||
match *origin {
|
||||
infer::RFC1214Subregion(ref suborigin) => {
|
||||
self.note_region_origin(suborigin);
|
||||
}
|
||||
infer::Subtype(ref trace) => {
|
||||
let desc = match trace.origin {
|
||||
TypeOrigin::Misc(_) => {
|
||||
|
@ -37,7 +37,6 @@ use middle::ty::relate::{Relate, RelateResult, TypeRelation};
|
||||
use rustc_data_structures::unify::{self, UnificationTable};
|
||||
use std::cell::{RefCell, Ref};
|
||||
use std::fmt;
|
||||
use std::rc::Rc;
|
||||
use syntax::ast;
|
||||
use syntax::codemap;
|
||||
use syntax::codemap::{Span, DUMMY_SP};
|
||||
@ -198,11 +197,6 @@ pub struct TypeTrace<'tcx> {
|
||||
/// See `error_reporting.rs` for more details
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum SubregionOrigin<'tcx> {
|
||||
// Marker to indicate a constraint that only arises due to new
|
||||
// provisions from RFC 1214. This will result in a warning, not an
|
||||
// error.
|
||||
RFC1214Subregion(Rc<SubregionOrigin<'tcx>>),
|
||||
|
||||
// Arose from a subtyping relation
|
||||
Subtype(TypeTrace<'tcx>),
|
||||
|
||||
@ -1568,7 +1562,6 @@ impl TypeOrigin {
|
||||
impl<'tcx> SubregionOrigin<'tcx> {
|
||||
pub fn span(&self) -> Span {
|
||||
match *self {
|
||||
RFC1214Subregion(ref a) => a.span(),
|
||||
Subtype(ref a) => a.span(),
|
||||
InfStackClosure(a) => a,
|
||||
InvokeClosure(a) => a,
|
||||
|
@ -36,7 +36,6 @@ use syntax::attr::{AttributeMethods, AttrMetaMethods};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Hash)]
|
||||
pub struct TraitErrorKey<'tcx> {
|
||||
is_warning: bool,
|
||||
span: Span,
|
||||
predicate: ty::Predicate<'tcx>
|
||||
}
|
||||
@ -47,7 +46,6 @@ impl<'tcx> TraitErrorKey<'tcx> {
|
||||
let predicate =
|
||||
infcx.resolve_type_vars_if_possible(&e.obligation.predicate);
|
||||
TraitErrorKey {
|
||||
is_warning: is_warning(&e.obligation),
|
||||
span: e.obligation.cause.span,
|
||||
predicate: infcx.tcx.erase_regions(&predicate)
|
||||
}
|
||||
@ -83,10 +81,6 @@ fn report_fulfillment_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_warning<T>(obligation: &Obligation<T>) -> bool {
|
||||
obligation.cause.code.is_rfc1214()
|
||||
}
|
||||
|
||||
pub fn report_projection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
|
||||
obligation: &PredicateObligation<'tcx>,
|
||||
error: &MismatchedProjectionTypes<'tcx>)
|
||||
@ -100,8 +94,8 @@ pub fn report_projection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
|
||||
// then $X will be unified with TyError, but the error still needs to be
|
||||
// reported.
|
||||
if !infcx.tcx.sess.has_errors() || !predicate.references_error() {
|
||||
span_err_or_warn!(
|
||||
is_warning(obligation), infcx.tcx.sess, obligation.cause.span, E0271,
|
||||
span_err!(
|
||||
infcx.tcx.sess, obligation.cause.span, E0271,
|
||||
"type mismatch resolving `{}`: {}",
|
||||
predicate,
|
||||
error.err);
|
||||
@ -208,12 +202,11 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
|
||||
obligation: &PredicateObligation<'tcx>,
|
||||
error: &SelectionError<'tcx>)
|
||||
{
|
||||
let is_warning = is_warning(obligation);
|
||||
match *error {
|
||||
SelectionError::Unimplemented => {
|
||||
if let ObligationCauseCode::CompareImplMethodObligation = obligation.cause.code {
|
||||
span_err_or_warn!(
|
||||
is_warning, infcx.tcx.sess, obligation.cause.span, E0276,
|
||||
span_err!(
|
||||
infcx.tcx.sess, obligation.cause.span, E0276,
|
||||
"the requirement `{}` appears on the impl \
|
||||
method but not on the corresponding trait method",
|
||||
obligation.predicate);
|
||||
@ -225,8 +218,8 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
|
||||
|
||||
if !infcx.tcx.sess.has_errors() || !trait_predicate.references_error() {
|
||||
let trait_ref = trait_predicate.to_poly_trait_ref();
|
||||
span_err_or_warn!(
|
||||
is_warning, infcx.tcx.sess, obligation.cause.span, E0277,
|
||||
span_err!(
|
||||
infcx.tcx.sess, obligation.cause.span, E0277,
|
||||
"the trait `{}` is not implemented for the type `{}`",
|
||||
trait_ref, trait_ref.self_ty());
|
||||
|
||||
@ -245,8 +238,8 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
|
||||
let predicate = infcx.resolve_type_vars_if_possible(predicate);
|
||||
let err = infcx.equality_predicate(obligation.cause.span,
|
||||
&predicate).err().unwrap();
|
||||
span_err_or_warn!(
|
||||
is_warning, infcx.tcx.sess, obligation.cause.span, E0278,
|
||||
span_err!(
|
||||
infcx.tcx.sess, obligation.cause.span, E0278,
|
||||
"the requirement `{}` is not satisfied (`{}`)",
|
||||
predicate,
|
||||
err);
|
||||
@ -257,8 +250,8 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
|
||||
let predicate = infcx.resolve_type_vars_if_possible(predicate);
|
||||
let err = infcx.region_outlives_predicate(obligation.cause.span,
|
||||
&predicate).err().unwrap();
|
||||
span_err_or_warn!(
|
||||
is_warning, infcx.tcx.sess, obligation.cause.span, E0279,
|
||||
span_err!(
|
||||
infcx.tcx.sess, obligation.cause.span, E0279,
|
||||
"the requirement `{}` is not satisfied (`{}`)",
|
||||
predicate,
|
||||
err);
|
||||
@ -268,8 +261,8 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
|
||||
ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => {
|
||||
let predicate =
|
||||
infcx.resolve_type_vars_if_possible(&obligation.predicate);
|
||||
span_err_or_warn!(
|
||||
is_warning, infcx.tcx.sess, obligation.cause.span, E0280,
|
||||
span_err!(
|
||||
infcx.tcx.sess, obligation.cause.span, E0280,
|
||||
"the requirement `{}` is not satisfied",
|
||||
predicate);
|
||||
note_obligation_cause(infcx, obligation);
|
||||
@ -281,8 +274,7 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
|
||||
report_object_safety_error(infcx.tcx,
|
||||
obligation.cause.span,
|
||||
trait_def_id,
|
||||
violations,
|
||||
is_warning);
|
||||
violations);
|
||||
note_obligation_cause(infcx, obligation);
|
||||
}
|
||||
|
||||
@ -304,8 +296,8 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
|
||||
let expected_trait_ref = infcx.resolve_type_vars_if_possible(&*expected_trait_ref);
|
||||
let actual_trait_ref = infcx.resolve_type_vars_if_possible(&*actual_trait_ref);
|
||||
if !actual_trait_ref.self_ty().references_error() {
|
||||
span_err_or_warn!(
|
||||
is_warning, infcx.tcx.sess, obligation.cause.span, E0281,
|
||||
span_err!(
|
||||
infcx.tcx.sess, obligation.cause.span, E0281,
|
||||
"type mismatch: the type `{}` implements the trait `{}`, \
|
||||
but the trait `{}` is required ({})",
|
||||
expected_trait_ref.self_ty(),
|
||||
@ -318,8 +310,7 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
|
||||
|
||||
TraitNotObjectSafe(did) => {
|
||||
let violations = object_safety_violations(infcx.tcx, did);
|
||||
report_object_safety_error(infcx.tcx, obligation.cause.span, did,
|
||||
violations, is_warning);
|
||||
report_object_safety_error(infcx.tcx, obligation.cause.span, did, violations);
|
||||
note_obligation_cause(infcx, obligation);
|
||||
}
|
||||
}
|
||||
@ -328,11 +319,10 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
|
||||
pub fn report_object_safety_error<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||
span: Span,
|
||||
trait_def_id: DefId,
|
||||
violations: Vec<ObjectSafetyViolation>,
|
||||
is_warning: bool)
|
||||
violations: Vec<ObjectSafetyViolation>)
|
||||
{
|
||||
span_err_or_warn!(
|
||||
is_warning, tcx.sess, span, E0038,
|
||||
span_err!(
|
||||
tcx.sess, span, E0038,
|
||||
"the trait `{}` cannot be made into an object",
|
||||
tcx.item_path_str(trait_def_id));
|
||||
|
||||
@ -402,7 +392,17 @@ pub fn maybe_report_ambiguity<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
|
||||
let self_ty = trait_ref.self_ty();
|
||||
let all_types = &trait_ref.substs().types;
|
||||
if all_types.references_error() {
|
||||
} else if all_types.needs_infer() {
|
||||
} else {
|
||||
// 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
|
||||
@ -430,16 +430,6 @@ pub fn maybe_report_ambiguity<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
|
||||
note_obligation_cause(infcx, obligation);
|
||||
}
|
||||
}
|
||||
} else if !infcx.tcx.sess.has_errors() {
|
||||
// Ambiguity. Coherence should have reported an error.
|
||||
infcx.tcx.sess.span_bug(
|
||||
obligation.cause.span,
|
||||
&format!(
|
||||
"coherence failed to report ambiguity: \
|
||||
cannot locate the impl of the trait `{}` for \
|
||||
the type `{}`",
|
||||
trait_ref,
|
||||
self_ty));
|
||||
}
|
||||
}
|
||||
|
||||
@ -491,10 +481,6 @@ fn note_obligation_cause_code<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>,
|
||||
let tcx = infcx.tcx;
|
||||
match *cause_code {
|
||||
ObligationCauseCode::MiscObligation => { }
|
||||
ObligationCauseCode::RFC1214(ref subcode) => {
|
||||
tcx.sess.note_rfc_1214(cause_span);
|
||||
note_obligation_cause_code(infcx, predicate, cause_span, subcode);
|
||||
}
|
||||
ObligationCauseCode::SliceOrArrayElem => {
|
||||
tcx.sess.fileline_note(
|
||||
cause_span,
|
||||
|
@ -21,16 +21,14 @@ use super::CodeSelectionError;
|
||||
use super::is_object_safe;
|
||||
use super::FulfillmentError;
|
||||
use super::ObligationCause;
|
||||
use super::ObligationCauseCode;
|
||||
use super::PredicateObligation;
|
||||
use super::project;
|
||||
use super::RFC1214Warning;
|
||||
use super::select::SelectionContext;
|
||||
use super::Unimplemented;
|
||||
use super::util::predicate_for_builtin_bound;
|
||||
|
||||
pub struct FulfilledPredicates<'tcx> {
|
||||
set: FnvHashSet<(RFC1214Warning, ty::Predicate<'tcx>)>
|
||||
set: FnvHashSet<ty::Predicate<'tcx>>
|
||||
}
|
||||
|
||||
/// The fulfillment context is used to drive trait resolution. It
|
||||
@ -194,9 +192,7 @@ impl<'tcx> FulfillmentContext<'tcx> {
|
||||
|
||||
assert!(!obligation.has_escaping_regions());
|
||||
|
||||
let w = RFC1214Warning(obligation.cause.code.is_rfc1214());
|
||||
|
||||
if self.is_duplicate_or_add(infcx.tcx, w, &obligation.predicate) {
|
||||
if self.is_duplicate_or_add(infcx.tcx, &obligation.predicate) {
|
||||
debug!("register_predicate({:?}) -- already seen, skip", obligation);
|
||||
return;
|
||||
}
|
||||
@ -261,7 +257,6 @@ impl<'tcx> FulfillmentContext<'tcx> {
|
||||
|
||||
fn is_duplicate_or_add(&mut self,
|
||||
tcx: &ty::ctxt<'tcx>,
|
||||
w: RFC1214Warning,
|
||||
predicate: &ty::Predicate<'tcx>)
|
||||
-> bool {
|
||||
// This is a kind of dirty hack to allow us to avoid "rederiving"
|
||||
@ -276,12 +271,10 @@ impl<'tcx> FulfillmentContext<'tcx> {
|
||||
// evaluating the 'nested obligations'. This cache lets us
|
||||
// skip those.
|
||||
|
||||
let will_warn_due_to_rfc1214 = w.0;
|
||||
let errors_will_be_reported = self.errors_will_be_reported && !will_warn_due_to_rfc1214;
|
||||
if errors_will_be_reported && predicate.is_global() {
|
||||
tcx.fulfilled_predicates.borrow_mut().is_duplicate_or_add(w, predicate)
|
||||
if self.errors_will_be_reported && predicate.is_global() {
|
||||
tcx.fulfilled_predicates.borrow_mut().is_duplicate_or_add(predicate)
|
||||
} else {
|
||||
self.duplicate_set.is_duplicate_or_add(w, predicate)
|
||||
self.duplicate_set.is_duplicate_or_add(predicate)
|
||||
}
|
||||
}
|
||||
|
||||
@ -496,12 +489,8 @@ fn process_predicate<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
|
||||
}
|
||||
|
||||
ty::Predicate::WellFormed(ty) => {
|
||||
let rfc1214 = match obligation.cause.code {
|
||||
ObligationCauseCode::RFC1214(_) => true,
|
||||
_ => false,
|
||||
};
|
||||
match ty::wf::obligations(selcx.infcx(), obligation.cause.body_id,
|
||||
ty, obligation.cause.span, rfc1214) {
|
||||
ty, obligation.cause.span) {
|
||||
Some(obligations) => {
|
||||
new_obligations.extend(obligations);
|
||||
true
|
||||
@ -539,13 +528,11 @@ impl<'tcx> FulfilledPredicates<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_duplicate(&self, w: RFC1214Warning, p: &ty::Predicate<'tcx>) -> bool {
|
||||
let key = (w, p.clone());
|
||||
self.set.contains(&key)
|
||||
pub fn is_duplicate(&self, key: &ty::Predicate<'tcx>) -> bool {
|
||||
self.set.contains(key)
|
||||
}
|
||||
|
||||
fn is_duplicate_or_add(&mut self, w: RFC1214Warning, p: &ty::Predicate<'tcx>) -> bool {
|
||||
let key = (w, p.clone());
|
||||
!self.set.insert(key)
|
||||
fn is_duplicate_or_add(&mut self, key: &ty::Predicate<'tcx>) -> bool {
|
||||
!self.set.insert(key.clone())
|
||||
}
|
||||
}
|
||||
|
@ -106,9 +106,6 @@ pub enum ObligationCauseCode<'tcx> {
|
||||
/// Not well classified or should be obvious from span.
|
||||
MiscObligation,
|
||||
|
||||
/// Obligation that triggers warning until RFC 1214 is fully in place.
|
||||
RFC1214(Rc<ObligationCauseCode<'tcx>>),
|
||||
|
||||
/// This is the trait reference from the given projection
|
||||
SliceOrArrayElem,
|
||||
|
||||
@ -554,24 +551,6 @@ impl<'tcx> ObligationCause<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// This marker is used in some caches to record whether the
|
||||
/// predicate, if it is found to be false, will yield a warning (due
|
||||
/// to RFC1214) or an error. We separate these two cases in the cache
|
||||
/// so that if we see the same predicate twice, first resulting in a
|
||||
/// warning, and next resulting in an error, we still report the
|
||||
/// error, rather than considering it a duplicate.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct RFC1214Warning(bool);
|
||||
|
||||
impl<'tcx> ObligationCauseCode<'tcx> {
|
||||
pub fn is_rfc1214(&self) -> bool {
|
||||
match *self {
|
||||
ObligationCauseCode::RFC1214(..) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, N> Vtable<'tcx, N> {
|
||||
pub fn nested_obligations(self) -> Vec<N> {
|
||||
match self {
|
||||
|
@ -26,7 +26,6 @@ use super::{ObligationCauseCode, BuiltinDerivedObligation, ImplDerivedObligation
|
||||
use super::{SelectionError, Unimplemented, OutputTypeParameterMismatch};
|
||||
use super::{ObjectCastObligation, Obligation};
|
||||
use super::TraitNotObjectSafe;
|
||||
use super::RFC1214Warning;
|
||||
use super::Selection;
|
||||
use super::SelectionResult;
|
||||
use super::{VtableBuiltin, VtableImpl, VtableParam, VtableClosure,
|
||||
@ -463,8 +462,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
// have been proven elsewhere. This cache only contains
|
||||
// predicates that are global in scope and hence unaffected by
|
||||
// the current environment.
|
||||
let w = RFC1214Warning(false);
|
||||
if self.tcx().fulfilled_predicates.borrow().is_duplicate(w, &obligation.predicate) {
|
||||
if self.tcx().fulfilled_predicates.borrow().is_duplicate(&obligation.predicate) {
|
||||
return EvaluatedToOk;
|
||||
}
|
||||
|
||||
@ -485,8 +483,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
|
||||
ty::Predicate::WellFormed(ty) => {
|
||||
match ty::wf::obligations(self.infcx, obligation.cause.body_id,
|
||||
ty, obligation.cause.span,
|
||||
obligation.cause.code.is_rfc1214()) {
|
||||
ty, obligation.cause.span) {
|
||||
Some(obligations) =>
|
||||
self.evaluate_predicates_recursively(previous_stack, obligations.iter()),
|
||||
None =>
|
||||
@ -2906,22 +2903,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
// chain. Ideally, we should have a way to configure this either
|
||||
// by using -Z verbose or just a CLI argument.
|
||||
if obligation.recursion_depth >= 0 {
|
||||
let derived_code = match obligation.cause.code {
|
||||
ObligationCauseCode::RFC1214(ref base_code) => {
|
||||
let derived_cause = DerivedObligationCause {
|
||||
parent_trait_ref: obligation.predicate.to_poly_trait_ref(),
|
||||
parent_code: base_code.clone(),
|
||||
};
|
||||
ObligationCauseCode::RFC1214(Rc::new(variant(derived_cause)))
|
||||
}
|
||||
_ => {
|
||||
let derived_cause = DerivedObligationCause {
|
||||
parent_trait_ref: obligation.predicate.to_poly_trait_ref(),
|
||||
parent_code: Rc::new(obligation.cause.code.clone())
|
||||
};
|
||||
variant(derived_cause)
|
||||
}
|
||||
let derived_cause = DerivedObligationCause {
|
||||
parent_trait_ref: obligation.predicate.to_poly_trait_ref(),
|
||||
parent_code: Rc::new(obligation.cause.code.clone())
|
||||
};
|
||||
let derived_code = variant(derived_cause);
|
||||
ObligationCause::new(obligation.cause.span, obligation.cause.body_id, derived_code)
|
||||
} else {
|
||||
obligation.cause.clone()
|
||||
|
@ -53,12 +53,6 @@ pub enum Component<'tcx> {
|
||||
// them. This gives us room to improve the regionck reasoning in
|
||||
// the future without breaking backwards compat.
|
||||
EscapingProjection(Vec<Component<'tcx>>),
|
||||
|
||||
// This is a temporary marker indicating "outlives components"
|
||||
// that are due to the new rules introduced by RFC 1214. For the
|
||||
// time being, violations of these requirements generally induce
|
||||
// warnings, not errors.
|
||||
RFC1214(Vec<Component<'tcx>>),
|
||||
}
|
||||
|
||||
/// Returns all the things that must outlive `'a` for the condition
|
||||
@ -124,20 +118,6 @@ fn compute_components<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
|
||||
}
|
||||
}
|
||||
|
||||
// Bare functions and traits are both binders. In the RFC,
|
||||
// this means we would add the bound regions to the "bound
|
||||
// regions list". In our representation, no such list is
|
||||
// maintained explicitly, because bound regions themselves can
|
||||
// be readily identified. However, because the outlives
|
||||
// relation did not used to be applied to fn/trait-object
|
||||
// arguments, we wrap the resulting components in an RFC1214
|
||||
// wrapper so we can issue warnings.
|
||||
ty::TyBareFn(..) | ty::TyTrait(..) => {
|
||||
// OutlivesFunction, OutlivesObject, OutlivesFragment
|
||||
let subcomponents = capture_components(infcx, ty);
|
||||
out.push(Component::RFC1214(subcomponents));
|
||||
}
|
||||
|
||||
// OutlivesTypeParameterEnv -- the actual checking that `X:'a`
|
||||
// is implied by the environment is done in regionck.
|
||||
ty::TyParam(p) => {
|
||||
@ -202,7 +182,15 @@ fn compute_components<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
|
||||
ty::TyRawPtr(..) | // ...
|
||||
ty::TyRef(..) | // OutlivesReference
|
||||
ty::TyTuple(..) | // ...
|
||||
ty::TyBareFn(..) | // OutlivesFunction (*)
|
||||
ty::TyTrait(..) | // OutlivesObject, OutlivesFragment (*)
|
||||
ty::TyError => {
|
||||
// (*) Bare functions and traits are both binders. In the
|
||||
// RFC, this means we would add the bound regions to the
|
||||
// "bound regions list". In our representation, no such
|
||||
// list is maintained explicitly, because bound regions
|
||||
// themselves can be readily identified.
|
||||
|
||||
push_region_constraints(out, ty.regions());
|
||||
for subty in ty.walk_shallow() {
|
||||
compute_components(infcx, subty, out);
|
||||
|
@ -15,8 +15,6 @@ use middle::subst::Substs;
|
||||
use middle::traits;
|
||||
use middle::ty::{self, RegionEscape, ToPredicate, Ty};
|
||||
use std::iter::once;
|
||||
use std::mem;
|
||||
use std::rc::Rc;
|
||||
use syntax::ast;
|
||||
use syntax::codemap::Span;
|
||||
use util::common::ErrorReported;
|
||||
@ -30,15 +28,13 @@ use util::common::ErrorReported;
|
||||
pub fn obligations<'a,'tcx>(infcx: &InferCtxt<'a, 'tcx>,
|
||||
body_id: ast::NodeId,
|
||||
ty: Ty<'tcx>,
|
||||
span: Span,
|
||||
rfc1214: bool)
|
||||
span: Span)
|
||||
-> Option<Vec<traits::PredicateObligation<'tcx>>>
|
||||
{
|
||||
let mut wf = WfPredicates { infcx: infcx,
|
||||
body_id: body_id,
|
||||
span: span,
|
||||
out: vec![],
|
||||
rfc1214: rfc1214 };
|
||||
out: vec![] };
|
||||
if wf.compute(ty) {
|
||||
debug!("wf::obligations({:?}, body_id={:?}) = {:?}", ty, body_id, wf.out);
|
||||
let result = wf.normalize();
|
||||
@ -56,12 +52,10 @@ pub fn obligations<'a,'tcx>(infcx: &InferCtxt<'a, 'tcx>,
|
||||
pub fn trait_obligations<'a,'tcx>(infcx: &InferCtxt<'a, 'tcx>,
|
||||
body_id: ast::NodeId,
|
||||
trait_ref: &ty::TraitRef<'tcx>,
|
||||
span: Span,
|
||||
rfc1214: bool)
|
||||
span: Span)
|
||||
-> Vec<traits::PredicateObligation<'tcx>>
|
||||
{
|
||||
let mut wf = WfPredicates { infcx: infcx, body_id: body_id, span: span,
|
||||
out: vec![], rfc1214: rfc1214 };
|
||||
let mut wf = WfPredicates { infcx: infcx, body_id: body_id, span: span, out: vec![] };
|
||||
wf.compute_trait_ref(trait_ref);
|
||||
wf.normalize()
|
||||
}
|
||||
@ -69,12 +63,10 @@ pub fn trait_obligations<'a,'tcx>(infcx: &InferCtxt<'a, 'tcx>,
|
||||
pub fn predicate_obligations<'a,'tcx>(infcx: &InferCtxt<'a, 'tcx>,
|
||||
body_id: ast::NodeId,
|
||||
predicate: &ty::Predicate<'tcx>,
|
||||
span: Span,
|
||||
rfc1214: bool)
|
||||
span: Span)
|
||||
-> Vec<traits::PredicateObligation<'tcx>>
|
||||
{
|
||||
let mut wf = WfPredicates { infcx: infcx, body_id: body_id, span: span,
|
||||
out: vec![], rfc1214: rfc1214 };
|
||||
let mut wf = WfPredicates { infcx: infcx, body_id: body_id, span: span, out: vec![] };
|
||||
|
||||
// (*) ok to skip binders, because wf code is prepared for it
|
||||
match *predicate {
|
||||
@ -150,7 +142,7 @@ pub fn implied_bounds<'a,'tcx>(
|
||||
// than the ultimate set. (Note: normally there won't be
|
||||
// unresolved inference variables here anyway, but there might be
|
||||
// during typeck under some circumstances.)
|
||||
let obligations = obligations(infcx, body_id, ty, span, false).unwrap_or(vec![]);
|
||||
let obligations = obligations(infcx, body_id, ty, span).unwrap_or(vec![]);
|
||||
|
||||
// From the full set of obligations, just filter down to the
|
||||
// region relationships.
|
||||
@ -223,8 +215,6 @@ fn implied_bounds_from_components<'tcx>(sub_region: ty::Region,
|
||||
vec!(),
|
||||
Component::UnresolvedInferenceVariable(..) =>
|
||||
vec!(),
|
||||
Component::RFC1214(components) =>
|
||||
implied_bounds_from_components(sub_region, components),
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
@ -235,24 +225,11 @@ struct WfPredicates<'a,'tcx:'a> {
|
||||
body_id: ast::NodeId,
|
||||
span: Span,
|
||||
out: Vec<traits::PredicateObligation<'tcx>>,
|
||||
rfc1214: bool
|
||||
}
|
||||
|
||||
impl<'a,'tcx> WfPredicates<'a,'tcx> {
|
||||
fn rfc1214<R,F:FnOnce(&mut WfPredicates<'a,'tcx>) -> R>(&mut self, f: F) -> R {
|
||||
let b = mem::replace(&mut self.rfc1214, true);
|
||||
let r = f(self);
|
||||
self.rfc1214 = b;
|
||||
r
|
||||
}
|
||||
|
||||
fn cause(&mut self, code: traits::ObligationCauseCode<'tcx>) -> traits::ObligationCause<'tcx> {
|
||||
if !self.rfc1214 {
|
||||
traits::ObligationCause::new(self.span, self.body_id, code)
|
||||
} else {
|
||||
let code = traits::ObligationCauseCode::RFC1214(Rc::new(code));
|
||||
traits::ObligationCause::new(self.span, self.body_id, code)
|
||||
}
|
||||
traits::ObligationCause::new(self.span, self.body_id, code)
|
||||
}
|
||||
|
||||
fn normalize(&mut self) -> Vec<traits::PredicateObligation<'tcx>> {
|
||||
@ -268,14 +245,6 @@ impl<'a,'tcx> WfPredicates<'a,'tcx> {
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn compute_rfc1214(&mut self, ty: Ty<'tcx>) {
|
||||
let b = mem::replace(&mut self.rfc1214, true);
|
||||
for subty in ty.walk().skip(1) {
|
||||
self.compute(subty);
|
||||
}
|
||||
self.rfc1214 = b;
|
||||
}
|
||||
|
||||
/// Pushes the obligations required for `trait_ref` to be WF into
|
||||
/// `self.out`.
|
||||
fn compute_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>) {
|
||||
@ -329,21 +298,19 @@ impl<'a,'tcx> WfPredicates<'a,'tcx> {
|
||||
|
||||
ty::TySlice(subty) |
|
||||
ty::TyArray(subty, _) => {
|
||||
self.rfc1214(|this| {
|
||||
if !subty.has_escaping_regions() {
|
||||
let cause = this.cause(traits::SliceOrArrayElem);
|
||||
match traits::trait_ref_for_builtin_bound(this.infcx.tcx,
|
||||
ty::BoundSized,
|
||||
subty) {
|
||||
Ok(trait_ref) => {
|
||||
this.out.push(
|
||||
traits::Obligation::new(cause,
|
||||
trait_ref.to_predicate()));
|
||||
}
|
||||
Err(ErrorReported) => { }
|
||||
if !subty.has_escaping_regions() {
|
||||
let cause = self.cause(traits::SliceOrArrayElem);
|
||||
match traits::trait_ref_for_builtin_bound(self.infcx.tcx,
|
||||
ty::BoundSized,
|
||||
subty) {
|
||||
Ok(trait_ref) => {
|
||||
self.out.push(
|
||||
traits::Obligation::new(cause,
|
||||
trait_ref.to_predicate()));
|
||||
}
|
||||
Err(ErrorReported) => { }
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
ty::TyBox(_) |
|
||||
@ -380,15 +347,16 @@ impl<'a,'tcx> WfPredicates<'a,'tcx> {
|
||||
ty::TyClosure(..) => {
|
||||
// the types in a closure are always the types of
|
||||
// local variables (or possibly references to local
|
||||
// variables), which are separately checked w/r/t
|
||||
// WFedness.
|
||||
// variables), we'll walk those.
|
||||
//
|
||||
// (Though, local variables are probably not
|
||||
// needed, as they are separately checked w/r/t
|
||||
// WFedness.)
|
||||
}
|
||||
|
||||
ty::TyBareFn(..) => {
|
||||
// process the bound types; because the old implicator
|
||||
// did not do this, go into RFC1214 mode.
|
||||
subtys.skip_current_subtree();
|
||||
self.compute_rfc1214(ty);
|
||||
// let the loop iterator into the argument/return
|
||||
// types appearing in the fn signature
|
||||
}
|
||||
|
||||
ty::TyTrait(ref data) => {
|
||||
@ -407,11 +375,6 @@ impl<'a,'tcx> WfPredicates<'a,'tcx> {
|
||||
traits::Obligation::new(
|
||||
cause,
|
||||
ty::Predicate::ObjectSafe(data.principal_def_id())));
|
||||
|
||||
// process the bound types; because the old implicator
|
||||
// did not do this, go into RFC1214 mode.
|
||||
subtys.skip_current_subtree();
|
||||
self.compute_rfc1214(ty);
|
||||
}
|
||||
|
||||
// Inference variables are the complicated case, since we don't
|
||||
|
@ -102,13 +102,6 @@ impl Session {
|
||||
None => self.diagnostic().span_err(sp, msg)
|
||||
}
|
||||
}
|
||||
pub fn note_rfc_1214(&self, span: Span) {
|
||||
self.span_note(
|
||||
span,
|
||||
&format!("this warning results from recent bug fixes and clarifications; \
|
||||
it will become a HARD ERROR in the next release. \
|
||||
See RFC 1214 for details."));
|
||||
}
|
||||
pub fn span_err_with_code(&self, sp: Span, msg: &str, code: &str) {
|
||||
match split_msg_into_multilines(msg) {
|
||||
Some(msg) => self.diagnostic().span_err_with_code(sp, &msg[..], code),
|
||||
|
@ -1136,7 +1136,7 @@ fn make_object_type<'tcx>(this: &AstConv<'tcx>,
|
||||
traits::astconv_object_safety_violations(tcx, principal.def_id());
|
||||
if !object_safety_violations.is_empty() {
|
||||
traits::report_object_safety_error(
|
||||
tcx, span, principal.def_id(), object_safety_violations, false);
|
||||
tcx, span, principal.def_id(), object_safety_violations);
|
||||
return tcx.types.err;
|
||||
}
|
||||
|
||||
|
@ -138,7 +138,6 @@ pub mod coercion;
|
||||
pub mod demand;
|
||||
pub mod method;
|
||||
mod upvar;
|
||||
mod wf;
|
||||
mod wfcheck;
|
||||
mod cast;
|
||||
mod closure;
|
||||
@ -382,21 +381,6 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckItemBodiesVisitor<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check_wf_old(ccx: &CrateCtxt) {
|
||||
// If types are not well-formed, it leads to all manner of errors
|
||||
// downstream, so stop reporting errors at this point.
|
||||
ccx.tcx.sess.abort_if_new_errors(|| {
|
||||
// FIXME(#25759). The new code below is much more reliable but (for now)
|
||||
// only generates warnings. So as to ensure that we continue
|
||||
// getting errors where we used to get errors, we run the old wf
|
||||
// code first and abort if it encounters any errors. If no abort
|
||||
// comes, we run the new code and issue warnings.
|
||||
let krate = ccx.tcx.map.krate();
|
||||
let mut visit = wf::CheckTypeWellFormedVisitor::new(ccx);
|
||||
krate.visit_all_items(&mut visit);
|
||||
});
|
||||
}
|
||||
|
||||
pub fn check_wf_new(ccx: &CrateCtxt) {
|
||||
ccx.tcx.sess.abort_if_new_errors(|| {
|
||||
let krate = ccx.tcx.map.krate();
|
||||
|
@ -99,7 +99,6 @@ use middle::ty::adjustment;
|
||||
use middle::ty::wf::ImpliedBound;
|
||||
|
||||
use std::mem;
|
||||
use std::rc::Rc;
|
||||
use syntax::ast;
|
||||
use syntax::codemap::Span;
|
||||
use rustc_front::intravisit::{self, Visitor};
|
||||
@ -426,8 +425,6 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> {
|
||||
code: &traits::ObligationCauseCode<'tcx>)
|
||||
-> SubregionOrigin<'tcx> {
|
||||
match *code {
|
||||
traits::ObligationCauseCode::RFC1214(ref code) =>
|
||||
infer::RFC1214Subregion(Rc::new(self.code_to_origin(span, sup_type, code))),
|
||||
traits::ObligationCauseCode::ReferenceOutlivesReferent(ref_type) =>
|
||||
infer::ReferenceOutlivesReferent(ref_type, span),
|
||||
_ =>
|
||||
@ -1606,10 +1603,6 @@ fn components_must_outlive<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
|
||||
origin.span(),
|
||||
&format!("unresolved inference variable in outlives: {:?}", v));
|
||||
}
|
||||
ty::outlives::Component::RFC1214(subcomponents) => {
|
||||
let suborigin = infer::RFC1214Subregion(Rc::new(origin));
|
||||
components_must_outlive(rcx, suborigin, subcomponents, region);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,673 +0,0 @@
|
||||
// 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.
|
||||
|
||||
use astconv::AstConv;
|
||||
use check::{FnCtxt, Inherited, blank_fn_ctxt, regionck, wfcheck};
|
||||
use constrained_type_params::{identify_constrained_type_params, Parameter};
|
||||
use CrateCtxt;
|
||||
use middle::region;
|
||||
use middle::subst::{self, TypeSpace, FnSpace, ParamSpace, SelfSpace};
|
||||
use middle::traits;
|
||||
use middle::ty::{self, Ty};
|
||||
use middle::ty::fold::{TypeFolder, TypeFoldable, super_fold_ty};
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashSet;
|
||||
use syntax::ast;
|
||||
use syntax::codemap::{DUMMY_SP, Span};
|
||||
use syntax::parse::token::special_idents;
|
||||
|
||||
use rustc_front::intravisit::{self, Visitor, FnKind};
|
||||
use rustc_front::hir;
|
||||
|
||||
pub struct CheckTypeWellFormedVisitor<'ccx, 'tcx:'ccx> {
|
||||
ccx: &'ccx CrateCtxt<'ccx, 'tcx>,
|
||||
cache: HashSet<Ty<'tcx>>
|
||||
}
|
||||
|
||||
impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
|
||||
pub fn new(ccx: &'ccx CrateCtxt<'ccx, 'tcx>) -> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
|
||||
CheckTypeWellFormedVisitor { ccx: ccx, cache: HashSet::new() }
|
||||
}
|
||||
|
||||
fn tcx(&self) -> &ty::ctxt<'tcx> {
|
||||
self.ccx.tcx
|
||||
}
|
||||
|
||||
/// Checks that the field types (in a struct def'n) or argument types (in an enum def'n) are
|
||||
/// well-formed, meaning that they do not require any constraints not declared in the struct
|
||||
/// definition itself. For example, this definition would be illegal:
|
||||
///
|
||||
/// struct Ref<'a, T> { x: &'a T }
|
||||
///
|
||||
/// because the type did not declare that `T:'a`.
|
||||
///
|
||||
/// We do this check as a pre-pass before checking fn bodies because if these constraints are
|
||||
/// not included it frequently leads to confusing errors in fn bodies. So it's better to check
|
||||
/// the types first.
|
||||
fn check_item_well_formed(&mut self, item: &hir::Item) {
|
||||
let ccx = self.ccx;
|
||||
debug!("check_item_well_formed(it.id={}, it.name={})",
|
||||
item.id,
|
||||
ccx.tcx.item_path_str(ccx.tcx.map.local_def_id(item.id)));
|
||||
|
||||
match item.node {
|
||||
/// Right now we check that every default trait implementation
|
||||
/// has an implementation of itself. Basically, a case like:
|
||||
///
|
||||
/// `impl Trait for T {}`
|
||||
///
|
||||
/// has a requirement of `T: Trait` which was required for default
|
||||
/// method implementations. Although this could be improved now that
|
||||
/// there's a better infrastructure in place for this, it's being left
|
||||
/// for a follow-up work.
|
||||
///
|
||||
/// Since there's such a requirement, we need to check *just* positive
|
||||
/// implementations, otherwise things like:
|
||||
///
|
||||
/// impl !Send for T {}
|
||||
///
|
||||
/// won't be allowed unless there's an *explicit* implementation of `Send`
|
||||
/// for `T`
|
||||
hir::ItemImpl(_, hir::ImplPolarity::Positive, _, _, _, _) => {
|
||||
self.check_impl(item);
|
||||
}
|
||||
hir::ItemImpl(_, hir::ImplPolarity::Negative, _, Some(_), _, _) => {
|
||||
let item_def_id = ccx.tcx.map.local_def_id(item.id);
|
||||
let trait_ref = ccx.tcx.impl_trait_ref(item_def_id).unwrap();
|
||||
ccx.tcx.populate_implementations_for_trait_if_necessary(trait_ref.def_id);
|
||||
match ccx.tcx.lang_items.to_builtin_kind(trait_ref.def_id) {
|
||||
Some(ty::BoundSend) | Some(ty::BoundSync) => {}
|
||||
Some(_) | None => {
|
||||
if !ccx.tcx.trait_has_default_impl(trait_ref.def_id) {
|
||||
wfcheck::error_192(ccx, item.span);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
hir::ItemFn(..) => {
|
||||
self.check_item_type(item);
|
||||
}
|
||||
hir::ItemStatic(..) => {
|
||||
self.check_item_type(item);
|
||||
}
|
||||
hir::ItemConst(..) => {
|
||||
self.check_item_type(item);
|
||||
}
|
||||
hir::ItemStruct(ref struct_def, ref ast_generics) => {
|
||||
self.check_type_defn(item, |fcx| {
|
||||
vec![struct_variant(fcx, struct_def)]
|
||||
});
|
||||
|
||||
self.check_variances_for_type_defn(item, ast_generics);
|
||||
}
|
||||
hir::ItemEnum(ref enum_def, ref ast_generics) => {
|
||||
self.check_type_defn(item, |fcx| {
|
||||
enum_variants(fcx, enum_def)
|
||||
});
|
||||
|
||||
self.check_variances_for_type_defn(item, ast_generics);
|
||||
}
|
||||
hir::ItemTrait(_, _, _, ref items) => {
|
||||
let trait_predicates =
|
||||
ccx.tcx.lookup_predicates(ccx.tcx.map.local_def_id(item.id));
|
||||
reject_non_type_param_bounds(ccx.tcx, item.span, &trait_predicates);
|
||||
if ccx.tcx.trait_has_default_impl(ccx.tcx.map.local_def_id(item.id)) {
|
||||
if !items.is_empty() {
|
||||
wfcheck::error_380(ccx, item.span);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn with_fcx<F>(&mut self, item: &hir::Item, mut f: F) where
|
||||
F: for<'fcx> FnMut(&mut CheckTypeWellFormedVisitor<'ccx, 'tcx>, &FnCtxt<'fcx, 'tcx>),
|
||||
{
|
||||
let ccx = self.ccx;
|
||||
let item_def_id = ccx.tcx.map.local_def_id(item.id);
|
||||
let type_scheme = ccx.tcx.lookup_item_type(item_def_id);
|
||||
let type_predicates = ccx.tcx.lookup_predicates(item_def_id);
|
||||
reject_non_type_param_bounds(ccx.tcx, item.span, &type_predicates);
|
||||
let free_id_outlive = ccx.tcx.region_maps.item_extent(item.id);
|
||||
let param_env = ccx.tcx.construct_parameter_environment(item.span,
|
||||
&type_scheme.generics,
|
||||
&type_predicates,
|
||||
free_id_outlive);
|
||||
let tables = RefCell::new(ty::Tables::empty());
|
||||
let inh = Inherited::new(ccx.tcx, &tables, param_env);
|
||||
let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(type_scheme.ty), item.id);
|
||||
f(self, &fcx);
|
||||
fcx.select_all_obligations_or_error();
|
||||
regionck::regionck_item(&fcx, item.id, item.span, &[]);
|
||||
}
|
||||
|
||||
/// In a type definition, we check that to ensure that the types of the fields are well-formed.
|
||||
fn check_type_defn<F>(&mut self, item: &hir::Item, mut lookup_fields: F) where
|
||||
F: for<'fcx> FnMut(&FnCtxt<'fcx, 'tcx>) -> Vec<AdtVariant<'tcx>>,
|
||||
{
|
||||
self.with_fcx(item, |this, fcx| {
|
||||
let variants = lookup_fields(fcx);
|
||||
let mut bounds_checker = BoundsChecker::new(fcx,
|
||||
item.id,
|
||||
Some(&mut this.cache));
|
||||
debug!("check_type_defn at bounds_checker.scope: {:?}", bounds_checker.scope);
|
||||
|
||||
for variant in &variants {
|
||||
for field in &variant.fields {
|
||||
// Regions are checked below.
|
||||
bounds_checker.check_traits_in_ty(field.ty, field.span);
|
||||
}
|
||||
|
||||
// For DST, all intermediate types must be sized.
|
||||
if let Some((_, fields)) = variant.fields.split_last() {
|
||||
for field in fields {
|
||||
fcx.register_builtin_bound(
|
||||
field.ty,
|
||||
ty::BoundSized,
|
||||
traits::ObligationCause::new(field.span,
|
||||
fcx.body_id,
|
||||
traits::FieldSized));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for field in variants.iter().flat_map(|v| v.fields.iter()) {
|
||||
fcx.register_old_wf_obligation(field.ty, field.span, traits::MiscObligation);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn check_item_type(&mut self,
|
||||
item: &hir::Item)
|
||||
{
|
||||
self.with_fcx(item, |this, fcx| {
|
||||
let mut bounds_checker = BoundsChecker::new(fcx,
|
||||
item.id,
|
||||
Some(&mut this.cache));
|
||||
debug!("check_item_type at bounds_checker.scope: {:?}", bounds_checker.scope);
|
||||
|
||||
let item_def_id = fcx.tcx().map.local_def_id(item.id);
|
||||
let type_scheme = fcx.tcx().lookup_item_type(item_def_id);
|
||||
let item_ty = fcx.instantiate_type_scheme(item.span,
|
||||
&fcx.inh
|
||||
.infcx
|
||||
.parameter_environment
|
||||
.free_substs,
|
||||
&type_scheme.ty);
|
||||
|
||||
bounds_checker.check_traits_in_ty(item_ty, item.span);
|
||||
});
|
||||
}
|
||||
|
||||
fn check_impl(&mut self,
|
||||
item: &hir::Item)
|
||||
{
|
||||
self.with_fcx(item, |this, fcx| {
|
||||
let mut bounds_checker = BoundsChecker::new(fcx,
|
||||
item.id,
|
||||
Some(&mut this.cache));
|
||||
debug!("check_impl at bounds_checker.scope: {:?}", bounds_checker.scope);
|
||||
|
||||
// Find the impl self type as seen from the "inside" --
|
||||
// that is, with all type parameters converted from bound
|
||||
// to free.
|
||||
let self_ty = fcx.tcx().node_id_to_type(item.id);
|
||||
let self_ty = fcx.instantiate_type_scheme(item.span,
|
||||
&fcx.inh
|
||||
.infcx
|
||||
.parameter_environment
|
||||
.free_substs,
|
||||
&self_ty);
|
||||
|
||||
bounds_checker.check_traits_in_ty(self_ty, item.span);
|
||||
|
||||
// Similarly, obtain an "inside" reference to the trait
|
||||
// that the impl implements.
|
||||
let trait_ref = match fcx.tcx().impl_trait_ref(fcx.tcx().map.local_def_id(item.id)) {
|
||||
None => { return; }
|
||||
Some(t) => { t }
|
||||
};
|
||||
|
||||
let trait_ref = fcx.instantiate_type_scheme(item.span,
|
||||
&fcx.inh
|
||||
.infcx
|
||||
.parameter_environment
|
||||
.free_substs,
|
||||
&trait_ref);
|
||||
|
||||
// We are stricter on the trait-ref in an impl than the
|
||||
// self-type. In particular, we enforce region
|
||||
// relationships. The reason for this is that (at least
|
||||
// presently) "applying" an impl does not require that the
|
||||
// application site check the well-formedness constraints on the
|
||||
// trait reference. Instead, this is done at the impl site.
|
||||
// Arguably this is wrong and we should treat the trait-reference
|
||||
// the same way as we treat the self-type.
|
||||
bounds_checker.check_trait_ref(&trait_ref, item.span);
|
||||
|
||||
let cause =
|
||||
traits::ObligationCause::new(
|
||||
item.span,
|
||||
fcx.body_id,
|
||||
traits::ItemObligation(trait_ref.def_id));
|
||||
|
||||
// Find the supertrait bounds. This will add `int:Bar`.
|
||||
let poly_trait_ref = ty::Binder(trait_ref);
|
||||
let predicates = fcx.tcx().lookup_super_predicates(poly_trait_ref.def_id());
|
||||
let predicates = predicates.instantiate_supertrait(fcx.tcx(), &poly_trait_ref);
|
||||
let predicates = {
|
||||
let selcx = &mut traits::SelectionContext::new(fcx.infcx());
|
||||
traits::normalize(selcx, cause.clone(), &predicates)
|
||||
};
|
||||
for predicate in predicates.value.predicates {
|
||||
fcx.register_predicate(traits::Obligation::new(cause.clone(), predicate));
|
||||
}
|
||||
for obligation in predicates.obligations {
|
||||
fcx.register_predicate(obligation);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn check_variances_for_type_defn(&self,
|
||||
item: &hir::Item,
|
||||
ast_generics: &hir::Generics)
|
||||
{
|
||||
let item_def_id = self.tcx().map.local_def_id(item.id);
|
||||
let ty_predicates = self.tcx().lookup_predicates(item_def_id);
|
||||
let variances = self.tcx().item_variances(item_def_id);
|
||||
|
||||
let mut constrained_parameters: HashSet<_> =
|
||||
variances.types
|
||||
.iter_enumerated()
|
||||
.filter(|&(_, _, &variance)| variance != ty::Bivariant)
|
||||
.map(|(space, index, _)| self.param_ty(ast_generics, space, index))
|
||||
.map(|p| Parameter::Type(p))
|
||||
.collect();
|
||||
|
||||
identify_constrained_type_params(self.tcx(),
|
||||
ty_predicates.predicates.as_slice(),
|
||||
None,
|
||||
&mut constrained_parameters);
|
||||
|
||||
for (space, index, _) in variances.types.iter_enumerated() {
|
||||
let param_ty = self.param_ty(ast_generics, space, index);
|
||||
if constrained_parameters.contains(&Parameter::Type(param_ty)) {
|
||||
continue;
|
||||
}
|
||||
let span = self.ty_param_span(ast_generics, item, space, index);
|
||||
self.report_bivariance(span, param_ty.name);
|
||||
}
|
||||
|
||||
for (space, index, &variance) in variances.regions.iter_enumerated() {
|
||||
if variance != ty::Bivariant {
|
||||
continue;
|
||||
}
|
||||
|
||||
assert_eq!(space, TypeSpace);
|
||||
let span = ast_generics.lifetimes[index].lifetime.span;
|
||||
let name = ast_generics.lifetimes[index].lifetime.name;
|
||||
self.report_bivariance(span, name);
|
||||
}
|
||||
}
|
||||
|
||||
fn param_ty(&self,
|
||||
ast_generics: &hir::Generics,
|
||||
space: ParamSpace,
|
||||
index: usize)
|
||||
-> ty::ParamTy
|
||||
{
|
||||
let name = match space {
|
||||
TypeSpace => ast_generics.ty_params[index].name,
|
||||
SelfSpace => special_idents::type_self.name,
|
||||
FnSpace => self.tcx().sess.bug("Fn space occupied?"),
|
||||
};
|
||||
|
||||
ty::ParamTy { space: space, idx: index as u32, name: name }
|
||||
}
|
||||
|
||||
fn ty_param_span(&self,
|
||||
ast_generics: &hir::Generics,
|
||||
item: &hir::Item,
|
||||
space: ParamSpace,
|
||||
index: usize)
|
||||
-> Span
|
||||
{
|
||||
match space {
|
||||
TypeSpace => ast_generics.ty_params[index].span,
|
||||
SelfSpace => item.span,
|
||||
FnSpace => self.tcx().sess.span_bug(item.span, "Fn space occupied?"),
|
||||
}
|
||||
}
|
||||
|
||||
fn report_bivariance(&self,
|
||||
span: Span,
|
||||
param_name: ast::Name)
|
||||
{
|
||||
wfcheck::error_392(self.tcx(), span, param_name);
|
||||
|
||||
let suggested_marker_id = self.tcx().lang_items.phantom_data();
|
||||
match suggested_marker_id {
|
||||
Some(def_id) => {
|
||||
self.tcx().sess.fileline_help(
|
||||
span,
|
||||
&format!("consider removing `{}` or using a marker such as `{}`",
|
||||
param_name,
|
||||
self.tcx().item_path_str(def_id)));
|
||||
}
|
||||
None => {
|
||||
// no lang items, no help!
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Reject any predicates that do not involve a type parameter.
|
||||
fn reject_non_type_param_bounds<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||
span: Span,
|
||||
predicates: &ty::GenericPredicates<'tcx>) {
|
||||
for predicate in &predicates.predicates {
|
||||
match predicate {
|
||||
&ty::Predicate::Trait(ty::Binder(ref tr)) => {
|
||||
let found_param = tr.input_types().iter()
|
||||
.flat_map(|ty| ty.walk())
|
||||
.any(is_ty_param);
|
||||
if !found_param { report_bound_error(tcx, span, tr.self_ty() )}
|
||||
}
|
||||
&ty::Predicate::TypeOutlives(ty::Binder(ty::OutlivesPredicate(ty, _))) => {
|
||||
let found_param = ty.walk().any(|t| is_ty_param(t));
|
||||
if !found_param { report_bound_error(tcx, span, ty) }
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
|
||||
fn report_bound_error<'t>(tcx: &ty::ctxt<'t>,
|
||||
span: Span,
|
||||
bounded_ty: ty::Ty<'t>) {
|
||||
span_err!(tcx.sess, span, E0193,
|
||||
"cannot bound type `{}`, where clause \
|
||||
bounds may only be attached to types involving \
|
||||
type parameters",
|
||||
bounded_ty)
|
||||
}
|
||||
|
||||
fn is_ty_param(ty: ty::Ty) -> bool {
|
||||
match &ty.sty {
|
||||
&ty::TyParam(_) => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn reject_shadowing_type_parameters<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||
span: Span,
|
||||
generics: &ty::Generics<'tcx>) {
|
||||
let impl_params = generics.types.get_slice(subst::TypeSpace).iter()
|
||||
.map(|tp| tp.name).collect::<HashSet<_>>();
|
||||
|
||||
for method_param in generics.types.get_slice(subst::FnSpace) {
|
||||
if impl_params.contains(&method_param.name) {
|
||||
wfcheck::error_194(tcx, span, method_param.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ccx, 'tcx, 'v> Visitor<'v> for CheckTypeWellFormedVisitor<'ccx, 'tcx> {
|
||||
fn visit_item(&mut self, i: &hir::Item) {
|
||||
self.check_item_well_formed(i);
|
||||
intravisit::walk_item(self, i);
|
||||
}
|
||||
|
||||
fn visit_fn(&mut self,
|
||||
fk: FnKind<'v>, fd: &'v hir::FnDecl,
|
||||
b: &'v hir::Block, span: Span, id: ast::NodeId) {
|
||||
match fk {
|
||||
FnKind::Closure | FnKind::ItemFn(..) => {}
|
||||
FnKind::Method(..) => {
|
||||
match self.tcx().impl_or_trait_item(self.tcx().map.local_def_id(id)) {
|
||||
ty::ImplOrTraitItem::MethodTraitItem(ty_method) => {
|
||||
reject_shadowing_type_parameters(self.tcx(), span, &ty_method.generics)
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
intravisit::walk_fn(self, fk, fd, b, span)
|
||||
}
|
||||
|
||||
fn visit_trait_item(&mut self, trait_item: &'v hir::TraitItem) {
|
||||
if let hir::MethodTraitItem(_, None) = trait_item.node {
|
||||
match self.tcx().impl_or_trait_item(self.tcx().map.local_def_id(trait_item.id)) {
|
||||
ty::ImplOrTraitItem::MethodTraitItem(ty_method) => {
|
||||
reject_non_type_param_bounds(
|
||||
self.tcx(),
|
||||
trait_item.span,
|
||||
&ty_method.predicates);
|
||||
reject_shadowing_type_parameters(
|
||||
self.tcx(),
|
||||
trait_item.span,
|
||||
&ty_method.generics);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
intravisit::walk_trait_item(self, trait_item)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BoundsChecker<'cx,'tcx:'cx> {
|
||||
fcx: &'cx FnCtxt<'cx,'tcx>,
|
||||
span: Span,
|
||||
|
||||
scope: region::CodeExtent,
|
||||
|
||||
binding_count: usize,
|
||||
cache: Option<&'cx mut HashSet<Ty<'tcx>>>,
|
||||
}
|
||||
|
||||
impl<'cx,'tcx> BoundsChecker<'cx,'tcx> {
|
||||
pub fn new(fcx: &'cx FnCtxt<'cx,'tcx>,
|
||||
scope: ast::NodeId,
|
||||
cache: Option<&'cx mut HashSet<Ty<'tcx>>>)
|
||||
-> BoundsChecker<'cx,'tcx> {
|
||||
let scope = fcx.tcx().region_maps.item_extent(scope);
|
||||
BoundsChecker { fcx: fcx, span: DUMMY_SP, scope: scope,
|
||||
cache: cache, binding_count: 0 }
|
||||
}
|
||||
|
||||
/// Given a trait ref like `A : Trait<B>`, where `Trait` is defined as (say):
|
||||
///
|
||||
/// trait Trait<B:OtherTrait> : Copy { ... }
|
||||
///
|
||||
/// This routine will check that `B : OtherTrait` and `A : Trait<B>`. It will also recursively
|
||||
/// check that the types `A` and `B` are well-formed.
|
||||
///
|
||||
/// Note that it does not (currently, at least) check that `A : Copy` (that check is delegated
|
||||
/// to the point where impl `A : Trait<B>` is implemented).
|
||||
pub fn check_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>, span: Span) {
|
||||
let trait_predicates = self.fcx.tcx().lookup_predicates(trait_ref.def_id);
|
||||
|
||||
let bounds = self.fcx.instantiate_bounds(span,
|
||||
trait_ref.substs,
|
||||
&trait_predicates);
|
||||
|
||||
self.fcx.add_obligations_for_parameters(
|
||||
traits::ObligationCause::new(
|
||||
span,
|
||||
self.fcx.body_id,
|
||||
traits::ItemObligation(trait_ref.def_id)),
|
||||
&bounds);
|
||||
|
||||
for &ty in &trait_ref.substs.types {
|
||||
self.check_traits_in_ty(ty, span);
|
||||
}
|
||||
}
|
||||
|
||||
fn check_traits_in_ty(&mut self, ty: Ty<'tcx>, span: Span) {
|
||||
self.span = span;
|
||||
// When checking types outside of a type def'n, we ignore
|
||||
// region obligations. See discussion below in fold_ty().
|
||||
self.binding_count += 1;
|
||||
ty.fold_with(self);
|
||||
self.binding_count -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
impl<'cx,'tcx> TypeFolder<'tcx> for BoundsChecker<'cx,'tcx> {
|
||||
fn tcx(&self) -> &ty::ctxt<'tcx> {
|
||||
self.fcx.tcx()
|
||||
}
|
||||
|
||||
fn fold_binder<T>(&mut self, binder: &ty::Binder<T>) -> ty::Binder<T>
|
||||
where T : TypeFoldable<'tcx>
|
||||
{
|
||||
self.binding_count += 1;
|
||||
let value = self.fcx.tcx().liberate_late_bound_regions(
|
||||
self.scope,
|
||||
binder);
|
||||
debug!("BoundsChecker::fold_binder: late-bound regions replaced: {:?} at scope: {:?}",
|
||||
value, self.scope);
|
||||
let value = value.fold_with(self);
|
||||
self.binding_count -= 1;
|
||||
ty::Binder(value)
|
||||
}
|
||||
|
||||
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
|
||||
debug!("BoundsChecker t={:?}",
|
||||
t);
|
||||
|
||||
match self.cache {
|
||||
Some(ref mut cache) => {
|
||||
if !cache.insert(t) {
|
||||
// Already checked this type! Don't check again.
|
||||
debug!("cached");
|
||||
return t;
|
||||
}
|
||||
}
|
||||
None => { }
|
||||
}
|
||||
|
||||
match t.sty{
|
||||
ty::TyStruct(def, substs) |
|
||||
ty::TyEnum(def, substs) => {
|
||||
let type_predicates = def.predicates(self.fcx.tcx());
|
||||
let bounds = self.fcx.instantiate_bounds(self.span, substs,
|
||||
&type_predicates);
|
||||
|
||||
if self.binding_count == 0 {
|
||||
self.fcx.add_obligations_for_parameters(
|
||||
traits::ObligationCause::new(self.span,
|
||||
self.fcx.body_id,
|
||||
traits::ItemObligation(def.did)),
|
||||
&bounds);
|
||||
} else {
|
||||
// There are two circumstances in which we ignore
|
||||
// region obligations.
|
||||
//
|
||||
// The first is when we are inside of a closure
|
||||
// type. This is because in that case the region
|
||||
// obligations for the parameter types are things
|
||||
// that the closure body gets to assume and the
|
||||
// caller must prove at the time of call. In other
|
||||
// words, if there is a type like `<'a, 'b> | &'a
|
||||
// &'b int |`, it is well-formed, and caller will
|
||||
// have to show that `'b : 'a` at the time of
|
||||
// call.
|
||||
//
|
||||
// The second is when we are checking for
|
||||
// well-formedness outside of a type def'n or fn
|
||||
// body. This is for a similar reason: in general,
|
||||
// we only do WF checking for regions in the
|
||||
// result of expressions and type definitions, so
|
||||
// to as allow for implicit where clauses.
|
||||
//
|
||||
// (I believe we should do the same for traits, but
|
||||
// that will require an RFC. -nmatsakis)
|
||||
let bounds = filter_to_trait_obligations(bounds);
|
||||
self.fcx.add_obligations_for_parameters(
|
||||
traits::ObligationCause::new(self.span,
|
||||
self.fcx.body_id,
|
||||
traits::ItemObligation(def.did)),
|
||||
&bounds);
|
||||
}
|
||||
|
||||
self.fold_substs(substs);
|
||||
}
|
||||
_ => {
|
||||
super_fold_ty(self, t);
|
||||
}
|
||||
}
|
||||
|
||||
t // we're not folding to produce a new type, so just return `t` here
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// ADT
|
||||
|
||||
struct AdtVariant<'tcx> {
|
||||
fields: Vec<AdtField<'tcx>>,
|
||||
}
|
||||
|
||||
struct AdtField<'tcx> {
|
||||
ty: Ty<'tcx>,
|
||||
span: Span,
|
||||
}
|
||||
|
||||
fn struct_variant<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
struct_def: &hir::VariantData)
|
||||
-> AdtVariant<'tcx> {
|
||||
let fields =
|
||||
struct_def.fields().iter()
|
||||
.map(|field| {
|
||||
let field_ty = fcx.tcx().node_id_to_type(field.node.id);
|
||||
let field_ty = fcx.instantiate_type_scheme(field.span,
|
||||
&fcx.inh
|
||||
.infcx
|
||||
.parameter_environment
|
||||
.free_substs,
|
||||
&field_ty);
|
||||
AdtField { ty: field_ty, span: field.span }
|
||||
})
|
||||
.collect();
|
||||
AdtVariant { fields: fields }
|
||||
}
|
||||
|
||||
fn enum_variants<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
enum_def: &hir::EnumDef)
|
||||
-> Vec<AdtVariant<'tcx>> {
|
||||
enum_def.variants.iter()
|
||||
.map(|variant| struct_variant(fcx, &variant.node.data))
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn filter_to_trait_obligations<'tcx>(bounds: ty::InstantiatedPredicates<'tcx>)
|
||||
-> ty::InstantiatedPredicates<'tcx>
|
||||
{
|
||||
let mut result = ty::InstantiatedPredicates::empty();
|
||||
for (space, _, predicate) in bounds.predicates.iter_enumerated() {
|
||||
match *predicate {
|
||||
ty::Predicate::Trait(..) |
|
||||
ty::Predicate::Projection(..) => {
|
||||
result.predicates.push(space, predicate.clone())
|
||||
}
|
||||
ty::Predicate::WellFormed(..) |
|
||||
ty::Predicate::ObjectSafe(..) |
|
||||
ty::Predicate::Equate(..) |
|
||||
ty::Predicate::TypeOutlives(..) |
|
||||
ty::Predicate::RegionOutlives(..) => {
|
||||
}
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
@ -21,7 +21,6 @@ use middle::ty::fold::{TypeFolder};
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashSet;
|
||||
use std::rc::Rc;
|
||||
use syntax::ast;
|
||||
use syntax::codemap::{Span};
|
||||
use syntax::parse::token::{special_idents};
|
||||
@ -38,8 +37,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
|
||||
-> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
|
||||
CheckTypeWellFormedVisitor {
|
||||
ccx: ccx,
|
||||
code: traits::ObligationCauseCode::RFC1214(
|
||||
Rc::new(traits::ObligationCauseCode::MiscObligation))
|
||||
code: traits::ObligationCauseCode::MiscObligation
|
||||
}
|
||||
}
|
||||
|
||||
@ -311,8 +309,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
|
||||
ty::wf::trait_obligations(fcx.infcx(),
|
||||
fcx.body_id,
|
||||
&trait_ref,
|
||||
ast_trait_ref.path.span,
|
||||
true);
|
||||
ast_trait_ref.path.span);
|
||||
for obligation in obligations {
|
||||
fcx.register_predicate(obligation);
|
||||
}
|
||||
@ -343,8 +340,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
|
||||
.flat_map(|p| ty::wf::predicate_obligations(fcx.infcx(),
|
||||
fcx.body_id,
|
||||
p,
|
||||
span,
|
||||
true));
|
||||
span));
|
||||
|
||||
for obligation in obligations {
|
||||
fcx.register_predicate(obligation);
|
||||
|
@ -190,7 +190,7 @@ impl<'cx, 'tcx,'v> intravisit::Visitor<'v> for OverlapChecker<'cx, 'tcx> {
|
||||
None => { }
|
||||
}
|
||||
}
|
||||
hir::ItemImpl(_, _, _, Some(_), ref self_ty, _) => {
|
||||
hir::ItemImpl(_, _, _, Some(_), _, _) => {
|
||||
let impl_def_id = self.tcx.map.local_def_id(item.id);
|
||||
let trait_ref = self.tcx.impl_trait_ref(impl_def_id).unwrap();
|
||||
let trait_def_id = trait_ref.def_id;
|
||||
@ -200,16 +200,10 @@ impl<'cx, 'tcx,'v> intravisit::Visitor<'v> for OverlapChecker<'cx, 'tcx> {
|
||||
// if Trait1 is a supertrait of Trait2 or Trait2 is not object safe.
|
||||
|
||||
if !traits::is_object_safe(self.tcx, data.principal_def_id()) {
|
||||
// FIXME(#27579). This just means the
|
||||
// self-ty is illegal; WF will report this
|
||||
// error. But it will do so as a warning
|
||||
// for a release or two. For backwards
|
||||
// compat reasons, then, we continue to
|
||||
// report it here so that things which
|
||||
// were errors remain errors.
|
||||
span_err!(self.tcx.sess, self_ty.span, E0372,
|
||||
"the trait `{}` cannot be made into an object",
|
||||
self.tcx.item_path_str(data.principal_def_id()));
|
||||
// This is an error, but it will be
|
||||
// reported by wfcheck. Ignore it
|
||||
// here. This is tested by
|
||||
// `coherence-impl-trait-for-trait-object-safe.rs`.
|
||||
} else {
|
||||
let mut supertrait_def_ids =
|
||||
traits::supertrait_def_ids(self.tcx, data.principal_def_id());
|
||||
|
@ -3114,14 +3114,6 @@ impl Baz for Bar { } // Note: This is OK
|
||||
```
|
||||
"##,
|
||||
|
||||
E0372: r##"
|
||||
Trying to implement a trait for a trait object (as in `impl Trait1 for
|
||||
Trait2 { ... }`) does not work if the trait is not object-safe. Please see the
|
||||
[RFC 255] for more details on object safety rules.
|
||||
|
||||
[RFC 255]: https://github.com/rust-lang/rfcs/pull/255
|
||||
"##,
|
||||
|
||||
E0379: r##"
|
||||
Trait methods cannot be declared `const` by design. For more information, see
|
||||
[RFC 911].
|
||||
@ -3486,6 +3478,7 @@ register_diagnostics! {
|
||||
// E0319, // trait impls for defaulted traits allowed just for structs/enums
|
||||
E0320, // recursive overflow during dropck
|
||||
E0328, // cannot implement Unsize explicitly
|
||||
// E0372, // coherence not object safe
|
||||
E0374, // the trait `CoerceUnsized` may only be implemented for a coercion
|
||||
// between structures with one field being coerced, none found
|
||||
E0375, // the trait `CoerceUnsized` may only be implemented for a coercion
|
||||
|
@ -346,8 +346,8 @@ pub fn check_crate(tcx: &ty::ctxt, trait_map: ty::TraitMap) {
|
||||
coherence::check_coherence(&ccx));
|
||||
});
|
||||
|
||||
time(time_passes, "wf checking (old)", ||
|
||||
check::check_wf_old(&ccx));
|
||||
time(time_passes, "wf checking", ||
|
||||
check::check_wf_new(&ccx));
|
||||
|
||||
time(time_passes, "item-types checking", ||
|
||||
check::check_item_types(&ccx));
|
||||
@ -358,11 +358,6 @@ pub fn check_crate(tcx: &ty::ctxt, trait_map: ty::TraitMap) {
|
||||
time(time_passes, "drop-impl checking", ||
|
||||
check::check_drop_impls(&ccx));
|
||||
|
||||
// Do this last so that if there are errors in the old code, they
|
||||
// get reported, and we don't get extra warnings.
|
||||
time(time_passes, "wf checking (new)", ||
|
||||
check::check_wf_new(&ccx));
|
||||
|
||||
check_for_entry_fn(&ccx);
|
||||
tcx.sess.abort_if_errors();
|
||||
}
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
#![crate_type="lib"]
|
||||
|
||||
pub trait Bar {
|
||||
pub trait Bar: Sized {
|
||||
type T;
|
||||
|
||||
fn get(x: Option<Self>) -> <Self as Bar>::T;
|
||||
|
@ -11,7 +11,7 @@
|
||||
#![crate_name="static_methods_crate"]
|
||||
#![crate_type = "lib"]
|
||||
|
||||
pub trait read {
|
||||
pub trait read: Sized {
|
||||
fn readMaybe(s: String) -> Option<Self>;
|
||||
}
|
||||
|
||||
|
@ -25,10 +25,7 @@ trait Get {
|
||||
|
||||
trait Other {
|
||||
fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
|
||||
// (note that we no longer catch the error here, since the
|
||||
// error below aborts compilation.
|
||||
// See also associated-types-no-suitable-supertrait-2.rs
|
||||
// which checks that this error would be caught eventually.)
|
||||
//~^ ERROR the trait `Get` is not implemented for the type `Self`
|
||||
}
|
||||
|
||||
impl<T:Get> Other for T {
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
use std::sync::mpsc::{channel, Sender};
|
||||
|
||||
trait Foo : Sync+'static {
|
||||
trait Foo : Sized+Sync+'static {
|
||||
fn foo(self, mut chan: Sender<Self>) { }
|
||||
}
|
||||
|
||||
|
@ -13,9 +13,7 @@
|
||||
|
||||
// If the trait is not object-safe, we give a more tailored message
|
||||
// because we're such schnuckels:
|
||||
trait NotObjectSafe { fn eq(&self, other: &Self); }
|
||||
impl NotObjectSafe for NotObjectSafe { //~ ERROR E0372
|
||||
fn eq(&self, other: &Self) { panic!(); }
|
||||
}
|
||||
trait NotObjectSafe { fn eq(&self, other: Self); }
|
||||
impl NotObjectSafe for NotObjectSafe { } //~ ERROR E0038
|
||||
|
||||
fn main() { }
|
||||
|
@ -21,14 +21,15 @@ trait Foo<X,Y>: Bar<X> {
|
||||
|
||||
trait Bar<X> { }
|
||||
|
||||
fn vacuous<A>()
|
||||
// We don't always check where clauses for sanity, but in this case
|
||||
// wfcheck does report an error here:
|
||||
fn vacuous<A>() //~ ERROR the trait `Bar<u32>` is not implemented for the type `i32`
|
||||
where i32: Foo<u32, A>
|
||||
{
|
||||
// vacuous could never be called, because it requires that i32:
|
||||
// Bar<u32>. But the code doesn't check that this could never be
|
||||
// satisfied.
|
||||
// ... the original intention was to check that we don't use that
|
||||
// vacuous where clause (which could never be satisfied) to accept
|
||||
// the following line and then mess up calls elsewhere.
|
||||
require::<i32, u32>();
|
||||
//~^ ERROR the trait `Bar<u32>` is not implemented for the type `i32`
|
||||
}
|
||||
|
||||
fn require<A,B>()
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
trait FromStructReader<'a> { }
|
||||
trait ResponseHook {
|
||||
fn get<'a, T: FromStructReader<'a>>(&'a self);
|
||||
fn get(&self);
|
||||
}
|
||||
fn foo(res : Box<ResponseHook>) { res.get } //~ ERROR attempted to take value of method
|
||||
fn main() {}
|
||||
|
@ -13,11 +13,14 @@ trait Node {
|
||||
}
|
||||
|
||||
trait Graph<N: Node> {
|
||||
fn nodes<'a, I: Iterator<Item=&'a N>>(&'a self) -> I;
|
||||
fn nodes<'a, I: Iterator<Item=&'a N>>(&'a self) -> I
|
||||
where N: 'a;
|
||||
}
|
||||
|
||||
impl<N: Node> Graph<N> for Vec<N> {
|
||||
fn nodes<'a, I: Iterator<Item=&'a N>>(&self) -> I {
|
||||
fn nodes<'a, I: Iterator<Item=&'a N>>(&self) -> I
|
||||
where N: 'a
|
||||
{
|
||||
self.iter() //~ ERROR mismatched types
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ use std::fmt::Debug;
|
||||
|
||||
trait Str {}
|
||||
|
||||
trait Something {
|
||||
trait Something: Sized {
|
||||
fn yay<T: Debug>(_: Option<Self>, thing: &[T]);
|
||||
}
|
||||
|
||||
|
@ -19,14 +19,12 @@ impl Foo for Thing {
|
||||
|
||||
#[inline(never)]
|
||||
fn foo(b: &Bar) {
|
||||
//~^ ERROR E0038
|
||||
b.foo(&0)
|
||||
//~^ ERROR the trait `Foo` is not implemented for the type `Bar`
|
||||
//~| ERROR E0038
|
||||
//~| WARNING E0038
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut thing = Thing;
|
||||
let test: &Bar = &mut thing; //~ ERROR E0038
|
||||
let test: &Bar = &mut thing;
|
||||
foo(test);
|
||||
}
|
||||
|
@ -19,10 +19,10 @@ impl Qiz for Foo {
|
||||
|
||||
struct Bar {
|
||||
foos: &'static [&'static (Qiz + 'static)]
|
||||
//~^ ERROR E0038
|
||||
}
|
||||
|
||||
const FOO : Foo = Foo;
|
||||
const BAR : Bar = Bar { foos: &[&FOO]};
|
||||
//~^ ERROR E0038
|
||||
|
||||
fn main() { }
|
||||
|
@ -15,13 +15,10 @@ trait From<Src> {
|
||||
}
|
||||
|
||||
trait To {
|
||||
fn to<Dst>(
|
||||
self //~ error: the trait `core::marker::Sized` is not implemented
|
||||
fn to<Dst>( //~ ERROR the trait `core::marker::Sized` is not implemented
|
||||
self
|
||||
) -> <Dst as From<Self>>::Result where Dst: From<Self> {
|
||||
From::from( //~ error: the trait `core::marker::Sized` is not implemented
|
||||
//~^ ERROR E0277
|
||||
self
|
||||
)
|
||||
From::from(self)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -38,6 +38,8 @@ impl<'a> Publisher<'a> for MyStruct<'a> {
|
||||
fn subscribe(&mut self, t : Box<Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
|
||||
// Not obvious, but there is an implicit lifetime here -------^
|
||||
//~^^ ERROR cannot infer
|
||||
//~| ERROR cannot infer
|
||||
//~| ERROR cannot infer
|
||||
//
|
||||
// The fact that `Publisher` is using an implicit lifetime is
|
||||
// what was causing the debruijn accounting to be off, so
|
||||
|
@ -17,11 +17,11 @@ trait Foo {
|
||||
fn foo(self);
|
||||
}
|
||||
|
||||
fn foo<'a,'b,T>(x: &'a T, y: &'b T)
|
||||
fn foo<'a,'b,T>(x: &'a T, y: &'b T) //~ ERROR type annotations required
|
||||
where &'a T : Foo,
|
||||
&'b T : Foo
|
||||
{
|
||||
x.foo(); //~ ERROR type annotations required
|
||||
x.foo();
|
||||
y.foo();
|
||||
}
|
||||
|
||||
|
@ -13,5 +13,5 @@ fn main()
|
||||
{
|
||||
fn bar(x:i32) ->i32 { 3*x };
|
||||
let b:Box<Any> = Box::new(bar as fn(_)->_);
|
||||
b.downcast_ref::<fn(_)->_>(); //~ ERROR E0101
|
||||
b.downcast_ref::<fn(_)->_>(); //~ ERROR E0282
|
||||
}
|
||||
|
@ -13,6 +13,6 @@ pub trait ToNbt<T> {
|
||||
}
|
||||
|
||||
impl ToNbt<Self> {} //~ ERROR use of `Self` outside of an impl or trait
|
||||
//~^ WARNING the trait `ToNbt` cannot be made into an object
|
||||
//~^ ERROR the trait `ToNbt` cannot be made into an object
|
||||
|
||||
fn main() {}
|
||||
|
@ -18,6 +18,6 @@ struct S {
|
||||
}
|
||||
|
||||
fn bar(_x: Foo) {}
|
||||
//~^ ERROR E0277
|
||||
//~^ ERROR E0038
|
||||
|
||||
fn main() {}
|
||||
|
@ -22,16 +22,13 @@ trait Quux {
|
||||
}
|
||||
|
||||
fn make_bar<T:Bar>(t: &T) -> &Bar {
|
||||
t
|
||||
//~^ ERROR E0038
|
||||
//~| NOTE method `bar` has generic type parameters
|
||||
t
|
||||
}
|
||||
|
||||
fn make_bar_explicit<T:Bar>(t: &T) -> &Bar {
|
||||
t as &Bar
|
||||
//~^ ERROR E0038
|
||||
//~| NOTE method `bar` has generic type parameters
|
||||
//~| ERROR E0038
|
||||
}
|
||||
|
||||
fn make_quux<T:Quux>(t: &T) -> &Quux {
|
||||
|
@ -25,29 +25,15 @@ trait Quux {
|
||||
}
|
||||
|
||||
fn make_bar<T:Bar>(t: &T) -> &Bar {
|
||||
t
|
||||
//~^ ERROR E0038
|
||||
//~| NOTE method `bar` references the `Self` type in its arguments or return type
|
||||
}
|
||||
|
||||
fn make_bar_explicit<T:Bar>(t: &T) -> &Bar {
|
||||
t as &Bar
|
||||
//~^ ERROR E0038
|
||||
//~| NOTE method `bar` references the `Self` type in its arguments or return type
|
||||
//~| ERROR E0038
|
||||
loop { }
|
||||
}
|
||||
|
||||
fn make_baz<T:Baz>(t: &T) -> &Baz {
|
||||
//~^ ERROR E0038
|
||||
//~| NOTE method `bar` references the `Self` type in its arguments or return type
|
||||
t
|
||||
//~^ ERROR E0038
|
||||
//~| NOTE method `bar` references the `Self` type in its arguments or return type
|
||||
}
|
||||
|
||||
fn make_baz_explicit<T:Baz>(t: &T) -> &Baz {
|
||||
t as &Baz
|
||||
//~^ ERROR E0038
|
||||
//~| NOTE method `bar` references the `Self` type in its arguments or return type
|
||||
//~| ERROR E0038
|
||||
}
|
||||
|
||||
fn make_quux<T:Quux>(t: &T) -> &Quux {
|
||||
|
@ -16,16 +16,8 @@ trait Foo {
|
||||
}
|
||||
|
||||
fn foo_implicit<T:Foo+'static>(b: Box<T>) -> Box<Foo+'static> {
|
||||
b
|
||||
//~^ ERROR E0038
|
||||
//~| NOTE method `foo` has no receiver
|
||||
}
|
||||
|
||||
fn foo_explicit<T:Foo+'static>(b: Box<T>) -> Box<Foo+'static> {
|
||||
b as Box<Foo>
|
||||
//~^ ERROR E0038
|
||||
//~| NOTE method `foo` has no receiver
|
||||
//~| ERROR E0038
|
||||
//~^ ERROR E0038
|
||||
loop { }
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
@ -18,16 +18,8 @@ trait Bar
|
||||
}
|
||||
|
||||
fn make_bar<T:Bar>(t: &T) -> &Bar {
|
||||
t
|
||||
//~^ ERROR E0038
|
||||
//~| NOTE the trait cannot require that `Self : Sized`
|
||||
}
|
||||
|
||||
fn make_bar_explicit<T:Bar>(t: &T) -> &Bar {
|
||||
t as &Bar
|
||||
//~^ ERROR E0038
|
||||
//~| NOTE the trait cannot require that `Self : Sized`
|
||||
//~| ERROR E0038
|
||||
loop { }
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
@ -16,16 +16,9 @@ trait Bar : Sized {
|
||||
}
|
||||
|
||||
fn make_bar<T:Bar>(t: &T) -> &Bar {
|
||||
//~^ ERROR E0038
|
||||
//~| NOTE the trait cannot require that `Self : Sized`
|
||||
t
|
||||
//~^ ERROR E0038
|
||||
//~| NOTE the trait cannot require that `Self : Sized`
|
||||
}
|
||||
|
||||
fn make_bar_explicit<T:Bar>(t: &T) -> &Bar {
|
||||
t as &Bar
|
||||
//~^ ERROR E0038
|
||||
//~| NOTE the trait cannot require that `Self : Sized`
|
||||
//~| ERROR E0038
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
@ -26,10 +26,10 @@ fn f<'a, T, U>(v: Box<A<T>+'static>) -> Box<X+'static> {
|
||||
// oh dear!
|
||||
box B(&*v) as Box<X>
|
||||
//~^ ERROR the parameter type `T` may not live long enough
|
||||
//~| WARNING the parameter type `T` may not live long enough
|
||||
//~| WARNING the parameter type `T` may not live long enough
|
||||
//~| ERROR the parameter type `T` may not live long enough
|
||||
//~| WARNING the parameter type `T` may not live long enough
|
||||
//~| ERROR the parameter type `T` may not live long enough
|
||||
//~| ERROR the parameter type `T` may not live long enough
|
||||
//~| ERROR the parameter type `T` may not live long enough
|
||||
//~| ERROR the parameter type `T` may not live long enough
|
||||
//~| ERROR the parameter type `T` may not live long enough
|
||||
}
|
||||
|
@ -0,0 +1,21 @@
|
||||
// Copyright 2012 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.
|
||||
|
||||
// Tests that callees correctly infer an ordering between free regions
|
||||
// that appear in their parameter list. See also
|
||||
// regions-free-region-ordering-caller.rs
|
||||
|
||||
fn ordering4<'a, 'b, F>(a: &'a usize, b: &'b usize, x: F) where F: FnOnce(&'a &'b usize) {
|
||||
//~^ ERROR reference has a longer lifetime than the data it references
|
||||
// Do not infer ordering from closure argument types.
|
||||
let z: Option<&'a &'b usize> = None;
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -30,11 +30,7 @@ fn ordering3<'a, 'b>(x: &'a usize, y: &'b usize) -> &'a &'b usize {
|
||||
panic!();
|
||||
}
|
||||
|
||||
fn ordering4<'a, 'b, F>(a: &'a usize, b: &'b usize, x: F) where F: FnOnce(&'a &'b usize) {
|
||||
// Do not infer ordering from closure argument types.
|
||||
let z: Option<&'a &'b usize> = None;
|
||||
//~^ ERROR reference has a longer lifetime than the data it references
|
||||
}
|
||||
// see regions-free-region-ordering-callee-4.rs
|
||||
|
||||
fn ordering5<'a, 'b>(a: &'a usize, b: &'b usize, x: Option<&'a &'b usize>) {
|
||||
let z: Option<&'a &'b usize> = None;
|
||||
|
@ -24,16 +24,13 @@ trait Trait2<'a, 'b> {
|
||||
type Foo;
|
||||
}
|
||||
|
||||
fn wf<T>() { }
|
||||
|
||||
// As a side-effect of the conservative process above, this argument
|
||||
// is not automatically considered well-formed, since for it to be WF,
|
||||
// we would need to know that `'y: 'x`, but we do not infer that.
|
||||
fn callee<'x, 'y, T>(
|
||||
t: &'x for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
|
||||
{
|
||||
wf::<&'x &'y i32>();
|
||||
// As a side-effect of the conservative process above, the type of
|
||||
// this argument `t` is not automatically considered well-formed,
|
||||
// since for it to be WF, we would need to know that `'y: 'x`, but we
|
||||
// do not infer that.
|
||||
fn callee<'x, 'y, T>(t: &'x for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
|
||||
//~^ ERROR reference has a longer lifetime than the data it references
|
||||
{
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
|
@ -14,8 +14,7 @@
|
||||
trait TheTrait<'t>: 't { }
|
||||
|
||||
struct Foo<'a,'b> {
|
||||
x: Box<TheTrait<'a>+'b>
|
||||
//~^ ERROR reference has a longer lifetime
|
||||
x: Box<TheTrait<'a>+'b> //~ ERROR E0478
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
|
@ -1,37 +0,0 @@
|
||||
// Copyright 2015 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.
|
||||
|
||||
// Test that an RFC1214 warning from an earlier function (`foo`) does
|
||||
// not suppress an error for the same problem (`WantEq<NotEq>`,
|
||||
// `NotEq: !Eq`) in a later function (`bar)`. Earlier versions of the
|
||||
// warning mechanism had an issue due to caching.
|
||||
|
||||
#![allow(dead_code)]
|
||||
#![allow(unused_variables)]
|
||||
|
||||
struct WantEq<T:Eq> { t: T }
|
||||
|
||||
struct NotEq;
|
||||
|
||||
trait Trait<T> { }
|
||||
|
||||
fn foo() {
|
||||
let x: Box<Trait<WantEq<NotEq>>> = loop { };
|
||||
//~^ WARN E0277
|
||||
}
|
||||
|
||||
fn bar() {
|
||||
wf::<WantEq<NotEq>>();
|
||||
//~^ ERROR E0277
|
||||
}
|
||||
|
||||
fn wf<T>() { }
|
||||
|
||||
fn main() { }
|
@ -14,7 +14,7 @@ trait Iterator<A> {
|
||||
fn next(&mut self) -> Option<A>;
|
||||
}
|
||||
|
||||
trait IteratorUtil<A>
|
||||
trait IteratorUtil<A>: Sized
|
||||
{
|
||||
fn zip<B, U: Iterator<U>>(self, other: U) -> ZipIterator<Self, U>;
|
||||
}
|
||||
|
@ -22,5 +22,4 @@ fn main() {
|
||||
//~^ ERROR E0038
|
||||
//~| ERROR E0038
|
||||
//~| ERROR E0277
|
||||
//~| WARNING E0038
|
||||
}
|
||||
|
@ -0,0 +1,36 @@
|
||||
// Copyright 2015 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.
|
||||
|
||||
// ignore-tidy-linelength
|
||||
|
||||
// Test that when a `..` impl applies, we also check that any
|
||||
// supertrait conditions are met.
|
||||
|
||||
#![feature(optin_builtin_traits)]
|
||||
|
||||
trait NotImplemented { }
|
||||
|
||||
trait MyTrait: Sized
|
||||
where Option<Self> : NotImplemented
|
||||
{}
|
||||
|
||||
impl NotImplemented for i32 {}
|
||||
|
||||
impl MyTrait for .. {}
|
||||
|
||||
fn bar<T:NotImplemented>() { }
|
||||
|
||||
fn test() {
|
||||
bar::<Option<i32>>();
|
||||
//~^ ERROR the trait `NotImplemented` is not implemented for the type `core::option::Option<i32>`
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
@ -17,7 +17,7 @@
|
||||
|
||||
trait NotImplemented { }
|
||||
|
||||
trait MyTrait
|
||||
trait MyTrait: Sized
|
||||
where Option<Self> : NotImplemented
|
||||
{}
|
||||
|
||||
@ -26,20 +26,11 @@ impl NotImplemented for i32 {}
|
||||
impl MyTrait for .. {}
|
||||
|
||||
fn foo<T:MyTrait>() {
|
||||
bar::<Option<T>>()
|
||||
//~^ ERROR the trait `NotImplemented` is not implemented for the type `core::option::Option<T>`
|
||||
//
|
||||
// This should probably typecheck. This is #20671.
|
||||
}
|
||||
|
||||
fn bar<T:NotImplemented>() { }
|
||||
|
||||
fn test() {
|
||||
bar::<Option<i32>>();
|
||||
//~^ ERROR the trait `NotImplemented` is not implemented for the type `core::option::Option<i32>`
|
||||
}
|
||||
|
||||
fn main() {
|
||||
foo::<u32>();
|
||||
//~^ ERROR the trait `NotImplemented` is not implemented for the type `core::option::Option<u32>`
|
||||
}
|
||||
|
@ -15,13 +15,13 @@ trait Get {
|
||||
}
|
||||
|
||||
fn get_min_from_max<'min, 'max, G>()
|
||||
where 'max : 'min, &'max G : Get
|
||||
where 'max : 'min, &'max G : Get, G : 'max
|
||||
{
|
||||
impls_get::<&'min G>(); //~ ERROR mismatched types
|
||||
}
|
||||
|
||||
fn get_max_from_min<'min, 'max, G>()
|
||||
where 'max : 'min, &'min G : Get
|
||||
where 'max : 'min, &'min G : Get, G : 'min
|
||||
{
|
||||
impls_get::<&'max G>(); //~ ERROR mismatched types
|
||||
}
|
||||
|
@ -14,8 +14,8 @@
|
||||
#![allow(dead_code)]
|
||||
|
||||
struct Foo {
|
||||
foo: [[u8]], //~ WARN E0277
|
||||
foo: [[u8]], //~ ERROR E0277
|
||||
}
|
||||
|
||||
#[rustc_error]
|
||||
fn main() { } //~ ERROR compilation successful
|
||||
fn main() { }
|
||||
|
@ -16,11 +16,11 @@
|
||||
|
||||
trait ExtraCopy<T:Copy> { }
|
||||
|
||||
enum SomeEnum<T,U> //~ WARN E0277
|
||||
enum SomeEnum<T,U> //~ ERROR E0277
|
||||
where T: ExtraCopy<U>
|
||||
{
|
||||
SomeVariant(T,U)
|
||||
}
|
||||
|
||||
#[rustc_error]
|
||||
fn main() { } //~ ERROR compilation successful
|
||||
fn main() { }
|
||||
|
@ -16,9 +16,9 @@
|
||||
|
||||
trait ExtraCopy<T:Copy> { }
|
||||
|
||||
fn foo<T,U>() where T: ExtraCopy<U> //~ WARN E0277
|
||||
fn foo<T,U>() where T: ExtraCopy<U> //~ ERROR E0277
|
||||
{
|
||||
}
|
||||
|
||||
#[rustc_error]
|
||||
fn main() { } //~ ERROR compilation successful
|
||||
fn main() { }
|
||||
|
@ -17,8 +17,8 @@ pub trait Foo<'a> {
|
||||
}
|
||||
|
||||
impl<'a, T> Foo<'a> for T {
|
||||
type Bar = &'a T; //~ WARN E0309
|
||||
type Bar = &'a T; //~ ERROR E0309
|
||||
}
|
||||
|
||||
#[rustc_error]
|
||||
fn main() { } //~ ERROR compilation
|
||||
fn main() { }
|
||||
|
@ -25,9 +25,9 @@ pub trait Foo {
|
||||
|
||||
impl<T> Foo for T {
|
||||
type Bar = MySet<T>;
|
||||
//~^ WARN the trait `MyHash` is not implemented for the type `T`
|
||||
//~^ ERROR the trait `MyHash` is not implemented for the type `T`
|
||||
}
|
||||
|
||||
#[rustc_error]
|
||||
fn main() { } //~ ERROR compilation successful
|
||||
fn main() { }
|
||||
|
||||
|
@ -20,13 +20,13 @@ struct MustBeCopy<T:Copy> {
|
||||
|
||||
struct Foo<T> {
|
||||
// needs T: 'static
|
||||
x: fn() -> &'static T //~ WARN E0310
|
||||
x: fn() -> &'static T //~ ERROR E0310
|
||||
}
|
||||
|
||||
struct Bar<T> {
|
||||
// needs T: Copy
|
||||
x: fn(&'static T) //~ WARN E0310
|
||||
x: fn(&'static T) //~ ERROR E0310
|
||||
}
|
||||
|
||||
#[rustc_error]
|
||||
fn main() { } //~ ERROR compilation successful
|
||||
fn main() { }
|
||||
|
@ -16,10 +16,10 @@
|
||||
trait MustBeCopy<T:Copy> {
|
||||
}
|
||||
|
||||
fn bar<T,U>() //~ WARN E0277
|
||||
fn bar<T,U>() //~ ERROR E0277
|
||||
where T: MustBeCopy<U>
|
||||
{
|
||||
}
|
||||
|
||||
#[rustc_error]
|
||||
fn main() { } //~ ERROR compilation successful
|
||||
fn main() { }
|
||||
|
@ -21,8 +21,8 @@ struct MustBeCopy<T:Copy> {
|
||||
|
||||
struct Foo<T> {
|
||||
// needs T: 'static
|
||||
x: Object<&'static T> //~ WARN E0310
|
||||
x: Object<&'static T> //~ ERROR E0310
|
||||
}
|
||||
|
||||
#[rustc_error]
|
||||
fn main() { } //~ ERROR compilation successful
|
||||
fn main() { }
|
||||
|
@ -19,9 +19,9 @@ trait ExtraCopy<T:Copy> { }
|
||||
struct Foo<T,U>(T,U);
|
||||
|
||||
impl<T,U> Foo<T,U> {
|
||||
fn foo(self) where T: ExtraCopy<U> //~ WARN E0277
|
||||
fn foo(self) where T: ExtraCopy<U> //~ ERROR E0277
|
||||
{}
|
||||
}
|
||||
|
||||
#[rustc_error]
|
||||
fn main() { } //~ ERROR compilation successful
|
||||
fn main() { }
|
||||
|
@ -18,9 +18,9 @@ trait ExtraCopy<T:Copy> { }
|
||||
|
||||
struct Foo<T,U>(T,U);
|
||||
|
||||
impl<T,U> Foo<T,U> where T: ExtraCopy<U> //~ WARN E0277
|
||||
impl<T,U> Foo<T,U> where T: ExtraCopy<U> //~ ERROR E0277
|
||||
{
|
||||
}
|
||||
|
||||
#[rustc_error]
|
||||
fn main() { } //~ ERROR compilation successful
|
||||
fn main() { }
|
||||
|
@ -19,14 +19,14 @@ trait Trait<T> { }
|
||||
|
||||
struct Foo<'a,T> {
|
||||
f: &'a fn(T),
|
||||
//~^ WARN E0309
|
||||
//~^ ERROR E0309
|
||||
}
|
||||
|
||||
struct Bar<'a,T> {
|
||||
f: &'a Trait<T>,
|
||||
//~^ WARN E0309
|
||||
//~^ ERROR E0309
|
||||
}
|
||||
|
||||
#[rustc_error]
|
||||
fn main() { } //~ ERROR compilation successful
|
||||
fn main() { }
|
||||
|
||||
|
@ -16,11 +16,11 @@
|
||||
|
||||
trait ExtraCopy<T:Copy> { }
|
||||
|
||||
struct SomeStruct<T,U> //~ WARN E0277
|
||||
struct SomeStruct<T,U> //~ ERROR E0277
|
||||
where T: ExtraCopy<U>
|
||||
{
|
||||
data: (T,U)
|
||||
}
|
||||
|
||||
#[rustc_error]
|
||||
fn main() { } //~ ERROR compilation successful
|
||||
fn main() { }
|
||||
|
@ -16,9 +16,9 @@
|
||||
|
||||
trait ExtraCopy<T:Copy> { }
|
||||
|
||||
trait SomeTrait<T> { //~ WARN E0277
|
||||
trait SomeTrait<T> { //~ ERROR E0277
|
||||
type Type1: ExtraCopy<T>;
|
||||
}
|
||||
|
||||
#[rustc_error]
|
||||
fn main() { } //~ ERROR compilation successful
|
||||
fn main() { }
|
||||
|
@ -17,8 +17,8 @@
|
||||
trait SomeTrait<'a> {
|
||||
type Type1;
|
||||
type Type2 = &'a Self::Type1;
|
||||
//~^ WARN E0309
|
||||
//~^ ERROR E0309
|
||||
}
|
||||
|
||||
#[rustc_error]
|
||||
fn main() { } //~ ERROR compilation successful
|
||||
fn main() { }
|
||||
|
@ -19,8 +19,8 @@ struct IsCopy<T:Copy> { x: T }
|
||||
trait SomeTrait {
|
||||
type Type1;
|
||||
type Type2 = IsCopy<Self::Type1>;
|
||||
//~^ WARN E0277
|
||||
//~^ ERROR E0277
|
||||
}
|
||||
|
||||
#[rustc_error]
|
||||
fn main() { } //~ ERROR compilation successful
|
||||
fn main() { }
|
||||
|
@ -16,10 +16,10 @@
|
||||
|
||||
trait ExtraCopy<T:Copy> { }
|
||||
|
||||
trait SomeTrait<T,U> //~ WARN E0277
|
||||
trait SomeTrait<T,U> //~ ERROR E0277
|
||||
where T: ExtraCopy<U>
|
||||
{
|
||||
}
|
||||
|
||||
#[rustc_error]
|
||||
fn main() { } //~ ERROR compilation successful
|
||||
fn main() { }
|
||||
|
@ -19,11 +19,11 @@ struct Bar<T:Eq+?Sized> { value: Box<T> }
|
||||
|
||||
trait Foo {
|
||||
fn bar(&self, x: &Bar<Self>) {
|
||||
//~^ WARN E0277
|
||||
//~^ ERROR E0277
|
||||
//
|
||||
// Here, Eq ought to be implemented.
|
||||
}
|
||||
}
|
||||
|
||||
#[rustc_error]
|
||||
fn main() { } //~ ERROR compilation successful
|
||||
fn main() { }
|
||||
|
@ -19,12 +19,11 @@ struct Bar<T:Eq+?Sized> { value: Box<T> }
|
||||
|
||||
trait Foo {
|
||||
fn bar(&self) -> Bar<Self> {
|
||||
//~^ WARN E0277
|
||||
//~^ ERROR E0277
|
||||
//
|
||||
// Here, Eq ought to be implemented.
|
||||
loop { }
|
||||
}
|
||||
}
|
||||
|
||||
#[rustc_error]
|
||||
fn main() { } //~ ERROR compilation successful
|
||||
fn main() { }
|
||||
|
@ -19,11 +19,11 @@ trait Bar<T:Eq+?Sized> { }
|
||||
|
||||
trait Foo {
|
||||
fn bar<A>(&self) where A: Bar<Self> {
|
||||
//~^ WARN E0277
|
||||
//~^ ERROR E0277
|
||||
//
|
||||
// Here, Eq ought to be implemented.
|
||||
}
|
||||
}
|
||||
|
||||
#[rustc_error]
|
||||
fn main() { } //~ ERROR compilation successful
|
||||
fn main() { }
|
||||
|
@ -18,10 +18,9 @@ struct Bar<T:Eq+?Sized> { value: Box<T> }
|
||||
|
||||
trait Foo {
|
||||
fn bar(&self, x: &Bar<Self>);
|
||||
//~^ WARN E0277
|
||||
//~^ ERROR E0277
|
||||
//
|
||||
// Here, Eq ought to be implemented.
|
||||
}
|
||||
|
||||
#[rustc_error]
|
||||
fn main() { } //~ ERROR compilation successful
|
||||
fn main() { }
|
||||
|
@ -18,10 +18,9 @@ struct Bar<T:Eq+?Sized> { value: Box<T> }
|
||||
|
||||
trait Foo {
|
||||
fn bar(&self) -> &Bar<Self>;
|
||||
//~^ WARN E0277
|
||||
//~^ ERROR E0277
|
||||
//
|
||||
// Here, Eq ought to be implemented.
|
||||
}
|
||||
|
||||
#[rustc_error]
|
||||
fn main() { } //~ ERROR compilation successful
|
||||
fn main() { }
|
||||
|
@ -18,10 +18,10 @@ struct Bar<T:Eq+?Sized> { value: Box<T> }
|
||||
|
||||
trait Foo {
|
||||
fn bar(&self) where Bar<Self>: Copy;
|
||||
//~^ WARN E0277
|
||||
//~^ ERROR E0277
|
||||
//
|
||||
// Here, Eq ought to be implemented.
|
||||
}
|
||||
|
||||
#[rustc_error]
|
||||
fn main() { } //~ ERROR compilation successful
|
||||
fn main() { }
|
||||
|
@ -16,8 +16,7 @@
|
||||
|
||||
trait ExtraCopy<T:Copy> { }
|
||||
|
||||
trait SomeTrait<T>: ExtraCopy<T> { //~ WARN E0277
|
||||
trait SomeTrait<T>: ExtraCopy<T> { //~ ERROR E0277
|
||||
}
|
||||
|
||||
#[rustc_error]
|
||||
fn main() { } //~ ERROR compilation successful
|
||||
fn main() { }
|
||||
|
@ -15,4 +15,6 @@
|
||||
trait Chromosome<X: Chromosome<i32>> {
|
||||
}
|
||||
|
||||
impl Chromosome<i32> for i32 { }
|
||||
|
||||
fn main() { }
|
||||
|
@ -22,4 +22,12 @@ trait Get<A> {
|
||||
|
||||
struct Struct<C:Chromosome> { c: C }
|
||||
|
||||
impl Chromosome for i32 { }
|
||||
|
||||
impl Get<Struct<i32>> for i32 {
|
||||
fn get(&self) -> Struct<i32> {
|
||||
Struct { c: *self }
|
||||
}
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
|
@ -14,7 +14,9 @@ fn main() {
|
||||
println!("{:?}",y);
|
||||
}
|
||||
|
||||
trait Foo {
|
||||
trait Foo
|
||||
where for<'a> &'a Self: Bar
|
||||
{
|
||||
fn foo<'a>(&'a self) -> <&'a Self as Bar>::Output;
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,7 @@ pub fn size_of_val<T>(val: &T) -> usize {
|
||||
val.size_of_val()
|
||||
}
|
||||
|
||||
pub trait TypeInfo {
|
||||
pub trait TypeInfo: Sized {
|
||||
fn size_of(_lame_type_hint: Option<Self>) -> usize;
|
||||
fn size_of_val(&self) -> usize;
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
use std::ops::Deref;
|
||||
|
||||
pub trait ToOwned {
|
||||
pub trait ToOwned: Sized {
|
||||
type Owned: Borrow<Self>;
|
||||
fn to_owned(&self) -> Self::Owned;
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ trait UseLife01 {
|
||||
}
|
||||
|
||||
trait UseLife02 {
|
||||
fn refs<'a, T, H: HasType<&'a T>>(&'a self) -> H;
|
||||
fn refs<'a, T: 'a, H: HasType<&'a T>>(&'a self) -> H;
|
||||
}
|
||||
|
||||
|
||||
@ -33,7 +33,7 @@ pub trait HasType<T>
|
||||
|
||||
|
||||
trait UseLife03<T> {
|
||||
fn refs<'a, H: HasType<&'a T>>(&'a self) -> H;
|
||||
fn refs<'a, H: HasType<&'a T>>(&'a self) -> H where T: 'a;
|
||||
}
|
||||
|
||||
|
||||
@ -45,7 +45,7 @@ pub fn top_refs_1<'a, H: HasLife<'a>>(_s: &'a ()) -> H {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn top_refs_2<'a, T, H: HasType<&'a T>>(_s: &'a ()) -> H {
|
||||
pub fn top_refs_2<'a, T: 'a, H: HasType<&'a T>>(_s: &'a ()) -> H {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
use std::cmp::PartialOrd;
|
||||
|
||||
pub trait NumCast {
|
||||
pub trait NumCast: Sized {
|
||||
fn from(i: i32) -> Option<Self>;
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
// pretty-expanded FIXME #23616
|
||||
|
||||
pub trait NumCast {
|
||||
pub trait NumCast: Sized {
|
||||
fn from(i: i32) -> Option<Self>;
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
pub trait NumCast {
|
||||
pub trait NumCast: Sized {
|
||||
fn from(i: i32) -> Option<Self>;
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
// pretty-expanded FIXME #23616
|
||||
|
||||
pub trait NumCast {
|
||||
pub trait NumCast: Sized {
|
||||
fn from(i: i32) -> Option<Self>;
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@ pub trait FuzzyEq<Eps> {
|
||||
fn fuzzy_eq_eps(&self, other: &Self, epsilon: &Eps) -> bool;
|
||||
}
|
||||
|
||||
trait Float: FuzzyEq<Self> {
|
||||
trait Float: Sized+FuzzyEq<Self> {
|
||||
fn two_pi() -> Self;
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,7 @@ trait Foo<T> {
|
||||
fn f(&self, x: &T);
|
||||
}
|
||||
|
||||
trait Bar : Foo<Self> {
|
||||
trait Bar : Sized + Foo<Self> {
|
||||
fn g(&self);
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,7 @@ pub trait Add<RHS,Result> {
|
||||
fn add(&self, rhs: &RHS) -> Result;
|
||||
}
|
||||
|
||||
trait MyNum : Add<Self,Self> { }
|
||||
trait MyNum : Sized + Add<Self,Self> { }
|
||||
|
||||
struct MyInt { val: isize }
|
||||
|
||||
|
@ -17,7 +17,7 @@ trait Add<RHS,Result>: Panda<RHS> {
|
||||
fn add(&self, rhs: &RHS) -> Result;
|
||||
}
|
||||
|
||||
trait MyNum : Add<Self,Self> { }
|
||||
trait MyNum : Sized + Add<Self,Self> { }
|
||||
|
||||
struct MyInt { val: isize }
|
||||
|
||||
|
@ -67,26 +67,26 @@ fn f7<X: ?Sized+T3>(x: &X) {
|
||||
|
||||
trait T4<X> {
|
||||
fn dummy(&self) { }
|
||||
fn m1(x: &T4<X>, y: X);
|
||||
fn m2(x: &T5<X>, y: X);
|
||||
fn m1(&self, x: &T4<X>, y: X);
|
||||
fn m2(&self, x: &T5<X>, y: X);
|
||||
}
|
||||
trait T5<X: ?Sized> {
|
||||
fn dummy(&self) { }
|
||||
// not an error (for now)
|
||||
fn m1(x: &T4<X>);
|
||||
fn m2(x: &T5<X>);
|
||||
fn m1(&self, x: &T4<X>);
|
||||
fn m2(&self, x: &T5<X>);
|
||||
}
|
||||
|
||||
trait T6<X: T> {
|
||||
fn dummy(&self) { }
|
||||
fn m1(x: &T4<X>);
|
||||
fn m2(x: &T5<X>);
|
||||
fn m1(&self, x: &T4<X>);
|
||||
fn m2(&self, x: &T5<X>);
|
||||
}
|
||||
trait T7<X: ?Sized+T> {
|
||||
fn dummy(&self) { }
|
||||
// not an error (for now)
|
||||
fn m1(x: &T4<X>);
|
||||
fn m2(x: &T5<X>);
|
||||
fn m1(&self, x: &T4<X>);
|
||||
fn m2(&self, x: &T5<X>);
|
||||
}
|
||||
|
||||
// The last field in a struct or variant may be unsized
|
||||
|
Loading…
x
Reference in New Issue
Block a user