diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md index 35904e15d3fee..7b0280d5b78a7 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -12,7 +12,7 @@ This option is deprecated and does nothing. This option lets you choose which code model to use. \ Code models put constraints on address ranges that the program and its symbols may use. \ With smaller address ranges machine instructions -may be able to use use more compact addressing modes. +may be able to use more compact addressing modes. The specific ranges depend on target architectures and addressing modes available to them. \ For x86 more detailed description of its code models can be found in diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 210ac078b4fe7..9ed5a1f962215 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -2974,8 +2974,15 @@ where #[inline(never)] #[cold] #[track_caller] -fn slice_index_len_fail(index: usize, len: usize) -> ! { - panic!("index {} out of range for slice of length {}", index, len); +fn slice_start_index_len_fail(index: usize, len: usize) -> ! { + panic!("range start index {} out of range for slice of length {}", index, len); +} + +#[inline(never)] +#[cold] +#[track_caller] +fn slice_end_index_len_fail(index: usize, len: usize) -> ! { + panic!("range end index {} out of range for slice of length {}", index, len); } #[inline(never)] @@ -3160,7 +3167,7 @@ unsafe impl SliceIndex<[T]> for ops::Range { if self.start > self.end { slice_index_order_fail(self.start, self.end); } else if self.end > slice.len() { - slice_index_len_fail(self.end, slice.len()); + slice_end_index_len_fail(self.end, slice.len()); } unsafe { &*self.get_unchecked(slice) } } @@ -3170,7 +3177,7 @@ unsafe impl SliceIndex<[T]> for ops::Range { if self.start > self.end { slice_index_order_fail(self.start, self.end); } else if self.end > slice.len() { - slice_index_len_fail(self.end, slice.len()); + slice_end_index_len_fail(self.end, slice.len()); } unsafe { &mut *self.get_unchecked_mut(slice) } } @@ -3241,12 +3248,18 @@ unsafe impl SliceIndex<[T]> for ops::RangeFrom { #[inline] fn index(self, slice: &[T]) -> &[T] { - (self.start..slice.len()).index(slice) + if self.start > slice.len() { + slice_start_index_len_fail(self.start, slice.len()); + } + unsafe { &*self.get_unchecked(slice) } } #[inline] fn index_mut(self, slice: &mut [T]) -> &mut [T] { - (self.start..slice.len()).index_mut(slice) + if self.start > slice.len() { + slice_start_index_len_fail(self.start, slice.len()); + } + unsafe { &mut *self.get_unchecked_mut(slice) } } } diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs index fba73be92be09..8e240832c13b8 100644 --- a/src/libcore/tests/slice.rs +++ b/src/libcore/tests/slice.rs @@ -1088,7 +1088,7 @@ mod slice_index { good: data[6..] == []; bad: data[7..]; - message: "but ends at"; // perhaps not ideal + message: "out of range"; } in mod rangeto_len { diff --git a/src/librustc_parse/parser/diagnostics.rs b/src/librustc_parse/parser/diagnostics.rs index 3244b35e89b0e..609a0c961e971 100644 --- a/src/librustc_parse/parser/diagnostics.rs +++ b/src/librustc_parse/parser/diagnostics.rs @@ -1,8 +1,10 @@ use super::ty::AllowPlus; use super::{BlockMode, Parser, PathStyle, SemiColonMode, SeqSep, TokenExpectType, TokenType}; -use rustc_ast::ast::{self, BinOpKind, BindingMode, BlockCheckMode, Expr, ExprKind, Item, Param}; -use rustc_ast::ast::{AttrVec, ItemKind, Mutability, Pat, PatKind, PathSegment, QSelf, Ty, TyKind}; +use rustc_ast::ast::{ + self, AngleBracketedArgs, AttrVec, BinOpKind, BindingMode, BlockCheckMode, Expr, ExprKind, + Item, ItemKind, Mutability, Param, Pat, PatKind, PathSegment, QSelf, Ty, TyKind, +}; use rustc_ast::ptr::P; use rustc_ast::token::{self, Lit, LitKind, TokenKind}; use rustc_ast::util::parser::AssocOp; @@ -488,6 +490,57 @@ impl<'a> Parser<'a> { false } + /// Check if a method call with an intended turbofish has been written without surrounding + /// angle brackets. + pub(super) fn check_turbofish_missing_angle_brackets(&mut self, segment: &mut PathSegment) { + if token::ModSep == self.token.kind && segment.args.is_none() { + let snapshot = self.clone(); + self.bump(); + let lo = self.token.span; + match self.parse_angle_args() { + Ok(args) => { + let span = lo.to(self.prev_token.span); + // Detect trailing `>` like in `x.collect::Vec<_>>()`. + let mut trailing_span = self.prev_token.span.shrink_to_hi(); + while self.token.kind == token::BinOp(token::Shr) + || self.token.kind == token::Gt + { + trailing_span = trailing_span.to(self.token.span); + self.bump(); + } + if self.token.kind == token::OpenDelim(token::Paren) { + // Recover from bad turbofish: `foo.collect::Vec<_>()`. + let args = AngleBracketedArgs { args, span }.into(); + segment.args = args; + + self.struct_span_err( + span, + "generic parameters without surrounding angle brackets", + ) + .multipart_suggestion( + "surround the type parameters with angle brackets", + vec![ + (span.shrink_to_lo(), "<".to_string()), + (trailing_span, ">".to_string()), + ], + Applicability::MachineApplicable, + ) + .emit(); + } else { + // This doesn't look like an invalid turbofish, can't recover parse state. + *self = snapshot; + } + } + Err(mut err) => { + // We could't parse generic parameters, unlikely to be a turbofish. Rely on + // generic parse error instead. + err.cancel(); + *self = snapshot; + } + } + } + } + /// Check to see if a pair of chained operators looks like an attempt at chained comparison, /// e.g. `1 < x <= 3`. If so, suggest either splitting the comparison into two, or /// parenthesising the leftmost comparison. diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index 3926122606e6d..d06b172bc1484 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -909,8 +909,9 @@ impl<'a> Parser<'a> { } let fn_span_lo = self.token.span; - let segment = self.parse_path_segment(PathStyle::Expr)?; + let mut segment = self.parse_path_segment(PathStyle::Expr)?; self.check_trailing_angle_brackets(&segment, &[&token::OpenDelim(token::Paren)]); + self.check_turbofish_missing_angle_brackets(&mut segment); if self.check(&token::OpenDelim(token::Paren)) { // Method call `expr.f()` diff --git a/src/librustc_parse/parser/path.rs b/src/librustc_parse/parser/path.rs index 67e9b3af4a8cf..3dcefd362574b 100644 --- a/src/librustc_parse/parser/path.rs +++ b/src/librustc_parse/parser/path.rs @@ -387,7 +387,7 @@ impl<'a> Parser<'a> { /// Parses (possibly empty) list of generic arguments / associated item constraints, /// possibly including trailing comma. - fn parse_angle_args(&mut self) -> PResult<'a, Vec> { + pub(super) fn parse_angle_args(&mut self) -> PResult<'a, Vec> { let mut args = Vec::new(); while let Some(arg) = self.parse_angle_arg()? { args.push(arg); diff --git a/src/librustc_trait_selection/traits/wf.rs b/src/librustc_trait_selection/traits/wf.rs index b8446fa0012ab..0e445e1e53bba 100644 --- a/src/librustc_trait_selection/traits/wf.rs +++ b/src/librustc_trait_selection/traits/wf.rs @@ -300,13 +300,21 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { trait_ref .substs .iter() - .filter(|arg| { + .enumerate() + .filter(|(_, arg)| { matches!(arg.unpack(), GenericArgKind::Type(..) | GenericArgKind::Const(..)) }) - .filter(|arg| !arg.has_escaping_bound_vars()) - .map(|arg| { + .filter(|(_, arg)| !arg.has_escaping_bound_vars()) + .map(|(i, arg)| { + let mut new_cause = cause.clone(); + // The first subst is the self ty - use the correct span for it. + if i == 0 { + if let Some(hir::ItemKind::Impl { self_ty, .. }) = item.map(|i| &i.kind) { + new_cause.make_mut().span = self_ty.span; + } + } traits::Obligation::new( - cause.clone(), + new_cause, param_env, ty::PredicateKind::WellFormed(arg).to_predicate(tcx), ) diff --git a/src/test/codegen/issue-69101-bounds-check.rs b/src/test/codegen/issue-69101-bounds-check.rs index 8ade583b57127..a3aca3a2912a6 100644 --- a/src/test/codegen/issue-69101-bounds-check.rs +++ b/src/test/codegen/issue-69101-bounds-check.rs @@ -12,7 +12,7 @@ // CHECK-LABEL: @already_sliced_no_bounds_check #[no_mangle] pub fn already_sliced_no_bounds_check(a: &[u8], b: &[u8], c: &mut [u8]) { - // CHECK: slice_index_len_fail + // CHECK: slice_end_index_len_fail // CHECK-NOT: panic_bounds_check let _ = (&a[..2048], &b[..2048], &mut c[..2048]); for i in 0..1024 { @@ -23,7 +23,7 @@ pub fn already_sliced_no_bounds_check(a: &[u8], b: &[u8], c: &mut [u8]) { // CHECK-LABEL: @already_sliced_no_bounds_check_exact #[no_mangle] pub fn already_sliced_no_bounds_check_exact(a: &[u8], b: &[u8], c: &mut [u8]) { - // CHECK: slice_index_len_fail + // CHECK: slice_end_index_len_fail // CHECK-NOT: panic_bounds_check let _ = (&a[..1024], &b[..1024], &mut c[..1024]); for i in 0..1024 { @@ -35,7 +35,7 @@ pub fn already_sliced_no_bounds_check_exact(a: &[u8], b: &[u8], c: &mut [u8]) { // CHECK-LABEL: @already_sliced_bounds_check #[no_mangle] pub fn already_sliced_bounds_check(a: &[u8], b: &[u8], c: &mut [u8]) { - // CHECK: slice_index_len_fail + // CHECK: slice_end_index_len_fail // CHECK: panic_bounds_check let _ = (&a[..1023], &b[..2048], &mut c[..2048]); for i in 0..1024 { diff --git a/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.stderr b/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.stderr index 85ed360a1f74a..cd18a013628c2 100644 --- a/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.stderr +++ b/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.stderr @@ -1,12 +1,12 @@ error[E0038]: the trait `NotObjectSafe` cannot be made into an object - --> $DIR/coherence-impl-trait-for-trait-object-safe.rs:7:6 + --> $DIR/coherence-impl-trait-for-trait-object-safe.rs:7:24 | LL | trait NotObjectSafe { fn eq(&self, other: Self); } | ------------- ---- ...because method `eq` references the `Self` type in this parameter | | | this trait cannot be made into an object... LL | impl NotObjectSafe for dyn NotObjectSafe { } - | ^^^^^^^^^^^^^ the trait `NotObjectSafe` cannot be made into an object + | ^^^^^^^^^^^^^^^^^ the trait `NotObjectSafe` cannot be made into an object | = help: consider moving `eq` to another trait diff --git a/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr b/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr index c66bbb0c5045f..e3272e8849f9b 100644 --- a/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr +++ b/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr @@ -52,7 +52,7 @@ LL | fn return_non_object_safe_rc() -> std::rc::Rc { = help: consider moving `foo` to another trait error[E0038]: the trait `NonObjectSafe1` cannot be made into an object - --> $DIR/feature-gate-object_safe_for_dispatch.rs:38:6 + --> $DIR/feature-gate-object_safe_for_dispatch.rs:38:16 | LL | trait NonObjectSafe1: Sized {} | -------------- ----- ...because it requires `Self: Sized` @@ -60,7 +60,7 @@ LL | trait NonObjectSafe1: Sized {} | this trait cannot be made into an object... ... LL | impl Trait for dyn NonObjectSafe1 {} - | ^^^^^ the trait `NonObjectSafe1` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^ the trait `NonObjectSafe1` cannot be made into an object error: aborting due to 5 previous errors diff --git a/src/test/ui/issues/issue-21837.stderr b/src/test/ui/issues/issue-21837.stderr index f7e46b25cf82b..27e5c606a64a4 100644 --- a/src/test/ui/issues/issue-21837.stderr +++ b/src/test/ui/issues/issue-21837.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `T: Bound` is not satisfied - --> $DIR/issue-21837.rs:8:9 + --> $DIR/issue-21837.rs:8:20 | LL | pub struct Foo(T); | ----- required by this bound in `Foo` ... LL | impl Trait2 for Foo {} - | ^^^^^^ the trait `Bound` is not implemented for `T` + | ^^^^^^ the trait `Bound` is not implemented for `T` | help: consider restricting type parameter `T` | diff --git a/src/test/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.rs b/src/test/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.rs new file mode 100644 index 0000000000000..333dce390461c --- /dev/null +++ b/src/test/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.rs @@ -0,0 +1,10 @@ +fn main() { + let _ = vec![1, 2, 3].into_iter().collect::Vec<_>(); + //~^ ERROR generic parameters without surrounding angle brackets + let _ = vec![1, 2, 3].into_iter().collect::Vec<_>>>>(); + //~^ ERROR generic parameters without surrounding angle brackets + let _ = vec![1, 2, 3].into_iter().collect::Vec<_>>>(); + //~^ ERROR generic parameters without surrounding angle brackets + let _ = vec![1, 2, 3].into_iter().collect::Vec<_>>(); + //~^ ERROR generic parameters without surrounding angle brackets +} diff --git a/src/test/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.stderr b/src/test/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.stderr new file mode 100644 index 0000000000000..981f95749d3ba --- /dev/null +++ b/src/test/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.stderr @@ -0,0 +1,46 @@ +error: generic parameters without surrounding angle brackets + --> $DIR/recover-missing-turbofish-surrounding-angle-braket.rs:2:48 + | +LL | let _ = vec![1, 2, 3].into_iter().collect::Vec<_>(); + | ^^^^^^ + | +help: surround the type parameters with angle brackets + | +LL | let _ = vec![1, 2, 3].into_iter().collect::>(); + | ^ ^ + +error: generic parameters without surrounding angle brackets + --> $DIR/recover-missing-turbofish-surrounding-angle-braket.rs:4:48 + | +LL | let _ = vec![1, 2, 3].into_iter().collect::Vec<_>>>>(); + | ^^^^^^ + | +help: surround the type parameters with angle brackets + | +LL | let _ = vec![1, 2, 3].into_iter().collect::>(); + | ^ ^ + +error: generic parameters without surrounding angle brackets + --> $DIR/recover-missing-turbofish-surrounding-angle-braket.rs:6:48 + | +LL | let _ = vec![1, 2, 3].into_iter().collect::Vec<_>>>(); + | ^^^^^^ + | +help: surround the type parameters with angle brackets + | +LL | let _ = vec![1, 2, 3].into_iter().collect::>(); + | ^ ^ + +error: generic parameters without surrounding angle brackets + --> $DIR/recover-missing-turbofish-surrounding-angle-braket.rs:8:48 + | +LL | let _ = vec![1, 2, 3].into_iter().collect::Vec<_>>(); + | ^^^^^^ + | +help: surround the type parameters with angle brackets + | +LL | let _ = vec![1, 2, 3].into_iter().collect::>(); + | ^ ^ + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/unsized/unsized-trait-impl-self-type.stderr b/src/test/ui/unsized/unsized-trait-impl-self-type.stderr index 4514208a90dc9..071547c945edc 100644 --- a/src/test/ui/unsized/unsized-trait-impl-self-type.stderr +++ b/src/test/ui/unsized/unsized-trait-impl-self-type.stderr @@ -1,11 +1,11 @@ error[E0277]: the size for values of type `X` cannot be known at compilation time - --> $DIR/unsized-trait-impl-self-type.rs:10:17 + --> $DIR/unsized-trait-impl-self-type.rs:10:27 | LL | struct S5(Y); | - required by this bound in `S5` LL | LL | impl T3 for S5 { - | - ^^^^^ doesn't have a size known at compile-time + | - ^^^^^ doesn't have a size known at compile-time | | | this type parameter needs to be `std::marker::Sized` | diff --git a/src/test/ui/wf/wf-impl-self-type.rs b/src/test/ui/wf/wf-impl-self-type.rs new file mode 100644 index 0000000000000..2dd9b4ef01dbc --- /dev/null +++ b/src/test/ui/wf/wf-impl-self-type.rs @@ -0,0 +1,7 @@ +// Tests that we point at the proper location for an error +// involving the self-type of an impl + +trait Foo {} +impl Foo for Option<[u8]> {} //~ ERROR the size for + +fn main() {} diff --git a/src/test/ui/wf/wf-impl-self-type.stderr b/src/test/ui/wf/wf-impl-self-type.stderr new file mode 100644 index 0000000000000..a3a53113b4fda --- /dev/null +++ b/src/test/ui/wf/wf-impl-self-type.stderr @@ -0,0 +1,16 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/wf-impl-self-type.rs:5:14 + | +LL | impl Foo for Option<[u8]> {} + | ^^^^^^^^^^^^ doesn't have a size known at compile-time + | + ::: $SRC_DIR/libcore/option.rs:LL:COL + | +LL | pub enum Option { + | - required by this bound in `std::option::Option` + | + = help: the trait `std::marker::Sized` is not implemented for `[u8]` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`.