suppress trait errors that are implied by other errors

Instead of suppressing only trait errors that are "exact duplicates",
display only the "most high-level" error when there are multiple trait
errors with the same span that imply each-other.

e.g. when there are both `[closure]: Fn` and `[closure]: FnOnce`, omit
displaying the `[closure]: FnOnce` bound.
This commit is contained in:
Ariel Ben-Yehuda 2017-05-08 19:45:27 +03:00
parent dfa7e21e4e
commit 7b9519a5d4
23 changed files with 291 additions and 279 deletions

View File

@ -74,6 +74,7 @@ use syntax_pos::{Pos, Span};
use errors::{DiagnosticBuilder, DiagnosticStyledString};
mod note;
mod need_type_info;
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
pub fn note_and_explain_region(self,

View File

@ -0,0 +1,153 @@
// Copyright 2017 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 hir::{self, map, Local, Pat, Body};
use hir::intravisit::{self, Visitor, NestedVisitorMap};
use infer::InferCtxt;
use infer::type_variable::TypeVariableOrigin;
use ty::{self, Ty, TyInfer, TyVar};
use syntax::ast::NodeId;
use syntax_pos::Span;
struct FindLocalByTypeVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
target_ty: &'a Ty<'tcx>,
hir_map: &'a hir::map::Map<'gcx>,
found_local_pattern: Option<&'gcx Pat>,
found_arg_pattern: Option<&'gcx Pat>,
}
impl<'a, 'gcx, 'tcx> FindLocalByTypeVisitor<'a, 'gcx, 'tcx> {
fn node_matches_type(&mut self, node_id: NodeId) -> bool {
let ty_opt = self.infcx.in_progress_tables.and_then(|tables| {
tables.borrow().node_id_to_type_opt(node_id)
});
match ty_opt {
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,
}
})
}
None => false,
}
}
}
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)
}
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);
}
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);
}
}
intravisit::walk_body(self, body);
}
}
impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
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()
}
}
pub fn need_type_info(&self, body_id: hir::BodyId, span: Span, ty: Ty<'tcx>) {
let ty = self.resolve_type_vars_if_possible(&ty);
let name = self.extract_type_name(&ty);
let mut err_span = span;
let mut labels = vec![(span, format!("cannot infer type for `{}`", name))];
let mut local_visitor = FindLocalByTypeVisitor {
infcx: &self,
target_ty: &ty,
hir_map: &self.tcx.hir,
found_local_pattern: None,
found_arg_pattern: None,
};
// #40294: cause.body_id can also be a fn declaration.
// Currently, if it's anything other than NodeExpr, we just ignore it
match self.tcx.hir.find(body_id.node_id) {
Some(map::NodeExpr(expr)) => local_visitor.visit_expr(expr),
_ => ()
}
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 {
if let Some(simple_name) = pattern.simple_name() {
labels.push((pattern.span, format!("consider giving `{}` a type", simple_name)));
} else {
labels.push((pattern.span, format!("consider giving the pattern a type")));
}
}
let mut err = struct_span_err!(self.tcx.sess,
err_span,
E0282,
"type annotations needed");
for (target_span, label_message) in labels {
err.span_label(target_span, label_message);
}
err.emit();
}
}

View File

