Auto merge of #131275 - workingjubilee:rollup-4yxqio3, r=workingjubilee

Rollup of 9 pull requests

Successful merges:

 - #129517 (Compute array length from type for unconditional panic lint. )
 - #130367 (Check elaborated projections from dyn don't mention unconstrained late bound lifetimes)
 - #130403 (Stabilize `const_slice_from_raw_parts_mut`)
 - #130633 (Add support for reborrowing pinned method receivers)
 - #131105 (update `Literal`'s intro)
 - #131194 (Fix needless_lifetimes in stable_mir)
 - #131260 (rustdoc: cleaner errors on disambiguator/namespace mismatches)
 - #131267 (Stabilize `BufRead::skip_until`)
 - #131273 (Account for `impl Trait {` when `impl Trait for Type {` was intended)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2024-10-05 03:41:42 +00:00
commit d30c3924a4
43 changed files with 559 additions and 94 deletions

View file

@ -13,6 +13,7 @@ use rustc_middle::ty::{
use rustc_span::{ErrorGuaranteed, Span};
use rustc_trait_selection::error_reporting::traits::report_dyn_incompatibility;
use rustc_trait_selection::traits::{self, hir_ty_lowering_dyn_compatibility_violations};
use rustc_type_ir::elaborate::ClauseWithSupertraitSpan;
use smallvec::{SmallVec, smallvec};
use tracing::{debug, instrument};
@ -124,16 +125,19 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
.into_iter()
.filter(|(trait_ref, _)| !tcx.trait_is_auto(trait_ref.def_id()));
for (base_trait_ref, span) in regular_traits_refs_spans {
for (base_trait_ref, original_span) in regular_traits_refs_spans {
let base_pred: ty::Predicate<'tcx> = base_trait_ref.upcast(tcx);
for pred in traits::elaborate(tcx, [base_pred]).filter_only_self() {
for ClauseWithSupertraitSpan { pred, original_span, supertrait_span } in
traits::elaborate(tcx, [ClauseWithSupertraitSpan::new(base_pred, original_span)])
.filter_only_self()
{
debug!("observing object predicate `{pred:?}`");
let bound_predicate = pred.kind();
match bound_predicate.skip_binder() {
ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
let pred = bound_predicate.rebind(pred);
associated_types.entry(span).or_default().extend(
associated_types.entry(original_span).or_default().extend(
tcx.associated_items(pred.def_id())
.in_definition_order()
.filter(|item| item.kind == ty::AssocKind::Type)
@ -172,8 +176,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
// the discussion in #56288 for alternatives.
if !references_self {
// Include projections defined on supertraits.
projection_bounds.push((pred, span));
projection_bounds.push((pred, original_span));
}
self.check_elaborated_projection_mentions_input_lifetimes(
pred,
original_span,
supertrait_span,
);
}
_ => (),
}
@ -360,6 +370,56 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
Ty::new_dynamic(tcx, existential_predicates, region_bound, representation)
}
/// Check that elaborating the principal of a trait ref doesn't lead to projections
/// that are unconstrained. This can happen because an otherwise unconstrained
/// *type variable* can be substituted with a type that has late-bound regions. See
/// `elaborated-predicates-unconstrained-late-bound.rs` for a test.
fn check_elaborated_projection_mentions_input_lifetimes(
&self,
pred: ty::PolyProjectionPredicate<'tcx>,
span: Span,
supertrait_span: Span,
) {
let tcx = self.tcx();
// Find any late-bound regions declared in `ty` that are not
// declared in the trait-ref or assoc_item. These are not well-formed.
//
// Example:
//
// for<'a> <T as Iterator>::Item = &'a str // <-- 'a is bad
// for<'a> <T as FnMut<(&'a u32,)>>::Output = &'a str // <-- 'a is ok
let late_bound_in_projection_term =
tcx.collect_constrained_late_bound_regions(pred.map_bound(|pred| pred.projection_term));
let late_bound_in_term =
tcx.collect_referenced_late_bound_regions(pred.map_bound(|pred| pred.term));
debug!(?late_bound_in_projection_term);
debug!(?late_bound_in_term);
// FIXME: point at the type params that don't have appropriate lifetimes:
// struct S1<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F);
// ---- ---- ^^^^^^^
// NOTE(associated_const_equality): This error should be impossible to trigger
// with associated const equality constraints.
self.validate_late_bound_regions(
late_bound_in_projection_term,
late_bound_in_term,
|br_name| {
let item_name = tcx.item_name(pred.projection_def_id());
struct_span_code_err!(
self.dcx(),
span,
E0582,
"binding for associated type `{}` references {}, \
which does not appear in the trait input types",
item_name,
br_name
)
.with_span_label(supertrait_span, "due to this supertrait")
},
);
}
}
fn replace_dummy_self_with_error<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(

View file

@ -108,17 +108,20 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
let tcx = self.tcx();
let parent_id = tcx.hir().get_parent_item(self_ty.hir_id).def_id;
if let hir::Node::Item(hir::Item {
kind:
hir::ItemKind::Impl(hir::Impl {
self_ty: impl_self_ty,
of_trait: Some(of_trait_ref),
generics,
..
}),
kind: hir::ItemKind::Impl(hir::Impl { self_ty: impl_self_ty, of_trait, generics, .. }),
..
}) = tcx.hir_node_by_def_id(parent_id)
&& self_ty.hir_id == impl_self_ty.hir_id
{
let Some(of_trait_ref) = of_trait else {
diag.span_suggestion_verbose(
impl_self_ty.span.shrink_to_hi(),
"you might have intended to implement this trait for a given type",
format!(" for /* Type */"),
Applicability::HasPlaceholders,
);
return;
};
if !of_trait_ref.trait_def_id().is_some_and(|def_id| def_id.is_local()) {
return;
}

View file

@ -235,6 +235,23 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
target,
});
}
Some(probe::AutorefOrPtrAdjustment::ReborrowPin(mutbl)) => {
let region = self.next_region_var(infer::Autoref(self.span));
target = match target.kind() {
ty::Adt(pin, args) if self.tcx.is_lang_item(pin.did(), hir::LangItem::Pin) => {
let inner_ty = match args[0].expect_ty().kind() {
ty::Ref(_, ty, _) => *ty,
_ => bug!("Expected a reference type for argument to Pin"),
};
Ty::new_pinned_ref(self.tcx, region, inner_ty, mutbl)
}
_ => bug!("Cannot adjust receiver type for reborrowing pin of {target:?}"),
};
adjustments.push(Adjustment { kind: Adjust::ReborrowPin(region, mutbl), target });
}
None => {}
}

View file

@ -121,16 +121,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
mutbl.ref_prefix_str()
}
Some(probe::AutorefOrPtrAdjustment::ToConstPtr) | None => "",
Some(probe::AutorefOrPtrAdjustment::ReborrowPin(mutbl)) => match mutbl {
hir::Mutability::Mut => "Pin<&mut ",
hir::Mutability::Not => "Pin<&",
},
};
if let Ok(self_expr) = self.sess().source_map().span_to_snippet(self_expr.span)
{
let self_adjusted = if let Some(probe::AutorefOrPtrAdjustment::ToConstPtr) =
let mut self_adjusted =
if let Some(probe::AutorefOrPtrAdjustment::ToConstPtr) =
pick.autoref_or_ptr_adjustment
{
format!("{derefs}{self_expr} as *const _")
} else {
format!("{autoref}{derefs}{self_expr}")
};
if let Some(probe::AutorefOrPtrAdjustment::ReborrowPin(_)) =
pick.autoref_or_ptr_adjustment
{
format!("{derefs}{self_expr} as *const _")
} else {
format!("{autoref}{derefs}{self_expr}")
};
self_adjusted.push('>');
}
lint.span_suggestion(
sp,
@ -400,6 +411,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let autoref = match pick.autoref_or_ptr_adjustment {
Some(probe::AutorefOrPtrAdjustment::Autoref { mutbl, .. }) => mutbl.ref_prefix_str(),
Some(probe::AutorefOrPtrAdjustment::ToConstPtr) | None => "",
Some(probe::AutorefOrPtrAdjustment::ReborrowPin(mutbl)) => match mutbl {
hir::Mutability::Mut => "Pin<&mut ",
hir::Mutability::Not => "Pin<&",
},
};
let (expr_text, precise) = if let Some(expr_text) = expr
@ -412,7 +427,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
("(..)".to_string(), false)
};
let adjusted_text = if let Some(probe::AutorefOrPtrAdjustment::ToConstPtr) =
let mut adjusted_text = if let Some(probe::AutorefOrPtrAdjustment::ToConstPtr) =
pick.autoref_or_ptr_adjustment
{
format!("{derefs}{expr_text} as *const _")
@ -420,6 +435,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
format!("{autoref}{derefs}{expr_text}")
};
if let Some(probe::AutorefOrPtrAdjustment::ReborrowPin(_)) = pick.autoref_or_ptr_adjustment
{
adjusted_text.push('>');
}
(adjusted_text, precise)
}
}

