From 9067e4417e52643596ae8dbc4ec6369a0d856b45 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Wed, 28 Dec 2022 18:06:11 +0100 Subject: Rename `Rptr` to `Ref` in AST and HIR The name makes a lot more sense, and `ty::TyKind` calls it `Ref` already as well. --- src/test/ui/macros/stringify.rs | 2 +- src/test/ui/stats/hir-stats.stderr | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src/test/ui') diff --git a/src/test/ui/macros/stringify.rs b/src/test/ui/macros/stringify.rs index bc0d4488162..5cd217df6fc 100644 --- a/src/test/ui/macros/stringify.rs +++ b/src/test/ui/macros/stringify.rs @@ -801,7 +801,7 @@ fn test_ty() { assert_eq!(stringify_ty!(*const T), "*const T"); assert_eq!(stringify_ty!(*mut T), "*mut T"); - // TyKind::Rptr + // TyKind::Ref assert_eq!(stringify_ty!(&T), "&T"); assert_eq!(stringify_ty!(&mut T), "&mut T"); assert_eq!(stringify_ty!(&'a T), "&'a T"); diff --git a/src/test/ui/stats/hir-stats.stderr b/src/test/ui/stats/hir-stats.stderr index 15900bef7f6..7d9ff2dfb4d 100644 --- a/src/test/ui/stats/hir-stats.stderr +++ b/src/test/ui/stats/hir-stats.stderr @@ -41,8 +41,8 @@ ast-stats-1 - Wild 88 ( 1.2%) 1 ast-stats-1 - Ident 440 ( 5.9%) 5 ast-stats-1 PathSegment 720 ( 9.7%) 30 24 ast-stats-1 Ty 896 (12.1%) 14 64 -ast-stats-1 - Rptr 64 ( 0.9%) 1 ast-stats-1 - Ptr 64 ( 0.9%) 1 +ast-stats-1 - Ref 64 ( 0.9%) 1 ast-stats-1 - ImplicitSelf 128 ( 1.7%) 2 ast-stats-1 - Path 640 ( 8.6%) 10 ast-stats-1 Item 1_656 (22.3%) 9 184 @@ -100,8 +100,8 @@ ast-stats-2 - Lit 144 ( 1.8%) 2 ast-stats-2 - Block 216 ( 2.7%) 3 ast-stats-2 PathSegment 792 ( 9.8%) 33 24 ast-stats-2 Ty 896 (11.0%) 14 64 -ast-stats-2 - Rptr 64 ( 0.8%) 1 ast-stats-2 - Ptr 64 ( 0.8%) 1 +ast-stats-2 - Ref 64 ( 0.8%) 1 ast-stats-2 - ImplicitSelf 128 ( 1.6%) 2 ast-stats-2 - Path 640 ( 7.9%) 10 ast-stats-2 Item 2_024 (25.0%) 11 184 @@ -154,7 +154,7 @@ hir-stats GenericParam 400 ( 4.4%) 5 80 hir-stats Generics 560 ( 6.2%) 10 56 hir-stats Ty 720 ( 8.0%) 15 48 hir-stats - Ptr 48 ( 0.5%) 1 -hir-stats - Rptr 48 ( 0.5%) 1 +hir-stats - Ref 48 ( 0.5%) 1 hir-stats - Path 624 ( 6.9%) 13 hir-stats Expr 768 ( 8.5%) 12 64 hir-stats - Path 64 ( 0.7%) 1 -- cgit 1.4.1-3-g733a5 From 01d784131f0a11d19d0ab5398b00ca6bbfd283b1 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 28 Dec 2022 06:35:34 +0000 Subject: Make trait/impl where clause mismatch on region error a bit more actionable --- .../rustc_infer/src/infer/error_reporting/note.rs | 129 ++++++++++++++------- src/test/ui/compare-method/region-extra-2.stderr | 5 + src/test/ui/compare-method/region-extra.stderr | 6 + .../ui/generic-associated-types/impl_bounds.stderr | 5 + .../ui/generic-associated-types/issue-90014.stderr | 6 +- .../ui/generic-associated-types/issue-91883.stderr | 6 +- .../ui/generic-associated-types/issue-92033.stderr | 6 +- .../missing-where-clause-on-trait.stderr | 6 + 8 files changed, 127 insertions(+), 42 deletions(-) (limited to 'src/test/ui') diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs index d2dffa4a0b7..891c77d1810 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs @@ -2,11 +2,14 @@ use crate::errors::RegionOriginNote; use crate::infer::error_reporting::{note_and_explain_region, TypeErrCtxt}; use crate::infer::{self, SubregionOrigin}; use rustc_errors::{ - fluent, struct_span_err, AddToDiagnostic, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, + fluent, struct_span_err, AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder, + ErrorGuaranteed, }; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::traits::ObligationCauseCode; use rustc_middle::ty::error::TypeError; -use rustc_middle::ty::{self, Region}; +use rustc_middle::ty::{self, IsSuggestable, Region}; +use rustc_span::symbol::kw; use super::ObligationCauseAsDiagArg; @@ -313,55 +316,43 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { ); err } - infer::CompareImplItemObligation { span, impl_item_def_id, trait_item_def_id } => self - .report_extra_impl_obligation( + infer::CompareImplItemObligation { span, impl_item_def_id, trait_item_def_id } => { + let mut err = self.report_extra_impl_obligation( span, impl_item_def_id, trait_item_def_id, &format!("`{}: {}`", sup, sub), - ), + ); + // We should only suggest rewriting the `where` clause if the predicate is within that `where` clause + if self + .tcx + .hir() + .get_generics(impl_item_def_id) + .unwrap() + .where_clause_span + .contains(span) + { + self.suggest_copy_trait_method_bounds( + trait_item_def_id, + impl_item_def_id, + &mut err, + ); + } + err + } infer::CheckAssociatedTypeBounds { impl_item_def_id, trait_item_def_id, parent } => { let mut err = self.report_concrete_failure(*parent, sub, sup); - let trait_item_span = self.tcx.def_span(trait_item_def_id); let item_name = self.tcx.item_name(impl_item_def_id.to_def_id()); err.span_label( trait_item_span, format!("definition of `{}` from trait", item_name), ); - - let trait_predicates = self.tcx.explicit_predicates_of(trait_item_def_id); - let impl_predicates = self.tcx.explicit_predicates_of(impl_item_def_id); - - let impl_predicates: rustc_data_structures::fx::FxHashSet<_> = - impl_predicates.predicates.into_iter().map(|(pred, _)| pred).collect(); - let clauses: Vec<_> = trait_predicates - .predicates - .into_iter() - .filter(|&(pred, _)| !impl_predicates.contains(pred)) - .map(|(pred, _)| format!("{}", pred)) - .collect(); - - if !clauses.is_empty() { - let generics = self.tcx.hir().get_generics(impl_item_def_id).unwrap(); - let where_clause_span = generics.tail_span_for_predicate_suggestion(); - - let suggestion = format!( - "{} {}", - generics.add_where_or_trailing_comma(), - clauses.join(", "), - ); - err.span_suggestion( - where_clause_span, - &format!( - "try copying {} from the trait", - if clauses.len() > 1 { "these clauses" } else { "this clause" } - ), - suggestion, - rustc_errors::Applicability::MaybeIncorrect, - ); - } - + self.suggest_copy_trait_method_bounds( + trait_item_def_id, + impl_item_def_id, + &mut err, + ); err } infer::AscribeUserTypeProvePredicate(span) => { @@ -388,6 +379,66 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } } + pub fn suggest_copy_trait_method_bounds( + &self, + trait_item_def_id: DefId, + impl_item_def_id: LocalDefId, + err: &mut Diagnostic, + ) { + // FIXME(compiler-errors): Right now this is only being used for region + // predicate mismatches. Ideally, we'd use it for *all* predicate mismatches, + // but right now it's not really very smart when it comes to implicit `Sized` + // predicates and bounds on the trait itself. + + let impl_def_id = + self.tcx.associated_item(impl_item_def_id).impl_container(self.tcx).unwrap(); + let trait_substs = self + .tcx + .impl_trait_ref(impl_def_id) + .unwrap() + // Replace the explicit self type with `Self` for better suggestion rendering + .with_self_ty(self.tcx, self.tcx.mk_ty_param(0, kw::SelfUpper)) + .substs; + let trait_item_substs = + ty::InternalSubsts::identity_for_item(self.tcx, impl_item_def_id.to_def_id()) + .rebase_onto(self.tcx, impl_def_id, trait_substs); + + let mut is_suggestable = true; + let trait_predicates = self + .tcx + .bound_explicit_predicates_of(trait_item_def_id) + .map_bound(|p| p.predicates) + .subst_iter_copied(self.tcx, trait_item_substs) + .map(|(pred, _)| { + if !pred.is_suggestable(self.tcx, false) { + is_suggestable = false; + } + pred.to_string() + }) + .collect::>(); + + let generics = self.tcx.hir().get_generics(impl_item_def_id).unwrap(); + + if is_suggestable { + if trait_predicates.is_empty() { + err.span_suggestion_verbose( + generics.where_clause_span, + "remove the `where` clause", + String::new(), + Applicability::MachineApplicable, + ); + } else { + let space = if generics.where_clause_span.is_empty() { " " } else { "" }; + err.span_suggestion_verbose( + generics.where_clause_span, + "copy the `where` clause predicates from the trait", + format!("{space}where {}", trait_predicates.join(", ")), + Applicability::MachineApplicable, + ); + } + } + } + pub(super) fn report_placeholder_failure( &self, placeholder_origin: SubregionOrigin<'tcx>, diff --git a/src/test/ui/compare-method/region-extra-2.stderr b/src/test/ui/compare-method/region-extra-2.stderr index f01d7f4710c..eb19d57ab05 100644 --- a/src/test/ui/compare-method/region-extra-2.stderr +++ b/src/test/ui/compare-method/region-extra-2.stderr @@ -6,6 +6,11 @@ LL | fn renew<'b: 'a>(self) -> &'b mut [T]; ... LL | fn renew<'b: 'a>(self) -> &'b mut [T] where 'a: 'b { | ^^ impl has extra requirement `'a: 'b` + | +help: copy the `where` clause predicates from the trait + | +LL | fn renew<'b: 'a>(self) -> &'b mut [T] where 'b: 'a { + | ~~~~~~~~~~~~ error: aborting due to previous error diff --git a/src/test/ui/compare-method/region-extra.stderr b/src/test/ui/compare-method/region-extra.stderr index 4a3af65e904..1a471e18d9d 100644 --- a/src/test/ui/compare-method/region-extra.stderr +++ b/src/test/ui/compare-method/region-extra.stderr @@ -6,6 +6,12 @@ LL | fn foo(); ... LL | fn foo() where 'a: 'b { } | ^^ impl has extra requirement `'a: 'b` + | +help: remove the `where` clause + | +LL - fn foo() where 'a: 'b { } +LL + fn foo() { } + | error: aborting due to previous error diff --git a/src/test/ui/generic-associated-types/impl_bounds.stderr b/src/test/ui/generic-associated-types/impl_bounds.stderr index 3acd85c8ac6..3456b345cc2 100644 --- a/src/test/ui/generic-associated-types/impl_bounds.stderr +++ b/src/test/ui/generic-associated-types/impl_bounds.stderr @@ -15,6 +15,11 @@ LL | type B<'a, 'b> where 'a: 'b; ... LL | type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a; | ^^ impl has extra requirement `'b: 'a` + | +help: copy the `where` clause predicates from the trait + | +LL | type B<'a, 'b> = (&'a(), &'b ()) where 'a: 'b; + | ~~~~~~~~~~~~ error[E0277]: the trait bound `T: Copy` is not satisfied --> $DIR/impl_bounds.rs:18:33 diff --git a/src/test/ui/generic-associated-types/issue-90014.stderr b/src/test/ui/generic-associated-types/issue-90014.stderr index 2d3f4a6af7e..b4b1bc7da7f 100644 --- a/src/test/ui/generic-associated-types/issue-90014.stderr +++ b/src/test/ui/generic-associated-types/issue-90014.stderr @@ -5,13 +5,17 @@ LL | type Fut<'a> where Self: 'a; | ------------ definition of `Fut` from trait ... LL | type Fut<'a> = impl Future; - | ^^^^^^^^^^^^^^^^^^^^^^^^- help: try copying this clause from the trait: `where Self: 'a` + | ^^^^^^^^^^^^^^^^^^^^^^^^ | note: type must outlive the lifetime `'a` as defined here --> $DIR/issue-90014.rs:13:14 | LL | type Fut<'a> = impl Future; | ^^ +help: copy the `where` clause predicates from the trait + | +LL | type Fut<'a> = impl Future where Self: 'a; + | ++++++++++++++ error: aborting due to previous error diff --git a/src/test/ui/generic-associated-types/issue-91883.stderr b/src/test/ui/generic-associated-types/issue-91883.stderr index 1cfc2aaf161..d5db962094c 100644 --- a/src/test/ui/generic-associated-types/issue-91883.stderr +++ b/src/test/ui/generic-associated-types/issue-91883.stderr @@ -5,7 +5,7 @@ LL | type Cursor<'tx>: Cursor<'tx> | ----------------------------- definition of `Cursor` from trait ... LL | type Cursor<'tx> = CursorImpl<'tx>; - | ^^^^^^^^^^^^^^^- help: try copying these clauses from the trait: `where 'db: 'tx, Self: 'tx` + | ^^^^^^^^^^^^^^^ | note: lifetime parameter instantiated with the lifetime `'db` as defined here --> $DIR/issue-91883.rs:29:6 @@ -17,6 +17,10 @@ note: but lifetime parameter must outlive the lifetime `'tx` as defined here | LL | type Cursor<'tx> = CursorImpl<'tx>; | ^^^ +help: copy the `where` clause predicates from the trait + | +LL | type Cursor<'tx> = CursorImpl<'tx> where 'db: 'tx, Self: 'tx; + | +++++++++++++++++++++++++ error: aborting due to previous error diff --git a/src/test/ui/generic-associated-types/issue-92033.stderr b/src/test/ui/generic-associated-types/issue-92033.stderr index cd7eed25421..ddc420a7b4e 100644 --- a/src/test/ui/generic-associated-types/issue-92033.stderr +++ b/src/test/ui/generic-associated-types/issue-92033.stderr @@ -5,13 +5,17 @@ LL | type TextureIter<'a>: Iterator | -------------------------------------------------- definition of `TextureIter` from trait ... LL | type TextureIter<'a> = std::option::IntoIter<&'a Texture>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- help: try copying this clause from the trait: `where Self: 'a` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: type must outlive the lifetime `'a` as defined here --> $DIR/issue-92033.rs:20:22 | LL | type TextureIter<'a> = std::option::IntoIter<&'a Texture>; | ^^ +help: copy the `where` clause predicates from the trait + | +LL | type TextureIter<'a> = std::option::IntoIter<&'a Texture> where Self: 'a; + | ++++++++++++++ error: aborting due to previous error diff --git a/src/test/ui/generic-associated-types/missing-where-clause-on-trait.stderr b/src/test/ui/generic-associated-types/missing-where-clause-on-trait.stderr index ffdba6676bf..8a71fc73a9d 100644 --- a/src/test/ui/generic-associated-types/missing-where-clause-on-trait.stderr +++ b/src/test/ui/generic-associated-types/missing-where-clause-on-trait.stderr @@ -6,6 +6,12 @@ LL | type Assoc<'a, 'b>; ... LL | type Assoc<'a, 'b> = () where 'a: 'b; | ^^ impl has extra requirement `'a: 'b` + | +help: remove the `where` clause + | +LL - type Assoc<'a, 'b> = () where 'a: 'b; +LL + type Assoc<'a, 'b> = () ; + | error: aborting due to previous error -- cgit 1.4.1-3-g733a5 From 992ba801c271aeb087b1619467c487e35bae4e65 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 28 Dec 2022 06:44:29 +0000 Subject: Add test for bad suggestion --- .../mismatched-where-clause-regions.rs | 12 ++++++++++++ .../mismatched-where-clause-regions.stderr | 17 +++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 src/test/ui/generic-associated-types/mismatched-where-clause-regions.rs create mode 100644 src/test/ui/generic-associated-types/mismatched-where-clause-regions.stderr (limited to 'src/test/ui') diff --git a/src/test/ui/generic-associated-types/mismatched-where-clause-regions.rs b/src/test/ui/generic-associated-types/mismatched-where-clause-regions.rs new file mode 100644 index 00000000000..8caf5317693 --- /dev/null +++ b/src/test/ui/generic-associated-types/mismatched-where-clause-regions.rs @@ -0,0 +1,12 @@ +trait Foo { + type T<'a1, 'b1> + where + 'a1: 'b1; +} + +impl Foo for () { + type T<'a2, 'b2> = () where 'b2: 'a2; + //~^ ERROR impl has stricter requirements than trait +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/mismatched-where-clause-regions.stderr b/src/test/ui/generic-associated-types/mismatched-where-clause-regions.stderr new file mode 100644 index 00000000000..91a03007640 --- /dev/null +++ b/src/test/ui/generic-associated-types/mismatched-where-clause-regions.stderr @@ -0,0 +1,17 @@ +error[E0276]: impl has stricter requirements than trait + --> $DIR/mismatched-where-clause-regions.rs:8:38 + | +LL | type T<'a1, 'b1> + | ---------------- definition of `T` from trait +... +LL | type T<'a2, 'b2> = () where 'b2: 'a2; + | ^^^ impl has extra requirement `'b2: 'a2` + | +help: copy the `where` clause predicates from the trait + | +LL | type T<'a2, 'b2> = () where 'a2: 'b2; + | ~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0276`. -- cgit 1.4.1-3-g733a5 From 083eb936ec0fd05fc6c227e5aa2992971f1fe2d1 Mon Sep 17 00:00:00 2001 From: Esteban Küber Date: Wed, 28 Dec 2022 09:26:30 -0800 Subject: On unsized locals with explicit types suggest `&` Fix #72742. --- .../src/traits/error_reporting/suggestions.rs | 9 ++++ src/test/ui/unsized-locals/suggest-borrow.rs | 7 +++ src/test/ui/unsized-locals/suggest-borrow.stderr | 60 ++++++++++++++++++++++ .../unsized-locals-using-unsized-fn-params.stderr | 4 ++ src/test/ui/unsized/unsized6.stderr | 16 ++++++ 5 files changed, 96 insertions(+) create mode 100644 src/test/ui/unsized-locals/suggest-borrow.rs create mode 100644 src/test/ui/unsized-locals/suggest-borrow.stderr (limited to 'src/test/ui') diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 472086eca8f..26ba3d780d5 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -2514,6 +2514,15 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ObligationCauseCode::VariableType(hir_id) => { let parent_node = self.tcx.hir().get_parent_node(hir_id); match self.tcx.hir().find(parent_node) { + Some(Node::Local(hir::Local { ty: Some(ty), .. })) => { + err.span_suggestion_verbose( + ty.span.shrink_to_lo(), + "consider borrowing here", + "&", + Applicability::MachineApplicable, + ); + err.note("all local variables must have a statically known size"); + } Some(Node::Local(hir::Local { init: Some(hir::Expr { kind: hir::ExprKind::Index(_, _), span, .. }), .. diff --git a/src/test/ui/unsized-locals/suggest-borrow.rs b/src/test/ui/unsized-locals/suggest-borrow.rs new file mode 100644 index 00000000000..08694857993 --- /dev/null +++ b/src/test/ui/unsized-locals/suggest-borrow.rs @@ -0,0 +1,7 @@ +fn main() { + let x: [u8] = vec!(1, 2, 3)[..]; //~ ERROR E0277 + let x: &[u8] = vec!(1, 2, 3)[..]; //~ ERROR E0308 + let x: [u8] = &vec!(1, 2, 3)[..]; //~ ERROR E0308 + //~^ ERROR E0277 + let x: &[u8] = &vec!(1, 2, 3)[..]; +} diff --git a/src/test/ui/unsized-locals/suggest-borrow.stderr b/src/test/ui/unsized-locals/suggest-borrow.stderr new file mode 100644 index 00000000000..08745eab28d --- /dev/null +++ b/src/test/ui/unsized-locals/suggest-borrow.stderr @@ -0,0 +1,60 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/suggest-borrow.rs:2:9 + | +LL | let x: [u8] = vec!(1, 2, 3)[..]; + | ^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature +help: consider borrowing here + | +LL | let x: &[u8] = vec!(1, 2, 3)[..]; + | + + +error[E0308]: mismatched types + --> $DIR/suggest-borrow.rs:3:20 + | +LL | let x: &[u8] = vec!(1, 2, 3)[..]; + | ----- ^^^^^^^^^^^^^^^^^ + | | | + | | expected `&[u8]`, found slice `[{integer}]` + | | help: consider borrowing here: `&vec!(1, 2, 3)[..]` + | expected due to this + +error[E0308]: mismatched types + --> $DIR/suggest-borrow.rs:4:19 + | +LL | let x: [u8] = &vec!(1, 2, 3)[..]; + | ---- ^^^^^^^^^^^^^^^^^^ expected slice `[u8]`, found `&[{integer}]` + | | + | expected due to this + | +help: consider removing the borrow + | +LL - let x: [u8] = &vec!(1, 2, 3)[..]; +LL + let x: [u8] = vec!(1, 2, 3)[..]; + | +help: alternatively, consider changing the type annotation + | +LL | let x: &[u8] = &vec!(1, 2, 3)[..]; + | + + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/suggest-borrow.rs:4:9 + | +LL | let x: [u8] = &vec!(1, 2, 3)[..]; + | ^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature +help: consider borrowing here + | +LL | let x: &[u8] = &vec!(1, 2, 3)[..]; + | + + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/unsized-locals/unsized-locals-using-unsized-fn-params.stderr b/src/test/ui/unsized-locals/unsized-locals-using-unsized-fn-params.stderr index da77026673d..ace5a87187b 100644 --- a/src/test/ui/unsized-locals/unsized-locals-using-unsized-fn-params.stderr +++ b/src/test/ui/unsized-locals/unsized-locals-using-unsized-fn-params.stderr @@ -27,6 +27,10 @@ LL | let _foo: [u8] = *foo; = help: the trait `Sized` is not implemented for `[u8]` = note: all local variables must have a statically known size = help: unsized locals are gated as an unstable feature +help: consider borrowing here + | +LL | let _foo: &[u8] = *foo; + | + error: aborting due to 3 previous errors diff --git a/src/test/ui/unsized/unsized6.stderr b/src/test/ui/unsized/unsized6.stderr index 011f2b426c7..18ac1ea1875 100644 --- a/src/test/ui/unsized/unsized6.stderr +++ b/src/test/ui/unsized/unsized6.stderr @@ -14,6 +14,10 @@ help: consider removing the `?Sized` bound to make the type parameter `Sized` LL - fn f1(x: &X) { LL + fn f1(x: &X) { | +help: consider borrowing here + | +LL | let y: &Y; + | + error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized6.rs:7:12 @@ -62,6 +66,10 @@ help: consider removing the `?Sized` bound to make the type parameter `Sized` LL - fn f2(x: &X) { LL + fn f2(x: &X) { | +help: consider borrowing here + | +LL | let y: &X; + | + error[E0277]: the size for values of type `Y` cannot be known at compilation time --> $DIR/unsized6.rs:17:12 @@ -94,6 +102,10 @@ help: consider removing the `?Sized` bound to make the type parameter `Sized` LL - fn f3(x1: Box, x2: Box, x3: Box) { LL + fn f3(x1: Box, x2: Box, x3: Box) { | +help: consider borrowing here + | +LL | let y: &X = *x1; + | + error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized6.rs:24:9 @@ -144,6 +156,10 @@ help: consider removing the `?Sized` bound to make the type parameter `Sized` LL - fn f4(x1: Box, x2: Box, x3: Box) { LL + fn f4(x1: Box, x2: Box, x3: Box) { | +help: consider borrowing here + | +LL | let y: &X = *x1; + | + error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized6.rs:32:9 -- cgit 1.4.1-3-g733a5 From 375f02580522ddacb4777d194d48d82454bb6aa9 Mon Sep 17 00:00:00 2001 From: Esteban Küber Date: Wed, 28 Dec 2022 17:56:22 -0800 Subject: Detect diff markers in the parser Partly address #32059. --- compiler/rustc_parse/src/parser/diagnostics.rs | 54 +++++++++++++++++++++- compiler/rustc_parse/src/parser/item.rs | 11 ++++- compiler/rustc_parse/src/parser/stmt.rs | 10 ++++ src/test/ui/parser/diff-markers/fn-arg.rs | 16 +++++++ src/test/ui/parser/diff-markers/fn-arg.stderr | 14 ++++++ src/test/ui/parser/diff-markers/item-with-attr.rs | 10 ++++ .../ui/parser/diff-markers/item-with-attr.stderr | 14 ++++++ src/test/ui/parser/diff-markers/item.rs | 9 ++++ src/test/ui/parser/diff-markers/item.stderr | 14 ++++++ src/test/ui/parser/diff-markers/statement.rs | 15 ++++++ src/test/ui/parser/diff-markers/statement.stderr | 14 ++++++ src/test/ui/parser/diff-markers/trait-item.rs | 14 ++++++ src/test/ui/parser/diff-markers/trait-item.stderr | 14 ++++++ src/test/ui/parser/diff-markers/use-statement.rs | 9 ++++ .../ui/parser/diff-markers/use-statement.stderr | 14 ++++++ 15 files changed, 229 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/parser/diff-markers/fn-arg.rs create mode 100644 src/test/ui/parser/diff-markers/fn-arg.stderr create mode 100644 src/test/ui/parser/diff-markers/item-with-attr.rs create mode 100644 src/test/ui/parser/diff-markers/item-with-attr.stderr create mode 100644 src/test/ui/parser/diff-markers/item.rs create mode 100644 src/test/ui/parser/diff-markers/item.stderr create mode 100644 src/test/ui/parser/diff-markers/statement.rs create mode 100644 src/test/ui/parser/diff-markers/statement.stderr create mode 100644 src/test/ui/parser/diff-markers/trait-item.rs create mode 100644 src/test/ui/parser/diff-markers/trait-item.stderr create mode 100644 src/test/ui/parser/diff-markers/use-statement.rs create mode 100644 src/test/ui/parser/diff-markers/use-statement.stderr (limited to 'src/test/ui') diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 61fe379c3e9..ffadb77320a 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -31,7 +31,8 @@ use rustc_ast::{ use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{ - fluent, Applicability, DiagnosticBuilder, DiagnosticMessage, Handler, MultiSpan, PResult, + fluent, Applicability, DiagnosticBuilder, DiagnosticMessage, FatalError, Handler, MultiSpan, + PResult, }; use rustc_errors::{pluralize, Diagnostic, ErrorGuaranteed, IntoDiagnostic}; use rustc_session::errors::ExprParenthesesNeeded; @@ -2556,6 +2557,57 @@ impl<'a> Parser<'a> { Ok(()) } + pub fn is_diff_marker(&mut self, long_kind: &TokenKind, short_kind: &TokenKind) -> bool { + (0..3).all(|i| self.look_ahead(i, |tok| tok == long_kind)) + && self.look_ahead(3, |tok| tok == short_kind) + } + + fn diff_marker(&mut self, long_kind: &TokenKind, short_kind: &TokenKind) -> Option { + if self.is_diff_marker(long_kind, short_kind) { + let lo = self.token.span; + for _ in 0..4 { + self.bump(); + } + return Some(lo.to(self.prev_token.span)); + } + None + } + + pub fn recover_diff_marker(&mut self) { + let Some(start) = self.diff_marker(&TokenKind::BinOp(token::Shl), &TokenKind::Lt) else { + return; + }; + let mut spans = Vec::with_capacity(3); + spans.push(start); + let mut middle = None; + let mut end = None; + loop { + if self.token.kind == TokenKind::Eof { + break; + } + if let Some(span) = self.diff_marker(&TokenKind::EqEq, &TokenKind::Eq) { + spans.push(span); + middle = Some(span); + } + if let Some(span) = self.diff_marker(&TokenKind::BinOp(token::Shr), &TokenKind::Gt) { + spans.push(span); + end = Some(span); + break; + } + self.bump(); + } + let mut err = self.struct_span_err(spans, "encountered diff marker"); + err.span_label(start, "start"); + if let Some(middle) = middle { + err.span_label(middle, "middle"); + } + if let Some(end) = end { + err.span_label(end, "end"); + } + err.emit(); + FatalError.raise() + } + /// Parse and throw away a parenthesized comma separated /// sequence of patterns until `)` is reached. fn skip_pat_list(&mut self) -> PResult<'a, ()> { diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index e1ced2eb965..51de3d40d91 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -98,7 +98,9 @@ impl<'a> Parser<'a> { fn_parse_mode: FnParseMode, force_collect: ForceCollect, ) -> PResult<'a, Option> { + self.recover_diff_marker(); let attrs = self.parse_outer_attributes()?; + self.recover_diff_marker(); self.parse_item_common(attrs, true, false, fn_parse_mode, force_collect) } @@ -704,6 +706,7 @@ impl<'a> Parser<'a> { if self.recover_doc_comment_before_brace() { continue; } + self.recover_diff_marker(); match parse_item(self) { Ok(None) => { let mut is_unnecessary_semicolon = !items.is_empty() @@ -1039,8 +1042,11 @@ impl<'a> Parser<'a> { /// USE_TREE_LIST = Ø | (USE_TREE `,`)* USE_TREE [`,`] /// ``` fn parse_use_tree_list(&mut self) -> PResult<'a, Vec<(UseTree, ast::NodeId)>> { - self.parse_delim_comma_seq(Delimiter::Brace, |p| Ok((p.parse_use_tree()?, DUMMY_NODE_ID))) - .map(|(r, _)| r) + self.parse_delim_comma_seq(Delimiter::Brace, |p| { + p.recover_diff_marker(); + Ok((p.parse_use_tree()?, DUMMY_NODE_ID)) + }) + .map(|(r, _)| r) } fn parse_rename(&mut self) -> PResult<'a, Option> { @@ -2427,6 +2433,7 @@ impl<'a> Parser<'a> { let mut first_param = true; // Parse the arguments, starting out with `self` being allowed... let (mut params, _) = self.parse_paren_comma_seq(|p| { + p.recover_diff_marker(); let param = p.parse_param_general(req_name, first_param).or_else(|mut e| { e.emit(); let lo = p.prev_token.span; diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index bae7f2670cb..4cbf89169b6 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -531,13 +531,23 @@ impl<'a> Parser<'a> { recover: AttemptLocalParseRecovery, ) -> PResult<'a, P> { let mut stmts = vec![]; + let mut snapshot = None; while !self.eat(&token::CloseDelim(Delimiter::Brace)) { if self.token == token::Eof { break; } + if self.is_diff_marker(&TokenKind::BinOp(token::Shl), &TokenKind::Lt) { + // Account for `<<<<<<<` diff markers. We can't proactivelly error here because + // that can be a valid path start, so we snapshot and reparse only we've + // encountered another parse error. + snapshot = Some(self.create_snapshot_for_diagnostic()); + } let stmt = match self.parse_full_stmt(recover) { Err(mut err) if recover.yes() => { self.maybe_annotate_with_ascription(&mut err, false); + if let Some(ref mut snapshot) = snapshot { + snapshot.recover_diff_marker(); + } err.emit(); self.recover_stmt_(SemiColonMode::Ignore, BlockMode::Ignore); Some(self.mk_stmt_err(self.token.span)) diff --git a/src/test/ui/parser/diff-markers/fn-arg.rs b/src/test/ui/parser/diff-markers/fn-arg.rs new file mode 100644 index 00000000000..86c355628ab --- /dev/null +++ b/src/test/ui/parser/diff-markers/fn-arg.rs @@ -0,0 +1,16 @@ +trait T { + fn foo( +<<<<<<< HEAD //~ ERROR encountered diff marker + x: u8, +======= + x: i8, +>>>>>>> branch + ) {} +} + +struct S; +impl T for S {} + +fn main() { + S::foo(42); +} diff --git a/src/test/ui/parser/diff-markers/fn-arg.stderr b/src/test/ui/parser/diff-markers/fn-arg.stderr new file mode 100644 index 00000000000..4a816ff75bc --- /dev/null +++ b/src/test/ui/parser/diff-markers/fn-arg.stderr @@ -0,0 +1,14 @@ +error: encountered diff marker + --> $DIR/fn-arg.rs:3:1 + | +LL | <<<<<<< HEAD + | ^^^^^^^ start +LL | x: u8, +LL | ======= + | ^^^^^^^ middle +LL | x: i8, +LL | >>>>>>> branch + | ^^^^^^^ end + +error: aborting due to previous error + diff --git a/src/test/ui/parser/diff-markers/item-with-attr.rs b/src/test/ui/parser/diff-markers/item-with-attr.rs new file mode 100644 index 00000000000..985907c08b2 --- /dev/null +++ b/src/test/ui/parser/diff-markers/item-with-attr.rs @@ -0,0 +1,10 @@ +#[attribute] +<<<<<<< HEAD //~ ERROR encountered diff marker +fn foo() {} +======= +fn bar() {} +>>>>>>> branch + +fn main() { + foo(); +} diff --git a/src/test/ui/parser/diff-markers/item-with-attr.stderr b/src/test/ui/parser/diff-markers/item-with-attr.stderr new file mode 100644 index 00000000000..4fcb782846e --- /dev/null +++ b/src/test/ui/parser/diff-markers/item-with-attr.stderr @@ -0,0 +1,14 @@ +error: encountered diff marker + --> $DIR/item-with-attr.rs:2:1 + | +LL | <<<<<<< HEAD + | ^^^^^^^ start +LL | fn foo() {} +LL | ======= + | ^^^^^^^ middle +LL | fn bar() {} +LL | >>>>>>> branch + | ^^^^^^^ end + +error: aborting due to previous error + diff --git a/src/test/ui/parser/diff-markers/item.rs b/src/test/ui/parser/diff-markers/item.rs new file mode 100644 index 00000000000..4ed36b7b42b --- /dev/null +++ b/src/test/ui/parser/diff-markers/item.rs @@ -0,0 +1,9 @@ +<<<<<<< HEAD //~ ERROR encountered diff marker +fn foo() {} +======= +fn bar() {} +>>>>>>> branch + +fn main() { + foo(); +} diff --git a/src/test/ui/parser/diff-markers/item.stderr b/src/test/ui/parser/diff-markers/item.stderr new file mode 100644 index 00000000000..7c81f0fafa6 --- /dev/null +++ b/src/test/ui/parser/diff-markers/item.stderr @@ -0,0 +1,14 @@ +error: encountered diff marker + --> $DIR/item.rs:1:1 + | +LL | <<<<<<< HEAD + | ^^^^^^^ start +LL | fn foo() {} +LL | ======= + | ^^^^^^^ middle +LL | fn bar() {} +LL | >>>>>>> branch + | ^^^^^^^ end + +error: aborting due to previous error + diff --git a/src/test/ui/parser/diff-markers/statement.rs b/src/test/ui/parser/diff-markers/statement.rs new file mode 100644 index 00000000000..e55d16d3bbb --- /dev/null +++ b/src/test/ui/parser/diff-markers/statement.rs @@ -0,0 +1,15 @@ +trait T { + fn foo() {} + fn bar() {} +} + +struct S; +impl T for S {} + +fn main() { +<<<<<<< HEAD //~ ERROR encountered diff marker + S::foo(); +======= + S::bar(); +>>>>>>> branch +} diff --git a/src/test/ui/parser/diff-markers/statement.stderr b/src/test/ui/parser/diff-markers/statement.stderr new file mode 100644 index 00000000000..4c821c02f0d --- /dev/null +++ b/src/test/ui/parser/diff-markers/statement.stderr @@ -0,0 +1,14 @@ +error: encountered diff marker + --> $DIR/statement.rs:10:1 + | +LL | <<<<<<< HEAD + | ^^^^^^^ start +LL | S::foo(); +LL | ======= + | ^^^^^^^ middle +LL | S::bar(); +LL | >>>>>>> branch + | ^^^^^^^ end + +error: aborting due to previous error + diff --git a/src/test/ui/parser/diff-markers/trait-item.rs b/src/test/ui/parser/diff-markers/trait-item.rs new file mode 100644 index 00000000000..3227c8212c9 --- /dev/null +++ b/src/test/ui/parser/diff-markers/trait-item.rs @@ -0,0 +1,14 @@ +trait T { +<<<<<<< HEAD //~ ERROR encountered diff marker + fn foo() {} +======= + fn bar() {} +>>>>>>> branch +} + +struct S; +impl T for S {} + +fn main() { + S::foo(); +} diff --git a/src/test/ui/parser/diff-markers/trait-item.stderr b/src/test/ui/parser/diff-markers/trait-item.stderr new file mode 100644 index 00000000000..8e18d5db7c7 --- /dev/null +++ b/src/test/ui/parser/diff-markers/trait-item.stderr @@ -0,0 +1,14 @@ +error: encountered diff marker + --> $DIR/trait-item.rs:2:1 + | +LL | <<<<<<< HEAD + | ^^^^^^^ start +LL | fn foo() {} +LL | ======= + | ^^^^^^^ middle +LL | fn bar() {} +LL | >>>>>>> branch + | ^^^^^^^ end + +error: aborting due to previous error + diff --git a/src/test/ui/parser/diff-markers/use-statement.rs b/src/test/ui/parser/diff-markers/use-statement.rs new file mode 100644 index 00000000000..6306243a514 --- /dev/null +++ b/src/test/ui/parser/diff-markers/use-statement.rs @@ -0,0 +1,9 @@ +use foo::{ +<<<<<<< HEAD //~ ERROR encountered diff marker + bar, +======= + baz, +>>>>>>> branch +}; + +fn main() {} diff --git a/src/test/ui/parser/diff-markers/use-statement.stderr b/src/test/ui/parser/diff-markers/use-statement.stderr new file mode 100644 index 00000000000..818c90aa59b --- /dev/null +++ b/src/test/ui/parser/diff-markers/use-statement.stderr @@ -0,0 +1,14 @@ +error: encountered diff marker + --> $DIR/use-statement.rs:2:1 + | +LL | <<<<<<< HEAD + | ^^^^^^^ start +LL | bar, +LL | ======= + | ^^^^^^^ middle +LL | baz, +LL | >>>>>>> branch + | ^^^^^^^ end + +error: aborting due to previous error + -- cgit 1.4.1-3-g733a5 From 38fd5a9acfd4893e572f20591ffea4f3cfd2fc2e Mon Sep 17 00:00:00 2001 From: Esteban Küber Date: Wed, 28 Dec 2022 18:26:59 -0800 Subject: Account for ADT bodies and struct expressions --- compiler/rustc_parse/src/parser/expr.rs | 1 + compiler/rustc_parse/src/parser/item.rs | 31 ++++++++++++++++++++-- src/test/ui/parser/diff-markers/enum-2.rs | 9 +++++++ src/test/ui/parser/diff-markers/enum-2.stderr | 14 ++++++++++ src/test/ui/parser/diff-markers/enum.rs | 7 +++++ src/test/ui/parser/diff-markers/enum.stderr | 14 ++++++++++ src/test/ui/parser/diff-markers/struct-expr.rs | 12 +++++++++ src/test/ui/parser/diff-markers/struct-expr.stderr | 14 ++++++++++ src/test/ui/parser/diff-markers/struct.rs | 7 +++++ src/test/ui/parser/diff-markers/struct.stderr | 14 ++++++++++ src/test/ui/parser/diff-markers/tuple-struct.rs | 7 +++++ .../ui/parser/diff-markers/tuple-struct.stderr | 14 ++++++++++ 12 files changed, 142 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/parser/diff-markers/enum-2.rs create mode 100644 src/test/ui/parser/diff-markers/enum-2.stderr create mode 100644 src/test/ui/parser/diff-markers/enum.rs create mode 100644 src/test/ui/parser/diff-markers/enum.stderr create mode 100644 src/test/ui/parser/diff-markers/struct-expr.rs create mode 100644 src/test/ui/parser/diff-markers/struct-expr.stderr create mode 100644 src/test/ui/parser/diff-markers/struct.rs create mode 100644 src/test/ui/parser/diff-markers/struct.stderr create mode 100644 src/test/ui/parser/diff-markers/tuple-struct.rs create mode 100644 src/test/ui/parser/diff-markers/tuple-struct.stderr (limited to 'src/test/ui') diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 6a115088eca..1fc1ffd6cb6 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -3039,6 +3039,7 @@ impl<'a> Parser<'a> { /// Parses `ident (COLON expr)?`. fn parse_expr_field(&mut self) -> PResult<'a, ExprField> { let attrs = self.parse_outer_attributes()?; + self.recover_diff_marker(); self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| { let lo = this.token.span; diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 51de3d40d91..b996ce0a155 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1385,7 +1385,9 @@ impl<'a> Parser<'a> { } fn parse_enum_variant(&mut self) -> PResult<'a, Option> { + self.recover_diff_marker(); let variant_attrs = self.parse_outer_attributes()?; + self.recover_diff_marker(); self.collect_tokens_trailing_token( variant_attrs, ForceCollect::No, @@ -1579,9 +1581,32 @@ impl<'a> Parser<'a> { self.parse_paren_comma_seq(|p| { let attrs = p.parse_outer_attributes()?; p.collect_tokens_trailing_token(attrs, ForceCollect::No, |p, attrs| { + let mut snapshot = None; + if p.is_diff_marker(&TokenKind::BinOp(token::Shl), &TokenKind::Lt) { + // Account for `<<<<<<<` diff markers. We can't proactivelly error here because + // that can be a valid type start, so we snapshot and reparse only we've + // encountered another parse error. + snapshot = Some(p.create_snapshot_for_diagnostic()); + } let lo = p.token.span; - let vis = p.parse_visibility(FollowedByType::Yes)?; - let ty = p.parse_ty()?; + let vis = match p.parse_visibility(FollowedByType::Yes) { + Ok(vis) => vis, + Err(err) => { + if let Some(ref mut snapshot) = snapshot { + snapshot.recover_diff_marker(); + } + return Err(err); + } + }; + let ty = match p.parse_ty() { + Ok(ty) => ty, + Err(err) => { + if let Some(ref mut snapshot) = snapshot { + snapshot.recover_diff_marker(); + } + return Err(err); + } + }; Ok(( FieldDef { @@ -1602,7 +1627,9 @@ impl<'a> Parser<'a> { /// Parses an element of a struct declaration. fn parse_field_def(&mut self, adt_ty: &str) -> PResult<'a, FieldDef> { + self.recover_diff_marker(); let attrs = self.parse_outer_attributes()?; + self.recover_diff_marker(); self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| { let lo = this.token.span; let vis = this.parse_visibility(FollowedByType::No)?; diff --git a/src/test/ui/parser/diff-markers/enum-2.rs b/src/test/ui/parser/diff-markers/enum-2.rs new file mode 100644 index 00000000000..d8c527281de --- /dev/null +++ b/src/test/ui/parser/diff-markers/enum-2.rs @@ -0,0 +1,9 @@ +enum E { + Foo { +<<<<<<< HEAD //~ ERROR encountered diff marker + x: u8, +======= + x: i8, +>>>>>>> branch + } +} diff --git a/src/test/ui/parser/diff-markers/enum-2.stderr b/src/test/ui/parser/diff-markers/enum-2.stderr new file mode 100644 index 00000000000..5264a596488 --- /dev/null +++ b/src/test/ui/parser/diff-markers/enum-2.stderr @@ -0,0 +1,14 @@ +error: encountered diff marker + --> $DIR/enum-2.rs:3:1 + | +LL | <<<<<<< HEAD + | ^^^^^^^ start +LL | x: u8, +LL | ======= + | ^^^^^^^ middle +LL | x: i8, +LL | >>>>>>> branch + | ^^^^^^^ end + +error: aborting due to previous error + diff --git a/src/test/ui/parser/diff-markers/enum.rs b/src/test/ui/parser/diff-markers/enum.rs new file mode 100644 index 00000000000..45df6e3251d --- /dev/null +++ b/src/test/ui/parser/diff-markers/enum.rs @@ -0,0 +1,7 @@ +enum E { +<<<<<<< HEAD //~ ERROR encountered diff marker + Foo(u8), +======= + Bar(i8), +>>>>>>> branch +} diff --git a/src/test/ui/parser/diff-markers/enum.stderr b/src/test/ui/parser/diff-markers/enum.stderr new file mode 100644 index 00000000000..6bdc20d3cd3 --- /dev/null +++ b/src/test/ui/parser/diff-markers/enum.stderr @@ -0,0 +1,14 @@ +error: encountered diff marker + --> $DIR/enum.rs:2:1 + | +LL | <<<<<<< HEAD + | ^^^^^^^ start +LL | Foo(u8), +LL | ======= + | ^^^^^^^ middle +LL | Bar(i8), +LL | >>>>>>> branch + | ^^^^^^^ end + +error: aborting due to previous error + diff --git a/src/test/ui/parser/diff-markers/struct-expr.rs b/src/test/ui/parser/diff-markers/struct-expr.rs new file mode 100644 index 00000000000..99d2fd662c6 --- /dev/null +++ b/src/test/ui/parser/diff-markers/struct-expr.rs @@ -0,0 +1,12 @@ +struct S { + x: u8, +} +fn main() { + let _ = S { +<<<<<<< HEAD //~ ERROR encountered diff marker + x: 42, +======= + x: 0, +>>>>>>> branch + } +} diff --git a/src/test/ui/parser/diff-markers/struct-expr.stderr b/src/test/ui/parser/diff-markers/struct-expr.stderr new file mode 100644 index 00000000000..0ddb1a301e3 --- /dev/null +++ b/src/test/ui/parser/diff-markers/struct-expr.stderr @@ -0,0 +1,14 @@ +error: encountered diff marker + --> $DIR/struct-expr.rs:6:1 + | +LL | <<<<<<< HEAD + | ^^^^^^^ start +LL | x: 42, +LL | ======= + | ^^^^^^^ middle +LL | x: 0, +LL | >>>>>>> branch + | ^^^^^^^ end + +error: aborting due to previous error + diff --git a/src/test/ui/parser/diff-markers/struct.rs b/src/test/ui/parser/diff-markers/struct.rs new file mode 100644 index 00000000000..d26464d47bc --- /dev/null +++ b/src/test/ui/parser/diff-markers/struct.rs @@ -0,0 +1,7 @@ +struct S { +<<<<<<< HEAD //~ ERROR encountered diff marker + x: u8, +======= + x: i8, +>>>>>>> branch +} diff --git a/src/test/ui/parser/diff-markers/struct.stderr b/src/test/ui/parser/diff-markers/struct.stderr new file mode 100644 index 00000000000..e47bcfdaedc --- /dev/null +++ b/src/test/ui/parser/diff-markers/struct.stderr @@ -0,0 +1,14 @@ +error: encountered diff marker + --> $DIR/struct.rs:2:1 + | +LL | <<<<<<< HEAD + | ^^^^^^^ start +LL | x: u8, +LL | ======= + | ^^^^^^^ middle +LL | x: i8, +LL | >>>>>>> branch + | ^^^^^^^ end + +error: aborting due to previous error + diff --git a/src/test/ui/parser/diff-markers/tuple-struct.rs b/src/test/ui/parser/diff-markers/tuple-struct.rs new file mode 100644 index 00000000000..7eec35c968d --- /dev/null +++ b/src/test/ui/parser/diff-markers/tuple-struct.rs @@ -0,0 +1,7 @@ +struct S( +<<<<<<< HEAD //~ ERROR encountered diff marker + u8, +======= + i8, +>>>>>>> branch +); diff --git a/src/test/ui/parser/diff-markers/tuple-struct.stderr b/src/test/ui/parser/diff-markers/tuple-struct.stderr new file mode 100644 index 00000000000..7f30cbcc1f7 --- /dev/null +++ b/src/test/ui/parser/diff-markers/tuple-struct.stderr @@ -0,0 +1,14 @@ +error: encountered diff marker + --> $DIR/tuple-struct.rs:2:1 + | +LL | <<<<<<< HEAD + | ^^^^^^^ start +LL | u8, +LL | ======= + | ^^^^^^^ middle +LL | i8, +LL | >>>>>>> branch + | ^^^^^^^ end + +error: aborting due to previous error + -- cgit 1.4.1-3-g733a5 From 698ebe357f3323a953d0751d5764966b3ffb3cb7 Mon Sep 17 00:00:00 2001 From: Esteban Küber Date: Wed, 28 Dec 2022 18:46:20 -0800 Subject: Tweak wording --- compiler/rustc_parse/src/parser/diagnostics.rs | 19 +++++++++++++++---- compiler/rustc_parse/src/parser/item.rs | 2 +- compiler/rustc_parse/src/parser/stmt.rs | 2 +- src/test/ui/parser/diff-markers/enum-2.stderr | 10 +++++++--- src/test/ui/parser/diff-markers/enum.stderr | 10 +++++++--- src/test/ui/parser/diff-markers/fn-arg.stderr | 10 +++++++--- src/test/ui/parser/diff-markers/item-with-attr.stderr | 10 +++++++--- src/test/ui/parser/diff-markers/item.stderr | 10 +++++++--- src/test/ui/parser/diff-markers/statement.stderr | 10 +++++++--- src/test/ui/parser/diff-markers/struct-expr.stderr | 10 +++++++--- src/test/ui/parser/diff-markers/struct.stderr | 10 +++++++--- src/test/ui/parser/diff-markers/trait-item.stderr | 10 +++++++--- src/test/ui/parser/diff-markers/tuple-struct.stderr | 10 +++++++--- src/test/ui/parser/diff-markers/use-statement.stderr | 10 +++++++--- 14 files changed, 94 insertions(+), 39 deletions(-) (limited to 'src/test/ui') diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index ffadb77320a..dd7341af4d5 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -2586,7 +2586,6 @@ impl<'a> Parser<'a> { break; } if let Some(span) = self.diff_marker(&TokenKind::EqEq, &TokenKind::Eq) { - spans.push(span); middle = Some(span); } if let Some(span) = self.diff_marker(&TokenKind::BinOp(token::Shr), &TokenKind::Gt) { @@ -2597,13 +2596,25 @@ impl<'a> Parser<'a> { self.bump(); } let mut err = self.struct_span_err(spans, "encountered diff marker"); - err.span_label(start, "start"); + err.span_label(start, "after this is the code before the merge"); if let Some(middle) = middle { - err.span_label(middle, "middle"); + err.span_label(middle, ""); } if let Some(end) = end { - err.span_label(end, "end"); + err.span_label(end, "above this are the incoming code changes"); } + err.help( + "if you're having merge conflicts after pulling new code, the top section is the code \ + you already had and the bottom section is the remote code", + ); + err.help( + "if you're in the middle of a rebase, the top section is the code being rebased onto \ + and the bottom section is the code coming from the current commit being rebased", + ); + err.note( + "for an explanation on these markers from the `git` documentation, visit \ + ", + ); err.emit(); FatalError.raise() } diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index b996ce0a155..c6b6c04de85 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1583,7 +1583,7 @@ impl<'a> Parser<'a> { p.collect_tokens_trailing_token(attrs, ForceCollect::No, |p, attrs| { let mut snapshot = None; if p.is_diff_marker(&TokenKind::BinOp(token::Shl), &TokenKind::Lt) { - // Account for `<<<<<<<` diff markers. We can't proactivelly error here because + // Account for `<<<<<<<` diff markers. We can't proactively error here because // that can be a valid type start, so we snapshot and reparse only we've // encountered another parse error. snapshot = Some(p.create_snapshot_for_diagnostic()); diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 4cbf89169b6..0daae457d30 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -537,7 +537,7 @@ impl<'a> Parser<'a> { break; } if self.is_diff_marker(&TokenKind::BinOp(token::Shl), &TokenKind::Lt) { - // Account for `<<<<<<<` diff markers. We can't proactivelly error here because + // Account for `<<<<<<<` diff markers. We can't proactively error here because // that can be a valid path start, so we snapshot and reparse only we've // encountered another parse error. snapshot = Some(self.create_snapshot_for_diagnostic()); diff --git a/src/test/ui/parser/diff-markers/enum-2.stderr b/src/test/ui/parser/diff-markers/enum-2.stderr index 5264a596488..4e612a5427a 100644 --- a/src/test/ui/parser/diff-markers/enum-2.stderr +++ b/src/test/ui/parser/diff-markers/enum-2.stderr @@ -2,13 +2,17 @@ error: encountered diff marker --> $DIR/enum-2.rs:3:1 | LL | <<<<<<< HEAD - | ^^^^^^^ start + | ^^^^^^^ after this is the code before the merge LL | x: u8, LL | ======= - | ^^^^^^^ middle + | ------- LL | x: i8, LL | >>>>>>> branch - | ^^^^^^^ end + | ^^^^^^^ above this are the incoming code changes + | + = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code + = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation, visit error: aborting due to previous error diff --git a/src/test/ui/parser/diff-markers/enum.stderr b/src/test/ui/parser/diff-markers/enum.stderr index 6bdc20d3cd3..abbf3fb41e7 100644 --- a/src/test/ui/parser/diff-markers/enum.stderr +++ b/src/test/ui/parser/diff-markers/enum.stderr @@ -2,13 +2,17 @@ error: encountered diff marker --> $DIR/enum.rs:2:1 | LL | <<<<<<< HEAD - | ^^^^^^^ start + | ^^^^^^^ after this is the code before the merge LL | Foo(u8), LL | ======= - | ^^^^^^^ middle + | ------- LL | Bar(i8), LL | >>>>>>> branch - | ^^^^^^^ end + | ^^^^^^^ above this are the incoming code changes + | + = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code + = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation, visit error: aborting due to previous error diff --git a/src/test/ui/parser/diff-markers/fn-arg.stderr b/src/test/ui/parser/diff-markers/fn-arg.stderr index 4a816ff75bc..933a206410e 100644 --- a/src/test/ui/parser/diff-markers/fn-arg.stderr +++ b/src/test/ui/parser/diff-markers/fn-arg.stderr @@ -2,13 +2,17 @@ error: encountered diff marker --> $DIR/fn-arg.rs:3:1 | LL | <<<<<<< HEAD - | ^^^^^^^ start + | ^^^^^^^ after this is the code before the merge LL | x: u8, LL | ======= - | ^^^^^^^ middle + | ------- LL | x: i8, LL | >>>>>>> branch - | ^^^^^^^ end + | ^^^^^^^ above this are the incoming code changes + | + = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code + = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation, visit error: aborting due to previous error diff --git a/src/test/ui/parser/diff-markers/item-with-attr.stderr b/src/test/ui/parser/diff-markers/item-with-attr.stderr index 4fcb782846e..850e2368e55 100644 --- a/src/test/ui/parser/diff-markers/item-with-attr.stderr +++ b/src/test/ui/parser/diff-markers/item-with-attr.stderr @@ -2,13 +2,17 @@ error: encountered diff marker --> $DIR/item-with-attr.rs:2:1 | LL | <<<<<<< HEAD - | ^^^^^^^ start + | ^^^^^^^ after this is the code before the merge LL | fn foo() {} LL | ======= - | ^^^^^^^ middle + | ------- LL | fn bar() {} LL | >>>>>>> branch - | ^^^^^^^ end + | ^^^^^^^ above this are the incoming code changes + | + = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code + = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation, visit error: aborting due to previous error diff --git a/src/test/ui/parser/diff-markers/item.stderr b/src/test/ui/parser/diff-markers/item.stderr index 7c81f0fafa6..9ab3631a60e 100644 --- a/src/test/ui/parser/diff-markers/item.stderr +++ b/src/test/ui/parser/diff-markers/item.stderr @@ -2,13 +2,17 @@ error: encountered diff marker --> $DIR/item.rs:1:1 | LL | <<<<<<< HEAD - | ^^^^^^^ start + | ^^^^^^^ after this is the code before the merge LL | fn foo() {} LL | ======= - | ^^^^^^^ middle + | ------- LL | fn bar() {} LL | >>>>>>> branch - | ^^^^^^^ end + | ^^^^^^^ above this are the incoming code changes + | + = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code + = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation, visit error: aborting due to previous error diff --git a/src/test/ui/parser/diff-markers/statement.stderr b/src/test/ui/parser/diff-markers/statement.stderr index 4c821c02f0d..7ca2495b829 100644 --- a/src/test/ui/parser/diff-markers/statement.stderr +++ b/src/test/ui/parser/diff-markers/statement.stderr @@ -2,13 +2,17 @@ error: encountered diff marker --> $DIR/statement.rs:10:1 | LL | <<<<<<< HEAD - | ^^^^^^^ start + | ^^^^^^^ after this is the code before the merge LL | S::foo(); LL | ======= - | ^^^^^^^ middle + | ------- LL | S::bar(); LL | >>>>>>> branch - | ^^^^^^^ end + | ^^^^^^^ above this are the incoming code changes + | + = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code + = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation, visit error: aborting due to previous error diff --git a/src/test/ui/parser/diff-markers/struct-expr.stderr b/src/test/ui/parser/diff-markers/struct-expr.stderr index 0ddb1a301e3..d70476a9833 100644 --- a/src/test/ui/parser/diff-markers/struct-expr.stderr +++ b/src/test/ui/parser/diff-markers/struct-expr.stderr @@ -2,13 +2,17 @@ error: encountered diff marker --> $DIR/struct-expr.rs:6:1 | LL | <<<<<<< HEAD - | ^^^^^^^ start + | ^^^^^^^ after this is the code before the merge LL | x: 42, LL | ======= - | ^^^^^^^ middle + | ------- LL | x: 0, LL | >>>>>>> branch - | ^^^^^^^ end + | ^^^^^^^ above this are the incoming code changes + | + = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code + = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation, visit error: aborting due to previous error diff --git a/src/test/ui/parser/diff-markers/struct.stderr b/src/test/ui/parser/diff-markers/struct.stderr index e47bcfdaedc..cc0b3da664e 100644 --- a/src/test/ui/parser/diff-markers/struct.stderr +++ b/src/test/ui/parser/diff-markers/struct.stderr @@ -2,13 +2,17 @@ error: encountered diff marker --> $DIR/struct.rs:2:1 | LL | <<<<<<< HEAD - | ^^^^^^^ start + | ^^^^^^^ after this is the code before the merge LL | x: u8, LL | ======= - | ^^^^^^^ middle + | ------- LL | x: i8, LL | >>>>>>> branch - | ^^^^^^^ end + | ^^^^^^^ above this are the incoming code changes + | + = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code + = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation, visit error: aborting due to previous error diff --git a/src/test/ui/parser/diff-markers/trait-item.stderr b/src/test/ui/parser/diff-markers/trait-item.stderr index 8e18d5db7c7..cdc19f8e076 100644 --- a/src/test/ui/parser/diff-markers/trait-item.stderr +++ b/src/test/ui/parser/diff-markers/trait-item.stderr @@ -2,13 +2,17 @@ error: encountered diff marker --> $DIR/trait-item.rs:2:1 | LL | <<<<<<< HEAD - | ^^^^^^^ start + | ^^^^^^^ after this is the code before the merge LL | fn foo() {} LL | ======= - | ^^^^^^^ middle + | ------- LL | fn bar() {} LL | >>>>>>> branch - | ^^^^^^^ end + | ^^^^^^^ above this are the incoming code changes + | + = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code + = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation, visit error: aborting due to previous error diff --git a/src/test/ui/parser/diff-markers/tuple-struct.stderr b/src/test/ui/parser/diff-markers/tuple-struct.stderr index 7f30cbcc1f7..d673db89837 100644 --- a/src/test/ui/parser/diff-markers/tuple-struct.stderr +++ b/src/test/ui/parser/diff-markers/tuple-struct.stderr @@ -2,13 +2,17 @@ error: encountered diff marker --> $DIR/tuple-struct.rs:2:1 | LL | <<<<<<< HEAD - | ^^^^^^^ start + | ^^^^^^^ after this is the code before the merge LL | u8, LL | ======= - | ^^^^^^^ middle + | ------- LL | i8, LL | >>>>>>> branch - | ^^^^^^^ end + | ^^^^^^^ above this are the incoming code changes + | + = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code + = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation, visit error: aborting due to previous error diff --git a/src/test/ui/parser/diff-markers/use-statement.stderr b/src/test/ui/parser/diff-markers/use-statement.stderr index 818c90aa59b..12e6f57dd50 100644 --- a/src/test/ui/parser/diff-markers/use-statement.stderr +++ b/src/test/ui/parser/diff-markers/use-statement.stderr @@ -2,13 +2,17 @@ error: encountered diff marker --> $DIR/use-statement.rs:2:1 | LL | <<<<<<< HEAD - | ^^^^^^^ start + | ^^^^^^^ after this is the code before the merge LL | bar, LL | ======= - | ^^^^^^^ middle + | ------- LL | baz, LL | >>>>>>> branch - | ^^^^^^^ end + | ^^^^^^^ above this are the incoming code changes + | + = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code + = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation, visit error: aborting due to previous error -- cgit 1.4.1-3-g733a5 From 62c8e3144a8bc7d07d66bc14c8a7cce94a3dbce5 Mon Sep 17 00:00:00 2001 From: Esteban Küber Date: Wed, 28 Dec 2022 20:55:46 -0800 Subject: Add support for diff3 format --- compiler/rustc_parse/src/parser/diagnostics.rs | 7 +++++++ src/test/ui/parser/diff-markers/enum-2.rs | 4 +++- src/test/ui/parser/diff-markers/enum-2.stderr | 5 ++++- 3 files changed, 14 insertions(+), 2 deletions(-) (limited to 'src/test/ui') diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index dd7341af4d5..7ab924bd39d 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -2579,12 +2579,16 @@ impl<'a> Parser<'a> { }; let mut spans = Vec::with_capacity(3); spans.push(start); + let mut middlediff3 = None; let mut middle = None; let mut end = None; loop { if self.token.kind == TokenKind::Eof { break; } + if let Some(span) = self.diff_marker(&TokenKind::OrOr, &TokenKind::BinOp(token::Or)) { + middlediff3 = Some(span); + } if let Some(span) = self.diff_marker(&TokenKind::EqEq, &TokenKind::Eq) { middle = Some(span); } @@ -2597,6 +2601,9 @@ impl<'a> Parser<'a> { } let mut err = self.struct_span_err(spans, "encountered diff marker"); err.span_label(start, "after this is the code before the merge"); + if let Some(middle) = middlediff3 { + err.span_label(middle, ""); + } if let Some(middle) = middle { err.span_label(middle, ""); } diff --git a/src/test/ui/parser/diff-markers/enum-2.rs b/src/test/ui/parser/diff-markers/enum-2.rs index d8c527281de..76ea980fc62 100644 --- a/src/test/ui/parser/diff-markers/enum-2.rs +++ b/src/test/ui/parser/diff-markers/enum-2.rs @@ -2,8 +2,10 @@ enum E { Foo { <<<<<<< HEAD //~ ERROR encountered diff marker x: u8, +||||||| + z: (), ======= - x: i8, + y: i8, >>>>>>> branch } } diff --git a/src/test/ui/parser/diff-markers/enum-2.stderr b/src/test/ui/parser/diff-markers/enum-2.stderr index 4e612a5427a..63da5c2a6e1 100644 --- a/src/test/ui/parser/diff-markers/enum-2.stderr +++ b/src/test/ui/parser/diff-markers/enum-2.stderr @@ -4,9 +4,12 @@ error: encountered diff marker LL | <<<<<<< HEAD | ^^^^^^^ after this is the code before the merge LL | x: u8, +LL | ||||||| + | ------- +LL | z: (), LL | ======= | ------- -LL | x: i8, +LL | y: i8, LL | >>>>>>> branch | ^^^^^^^ above this are the incoming code changes | -- cgit 1.4.1-3-g733a5