@ -36,7 +36,7 @@ use std::fmt;
use syntax::ast;
use errors::DiagnosticBuilder;
use syntax_pos::{self, Span, DUMMY_SP};
use util::nodemap::{FxHashMap, FxHashSet};
use util::nodemap::FxHashMap;
use arena::DroplessArena;
use self::combine::CombineFields;
@ -110,7 +110,7 @@ pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
// the set of predicates on which errors have been reported, to
// avoid reporting the same error twice.
pub reported_trait_errors: RefCell<FxHashSet<traits::TraitErrorKey<'tcx>>>,
pub reported_trait_errors: RefCell<FxHashMap<Span, Vec<ty::Predicate<'tcx>>>>,
// When an error occurs, we want to avoid reporting "derived"
// errors that are due to this original failure. Normally, we
@ -350,6 +350,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> {
global_tcx: self,
arena: DroplessArena::new(),
fresh_tables: None,
}
}
}
@ -381,7 +382,7 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> {
region_vars: RegionVarBindings::new(tcx),
selection_cache: traits::SelectionCache::new(),
evaluation_cache: traits::EvaluationCache::new(),
reported_trait_errors: RefCell::new(FxHashSet()),
reported_trait_errors: RefCell::new(FxHashMap()),
tainted_by_errors_flag: Cell::new(false),
err_count_on_creation: tcx.sess.err_count(),
in_snapshot: Cell::new(false),

View File

@ -18,6 +18,7 @@ use super::{
OutputTypeParameterMismatch,
TraitNotObjectSafe,
PredicateObligation,
Reveal,
SelectionContext,
SelectionError,
ObjectSafetyViolation,
@ -25,16 +26,14 @@ use super::{
use errors::DiagnosticBuilder;
use fmt_macros::{Parser, Piece, Position};
use hir::{self, intravisit, Local, Pat, Body};
use hir::intravisit::{Visitor, NestedVisitorMap};
use hir::map::NodeExpr;
use hir;
use hir::def_id::DefId;
use infer::{self, InferCtxt};
use infer::type_variable::TypeVariableOrigin;
use rustc::lint::builtin::EXTRA_REQUIREMENT_IN_IMPL;
use std::fmt;
use syntax::ast::{self, NodeId};
use ty::{self, AdtKind, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable, TyInfer, TyVar};
use syntax::ast;
use ty::{self, AdtKind, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable};
use ty::error::{ExpectedFound, TypeError};
use ty::fast_reject;
use ty::fold::TypeFolder;
@ -44,96 +43,113 @@ use util::nodemap::{FxHashMap, FxHashSet};
use syntax_pos::{DUMMY_SP, Span};
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct TraitErrorKey<'tcx> {
span: Span,
predicate: ty::Predicate<'tcx>
}
impl<'a, 'gcx, 'tcx> TraitErrorKey<'tcx> {
fn from_error(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
e: &FulfillmentError<'tcx>) -> Self {
let predicate =
infcx.resolve_type_vars_if_possible(&e.obligation.predicate);
TraitErrorKey {
span: e.obligation.cause.span,
predicate: infcx.tcx.erase_regions(&predicate)
}
}
}
struct FindLocalByTypeVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
target_ty: &'a Ty<'tcx>,
hir_map: &'a hir::map::Map<'gcx>,
found_local_pattern: Option<&'gcx Pat>,
found_arg_pattern: Option<&'gcx Pat>,
}
impl<'a, 'gcx, 'tcx> FindLocalByTypeVisitor<'a, 'gcx, 'tcx> {
fn node_matches_type(&mut self, node_id: NodeId) -> bool {
let ty_opt = self.infcx.in_progress_tables.and_then(|tables| {
tables.borrow().node_id_to_type_opt(node_id)
});
match ty_opt {
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,
}
})
}
None => false,
}
}
}
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)
}
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);
}
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);
}
}
intravisit::walk_body(self, body);
}
}
impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
pub fn report_fulfillment_errors(&self, errors: &Vec<FulfillmentError<'tcx>>) {
for error in errors {
self.report_fulfillment_error(error);
pub fn report_fulfillment_errors(&self,
errors: &Vec<FulfillmentError<'tcx>>) {
#[derive(Debug)]
struct ErrorDescriptor<'tcx> {
predicate: ty::Predicate<'tcx>,
index: Option<usize>, // None if this is an old error
}
let mut error_map : FxHashMap<_, _> =
self.reported_trait_errors.borrow().iter().map(|(&span, predicates)| {
(span, predicates.iter().map(|predicate| ErrorDescriptor {
predicate: predicate.clone(),
index: None
}).collect())
}).collect();
for (index, error) in errors.iter().enumerate() {
error_map.entry(error.obligation.cause.span).or_insert(Vec::new()).push(
ErrorDescriptor {
predicate: error.obligation.predicate.clone(),
index: Some(index)
});
self.reported_trait_errors.borrow_mut()
.entry(error.obligation.cause.span).or_insert(Vec::new())
.push(error.obligation.predicate.clone());
}
// We do this in 2 passes because we want to display errors in order, tho
// maybe it *is* better to sort errors by span or something.
let mut is_suppressed: Vec<bool> = errors.iter().map(|_| false).collect();
for (_, error_set) in error_map.iter() {
// We want to suppress "duplicate" errors with the same span.
for error in error_set {
if let Some(index) = error.index {
// Suppress errors that are either:
// 1) strictly implied by another error.
// 2) implied by an error with a smaller index.
for error2 in error_set {
if error2.index.map_or(false, |index2| is_suppressed[index2]) {
// Avoid errors being suppressed by already-suppressed
// errors, to prevent all errors from being suppressed
// at once.
continue
}
if self.error_implies(&error2.predicate, &error.predicate) &&
!(error2.index >= error.index &&
self.error_implies(&error.predicate, &error2.predicate))
{
info!("skipping {:?} (implied by {:?})", error, error2);
is_suppressed[index] = true;
break
}
}
}
}
}
for (error, suppressed) in errors.iter().zip(is_suppressed) {
if !suppressed {
self.report_fulfillment_error(error);
}
}
}
fn report_fulfillment_error(&self,
error: &FulfillmentError<'tcx>) {
let error_key = TraitErrorKey::from_error(self, error);
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;
// returns if `cond` not occuring implies that `error` does not occur - i.e. that
// `error` occuring implies that `cond` occurs.
fn error_implies(&self,
cond: &ty::Predicate<'tcx>,
error: &ty::Predicate<'tcx>)
-> bool
{
if cond == error {
return true
}
let (cond, error) = match (cond, error) {
(&ty::Predicate::Trait(..), &ty::Predicate::Trait(ref error))
=> (cond, error),
_ => {
// FIXME: make this work in other cases too.
return false
}
};
for implication in super::elaborate_predicates(self.tcx, vec![cond.clone()]) {
if let ty::Predicate::Trait(implication) = implication {
let error = error.to_poly_trait_ref();
let implication = implication.to_poly_trait_ref();
// FIXME: I'm just not taking associated types at all here.
// Eventually I'll need to implement param-env-aware
// `Γ₁ ⊦ φ₁ => Γ₂ ⊦ φ₂` logic.
let param_env = ty::ParamEnv::empty(Reveal::UserFacing);
if let Ok(_) = self.can_sub(param_env, error, implication) {
debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implication);
return true
}
}
}
false
}
fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>) {
debug!("report_fulfillment_errors({:?})", error);
match error.code {
FulfillmentErrorCode::CodeSelectionError(ref e) => {
self.report_selection_error(&error.obligation, e);
@ -1008,83 +1024,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
})
}
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()
}
}
pub fn need_type_info(&self, body_id: hir::BodyId, span: Span, ty: Ty<'tcx>) {
let ty = self.resolve_type_vars_if_possible(&ty);
let name = self.extract_type_name(&ty);
let mut err_span = span;
let mut labels = vec![(span, format!("cannot infer type for `{}`", name))];
let mut local_visitor = FindLocalByTypeVisitor {
infcx: &self,
target_ty: &ty,
hir_map: &self.tcx.hir,
found_local_pattern: None,
found_arg_pattern: None,
};
// #40294: cause.body_id can also be a fn declaration.
// Currently, if it's anything other than NodeExpr, we just ignore it
match self.tcx.hir.find(body_id.node_id) {
Some(NodeExpr(expr)) => local_visitor.visit_expr(expr),
_ => ()
}
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 {
if let Some(simple_name) = pattern.simple_name() {
labels.push((pattern.span, format!("consider giving `{}` a type", simple_name)));
} else {
labels.push((pattern.span, format!("consider giving the pattern a type")));
}
}
let mut err = struct_span_err!(self.tcx.sess,
err_span,
E0282,
"type annotations needed");
for (target_span, label_message) in labels {
err.span_label(target_span, label_message);
}
err.emit();
}
fn note_obligation_cause<T>(&self,
err: &mut DiagnosticBuilder,
obligation: &Obligation<'tcx, T>)
@ -1205,4 +1144,3 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
suggested_limit));
}
}