View file

@ -136,7 +136,7 @@ enum ProbeResult {
/// `mut`), or it has type `*mut T` and we convert it to `*const T`.
#[derive(Debug, PartialEq, Copy, Clone)]
pub(crate) enum AutorefOrPtrAdjustment {
/// Receiver has type `T`, add `&` or `&mut` (it `T` is `mut`), and maybe also "unsize" it.
/// Receiver has type `T`, add `&` or `&mut` (if `T` is `mut`), and maybe also "unsize" it.
/// Unsizing is used to convert a `[T; N]` to `[T]`, which only makes sense when autorefing.
Autoref {
mutbl: hir::Mutability,
@ -147,6 +147,9 @@ pub(crate) enum AutorefOrPtrAdjustment {
},
/// Receiver has type `*mut T`, convert to `*const T`
ToConstPtr,
/// Reborrow a `Pin<&mut T>` or `Pin<&T>`.
ReborrowPin(hir::Mutability),
}
impl AutorefOrPtrAdjustment {
@ -154,6 +157,7 @@ impl AutorefOrPtrAdjustment {
match self {
AutorefOrPtrAdjustment::Autoref { mutbl: _, unsize } => *unsize,
AutorefOrPtrAdjustment::ToConstPtr => false,
AutorefOrPtrAdjustment::ReborrowPin(_) => false,
}
}
}
@ -1103,6 +1107,13 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
unstable_candidates.as_deref_mut(),
)
})
.or_else(|| {
self.pick_reborrow_pin_method(
step,
self_ty,
unstable_candidates.as_deref_mut(),
)
})
})
})
}
@ -1127,13 +1138,28 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
r.map(|mut pick| {
pick.autoderefs = step.autoderefs;
// Insert a `&*` or `&mut *` if this is a reference type:
if let ty::Ref(_, _, mutbl) = *step.self_ty.value.value.kind() {
pick.autoderefs += 1;
pick.autoref_or_ptr_adjustment = Some(AutorefOrPtrAdjustment::Autoref {
mutbl,
unsize: pick.autoref_or_ptr_adjustment.is_some_and(|a| a.get_unsize()),
})
match *step.self_ty.value.value.kind() {
// Insert a `&*` or `&mut *` if this is a reference type:
ty::Ref(_, _, mutbl) => {
pick.autoderefs += 1;
pick.autoref_or_ptr_adjustment = Some(AutorefOrPtrAdjustment::Autoref {
mutbl,
unsize: pick.autoref_or_ptr_adjustment.is_some_and(|a| a.get_unsize()),
})
}
ty::Adt(def, args)
if self.tcx.features().pin_ergonomics
&& self.tcx.is_lang_item(def.did(), hir::LangItem::Pin) =>
{
// make sure this is a pinned reference (and not a `Pin<Box>` or something)
if let ty::Ref(_, _, mutbl) = args[0].expect_ty().kind() {
pick.autoref_or_ptr_adjustment =
Some(AutorefOrPtrAdjustment::ReborrowPin(*mutbl));
}
}
_ => (),
}
pick
@ -1164,6 +1190,43 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
})
}
/// Looks for applicable methods if we reborrow a `Pin<&mut T>` as a `Pin<&T>`.
#[instrument(level = "debug", skip(self, step, unstable_candidates))]
fn pick_reborrow_pin_method(
&self,
step: &CandidateStep<'tcx>,
self_ty: Ty<'tcx>,
unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>,
) -> Option<PickResult<'tcx>> {
if !self.tcx.features().pin_ergonomics {
return None;
}
// make sure self is a Pin<&mut T>
let inner_ty = match self_ty.kind() {
ty::Adt(def, args) if self.tcx.is_lang_item(def.did(), hir::LangItem::Pin) => {
match args[0].expect_ty().kind() {
ty::Ref(_, ty, hir::Mutability::Mut) => *ty,
_ => {
return None;
}
}
}
_ => return None,
};
let region = self.tcx.lifetimes.re_erased;
let autopin_ty = Ty::new_pinned_ref(self.tcx, region, inner_ty, hir::Mutability::Not);
self.pick_method(autopin_ty, unstable_candidates).map(|r| {
r.map(|mut pick| {
pick.autoderefs = step.autoderefs;
pick.autoref_or_ptr_adjustment =
Some(AutorefOrPtrAdjustment::ReborrowPin(hir::Mutability::Not));
pick
})
})
}
/// If `self_ty` is `*mut T` then this picks `*const T` methods. The reason why we have a
/// special case for this is because going from `*mut T` to `*const T` with autoderefs and
/// autorefs would require dereferencing the pointer, which is not safe.

