diff --git a/src/doc/reference b/src/doc/reference index 320d232b206ed..5b9d2fcefadfc 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 320d232b206edecb67489316f71a14e31dbc6c08 +Subproject commit 5b9d2fcefadfc32fceafacfc0dd9441d9b57dd94 diff --git a/src/librustc/error_codes.rs b/src/librustc/error_codes.rs index 66c51000066b2..502172db91c9b 100644 --- a/src/librustc/error_codes.rs +++ b/src/librustc/error_codes.rs @@ -1700,6 +1700,27 @@ To understand better how closures work in Rust, read: https://doc.rust-lang.org/book/ch13-01-closures.html "##, +E0566: r##" +Conflicting representation hints have been used on a same item. + +Erroneous code example: + +``` +#[repr(u32, u64)] // warning! +enum Repr { A } +``` + +In most cases (if not all), using just one representation hint is more than +enough. If you want to have a representation hint depending on the current +architecture, use `cfg_attr`. Example: + +``` +#[cfg_attr(linux, repr(u32))] +#[cfg_attr(not(linux), repr(u64))] +enum Repr { A } +``` +"##, + E0580: r##" The `main` function was incorrectly declared. @@ -2097,7 +2118,6 @@ rejected in your own crates. E0490, // a value of type `..` is borrowed for too long E0495, // cannot infer an appropriate lifetime due to conflicting // requirements - E0566, // conflicting representation hints E0623, // lifetime mismatch where both parameters are anonymous regions E0628, // generators cannot have explicit parameters E0631, // type mismatch in closure arguments diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index d5892794d6496..42c5728dcc697 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -1053,6 +1053,13 @@ impl Mutability { MutImmutable => MutImmutable, } } + + pub fn invert(self) -> Self { + match self { + MutMutable => MutImmutable, + MutImmutable => MutMutable, + } + } } #[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Hash, HashStable)] diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index a1c97d6c68790..1e8f699b520f9 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -453,21 +453,17 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } - fn find_similar_impl_candidates(&self, - trait_ref: ty::PolyTraitRef<'tcx>) - -> Vec> - { - let simp = fast_reject::simplify_type(self.tcx, - trait_ref.skip_binder().self_ty(), - true); + fn find_similar_impl_candidates( + &self, + trait_ref: ty::PolyTraitRef<'tcx>, + ) -> Vec> { + let simp = fast_reject::simplify_type(self.tcx, trait_ref.skip_binder().self_ty(), true); let all_impls = self.tcx.all_impls(trait_ref.def_id()); match simp { Some(simp) => all_impls.iter().filter_map(|&def_id| { let imp = self.tcx.impl_trait_ref(def_id).unwrap(); - let imp_simp = fast_reject::simplify_type(self.tcx, - imp.self_ty(), - true); + let imp_simp = fast_reject::simplify_type(self.tcx, imp.self_ty(), true); if let Some(imp_simp) = imp_simp { if simp != imp_simp { return None @@ -482,10 +478,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } - fn report_similar_impl_candidates(&self, - impl_candidates: Vec>, - err: &mut DiagnosticBuilder<'_>) - { + fn report_similar_impl_candidates( + &self, + impl_candidates: Vec>, + err: &mut DiagnosticBuilder<'_>, + ) { if impl_candidates.is_empty() { return; } @@ -720,10 +717,18 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // which is somewhat confusing. err.help(&format!("consider adding a `where {}` bound", trait_ref.to_predicate())); - } else if !have_alt_message { - // Can't show anything else useful, try to find similar impls. - let impl_candidates = self.find_similar_impl_candidates(trait_ref); - self.report_similar_impl_candidates(impl_candidates, &mut err); + } else { + if !have_alt_message { + // Can't show anything else useful, try to find similar impls. + let impl_candidates = self.find_similar_impl_candidates(trait_ref); + self.report_similar_impl_candidates(impl_candidates, &mut err); + } + self.suggest_change_mut( + &obligation, + &mut err, + &trait_ref, + points_at_arg, + ); } // If this error is due to `!: Trait` not implemented but `(): Trait` is @@ -1081,9 +1086,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let substs = self.tcx.mk_substs_trait(trait_type, &[]); let new_trait_ref = ty::TraitRef::new(trait_ref.def_id, substs); - let new_obligation = Obligation::new(ObligationCause::dummy(), - obligation.param_env, - new_trait_ref.to_predicate()); + let new_obligation = Obligation::new( + ObligationCause::dummy(), + obligation.param_env, + new_trait_ref.to_predicate(), + ); if self.predicate_may_hold(&new_obligation) { let sp = self.tcx.sess.source_map() @@ -1105,6 +1112,71 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } + /// Check if the trait bound is implemented for a different mutability and note it in the + /// final error. + fn suggest_change_mut( + &self, + obligation: &PredicateObligation<'tcx>, + err: &mut DiagnosticBuilder<'tcx>, + trait_ref: &ty::Binder>, + points_at_arg: bool, + ) { + let span = obligation.cause.span; + if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { + let refs_number = snippet.chars() + .filter(|c| !c.is_whitespace()) + .take_while(|c| *c == '&') + .count(); + if let Some('\'') = snippet.chars() + .filter(|c| !c.is_whitespace()) + .skip(refs_number) + .next() + { // Do not suggest removal of borrow from type arguments. + return; + } + + if let ty::Ref(region, t_type, mutability) = trait_ref.skip_binder().self_ty().kind { + let trait_type = match mutability { + hir::Mutability::MutMutable => self.tcx.mk_imm_ref(region, t_type), + hir::Mutability::MutImmutable => self.tcx.mk_mut_ref(region, t_type), + }; + + let substs = self.tcx.mk_substs_trait(&trait_type, &[]); + let new_trait_ref = ty::TraitRef::new(trait_ref.skip_binder().def_id, substs); + let new_obligation = Obligation::new( + ObligationCause::dummy(), + obligation.param_env, + new_trait_ref.to_predicate(), + ); + + if self.evaluate_obligation_no_overflow( + &new_obligation, + ).must_apply_modulo_regions() { + let sp = self.tcx.sess.source_map() + .span_take_while(span, |c| c.is_whitespace() || *c == '&'); + if points_at_arg && + mutability == hir::Mutability::MutImmutable && + refs_number > 0 + { + err.span_suggestion( + sp, + "consider changing this borrow's mutability", + "&mut ".to_string(), + Applicability::MachineApplicable, + ); + } else { + err.note(&format!( + "`{}` is implemented for `{:?}`, but not for `{:?}`", + trait_ref, + trait_type, + trait_ref.skip_binder().self_ty(), + )); + } + } + } + } + } + fn suggest_semicolon_removal( &self, obligation: &PredicateObligation<'tcx>, diff --git a/src/librustc/traits/query/evaluate_obligation.rs b/src/librustc/traits/query/evaluate_obligation.rs index 17684df7e9b8e..0d426cab9b751 100644 --- a/src/librustc/traits/query/evaluate_obligation.rs +++ b/src/librustc/traits/query/evaluate_obligation.rs @@ -56,7 +56,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { // Helper function that canonicalizes and runs the query. If an // overflow results, we re-run it in the local context so we can // report a nice error. - fn evaluate_obligation_no_overflow( + crate fn evaluate_obligation_no_overflow( &self, obligation: &PredicateObligation<'tcx>, ) -> EvaluationResult { diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 41224ba40f33c..2d63711fc7e89 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -1775,6 +1775,10 @@ impl<'tcx> TyS<'tcx> { #[inline] pub fn is_bool(&self) -> bool { self.kind == Bool } + /// Returns `true` if this type is a `str`. + #[inline] + pub fn is_str(&self) -> bool { self.kind == Str } + #[inline] pub fn is_param(&self, index: u32) -> bool { match self.kind { diff --git a/src/librustc_errors/styled_buffer.rs b/src/librustc_errors/styled_buffer.rs index 6e03618d2b0b5..b12ab9e457602 100644 --- a/src/librustc_errors/styled_buffer.rs +++ b/src/librustc_errors/styled_buffer.rs @@ -111,7 +111,7 @@ impl StyledBuffer { pub fn prepend(&mut self, line: usize, string: &str, style: Style) { self.ensure_lines(line); - let string_len = string.len(); + let string_len = string.chars().count(); // Push the old content over to make room for new content for _ in 0..string_len { diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 2ea0afb179356..78bd4508e21a4 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -349,7 +349,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // If the span is from a macro, then it's hard to extract the text // and make a good suggestion, so don't bother. - let is_macro = sp.from_expansion(); + let is_desugaring = match sp.desugaring_kind() { + Some(k) => sp.is_desugaring(k), + None => false + }; + let is_macro = sp.from_expansion() && !is_desugaring; match (&expr.kind, &expected.kind, &checked_ty.kind) { (_, &ty::Ref(_, exp, _), &ty::Ref(_, check, _)) => match (&exp.kind, &check.kind) { diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index 7a6fe9560fbff..aa26c74967a1e 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -87,6 +87,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } if let Some(mut err) = self.demand_suptype_diag(expr.span, expected_ty, ty) { + self.suggest_ref_or_into(&mut err, expr, expected_ty, ty); + let expr = match &expr.kind { ExprKind::DropTemps(expr) => expr, _ => expr, diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 2be311127214d..434ead50e0423 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -58,7 +58,7 @@ pub enum MethodError<'tcx> { // Found a `Self: Sized` bound where `Self` is a trait object, also the caller may have // forgotten to import a trait. - IllegalSizedBound(Vec), + IllegalSizedBound(Vec, bool), // Found a match, but the return type is wrong BadReturnType, @@ -213,33 +213,49 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { segment, ); + let mut needs_mut = false; + if let ty::Ref(region, t_type, mutability) = self_ty.kind { + let trait_type = self.tcx.mk_ref(region, ty::TypeAndMut { + ty: t_type, + mutbl: mutability.invert(), + }); + match self.lookup_probe( + span, + segment.ident, + trait_type, + call_expr, + ProbeScope::TraitsInScope + ) { + Ok(ref new_pick) if *new_pick != pick => { + needs_mut = true; + } + _ => {} + } + } + if result.illegal_sized_bound { // We probe again, taking all traits into account (not only those in scope). - let candidates = - match self.lookup_probe(span, - segment.ident, - self_ty, - call_expr, - ProbeScope::AllTraits) { - - // If we find a different result the caller probably forgot to import a trait. - Ok(ref new_pick) if *new_pick != pick => vec![new_pick.item.container.id()], - Err(Ambiguity(ref sources)) => { - sources.iter() - .filter_map(|source| { - match *source { - // Note: this cannot come from an inherent impl, - // because the first probing succeeded. - ImplSource(def) => self.tcx.trait_id_of_impl(def), - TraitSource(_) => None, - } - }) - .collect() + let candidates = match self.lookup_probe( + span, + segment.ident, + self_ty, + call_expr, + ProbeScope::AllTraits, + ) { + // If we find a different result the caller probably forgot to import a trait. + Ok(ref new_pick) if *new_pick != pick => vec![new_pick.item.container.id()], + Err(Ambiguity(ref sources)) => sources.iter().filter_map(|source| { + match *source { + // Note: this cannot come from an inherent impl, + // because the first probing succeeded. + ImplSource(def) => self.tcx.trait_id_of_impl(def), + TraitSource(_) => None, } - _ => Vec::new(), - }; + }).collect(), + _ => Vec::new(), + }; - return Err(IllegalSizedBound(candidates)); + return Err(IllegalSizedBound(candidates, needs_mut)); } Ok(result.callee) diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 2b34c24b266d0..c19ea57802361 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -518,7 +518,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - if let Some(lev_candidate) = lev_candidate { + if item_name.as_str() == "as_str" && actual.peel_refs().is_str() { + // FIXME: the span is not quite correct, it should point to ".as_str()" instead + // of just "as_str". + err.span_label( + span, + "try removing `as_str`" + ); + } else if let Some(lev_candidate) = lev_candidate { let def_kind = lev_candidate.def_kind(); err.span_suggestion( span, @@ -553,22 +560,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.emit(); } - MethodError::IllegalSizedBound(candidates) => { + MethodError::IllegalSizedBound(candidates, needs_mut) => { let msg = format!("the `{}` method cannot be invoked on a trait object", item_name); let mut err = self.sess().struct_span_err(span, &msg); if !candidates.is_empty() { - let help = format!("{an}other candidate{s} {were} found in the following \ - trait{s}, perhaps add a `use` for {one_of_them}:", - an = if candidates.len() == 1 {"an" } else { "" }, - s = pluralise!(candidates.len()), - were = if candidates.len() == 1 { "was" } else { "were" }, - one_of_them = if candidates.len() == 1 { - "it" - } else { - "one_of_them" - }); + let help = format!( + "{an}other candidate{s} {were} found in the following trait{s}, perhaps \ + add a `use` for {one_of_them}:", + an = if candidates.len() == 1 {"an" } else { "" }, + s = pluralise!(candidates.len()), + were = if candidates.len() == 1 { "was" } else { "were" }, + one_of_them = if candidates.len() == 1 { + "it" + } else { + "one_of_them" + }, + ); self.suggest_use_candidates(&mut err, help, candidates); } + if let ty::Ref(region, t_type, mutability) = rcvr_ty.kind { + if needs_mut { + let trait_type = self.tcx.mk_ref(region, ty::TypeAndMut { + ty: t_type, + mutbl: mutability.invert(), + }); + err.note(&format!("you need `{}` instead of `{}`", trait_type, rcvr_ty)); + } + } err.emit(); } diff --git a/src/test/ui/conflicting-repr-hints.stderr b/src/test/ui/conflicting-repr-hints.stderr index 6b15b7ebbe9ee..832f5c3ac2bb7 100644 --- a/src/test/ui/conflicting-repr-hints.stderr +++ b/src/test/ui/conflicting-repr-hints.stderr @@ -66,3 +66,4 @@ LL | | } error: aborting due to 8 previous errors +For more information about this error, try `rustc --explain E0566`. diff --git a/src/test/ui/feature-gates/feature-gate-repr-simd.stderr b/src/test/ui/feature-gates/feature-gate-repr-simd.stderr index dfaa85bc5f014..02c8400e03e82 100644 --- a/src/test/ui/feature-gates/feature-gate-repr-simd.stderr +++ b/src/test/ui/feature-gates/feature-gate-repr-simd.stderr @@ -26,4 +26,5 @@ LL | #[repr(simd)] error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0566, E0658. +For more information about an error, try `rustc --explain E0566`. diff --git a/src/test/ui/if/if-no-match-bindings.stderr b/src/test/ui/if/if-no-match-bindings.stderr index cbf52476ae37f..53b7aafc430a2 100644 --- a/src/test/ui/if/if-no-match-bindings.stderr +++ b/src/test/ui/if/if-no-match-bindings.stderr @@ -2,7 +2,10 @@ error[E0308]: mismatched types --> $DIR/if-no-match-bindings.rs:18:8 | LL | if b_ref() {} - | ^^^^^^^ expected bool, found &bool + | ^^^^^^^ + | | + | expected bool, found &bool + | help: consider dereferencing the borrow: `*b_ref()` | = note: expected type `bool` found type `&bool` @@ -11,7 +14,10 @@ error[E0308]: mismatched types --> $DIR/if-no-match-bindings.rs:19:8 | LL | if b_mut_ref() {} - | ^^^^^^^^^^^ expected bool, found &mut bool + | ^^^^^^^^^^^ + | | + | expected bool, found &mut bool + | help: consider dereferencing the borrow: `*b_mut_ref()` | = note: expected type `bool` found type `&mut bool` @@ -20,7 +26,10 @@ error[E0308]: mismatched types --> $DIR/if-no-match-bindings.rs:20:8 | LL | if &true {} - | ^^^^^ expected bool, found &bool + | ^^^^^ + | | + | expected bool, found &bool + | help: consider dereferencing the borrow: `*&true` | = note: expected type `bool` found type `&bool` @@ -29,7 +38,10 @@ error[E0308]: mismatched types --> $DIR/if-no-match-bindings.rs:21:8 | LL | if &mut true {} - | ^^^^^^^^^ expected bool, found &mut bool + | ^^^^^^^^^ + | | + | expected bool, found &mut bool + | help: consider dereferencing the borrow: `*&mut true` | = note: expected type `bool` found type `&mut bool` @@ -38,7 +50,10 @@ error[E0308]: mismatched types --> $DIR/if-no-match-bindings.rs:24:11 | LL | while b_ref() {} - | ^^^^^^^ expected bool, found &bool + | ^^^^^^^ + | | + | expected bool, found &bool + | help: consider dereferencing the borrow: `*b_ref()` | = note: expected type `bool` found type `&bool` @@ -47,7 +62,10 @@ error[E0308]: mismatched types --> $DIR/if-no-match-bindings.rs:25:11 | LL | while b_mut_ref() {} - | ^^^^^^^^^^^ expected bool, found &mut bool + | ^^^^^^^^^^^ + | | + | expected bool, found &mut bool + | help: consider dereferencing the borrow: `*b_mut_ref()` | = note: expected type `bool` found type `&mut bool` @@ -56,7 +74,10 @@ error[E0308]: mismatched types --> $DIR/if-no-match-bindings.rs:26:11 | LL | while &true {} - | ^^^^^ expected bool, found &bool + | ^^^^^ + | | + | expected bool, found &bool + | help: consider dereferencing the borrow: `*&true` | = note: expected type `bool` found type `&bool` @@ -65,7 +86,10 @@ error[E0308]: mismatched types --> $DIR/if-no-match-bindings.rs:27:11 | LL | while &mut true {} - | ^^^^^^^^^ expected bool, found &mut bool + | ^^^^^^^^^ + | | + | expected bool, found &mut bool + | help: consider dereferencing the borrow: `*&mut true` | = note: expected type `bool` found type `&mut bool` diff --git a/src/test/ui/not-panic/not-panic-safe.stderr b/src/test/ui/not-panic/not-panic-safe.stderr index aa18b923044c6..2362ccd32de99 100644 --- a/src/test/ui/not-panic/not-panic-safe.stderr +++ b/src/test/ui/not-panic/not-panic-safe.stderr @@ -8,6 +8,7 @@ LL | assert::<&mut i32>(); | ^^^^^^^^^^^^^^^^^^ `&mut i32` may not be safely transferred across an unwind boundary | = help: the trait `std::panic::UnwindSafe` is not implemented for `&mut i32` + = note: `std::panic::UnwindSafe` is implemented for `&i32`, but not for `&mut i32` error: aborting due to previous error diff --git a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr index 4edc00efc7e72..619f9c85b24db 100644 --- a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr +++ b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr @@ -517,7 +517,10 @@ error[E0308]: mismatched types --> $DIR/disallowed-positions.rs:32:8 | LL | if &let 0 = 0 {} - | ^^^^^^^^^^ expected bool, found &bool + | ^^^^^^^^^^ + | | + | expected bool, found &bool + | help: consider dereferencing the borrow: `*&let 0 = 0` | = note: expected type `bool` found type `&bool` @@ -702,7 +705,10 @@ error[E0308]: mismatched types --> $DIR/disallowed-positions.rs:96:11 | LL | while &let 0 = 0 {} - | ^^^^^^^^^^ expected bool, found &bool + | ^^^^^^^^^^ + | | + | expected bool, found &bool + | help: consider dereferencing the borrow: `*&let 0 = 0` | = note: expected type `bool` found type `&bool` diff --git a/src/test/ui/suggestions/imm-ref-trait-object-literal.rs b/src/test/ui/suggestions/imm-ref-trait-object-literal.rs new file mode 100644 index 0000000000000..22ca6dde45eee --- /dev/null +++ b/src/test/ui/suggestions/imm-ref-trait-object-literal.rs @@ -0,0 +1,14 @@ +trait Trait {} + +struct S; + +impl<'a> Trait for &'a mut S {} + +fn foo(_: X) {} + + +fn main() { + let s = S; + foo(&s); //~ ERROR the trait bound `&S: Trait` is not satisfied + foo(s); //~ ERROR the trait bound `S: Trait` is not satisfied +} diff --git a/src/test/ui/suggestions/imm-ref-trait-object-literal.stderr b/src/test/ui/suggestions/imm-ref-trait-object-literal.stderr new file mode 100644 index 0000000000000..ccaceefacd739 --- /dev/null +++ b/src/test/ui/suggestions/imm-ref-trait-object-literal.stderr @@ -0,0 +1,30 @@ +error[E0277]: the trait bound `&S: Trait` is not satisfied + --> $DIR/imm-ref-trait-object-literal.rs:12:7 + | +LL | fn foo(_: X) {} + | --- ----- required by this bound in `foo` +... +LL | foo(&s); + | -^ + | | + | the trait `Trait` is not implemented for `&S` + | help: consider changing this borrow's mutability: `&mut` + | + = help: the following implementations were found: + <&'a mut S as Trait> + +error[E0277]: the trait bound `S: Trait` is not satisfied + --> $DIR/imm-ref-trait-object-literal.rs:13:7 + | +LL | fn foo(_: X) {} + | --- ----- required by this bound in `foo` +... +LL | foo(s); + | ^ the trait `Trait` is not implemented for `S` + | + = help: the following implementations were found: + <&'a mut S as Trait> + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/imm-ref-trait-object.rs b/src/test/ui/suggestions/imm-ref-trait-object.rs new file mode 100644 index 0000000000000..288d6c699f59a --- /dev/null +++ b/src/test/ui/suggestions/imm-ref-trait-object.rs @@ -0,0 +1,8 @@ +fn test(t: &dyn Iterator) -> u64 { + t.min().unwrap() //~ ERROR the `min` method cannot be invoked on a trait object +} + +fn main() { + let array = [0u64]; + test(&mut array.iter()); +} diff --git a/src/test/ui/suggestions/imm-ref-trait-object.stderr b/src/test/ui/suggestions/imm-ref-trait-object.stderr new file mode 100644 index 0000000000000..9185eaa65c06d --- /dev/null +++ b/src/test/ui/suggestions/imm-ref-trait-object.stderr @@ -0,0 +1,10 @@ +error: the `min` method cannot be invoked on a trait object + --> $DIR/imm-ref-trait-object.rs:2:8 + | +LL | t.min().unwrap() + | ^^^ + | + = note: you need `&mut dyn std::iter::Iterator` instead of `&dyn std::iter::Iterator` + +error: aborting due to previous error + diff --git a/src/test/ui/suggestions/into-str.stderr b/src/test/ui/suggestions/into-str.stderr index fb3e1096ad54c..a1e1f4d13572a 100644 --- a/src/test/ui/suggestions/into-str.stderr +++ b/src/test/ui/suggestions/into-str.stderr @@ -8,6 +8,7 @@ LL | foo(String::new()); | ^^^ the trait `std::convert::From` is not implemented for `&str` | = note: to coerce a `std::string::String` into a `&str`, use `&*` as a prefix + = note: `std::convert::From` is implemented for `&mut str`, but not for `&str` = note: required because of the requirements on the impl of `std::convert::Into<&str>` for `std::string::String` error: aborting due to previous error diff --git a/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs b/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs new file mode 100644 index 0000000000000..dcef2ada63bea --- /dev/null +++ b/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs @@ -0,0 +1,23 @@ +use std::env::args; +use std::fs::File; +use std::io::{stdout, Write, BufWriter}; + +fn main() { + let mut args = args(); + let _ = args.next(); + let dest = args.next(); + + let h1; let h2; let h3; + + let fp: &dyn Write = match dest { + Some(path) => { h1 = File::create(path).unwrap(); &h1 }, + None => { h2 = stdout(); h3 = h2.lock(); &h3 } + }; + + let fp = BufWriter::new(fp); + //~^ ERROR the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied + //~| ERROR the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied + //~| ERROR the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied + + writeln!(fp, "hello world").unwrap(); //~ ERROR no method named `write_fmt` found for type +} diff --git a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr new file mode 100644 index 0000000000000..daa8e1162d197 --- /dev/null +++ b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr @@ -0,0 +1,41 @@ +error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied + --> $DIR/mut-borrow-needed-by-trait.rs:17:29 + | +LL | let fp = BufWriter::new(fp); + | ^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write` + | + = note: `std::io::Write` is implemented for `&mut dyn std::io::Write`, but not for `&dyn std::io::Write` + = note: required by `std::io::BufWriter::::new` + +error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied + --> $DIR/mut-borrow-needed-by-trait.rs:17:14 + | +LL | let fp = BufWriter::new(fp); + | ^^^^^^^^^^^^^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write` + | + = note: `std::io::Write` is implemented for `&mut dyn std::io::Write`, but not for `&dyn std::io::Write` + = note: required by `std::io::BufWriter` + +error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied + --> $DIR/mut-borrow-needed-by-trait.rs:17:14 + | +LL | let fp = BufWriter::new(fp); + | ^^^^^^^^^^^^^^^^^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write` + | + = note: `std::io::Write` is implemented for `&mut dyn std::io::Write`, but not for `&dyn std::io::Write` + = note: required by `std::io::BufWriter` + +error[E0599]: no method named `write_fmt` found for type `std::io::BufWriter<&dyn std::io::Write>` in the current scope + --> $DIR/mut-borrow-needed-by-trait.rs:22:5 + | +LL | writeln!(fp, "hello world").unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ method not found in `std::io::BufWriter<&dyn std::io::Write>` + | + = note: the method `write_fmt` exists but the following trait bounds were not satisfied: + `std::io::BufWriter<&dyn std::io::Write> : std::io::Write` + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0277, E0599. +For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/remove-as_str.rs b/src/test/ui/suggestions/remove-as_str.rs new file mode 100644 index 0000000000000..d10300b48ba1e --- /dev/null +++ b/src/test/ui/suggestions/remove-as_str.rs @@ -0,0 +1,21 @@ +fn foo1(s: &str) { + s.as_str(); + //~^ ERROR no method named `as_str` found for type `&str` in the current scope +} + +fn foo2<'a>(s: &'a str) { + s.as_str(); + //~^ ERROR no method named `as_str` found for type `&'a str` in the current scope +} + +fn foo3(s: &mut str) { + s.as_str(); + //~^ ERROR no method named `as_str` found for type `&mut str` in the current scope +} + +fn foo4(s: &&str) { + s.as_str(); + //~^ ERROR no method named `as_str` found for type `&&str` in the current scope +} + +fn main() {} diff --git a/src/test/ui/suggestions/remove-as_str.stderr b/src/test/ui/suggestions/remove-as_str.stderr new file mode 100644 index 0000000000000..2e8b72ebd4f6d --- /dev/null +++ b/src/test/ui/suggestions/remove-as_str.stderr @@ -0,0 +1,27 @@ +error[E0599]: no method named `as_str` found for type `&str` in the current scope + --> $DIR/remove-as_str.rs:2:7 + | +LL | s.as_str(); + | ^^^^^^ try removing `as_str` + +error[E0599]: no method named `as_str` found for type `&'a str` in the current scope + --> $DIR/remove-as_str.rs:7:7 + | +LL | s.as_str(); + | ^^^^^^ try removing `as_str` + +error[E0599]: no method named `as_str` found for type `&mut str` in the current scope + --> $DIR/remove-as_str.rs:12:7 + | +LL | s.as_str(); + | ^^^^^^ try removing `as_str` + +error[E0599]: no method named `as_str` found for type `&&str` in the current scope + --> $DIR/remove-as_str.rs:17:7 + | +LL | s.as_str(); + | ^^^^^^ try removing `as_str` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/suggestions/suggest-remove-refs-1.stderr b/src/test/ui/suggestions/suggest-remove-refs-1.stderr index bfc313cabdc44..04d17a16cc356 100644 --- a/src/test/ui/suggestions/suggest-remove-refs-1.stderr +++ b/src/test/ui/suggestions/suggest-remove-refs-1.stderr @@ -8,6 +8,7 @@ LL | for (i, n) in &v.iter().enumerate() { | help: consider removing 1 leading `&`-references | = help: the trait `std::iter::Iterator` is not implemented for `&std::iter::Enumerate>` + = note: `std::iter::Iterator` is implemented for `&mut std::iter::Enumerate>`, but not for `&std::iter::Enumerate>` = note: required by `std::iter::IntoIterator::into_iter` error: aborting due to previous error