View File

@ -28,7 +28,6 @@ use std::rc::Rc;
use syntax::ast;
use syntax_pos::{Span, DUMMY_SP};
pub use self::error_reporting::TraitErrorKey;
pub use self::coherence::orphan_check;
pub use self::coherence::overlapping_impls;
pub use self::coherence::OrphanCheckErr;

View File

@ -1101,7 +1101,10 @@ pub fn monitor<F: FnOnce() + Send + 'static>(f: F) {
}
let xs = ["the compiler unexpectedly panicked. this is a bug.".to_string(),
format!("we would appreciate a bug report: {}", BUG_REPORT_URL)];
format!("we would appreciate a bug report: {}", BUG_REPORT_URL),
format!("rustc {} running on {}",
option_env!("CFG_VERSION").unwrap_or("unknown_version"),
config::host_triple())];
for note in &xs {
handler.emit(&MultiSpan::new(),
&note,

View File

@ -18,5 +18,4 @@ fn main() {
let _x: extern "C" fn() = f; // OK
is_fn(f);
//~^ ERROR `extern "C" fn() {f}: std::ops::Fn<()>` is not satisfied
//~| ERROR `extern "C" fn() {f}: std::ops::FnOnce<()>` is not satisfied
}

View File

@ -28,5 +28,4 @@ fn main() {
needs_fn(1);
//~^ ERROR : std::ops::Fn<(isize,)>`
//~| ERROR : std::ops::FnOnce<(isize,)>`
}

View File

@ -17,6 +17,5 @@ fn main() {
let _: &mut Fn() = unsafe {
&mut *(ptr as *mut Fn())
//~^ ERROR `(): std::ops::Fn<()>` is not satisfied
//~| ERROR `(): std::ops::FnOnce<()>` is not satisfied
};
}

View File

@ -11,5 +11,4 @@
fn main() {
"".chars().fold(|_, _| (), ());
//~^ ERROR E0277
//~| ERROR E0277
}

View File

@ -17,8 +17,8 @@ use std::ops::*;
struct AllTheRanges {
a: Range<usize>,
//~^ ERROR PartialOrd
//~^^ ERROR PartialOrd
//~^^^ ERROR Ord
//~^^ ERROR Ord
//~^^^ ERROR binary operation
//~^^^^ ERROR binary operation
//~^^^^^ ERROR binary operation
//~^^^^^^ ERROR binary operation
@ -26,11 +26,10 @@ struct AllTheRanges {
//~^^^^^^^^ ERROR binary operation
//~^^^^^^^^^ ERROR binary operation
//~^^^^^^^^^^ ERROR binary operation
//~^^^^^^^^^^^ ERROR binary operation
b: RangeTo<usize>,
//~^ ERROR PartialOrd
//~^^ ERROR PartialOrd
//~^^^ ERROR Ord
//~^^ ERROR Ord
//~^^^ ERROR binary operation
//~^^^^ ERROR binary operation
//~^^^^^ ERROR binary operation
//~^^^^^^ ERROR binary operation
@ -38,11 +37,10 @@ struct AllTheRanges {
//~^^^^^^^^ ERROR binary operation
//~^^^^^^^^^ ERROR binary operation
//~^^^^^^^^^^ ERROR binary operation
//~^^^^^^^^^^^ ERROR binary operation
c: RangeFrom<usize>,
//~^ ERROR PartialOrd
//~^^ ERROR PartialOrd
//~^^^ ERROR Ord
//~^^ ERROR Ord
//~^^^ ERROR binary operation
//~^^^^ ERROR binary operation
//~^^^^^ ERROR binary operation
//~^^^^^^ ERROR binary operation
@ -50,11 +48,10 @@ struct AllTheRanges {
//~^^^^^^^^ ERROR binary operation
//~^^^^^^^^^ ERROR binary operation
//~^^^^^^^^^^ ERROR binary operation
//~^^^^^^^^^^^ ERROR binary operation
d: RangeFull,
//~^ ERROR PartialOrd
//~^^ ERROR PartialOrd
//~^^^ ERROR Ord
//~^^ ERROR Ord
//~^^^ ERROR binary operation
//~^^^^ ERROR binary operation
//~^^^^^ ERROR binary operation
//~^^^^^^ ERROR binary operation
@ -62,11 +59,10 @@ struct AllTheRanges {
//~^^^^^^^^ ERROR binary operation
//~^^^^^^^^^ ERROR binary operation
//~^^^^^^^^^^ ERROR binary operation
//~^^^^^^^^^^^ ERROR binary operation
e: RangeInclusive<usize>,
//~^ ERROR PartialOrd
//~^^ ERROR PartialOrd
//~^^^ ERROR Ord
//~^^ ERROR Ord
//~^^^ ERROR binary operation
//~^^^^ ERROR binary operation
//~^^^^^ ERROR binary operation
//~^^^^^^ ERROR binary operation
@ -74,11 +70,10 @@ struct AllTheRanges {
//~^^^^^^^^ ERROR binary operation
//~^^^^^^^^^ ERROR binary operation
//~^^^^^^^^^^ ERROR binary operation
//~^^^^^^^^^^^ ERROR binary operation
f: RangeToInclusive<usize>,
//~^ ERROR PartialOrd
//~^^ ERROR PartialOrd
//~^^^ ERROR Ord
//~^^ ERROR Ord
//~^^^ ERROR binary operation
//~^^^^ ERROR binary operation
//~^^^^^ ERROR binary operation
//~^^^^^^ ERROR binary operation
@ -86,8 +81,6 @@ struct AllTheRanges {
//~^^^^^^^^ ERROR binary operation
//~^^^^^^^^^ ERROR binary operation
//~^^^^^^^^^^ ERROR binary operation
//~^^^^^^^^^^^ ERROR binary operation
}
fn main() {}

View File

@ -15,8 +15,7 @@ fn mutate(s: &mut str) {
//~^ ERROR `str: std::marker::Sized` is not satisfied
//~| ERROR `str: std::marker::Sized` is not satisfied
s[1usize] = bot();
//~^ ERROR `str: std::ops::Index<usize>` is not satisfied
//~| ERROR `str: std::ops::IndexMut<usize>` is not satisfied
//~^ ERROR `str: std::ops::IndexMut<usize>` is not satisfied
}
pub fn main() {}

View File

@ -21,13 +21,11 @@ fn call_it_once<F:FnOnce(&isize)->isize>(_: F, _: isize) -> isize { 0 }
fn a() {
let x = call_it(&square, 22);
//~^ ERROR E0277
//~| ERROR E0277
}
fn b() {
let y = call_it_mut(&mut square, 22);
//~^ ERROR E0277
//~| ERROR E0277
}
fn c() {

View File

@ -21,13 +21,11 @@ fn call_it_once<F:FnOnce(&isize)->isize>(_: F, _: isize) -> isize { 0 }
fn a() {
let x = call_it(&square, 22);
//~^ ERROR E0277
//~| ERROR E0277
}
fn b() {
let y = call_it_mut(&mut square, 22);
//~^ ERROR E0277
//~| ERROR E0277
}
fn c() {

View File

@ -22,13 +22,11 @@ fn call_it_once<F:FnOnce(&isize)->isize>(_: F, _: isize) -> isize { 0 }
fn a() {
let x = call_it(&square, 22);
//~^ ERROR E0277
//~| ERROR E0277
}
fn b() {
let y = call_it_mut(&mut square, 22);
//~^ ERROR E0277
//~| ERROR E0277
}
fn c() {

View File

@ -12,15 +12,15 @@
trait T {}
fn f1<X: ?Sized>(x: &X) {
let _: X; // <-- this is OK, no bindings created, no initializer.
fn f1<W: ?Sized, X: ?Sized, Y: ?Sized, Z: ?Sized>(x: &X) {
let _: W; // <-- this is OK, no bindings created, no initializer.
let _: (isize, (X, isize)); //~ERROR `X: std::marker::Sized` is not satisfie
let y: X; //~ERROR `X: std::marker::Sized` is not satisfied
let y: (isize, (X, usize));
let y: Y; //~ERROR `Y: std::marker::Sized` is not satisfied
let y: (isize, (Z, usize)); //~ERROR `Z: std::marker::Sized` is not satisfied
}
fn f2<X: ?Sized + T>(x: &X) {
fn f2<X: ?Sized, Y: ?Sized>(x: &X) {
let y: X; //~ERROR `X: std::marker::Sized` is not satisfied
let y: (isize, (X, isize)); //~ERROR `X: std::marker::Sized` is not satisfied
let y: (isize, (Y, isize)); //~ERROR `Y: std::marker::Sized` is not satisfied
}
fn f3<X: ?Sized>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {

View File

@ -9,16 +9,5 @@ error[E0281]: type mismatch: `[closure@$DIR/E0281.rs:14:9: 14:24]` implements th
|
= note: required by `foo`
error[E0281]: type mismatch: `[closure@$DIR/E0281.rs:14:9: 14:24]` implements the trait `std::ops::FnOnce<(std::string::String,)>`, but the trait `std::ops::FnOnce<(usize,)>` is required
--> $DIR/E0281.rs:14:5
|
14 | foo(|y: String| { });
| ^^^ --------------- implements `std::ops::FnOnce<(std::string::String,)>`
| |
| requires `std::ops::FnOnce<(usize,)>`
| expected usize, found struct `std::string::String`
|
= note: required by `foo`
error: aborting due to previous error(s)

View File

@ -30,14 +30,6 @@ error[E0277]: the trait bound `{integer}: std::ops::Div<&str>` is not satisfied
|
= help: the trait `std::ops::Div<&str>` is not implemented for `{integer}`
error[E0277]: the trait bound `{integer}: std::cmp::PartialEq<std::string::String>` is not satisfied
--> $DIR/binops.rs:16:7
|
16 | 5 < String::new();
| ^ can't compare `{integer}` with `std::string::String`
|
= help: the trait `std::cmp::PartialEq<std::string::String>` is not implemented for `{integer}`
error[E0277]: the trait bound `{integer}: std::cmp::PartialOrd<std::string::String>` is not satisfied
--> $DIR/binops.rs:16:7
|

View File

@ -6,22 +6,6 @@ error[E0593]: closure takes 0 arguments but 2 arguments are required
| |
| expected closure that takes 2 arguments
error[E0593]: closure takes 0 arguments but 2 arguments are required
--> $DIR/closure-arg-count.rs:12:15
|
12 | [1, 2, 3].sort_by(|| panic!());
| ^^^^^^^ ----------- takes 0 arguments
| |
| expected closure that takes 2 arguments
error[E0593]: closure takes 1 argument but 2 arguments are required
--> $DIR/closure-arg-count.rs:13:15
|
13 | [1, 2, 3].sort_by(|tuple| panic!());
| ^^^^^^^ ---------------- takes 1 argument
| |
| expected closure that takes 2 arguments
error[E0593]: closure takes 1 argument but 2 arguments are required
--> $DIR/closure-arg-count.rs:13:15
|
@ -47,13 +31,5 @@ error[E0593]: closure takes 1 argument but 2 arguments are required
| |
| expected closure that takes 2 arguments
error[E0593]: closure takes 1 argument but 2 arguments are required
--> $DIR/closure-arg-count.rs:14:15
|
14 | [1, 2, 3].sort_by(|(tuple, tuple2)| panic!());
| ^^^^^^^ -------------------------- takes 1 argument
| |
| expected closure that takes 2 arguments
error: aborting due to previous error(s)

View File

@ -17,14 +17,5 @@ error[E0281]: type mismatch: `[closure@$DIR/issue-36053-2.rs:17:39: 17:53]` impl
| requires `for<'r> std::ops::FnMut<(&'r &str,)>`
| expected &str, found str
error[E0281]: type mismatch: `[closure@$DIR/issue-36053-2.rs:17:39: 17:53]` implements the trait `for<'r> std::ops::FnOnce<(&'r str,)>`, but the trait `for<'r> std::ops::FnOnce<(&'r &str,)>` is required
--> $DIR/issue-36053-2.rs:17:32
|
17 | once::<&str>("str").fuse().filter(|a: &str| true).count();
| ^^^^^^ -------------- implements `for<'r> std::ops::FnOnce<(&'r str,)>`
| |
| requires `for<'r> std::ops::FnOnce<(&'r &str,)>`
| expected &str, found str
error: aborting due to previous error(s)

View File

@ -24,7 +24,6 @@ pub fn main() {
//~| NOTE implements
let z = call_it(3, f);
//~^ ERROR type mismatch
//~| ERROR type mismatch
//~| NOTE expected isize, found usize
//~| NOTE expected isize, found usize
//~| NOTE requires

View File

@ -12,19 +12,5 @@ error[E0281]: type mismatch: `[closure@$DIR/unboxed-closures-vtable-mismatch.rs:
|
= note: required by `call_it`
error[E0281]: type mismatch: `[closure@$DIR/unboxed-closures-vtable-mismatch.rs:22:23: 22:73]` implements the trait `std::ops::FnOnce<(usize, isize)>`, but the trait `std::ops::FnOnce<(isize, isize)>` is required
--> $DIR/unboxed-closures-vtable-mismatch.rs:25:13
|
22 | let f = to_fn_mut(|x: usize, y: isize| -> isize { (x as isize) + y });
| -------------------------------------------------- implements `std::ops::FnOnce<(usize, isize)>`
...
25 | let z = call_it(3, f);
| ^^^^^^^
| |
| requires `std::ops::FnOnce<(isize, isize)>`
| expected isize, found usize
|
= note: required by `call_it`
error: aborting due to previous error(s)

View File

@ -1,4 +1,4 @@
error[E0282]: type annotations needed
error[E0283]: type annotations required: cannot resolve `&'a T: Foo`
--> $DIR/issue-40294.rs:15:1
|
15 | / fn foo<'a,'b,T>(x: &'a T, y: &'b T)
@ -8,7 +8,9 @@ error[E0282]: type annotations needed
19 | | x.foo();
20 | | y.foo();
21 | | }
| |_^ cannot infer type for `&'a T`
| |_^
|
= note: required by `Foo`
error: aborting due to previous error(s)