View file

@ -179,6 +179,10 @@ pub struct Clause<'tcx>(
);
impl<'tcx> rustc_type_ir::inherent::Clause<TyCtxt<'tcx>> for Clause<'tcx> {
fn as_predicate(self) -> Predicate<'tcx> {
self.as_predicate()
}
fn instantiate_supertrait(self, tcx: TyCtxt<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>) -> Self {
self.instantiate_supertrait(tcx, trait_ref)
}

View file

@ -584,6 +584,16 @@ impl<'tcx> Ty<'tcx> {
Ty::new_ref(tcx, r, ty, hir::Mutability::Not)
}
pub fn new_pinned_ref(
tcx: TyCtxt<'tcx>,
r: Region<'tcx>,
ty: Ty<'tcx>,
mutbl: ty::Mutability,
) -> Ty<'tcx> {
let pin = tcx.adt_def(tcx.require_lang_item(LangItem::Pin, None));
Ty::new_adt(tcx, pin, tcx.mk_args(&[Ty::new_ref(tcx, r, ty, mutbl).into()]))
}
#[inline]
pub fn new_ptr(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, mutbl: ty::Mutability) -> Ty<'tcx> {
Ty::new(tcx, ty::RawPtr(ty, mutbl))

View file

@ -600,13 +600,15 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
}
Len(place) => {
let len = match self.get_const(place)? {
Value::Immediate(src) => src.len(&self.ecx).discard_err()?,
Value::Aggregate { fields, .. } => fields.len() as u64,
Value::Uninit => match place.ty(self.local_decls(), self.tcx).ty.kind() {
ty::Array(_, n) => n.try_eval_target_usize(self.tcx, self.param_env)?,
_ => return None,
},
let len = if let ty::Array(_, n) = place.ty(self.local_decls(), self.tcx).ty.kind()
{
n.try_eval_target_usize(self.tcx, self.param_env)?
} else {
match self.get_const(place)? {
Value::Immediate(src) => src.len(&self.ecx).discard_err()?,
Value::Aggregate { fields, .. } => fields.len() as u64,
Value::Uninit => return None,
}
};
ImmTy::from_scalar(Scalar::from_target_usize(len, self), layout).into()
}

View file

@ -1,6 +1,7 @@
use core::ops::ControlFlow;
use std::borrow::Cow;
use rustc_ast::TraitObjectSyntax;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::unord::UnordSet;
use rustc_errors::codes::*;
@ -573,7 +574,26 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
ty::PredicateKind::DynCompatible(trait_def_id) => {
let violations = self.tcx.dyn_compatibility_violations(trait_def_id);
report_dyn_incompatibility(self.tcx, span, None, trait_def_id, violations)
let mut err = report_dyn_incompatibility(
self.tcx,
span,
None,
trait_def_id,
violations,
);
if let hir::Node::Item(item) =
self.tcx.hir_node_by_def_id(obligation.cause.body_id)
&& let hir::ItemKind::Impl(impl_) = item.kind
&& let None = impl_.of_trait
&& let hir::TyKind::TraitObject(_, _, syntax) = impl_.self_ty.kind
&& let TraitObjectSyntax::None = syntax
&& impl_.self_ty.span.edition().at_least_rust_2021()
{
// Silence the dyn-compatibility error in favor of the missing dyn on
// self type error. #131051.
err.downgrade_to_delayed_bug();
}
err
}
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(ty)) => {

View file

@ -44,6 +44,46 @@ pub trait Elaboratable<I: Interner> {
) -> Self;
}
pub struct ClauseWithSupertraitSpan<I: Interner> {
pub pred: I::Predicate,
// Span of the original elaborated predicate.
pub original_span: I::Span,
// Span of the supertrait predicatae that lead to this clause.
pub supertrait_span: I::Span,
}
impl<I: Interner> ClauseWithSupertraitSpan<I> {
pub fn new(pred: I::Predicate, span: I::Span) -> Self {
ClauseWithSupertraitSpan { pred, original_span: span, supertrait_span: span }
}
}
impl<I: Interner> Elaboratable<I> for ClauseWithSupertraitSpan<I> {
fn predicate(&self) -> <I as Interner>::Predicate {
self.pred
}
fn child(&self, clause: <I as Interner>::Clause) -> Self {
ClauseWithSupertraitSpan {
pred: clause.as_predicate(),
original_span: self.original_span,
supertrait_span: self.supertrait_span,
}
}
fn child_with_derived_cause(
&self,
clause: <I as Interner>::Clause,
supertrait_span: <I as Interner>::Span,
_parent_trait_pred: crate::Binder<I, crate::TraitPredicate<I>>,
_index: usize,
) -> Self {
ClauseWithSupertraitSpan {
pred: clause.as_predicate(),
original_span: self.original_span,
supertrait_span: supertrait_span,
}
}
}
pub fn elaborate<I: Interner, O: Elaboratable<I>>(
cx: I,
obligations: impl IntoIterator<Item = O>,

View file

@ -460,6 +460,8 @@ pub trait Clause<I: Interner<Clause = Self>>:
+ IntoKind<Kind = ty::Binder<I, ty::ClauseKind<I>>>
+ Elaboratable<I>
{
fn as_predicate(self) -> I::Predicate;
fn as_trait_clause(self) -> Option<ty::Binder<I, ty::TraitPredicate<I>>> {
self.kind()
.map_bound(|clause| if let ty::ClauseKind::Trait(t) = clause { Some(t) } else { None })

View file

@ -76,9 +76,9 @@ pub trait MirVisitor {
self.super_place(place, ptx, location)
}
fn visit_projection_elem<'a>(
fn visit_projection_elem(
&mut self,
place_ref: PlaceRef<'a>,
place_ref: PlaceRef<'_>,
elem: &ProjectionElem,
ptx: PlaceContext,
location: Location,

View file

@ -7,7 +7,6 @@
#![feature(const_cow_is_borrowed)]
#![feature(const_heap)]
#![cfg_attr(bootstrap, feature(const_mut_refs))]
#![feature(const_slice_from_raw_parts_mut)]
#![feature(const_ptr_write)]
#![feature(const_try)]
#![feature(core_intrinsics)]

View file

@ -145,7 +145,6 @@
#![feature(const_replace)]
#![feature(const_size_of_val)]
#![feature(const_size_of_val_raw)]
#![feature(const_slice_from_raw_parts_mut)]
#![feature(const_slice_from_ref)]
#![feature(const_slice_split_at_mut)]
#![feature(const_strict_overflow_ops)]

View file

@ -992,7 +992,7 @@ pub const fn slice_from_raw_parts<T>(data: *const T, len: usize) -> *const [T] {
/// ```
#[inline]
#[stable(feature = "slice_from_raw_parts", since = "1.42.0")]
#[rustc_const_unstable(feature = "const_slice_from_raw_parts_mut", issue = "67456")]
#[rustc_const_stable(feature = "const_slice_from_raw_parts_mut", since = "CURRENT_RUSTC_VERSION")]
#[rustc_diagnostic_item = "ptr_slice_from_raw_parts_mut"]
pub const fn slice_from_raw_parts_mut<T>(data: *mut T, len: usize) -> *mut [T] {
from_raw_parts_mut(data, len)

View file

@ -1434,7 +1434,10 @@ impl<T> NonNull<[T]> {
/// (Note that this example artificially demonstrates a use of this method,
/// but `let slice = NonNull::from(&x[..]);` would be a better way to write code like this.)
#[stable(feature = "nonnull_slice_from_raw_parts", since = "1.70.0")]
#[rustc_const_unstable(feature = "const_slice_from_raw_parts_mut", issue = "67456")]
#[rustc_const_stable(
feature = "const_slice_from_raw_parts_mut",
since = "CURRENT_RUSTC_VERSION"
)]
#[must_use]
#[inline]
pub const fn slice_from_raw_parts(data: NonNull<T>, len: usize) -> Self {

View file

@ -171,7 +171,8 @@ pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T]
/// [`NonNull::dangling()`]: ptr::NonNull::dangling
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_slice_from_raw_parts_mut", issue = "67456")]
#[rustc_const_stable(feature = "const_slice_from_raw_parts_mut", since = "CURRENT_RUSTC_VERSION")]
#[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))]
#[must_use]
#[rustc_diagnostic_item = "slice_from_raw_parts_mut"]
pub const unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] {

View file

@ -1166,7 +1166,7 @@ impl fmt::Debug for Ident {
}
}
/// A literal string (`"hello"`), byte string (`b"hello"`),
/// A literal string (`"hello"`), byte string (`b"hello"`), C string (`c"hello"`),
/// character (`'a'`), byte character (`b'a'`), an integer or floating point number
/// with or without a suffix (`1`, `1u8`, `2.3`, `2.3f32`).
/// Boolean literals like `true` and `false` do not belong here, they are `Ident`s.

View file

@ -2382,8 +2382,6 @@ pub trait BufRead: Read {
/// about Ferris from a binary string, skipping the fun fact:
///
/// ```
/// #![feature(bufread_skip_until)]
///
/// use std::io::{self, BufRead};
///
/// let mut cursor = io::Cursor::new(b"Ferris\0Likes long walks on the beach\0Crustacean\0");
@ -2407,7 +2405,7 @@ pub trait BufRead: Read {
/// assert_eq!(num_bytes, 11);
/// assert_eq!(animal, b"Crustacean\0");
/// ```
#[unstable(feature = "bufread_skip_until", issue = "111735")]
#[stable(feature = "bufread_skip_until", since = "CURRENT_RUSTC_VERSION")]
fn skip_until(&mut self, byte: u8) -> Result<usize> {
skip_until(self, byte)
}

View file

@ -1996,11 +1996,22 @@ fn resolution_failure(
&diag_info,
);
format!(
"this link resolves to {}, which is not in the {} namespace",
item(res),
expected_ns.descr()
)
if let Some(disambiguator) = disambiguator
&& !matches!(disambiguator, Disambiguator::Namespace(..))
{
format!(
"this link resolves to {}, which is not {} {}",
item(res),
disambiguator.article(),
disambiguator.descr()
)
} else {
format!(
"this link resolves to {}, which is not in the {} namespace",
item(res),
expected_ns.descr()
)
}
}
};
if let Some(span) = sp {

View file

@ -86,6 +86,7 @@ mod issue9612 {
util();
}
#[allow(unconditional_panic)]
fn util() {
let _a: u8 = 4.try_into().unwrap();
let _a: u8 = 5.try_into().expect("");

View file

@ -86,6 +86,7 @@ mod issue9612 {
util();
}
#[allow(unconditional_panic)]
fn util() {
let _a: u8 = 4.try_into().unwrap();
let _a: u8 = 5.try_into().expect("");

View file

@ -274,7 +274,7 @@ LL | let _ = &boxed_slice[1];
| ~~~~~~~~~~~~~~~
error: called `.get().unwrap()` on a slice
--> tests/ui-toml/unwrap_used/unwrap_used.rs:93:17
--> tests/ui-toml/unwrap_used/unwrap_used.rs:94:17
|
LL | let _ = Box::new([0]).get(1).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View file

@ -70,6 +70,7 @@ fn main() {
mod issue9909 {
#![allow(clippy::identity_op, clippy::unwrap_used, dead_code)]
#[allow(unconditional_panic)]
fn reduced() {
let f = &[1, 2, 3];

View file

@ -70,6 +70,7 @@ fn main() {
mod issue9909 {
#![allow(clippy::identity_op, clippy::unwrap_used, dead_code)]
#[allow(unconditional_panic)]
fn reduced() {
let f = &[1, 2, 3];

View file

@ -266,7 +266,7 @@ LL | let _ = some_vec.get_mut(0..1).unwrap().to_vec();
= help: consider using `expect()` to provide a better panic message
error: called `.get().unwrap()` on a slice
--> tests/ui/get_unwrap.rs:77:24
--> tests/ui/get_unwrap.rs:78:24
|
LL | let _x: &i32 = f.get(1 + 2).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^
@ -277,7 +277,7 @@ LL | let _x: &i32 = &f[1 + 2];
| ~~~~~~~~~
error: called `.get().unwrap()` on a slice
--> tests/ui/get_unwrap.rs:80:18
--> tests/ui/get_unwrap.rs:81:18
|
LL | let _x = f.get(1 + 2).unwrap().to_string();
| ^^^^^^^^^^^^^^^^^^^^^
@ -288,7 +288,7 @@ LL | let _x = f[1 + 2].to_string();
| ~~~~~~~~
error: called `.get().unwrap()` on a slice
--> tests/ui/get_unwrap.rs:83:18
--> tests/ui/get_unwrap.rs:84:18
|
LL | let _x = f.get(1 + 2).unwrap().abs();
| ^^^^^^^^^^^^^^^^^^^^^
@ -299,7 +299,7 @@ LL | let _x = f[1 + 2].abs();
| ~~~~~~~~
error: called `.get_mut().unwrap()` on a slice
--> tests/ui/get_unwrap.rs:100:33
--> tests/ui/get_unwrap.rs:101:33
|
LL | let b = rest.get_mut(linidx(j, k) - linidx(i, k) - 1).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View file

@ -74,7 +74,7 @@ error: unresolved link to `m`
--> $DIR/disambiguator-mismatch.rs:52:14
|
LL | /// Link to [m()]
| ^^^ this link resolves to the macro `m`, which is not in the value namespace
| ^^^ this link resolves to the macro `m`, which is not a function
|
help: to link to the macro, add an exclamation mark
|
@ -142,7 +142,7 @@ error: unresolved link to `std`
--> $DIR/disambiguator-mismatch.rs:83:14
|
LL | /// Link to [fn@std]
| ^^^^^^ this link resolves to the crate `std`, which is not in the value namespace
| ^^^^^^ this link resolves to the crate `std`, which is not a function
|
help: to link to the crate, prefix with `mod@`
|
@ -164,7 +164,7 @@ error: unresolved link to `S::A`
--> $DIR/disambiguator-mismatch.rs:93:14
|
LL | /// Link to [field@S::A]
| ^^^^^^^^^^ this link resolves to the variant `A`, which is not in the value namespace
| ^^^^^^^^^^ this link resolves to the variant `A`, which is not a field
|
help: to link to the variant, prefix with `variant@`
|

View file

@ -98,7 +98,7 @@ pub trait T {
/// [m()]
//~^ ERROR unresolved link
//~| HELP to link to the macro
//~| NOTE not in the value namespace
//~| NOTE not a function
#[macro_export]
macro_rules! m {
() => {};

View file

@ -104,7 +104,7 @@ error: unresolved link to `S`
--> $DIR/errors.rs:68:6
|
LL | /// [S!]
| ^^ this link resolves to the struct `S`, which is not in the macro namespace
| ^^ this link resolves to the struct `S`, which is not a macro
|
help: to link to the struct, prefix with `struct@`
|
@ -158,7 +158,7 @@ error: unresolved link to `m`
--> $DIR/errors.rs:98:6
|
LL | /// [m()]
| ^^^ this link resolves to the macro `m`, which is not in the value namespace
| ^^^ this link resolves to the macro `m`, which is not a function
|
help: to link to the macro, add an exclamation mark
|

View file

@ -2,7 +2,7 @@ error: unresolved link to `Clone`
--> $DIR/issue-110495-suffix-with-space.rs:3:6
|
LL | //! [Clone ()].
| ^^^^^^^^ this link resolves to the trait `Clone`, which is not in the value namespace
| ^^^^^^^^ this link resolves to the trait `Clone`, which is not a function
|
note: the lint level is defined here
--> $DIR/issue-110495-suffix-with-space.rs:2:9
@ -31,7 +31,7 @@ error: unresolved link to `Clone`
--> $DIR/issue-110495-suffix-with-space.rs:5:7
|
LL | //! [`Clone ()`].
| ^^^^^^^^ this link resolves to the trait `Clone`, which is not in the value namespace
| ^^^^^^^^ this link resolves to the trait `Clone`, which is not a function
|
help: to link to the trait, prefix with `trait@`
|

View file

@ -40,7 +40,7 @@ error: unresolved link to `Clone`
--> $DIR/weird-syntax.rs:27:9
|
LL | /// [ `Clone ()` ]
| ^^^^^^^^ this link resolves to the trait `Clone`, which is not in the value namespace
| ^^^^^^^^ this link resolves to the trait `Clone`, which is not a function
|
help: to link to the trait, prefix with `trait@`
|
@ -52,7 +52,7 @@ error: unresolved link to `Clone`
--> $DIR/weird-syntax.rs:30:7
|
LL | /// [`Clone ()` ]
| ^^^^^^^^ this link resolves to the trait `Clone`, which is not in the value namespace
| ^^^^^^^^ this link resolves to the trait `Clone`, which is not a function
|
help: to link to the trait, prefix with `trait@`
|
@ -64,7 +64,7 @@ error: unresolved link to `Clone`
--> $DIR/weird-syntax.rs:33:9
|
LL | /// [ `Clone ()`]
| ^^^^^^^^ this link resolves to the trait `Clone`, which is not in the value namespace
| ^^^^^^^^ this link resolves to the trait `Clone`, which is not a function
|
help: to link to the trait, prefix with `trait@`
|
@ -76,7 +76,7 @@ error: unresolved link to `Clone`
--> $DIR/weird-syntax.rs:36:9
|
LL | /// [```Clone ()```]
| ^^^^^^^^ this link resolves to the trait `Clone`, which is not in the value namespace
| ^^^^^^^^ this link resolves to the trait `Clone`, which is not a function
|
help: to link to the trait, prefix with `trait@`
|
@ -88,7 +88,7 @@ error: unresolved link to `Clone`
--> $DIR/weird-syntax.rs:42:13
|
LL | /// [ ``` Clone () ``` ]
| ^^^^^^^^ this link resolves to the trait `Clone`, which is not in the value namespace
| ^^^^^^^^ this link resolves to the trait `Clone`, which is not a function
|
help: to link to the trait, prefix with `trait@`
|
@ -122,7 +122,7 @@ error: unresolved link to `Clone`
--> $DIR/weird-syntax.rs:74:9
|
LL | /// [x][Clone()]
| ^^^^^^^ this link resolves to the trait `Clone`, which is not in the value namespace
| ^^^^^^^ this link resolves to the trait `Clone`, which is not a function
|
help: to link to the trait, prefix with `trait@`
|
@ -134,7 +134,7 @@ error: unresolved link to `Clone`
--> $DIR/weird-syntax.rs:77:9
|
LL | /// [x][Clone ()]
| ^^^^^^^^^ this link resolves to the trait `Clone`, which is not in the value namespace
| ^^^^^^^^^ this link resolves to the trait `Clone`, which is not a function
|
help: to link to the trait, prefix with `trait@`
|
@ -176,7 +176,7 @@ error: unresolved link to `Clone`
--> $DIR/weird-syntax.rs:97:9
|
LL | /// [w](Clone\(\))
| ^^^^^^^^^ this link resolves to the trait `Clone`, which is not in the value namespace
| ^^^^^^^^^ this link resolves to the trait `Clone`, which is not a function
|
help: to link to the trait, prefix with `trait@`
|
@ -188,7 +188,7 @@ error: unresolved link to `Clone`
--> $DIR/weird-syntax.rs:103:9
|
LL | /// [w](Clone())
| ^^^^^^^ this link resolves to the trait `Clone`, which is not in the value namespace
| ^^^^^^^ this link resolves to the trait `Clone`, which is not a function
|
help: to link to the trait, prefix with `trait@`
|
@ -256,7 +256,7 @@ error: unresolved link to `Clone`
--> $DIR/weird-syntax.rs:132:9
|
LL | /// The [cln][] link here will produce a plain text suggestion
| ^^^^^ this link resolves to the trait `Clone`, which is not in the value namespace
| ^^^^^ this link resolves to the trait `Clone`, which is not a function
|
= help: to link to the trait, prefix with `trait@`: trait@Clone

View file

@ -1,24 +1,33 @@
//@ check-pass
//@ignore-test
// Currently ignored due to self reborrowing not being implemented for Pin
#![feature(pin_ergonomics)]
#![allow(incomplete_features)]
use std::pin::Pin;
struct Foo;
pub struct Foo;
impl Foo {
fn foo(self: Pin<&mut Self>) {
}
fn baz(self: Pin<&Self>) {
}
}
fn bar(x: Pin<&mut Foo>) {
pub fn bar(x: Pin<&mut Foo>) {
x.foo();
x.foo(); // for this to work we need to automatically reborrow,
// as if the user had written `x.as_mut().foo()`.
Foo::baz(x);
x.baz();
}
pub fn baaz(x: Pin<&Foo>) {
x.baz();
x.baz();
}
fn main() {}

View file

@ -4,6 +4,11 @@ use std::pin::Pin;
struct Foo;
impl Foo {
fn foo(self: Pin<&mut Self>) {
}
}
fn foo(_: Pin<&mut Foo>) {
}
@ -12,4 +17,9 @@ fn bar(mut x: Pin<&mut Foo>) {
foo(x); //~ ERROR use of moved value: `x`
}
fn baz(mut x: Pin<&mut Foo>) {
x.foo();
x.foo(); //~ ERROR use of moved value: `x`
}
fn main() {}

View file

@ -1,5 +1,5 @@
error[E0382]: use of moved value: `x`
--> $DIR/feature-gate-pin_ergonomics.rs:12:9
--> $DIR/feature-gate-pin_ergonomics.rs:17:9
|
LL | fn bar(mut x: Pin<&mut Foo>) {
| ----- move occurs because `x` has type `Pin<&mut Foo>`, which does not implement the `Copy` trait
@ -9,13 +9,33 @@ LL | foo(x);
| ^ value used here after move
|
note: consider changing this parameter type in function `foo` to borrow instead if owning the value isn't necessary
--> $DIR/feature-gate-pin_ergonomics.rs:7:11
--> $DIR/feature-gate-pin_ergonomics.rs:12:11
|
LL | fn foo(_: Pin<&mut Foo>) {
| --- ^^^^^^^^^^^^^ this parameter takes ownership of the value
| |
| in this function
error: aborting due to 1 previous error
error[E0382]: use of moved value: `x`
--> $DIR/feature-gate-pin_ergonomics.rs:22:5
|
LL | fn baz(mut x: Pin<&mut Foo>) {
| ----- move occurs because `x` has type `Pin<&mut Foo>`, which does not implement the `Copy` trait
LL | x.foo();
| ----- `x` moved due to this method call
LL | x.foo();
| ^ value used here after move
|
note: `Foo::foo` takes ownership of the receiver `self`, which moves `x`
--> $DIR/feature-gate-pin_ergonomics.rs:8:12
|
LL | fn foo(self: Pin<&mut Self>) {
| ^^^^
help: consider reborrowing the `Pin` instead of moving it
|
LL | x.as_mut().foo();
| +++++++++
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0382`.

View file

@ -0,0 +1,8 @@
//@ build-fail
fn main() {
// MIR encodes this as a reborrow from a promoted constant.
// But the array lenth can still be gotten from the type.
let slice = &[0, 1];
let _ = slice[2]; //~ ERROR: this operation will panic at runtime [unconditional_panic]
}

View file

@ -0,0 +1,10 @@
error: this operation will panic at runtime
--> $DIR/unconditional_panic_promoted.rs:7:13
|
LL | let _ = slice[2];
| ^^^^^^^^ index out of bounds: the length is 2 but the index is 2
|
= note: `#[deny(unconditional_panic)]` on by default
error: aborting due to 1 previous error

View file

@ -0,0 +1,74 @@
warning: trait objects without an explicit `dyn` are deprecated
--> $DIR/missing-for-type-in-impl.rs:8:6
|
LL | impl Foo<i64> {
| ^^^^^^^^
|
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
= note: `#[warn(bare_trait_objects)]` on by default
help: if this is a dyn-compatible trait, use `dyn`
|
LL | impl dyn Foo<i64> {
| +++
help: you might have intended to implement this trait for a given type
|
LL | impl Foo<i64> for /* Type */ {
| ++++++++++++++
warning: trait objects without an explicit `dyn` are deprecated
--> $DIR/missing-for-type-in-impl.rs:8:6
|
LL | impl Foo<i64> {
| ^^^^^^^^
|
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
help: if this is a dyn-compatible trait, use `dyn`
|
LL | impl dyn Foo<i64> {
| +++
help: you might have intended to implement this trait for a given type
|
LL | impl Foo<i64> for /* Type */ {
| ++++++++++++++
error[E0038]: the trait `Foo` cannot be made into an object
--> $DIR/missing-for-type-in-impl.rs:8:6
|
LL | impl Foo<i64> {
| ^^^^^^^^ `Foo` cannot be made into an object
|
note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/missing-for-type-in-impl.rs:4:8
|
LL | trait Foo<T> {
| --- this trait cannot be made into an object...
LL | fn id(me: T) -> T;
| ^^ ...because associated function `id` has no `self` parameter
help: consider turning `id` into a method by giving it a `&self` argument
|
LL | fn id(&self, me: T) -> T;
| ++++++
help: alternatively, consider constraining `id` so it does not apply to trait objects
|
LL | fn id(me: T) -> T where Self: Sized;
| +++++++++++++++++
error[E0277]: the trait bound `i64: Foo<i64>` is not satisfied
--> $DIR/missing-for-type-in-impl.rs:19:19
|
LL | let x: i64 = <i64 as Foo<i64>>::id(10);
| ^^^ the trait `Foo<i64>` is not implemented for `i64`
|
help: this trait has no implementations, consider adding one
--> $DIR/missing-for-type-in-impl.rs:3:1
|
LL | trait Foo<T> {
| ^^^^^^^^^^^^
error: aborting due to 2 previous errors; 2 warnings emitted
Some errors have detailed explanations: E0038, E0277.
For more information about an error, try `rustc --explain E0038`.

View file

@ -0,0 +1,31 @@
error[E0277]: the trait bound `i64: Foo<i64>` is not satisfied
--> $DIR/missing-for-type-in-impl.rs:19:19
|
LL | let x: i64 = <i64 as Foo<i64>>::id(10);
| ^^^ the trait `Foo<i64>` is not implemented for `i64`
|
help: this trait has no implementations, consider adding one
--> $DIR/missing-for-type-in-impl.rs:3:1
|
LL | trait Foo<T> {
| ^^^^^^^^^^^^
error[E0782]: trait objects must include the `dyn` keyword
--> $DIR/missing-for-type-in-impl.rs:8:6
|
LL | impl Foo<i64> {
| ^^^^^^^^
|
help: add `dyn` keyword before this trait
|
LL | impl dyn Foo<i64> {
| +++
help: you might have intended to implement this trait for a given type
|
LL | impl Foo<i64> for /* Type */ {
| ++++++++++++++
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0277, E0782.
For more information about an error, try `rustc --explain E0277`.

View file

@ -0,0 +1,22 @@
//@revisions: e2021 e2015
//@[e2021]edition: 2021
trait Foo<T> {
fn id(me: T) -> T;
}
/* note the "missing" for ... (in this case for i64, in order for this to compile) */
impl Foo<i64> {
//[e2021]~^ ERROR trait objects must include the `dyn` keyword
//[e2015]~^^ WARNING trait objects without an explicit `dyn` are deprecated
//[e2015]~| WARNING trait objects without an explicit `dyn` are deprecated
//[e2015]~| WARNING this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
//[e2015]~| WARNING this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
//[e2015]~| ERROR the trait `Foo` cannot be made into an object
fn id(me: i64) -> i64 {me}
}
fn main() {
let x: i64 = <i64 as Foo<i64>>::id(10);
//~^ ERROR the trait bound `i64: Foo<i64>` is not satisfied
println!("{}", x);
}

View file

@ -0,0 +1,24 @@
// Make sure that when elaborating the principal of a dyn trait for projection predicates
// we don't end up in a situation where we have an unconstrained late-bound lifetime in
// the output of a projection.
// Fix for <https://github.com/rust-lang/rust/issues/130347>.
trait A<T>: B<T = T> {}
trait B {
type T;
}
struct Erase<T: ?Sized + B>(T::T);
fn main() {
let x = {
let x = String::from("hello");
Erase::<dyn for<'a> A<&'a _>>(x.as_str())
//~^ ERROR binding for associated type `T` references lifetime `'a`, which does not appear in the trait input types
};
dbg!(x.0);
}

View file

@ -0,0 +1,12 @@
error[E0582]: binding for associated type `T` references lifetime `'a`, which does not appear in the trait input types
--> $DIR/elaborated-predicates-unconstrained-late-bound.rs:19:21
|
LL | trait A<T>: B<T = T> {}
| ----- due to this supertrait
...
LL | Erase::<dyn for<'a> A<&'a _>>(x.as_str())
| ^^^^^^^^^^^^^^^^
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0582`.

View file

@ -13,7 +13,7 @@ trait SuperGeneric<'a> {
}
trait AnyGeneric<'a>: SuperGeneric<'a> {}
trait FixedGeneric1<'a>: SuperGeneric<'a, Assoc2 = &'a u8> {}
trait FixedGeneric2<'a>: Super<Assoc = &'a u8> {}
// trait FixedGeneric2<'a>: Super<Assoc = &'a u8> {} // Unsound!
trait FixedHrtb: for<'a> SuperGeneric<'a, Assoc2 = &'a u8> {}
trait AnyDifferentBinders: for<'a> SuperGeneric<'a, Assoc2 = &'a u8> + Super {}
trait FixedDifferentBinders: for<'a> SuperGeneric<'a, Assoc2 = &'a u8> + Super<Assoc = u8> {}
@ -32,7 +32,7 @@ fn dyn_fixed_static(x: &dyn FixedStatic) { x } //~ERROR mismatched types
fn dyn_super_generic(x: &dyn for<'a> SuperGeneric<'a, Assoc2 = &'a u8>) { x } //~ERROR mismatched types
fn dyn_any_generic(x: &dyn for<'a> AnyGeneric<'a, Assoc2 = &'a u8>) { x } //~ERROR mismatched types
fn dyn_fixed_generic1(x: &dyn for<'a> FixedGeneric1<'a>) { x } //~ERROR mismatched types
fn dyn_fixed_generic2(x: &dyn for<'a> FixedGeneric2<'a>) { x } //~ERROR mismatched types
// fn dyn_fixed_generic2(x: &dyn for<'a> FixedGeneric2<'a>) { x } // Unsound!
fn dyn_fixed_generic_multi(x: &dyn for<'a> FixedGeneric1<'a, Assoc2 = &u8>) { x } //~ERROR mismatched types
fn dyn_fixed_hrtb(x: &dyn FixedHrtb) { x } //~ERROR mismatched types
fn dyn_any_different_binders(x: &dyn AnyDifferentBinders<Assoc = u8>) { x } //~ERROR mismatched types

View file

@ -106,17 +106,6 @@ LL | fn dyn_fixed_generic1(x: &dyn for<'a> FixedGeneric1<'a>) { x }
= note: expected unit type `()`
found reference `&dyn for<'a> FixedGeneric1<'a>`
error[E0308]: mismatched types
--> $DIR/pretty.rs:35:60
|
LL | fn dyn_fixed_generic2(x: &dyn for<'a> FixedGeneric2<'a>) { x }
| - ^ expected `()`, found `&dyn FixedGeneric2<'a>`
| |
| help: try adding a return type: `-> &dyn for<'a> FixedGeneric2<'a>`
|
= note: expected unit type `()`
found reference `&dyn for<'a> FixedGeneric2<'a>`
error[E0308]: mismatched types
--> $DIR/pretty.rs:36:79
|
@ -172,6 +161,6 @@ LL | fn dyn_has_gat(x: &dyn HasGat<u8, Assoc<bool> = ()>) { x }
= note: expected unit type `()`
found reference `&dyn HasGat<u8, Assoc<bool> = ()>`
error: aborting due to 15 previous errors; 1 warning emitted
error: aborting due to 14 previous errors; 1 warning emitted
For more information about this error, try `rustc --explain E0308`.