diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 0515e1cc304..11bac21bc42 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -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, diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs new file mode 100644 index 00000000000..7361d66428f --- /dev/null +++ b/src/librustc/infer/error_reporting/need_type_info.rs @@ -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 or the MIT license +// , 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(); + } +} diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 4bc0005d568..f96e8c389d6 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -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>>, + pub reported_trait_errors: RefCell>>>, // 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), diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 64438f586d7..247fb079fe7 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -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>) { - for error in errors { - self.report_fulfillment_error(error); + pub fn report_fulfillment_errors(&self, + errors: &Vec>) { + #[derive(Debug)] + struct ErrorDescriptor<'tcx> { + predicate: ty::Predicate<'tcx>, + index: Option, // 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 = 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(&self, err: &mut DiagnosticBuilder, obligation: &Obligation<'tcx, T>) @@ -1205,4 +1144,3 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { suggested_limit)); } } - diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 3ce7ee847cc..e9196cd1243 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -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; diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index c5f89e861fa..8bd992b12e6 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -1101,7 +1101,10 @@ pub fn monitor(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(), ¬e, diff --git a/src/test/compile-fail/extern-wrong-value-type.rs b/src/test/compile-fail/extern-wrong-value-type.rs index 576368aef31..66b06c505e4 100644 --- a/src/test/compile-fail/extern-wrong-value-type.rs +++ b/src/test/compile-fail/extern-wrong-value-type.rs @@ -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 } diff --git a/src/test/compile-fail/fn-trait-formatting.rs b/src/test/compile-fail/fn-trait-formatting.rs index 6377550d3d2..6d70f54edb4 100644 --- a/src/test/compile-fail/fn-trait-formatting.rs +++ b/src/test/compile-fail/fn-trait-formatting.rs @@ -28,5 +28,4 @@ fn main() { needs_fn(1); //~^ ERROR : std::ops::Fn<(isize,)>` - //~| ERROR : std::ops::FnOnce<(isize,)>` } diff --git a/src/test/compile-fail/issue-22034.rs b/src/test/compile-fail/issue-22034.rs index dfa9520f38b..5271ea79917 100644 --- a/src/test/compile-fail/issue-22034.rs +++ b/src/test/compile-fail/issue-22034.rs @@ -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 }; } diff --git a/src/test/compile-fail/issue-23966.rs b/src/test/compile-fail/issue-23966.rs index 7f9c7a292f2..544d3c8af20 100644 --- a/src/test/compile-fail/issue-23966.rs +++ b/src/test/compile-fail/issue-23966.rs @@ -11,5 +11,4 @@ fn main() { "".chars().fold(|_, _| (), ()); //~^ ERROR E0277 - //~| ERROR E0277 } diff --git a/src/test/compile-fail/range_traits-1.rs b/src/test/compile-fail/range_traits-1.rs index 85219717758..cf5c40bd176 100644 --- a/src/test/compile-fail/range_traits-1.rs +++ b/src/test/compile-fail/range_traits-1.rs @@ -17,8 +17,8 @@ use std::ops::*; struct AllTheRanges { a: Range, //~^ 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, //~^ 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, //~^ 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, //~^ 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, //~^ 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() {} - diff --git a/src/test/compile-fail/str-mut-idx.rs b/src/test/compile-fail/str-mut-idx.rs index 8851e5e0797..219fcdfd702 100644 --- a/src/test/compile-fail/str-mut-idx.rs +++ b/src/test/compile-fail/str-mut-idx.rs @@ -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` is not satisfied - //~| ERROR `str: std::ops::IndexMut` is not satisfied + //~^ ERROR `str: std::ops::IndexMut` is not satisfied } pub fn main() {} diff --git a/src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs b/src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs index 2b0a8baf4f2..5ba93bf483f 100644 --- a/src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs +++ b/src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs @@ -21,13 +21,11 @@ fn call_it_onceisize>(_: 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() { diff --git a/src/test/compile-fail/unboxed-closures-wrong-abi.rs b/src/test/compile-fail/unboxed-closures-wrong-abi.rs index f6ba25f4368..ff06f7c559b 100644 --- a/src/test/compile-fail/unboxed-closures-wrong-abi.rs +++ b/src/test/compile-fail/unboxed-closures-wrong-abi.rs @@ -21,13 +21,11 @@ fn call_it_onceisize>(_: 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() { diff --git a/src/test/compile-fail/unboxed-closures-wrong-arg-type-extern-fn.rs b/src/test/compile-fail/unboxed-closures-wrong-arg-type-extern-fn.rs index 9d907ffc17f..d77750d2a04 100644 --- a/src/test/compile-fail/unboxed-closures-wrong-arg-type-extern-fn.rs +++ b/src/test/compile-fail/unboxed-closures-wrong-arg-type-extern-fn.rs @@ -22,13 +22,11 @@ fn call_it_onceisize>(_: 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() { diff --git a/src/test/compile-fail/unsized6.rs b/src/test/compile-fail/unsized6.rs index 462d760a60c..dec8699f46e 100644 --- a/src/test/compile-fail/unsized6.rs +++ b/src/test/compile-fail/unsized6.rs @@ -12,15 +12,15 @@ trait T {} -fn f1(x: &X) { - let _: X; // <-- this is OK, no bindings created, no initializer. +fn f1(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: &X) { +fn f2(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(x1: Box, x2: Box, x3: Box) { diff --git a/src/test/ui/mismatched_types/E0281.stderr b/src/test/ui/mismatched_types/E0281.stderr index fab48e9a740..3eb5c125789 100644 --- a/src/test/ui/mismatched_types/E0281.stderr +++ b/src/test/ui/mismatched_types/E0281.stderr @@ -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) diff --git a/src/test/ui/mismatched_types/binops.stderr b/src/test/ui/mismatched_types/binops.stderr index 1faf72cd760..cebdc12f568 100644 --- a/src/test/ui/mismatched_types/binops.stderr +++ b/src/test/ui/mismatched_types/binops.stderr @@ -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` 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` is not implemented for `{integer}` - error[E0277]: the trait bound `{integer}: std::cmp::PartialOrd` is not satisfied --> $DIR/binops.rs:16:7 | diff --git a/src/test/ui/mismatched_types/closure-arg-count.stderr b/src/test/ui/mismatched_types/closure-arg-count.stderr index cd16e5d70b6..85734dfac70 100644 --- a/src/test/ui/mismatched_types/closure-arg-count.stderr +++ b/src/test/ui/mismatched_types/closure-arg-count.stderr @@ -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) diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr index 8b756814ced..f818bd8bcb1 100644 --- a/src/test/ui/mismatched_types/issue-36053-2.stderr +++ b/src/test/ui/mismatched_types/issue-36053-2.stderr @@ -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) diff --git a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs index 7400a27fb6b..693a1585320 100644 --- a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs +++ b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs @@ -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 diff --git a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr index c5bfb6e45e7..643c9b36dbd 100644 --- a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr +++ b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr @@ -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) diff --git a/src/test/ui/type-check/issue-40294.stderr b/src/test/ui/type-check/issue-40294.stderr index bf03e52369f..cd474b14193 100644 --- a/src/test/ui/type-check/issue-40294.stderr +++ b/src/test/ui/type-check/issue-40294.stderr @@ -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)