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:
commit
d30c3924a4
43 changed files with 559 additions and 94 deletions
|
@ -13,6 +13,7 @@ use rustc_middle::ty::{
|
||||||
use rustc_span::{ErrorGuaranteed, Span};
|
use rustc_span::{ErrorGuaranteed, Span};
|
||||||
use rustc_trait_selection::error_reporting::traits::report_dyn_incompatibility;
|
use rustc_trait_selection::error_reporting::traits::report_dyn_incompatibility;
|
||||||
use rustc_trait_selection::traits::{self, hir_ty_lowering_dyn_compatibility_violations};
|
use rustc_trait_selection::traits::{self, hir_ty_lowering_dyn_compatibility_violations};
|
||||||
|
use rustc_type_ir::elaborate::ClauseWithSupertraitSpan;
|
||||||
use smallvec::{SmallVec, smallvec};
|
use smallvec::{SmallVec, smallvec};
|
||||||
use tracing::{debug, instrument};
|
use tracing::{debug, instrument};
|
||||||
|
|
||||||
|
@ -124,16 +125,19 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|(trait_ref, _)| !tcx.trait_is_auto(trait_ref.def_id()));
|
.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);
|
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:?}`");
|
debug!("observing object predicate `{pred:?}`");
|
||||||
|
|
||||||
let bound_predicate = pred.kind();
|
let bound_predicate = pred.kind();
|
||||||
match bound_predicate.skip_binder() {
|
match bound_predicate.skip_binder() {
|
||||||
ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
|
ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
|
||||||
let pred = bound_predicate.rebind(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())
|
tcx.associated_items(pred.def_id())
|
||||||
.in_definition_order()
|
.in_definition_order()
|
||||||
.filter(|item| item.kind == ty::AssocKind::Type)
|
.filter(|item| item.kind == ty::AssocKind::Type)
|
||||||
|
@ -172,8 +176,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
// the discussion in #56288 for alternatives.
|
// the discussion in #56288 for alternatives.
|
||||||
if !references_self {
|
if !references_self {
|
||||||
// Include projections defined on supertraits.
|
// 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)
|
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>>>(
|
fn replace_dummy_self_with_error<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
|
||||||
|
|
|
@ -108,17 +108,20 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
let parent_id = tcx.hir().get_parent_item(self_ty.hir_id).def_id;
|
let parent_id = tcx.hir().get_parent_item(self_ty.hir_id).def_id;
|
||||||
if let hir::Node::Item(hir::Item {
|
if let hir::Node::Item(hir::Item {
|
||||||
kind:
|
kind: hir::ItemKind::Impl(hir::Impl { self_ty: impl_self_ty, of_trait, generics, .. }),
|
||||||
hir::ItemKind::Impl(hir::Impl {
|
|
||||||
self_ty: impl_self_ty,
|
|
||||||
of_trait: Some(of_trait_ref),
|
|
||||||
generics,
|
|
||||||
..
|
|
||||||
}),
|
|
||||||
..
|
..
|
||||||
}) = tcx.hir_node_by_def_id(parent_id)
|
}) = tcx.hir_node_by_def_id(parent_id)
|
||||||
&& self_ty.hir_id == impl_self_ty.hir_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()) {
|
if !of_trait_ref.trait_def_id().is_some_and(|def_id| def_id.is_local()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -235,6 +235,23 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
||||||
target,
|
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 => {}
|
None => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -121,16 +121,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
mutbl.ref_prefix_str()
|
mutbl.ref_prefix_str()
|
||||||
}
|
}
|
||||||
Some(probe::AutorefOrPtrAdjustment::ToConstPtr) | None => "",
|
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)
|
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
|
pick.autoref_or_ptr_adjustment
|
||||||
{
|
{
|
||||||
format!("{derefs}{self_expr} as *const _")
|
self_adjusted.push('>');
|
||||||
} else {
|
}
|
||||||
format!("{autoref}{derefs}{self_expr}")
|
|
||||||
};
|
|
||||||
|
|
||||||
lint.span_suggestion(
|
lint.span_suggestion(
|
||||||
sp,
|
sp,
|
||||||
|
@ -400,6 +411,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
let autoref = match pick.autoref_or_ptr_adjustment {
|
let autoref = match pick.autoref_or_ptr_adjustment {
|
||||||
Some(probe::AutorefOrPtrAdjustment::Autoref { mutbl, .. }) => mutbl.ref_prefix_str(),
|
Some(probe::AutorefOrPtrAdjustment::Autoref { mutbl, .. }) => mutbl.ref_prefix_str(),
|
||||||
Some(probe::AutorefOrPtrAdjustment::ToConstPtr) | None => "",
|
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
|
let (expr_text, precise) = if let Some(expr_text) = expr
|
||||||
|
@ -412,7 +427,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
("(..)".to_string(), false)
|
("(..)".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
|
pick.autoref_or_ptr_adjustment
|
||||||
{
|
{
|
||||||
format!("{derefs}{expr_text} as *const _")
|
format!("{derefs}{expr_text} as *const _")
|
||||||
|
@ -420,6 +435,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
format!("{autoref}{derefs}{expr_text}")
|
format!("{autoref}{derefs}{expr_text}")
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if let Some(probe::AutorefOrPtrAdjustment::ReborrowPin(_)) = pick.autoref_or_ptr_adjustment
|
||||||
|
{
|
||||||
|
adjusted_text.push('>');
|
||||||
|
}
|
||||||
|
|
||||||
(adjusted_text, precise)
|
(adjusted_text, precise)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -136,7 +136,7 @@ enum ProbeResult {
|
||||||
/// `mut`), or it has type `*mut T` and we convert it to `*const T`.
|
/// `mut`), or it has type `*mut T` and we convert it to `*const T`.
|
||||||
#[derive(Debug, PartialEq, Copy, Clone)]
|
#[derive(Debug, PartialEq, Copy, Clone)]
|
||||||
pub(crate) enum AutorefOrPtrAdjustment {
|
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.
|
/// Unsizing is used to convert a `[T; N]` to `[T]`, which only makes sense when autorefing.
|
||||||
Autoref {
|
Autoref {
|
||||||
mutbl: hir::Mutability,
|
mutbl: hir::Mutability,
|
||||||
|
@ -147,6 +147,9 @@ pub(crate) enum AutorefOrPtrAdjustment {
|
||||||
},
|
},
|
||||||
/// Receiver has type `*mut T`, convert to `*const T`
|
/// Receiver has type `*mut T`, convert to `*const T`
|
||||||
ToConstPtr,
|
ToConstPtr,
|
||||||
|
|
||||||
|
/// Reborrow a `Pin<&mut T>` or `Pin<&T>`.
|
||||||
|
ReborrowPin(hir::Mutability),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AutorefOrPtrAdjustment {
|
impl AutorefOrPtrAdjustment {
|
||||||
|
@ -154,6 +157,7 @@ impl AutorefOrPtrAdjustment {
|
||||||
match self {
|
match self {
|
||||||
AutorefOrPtrAdjustment::Autoref { mutbl: _, unsize } => *unsize,
|
AutorefOrPtrAdjustment::Autoref { mutbl: _, unsize } => *unsize,
|
||||||
AutorefOrPtrAdjustment::ToConstPtr => false,
|
AutorefOrPtrAdjustment::ToConstPtr => false,
|
||||||
|
AutorefOrPtrAdjustment::ReborrowPin(_) => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1103,6 +1107,13 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
||||||
unstable_candidates.as_deref_mut(),
|
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| {
|
r.map(|mut pick| {
|
||||||
pick.autoderefs = step.autoderefs;
|
pick.autoderefs = step.autoderefs;
|
||||||
|
|
||||||
// Insert a `&*` or `&mut *` if this is a reference type:
|
match *step.self_ty.value.value.kind() {
|
||||||
if let ty::Ref(_, _, mutbl) = *step.self_ty.value.value.kind() {
|
// Insert a `&*` or `&mut *` if this is a reference type:
|
||||||
pick.autoderefs += 1;
|
ty::Ref(_, _, mutbl) => {
|
||||||
pick.autoref_or_ptr_adjustment = Some(AutorefOrPtrAdjustment::Autoref {
|
pick.autoderefs += 1;
|
||||||
mutbl,
|
pick.autoref_or_ptr_adjustment = Some(AutorefOrPtrAdjustment::Autoref {
|
||||||
unsize: pick.autoref_or_ptr_adjustment.is_some_and(|a| a.get_unsize()),
|
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
|
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
|
/// 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
|
/// 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.
|
/// autorefs would require dereferencing the pointer, which is not safe.
|
||||||
|
|
|
@ -179,6 +179,10 @@ pub struct Clause<'tcx>(
|
||||||
);
|
);
|
||||||
|
|
||||||
impl<'tcx> rustc_type_ir::inherent::Clause<TyCtxt<'tcx>> for 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 {
|
fn instantiate_supertrait(self, tcx: TyCtxt<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>) -> Self {
|
||||||
self.instantiate_supertrait(tcx, trait_ref)
|
self.instantiate_supertrait(tcx, trait_ref)
|
||||||
}
|
}
|
||||||
|
|
|
@ -584,6 +584,16 @@ impl<'tcx> Ty<'tcx> {
|
||||||
Ty::new_ref(tcx, r, ty, hir::Mutability::Not)
|
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]
|
#[inline]
|
||||||
pub fn new_ptr(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, mutbl: ty::Mutability) -> Ty<'tcx> {
|
pub fn new_ptr(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, mutbl: ty::Mutability) -> Ty<'tcx> {
|
||||||
Ty::new(tcx, ty::RawPtr(ty, mutbl))
|
Ty::new(tcx, ty::RawPtr(ty, mutbl))
|
||||||
|
|
|
@ -600,13 +600,15 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Len(place) => {
|
Len(place) => {
|
||||||
let len = match self.get_const(place)? {
|
let len = if let ty::Array(_, n) = place.ty(self.local_decls(), self.tcx).ty.kind()
|
||||||
Value::Immediate(src) => src.len(&self.ecx).discard_err()?,
|
{
|
||||||
Value::Aggregate { fields, .. } => fields.len() as u64,
|
n.try_eval_target_usize(self.tcx, self.param_env)?
|
||||||
Value::Uninit => match place.ty(self.local_decls(), self.tcx).ty.kind() {
|
} else {
|
||||||
ty::Array(_, n) => n.try_eval_target_usize(self.tcx, self.param_env)?,
|
match self.get_const(place)? {
|
||||||
_ => return None,
|
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()
|
ImmTy::from_scalar(Scalar::from_target_usize(len, self), layout).into()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use core::ops::ControlFlow;
|
use core::ops::ControlFlow;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
|
use rustc_ast::TraitObjectSyntax;
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_data_structures::unord::UnordSet;
|
use rustc_data_structures::unord::UnordSet;
|
||||||
use rustc_errors::codes::*;
|
use rustc_errors::codes::*;
|
||||||
|
@ -573,7 +574,26 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
|
|
||||||
ty::PredicateKind::DynCompatible(trait_def_id) => {
|
ty::PredicateKind::DynCompatible(trait_def_id) => {
|
||||||
let violations = self.tcx.dyn_compatibility_violations(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)) => {
|
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(ty)) => {
|
||||||
|
|
|
@ -44,6 +44,46 @@ pub trait Elaboratable<I: Interner> {
|
||||||
) -> Self;
|
) -> 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>>(
|
pub fn elaborate<I: Interner, O: Elaboratable<I>>(
|
||||||
cx: I,
|
cx: I,
|
||||||
obligations: impl IntoIterator<Item = O>,
|
obligations: impl IntoIterator<Item = O>,
|
||||||
|
|
|
@ -460,6 +460,8 @@ pub trait Clause<I: Interner<Clause = Self>>:
|
||||||
+ IntoKind<Kind = ty::Binder<I, ty::ClauseKind<I>>>
|
+ IntoKind<Kind = ty::Binder<I, ty::ClauseKind<I>>>
|
||||||
+ Elaboratable<I>
|
+ Elaboratable<I>
|
||||||
{
|
{
|
||||||
|
fn as_predicate(self) -> I::Predicate;
|
||||||
|
|
||||||
fn as_trait_clause(self) -> Option<ty::Binder<I, ty::TraitPredicate<I>>> {
|
fn as_trait_clause(self) -> Option<ty::Binder<I, ty::TraitPredicate<I>>> {
|
||||||
self.kind()
|
self.kind()
|
||||||
.map_bound(|clause| if let ty::ClauseKind::Trait(t) = clause { Some(t) } else { None })
|
.map_bound(|clause| if let ty::ClauseKind::Trait(t) = clause { Some(t) } else { None })
|
||||||
|
|
|
@ -76,9 +76,9 @@ pub trait MirVisitor {
|
||||||
self.super_place(place, ptx, location)
|
self.super_place(place, ptx, location)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_projection_elem<'a>(
|
fn visit_projection_elem(
|
||||||
&mut self,
|
&mut self,
|
||||||
place_ref: PlaceRef<'a>,
|
place_ref: PlaceRef<'_>,
|
||||||
elem: &ProjectionElem,
|
elem: &ProjectionElem,
|
||||||
ptx: PlaceContext,
|
ptx: PlaceContext,
|
||||||
location: Location,
|
location: Location,
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
#![feature(const_cow_is_borrowed)]
|
#![feature(const_cow_is_borrowed)]
|
||||||
#![feature(const_heap)]
|
#![feature(const_heap)]
|
||||||
#![cfg_attr(bootstrap, feature(const_mut_refs))]
|
#![cfg_attr(bootstrap, feature(const_mut_refs))]
|
||||||
#![feature(const_slice_from_raw_parts_mut)]
|
|
||||||
#![feature(const_ptr_write)]
|
#![feature(const_ptr_write)]
|
||||||
#![feature(const_try)]
|
#![feature(const_try)]
|
||||||
#![feature(core_intrinsics)]
|
#![feature(core_intrinsics)]
|
||||||
|
|
|
@ -145,7 +145,6 @@
|
||||||
#![feature(const_replace)]
|
#![feature(const_replace)]
|
||||||
#![feature(const_size_of_val)]
|
#![feature(const_size_of_val)]
|
||||||
#![feature(const_size_of_val_raw)]
|
#![feature(const_size_of_val_raw)]
|
||||||
#![feature(const_slice_from_raw_parts_mut)]
|
|
||||||
#![feature(const_slice_from_ref)]
|
#![feature(const_slice_from_ref)]
|
||||||
#![feature(const_slice_split_at_mut)]
|
#![feature(const_slice_split_at_mut)]
|
||||||
#![feature(const_strict_overflow_ops)]
|
#![feature(const_strict_overflow_ops)]
|
||||||
|
|
|
@ -992,7 +992,7 @@ pub const fn slice_from_raw_parts<T>(data: *const T, len: usize) -> *const [T] {
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "slice_from_raw_parts", since = "1.42.0")]
|
#[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"]
|
#[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] {
|
pub const fn slice_from_raw_parts_mut<T>(data: *mut T, len: usize) -> *mut [T] {
|
||||||
from_raw_parts_mut(data, len)
|
from_raw_parts_mut(data, len)
|
||||||
|
|
|
@ -1434,7 +1434,10 @@ impl<T> NonNull<[T]> {
|
||||||
/// (Note that this example artificially demonstrates a use of this method,
|
/// (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.)
|
/// 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")]
|
#[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]
|
#[must_use]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn slice_from_raw_parts(data: NonNull<T>, len: usize) -> Self {
|
pub const fn slice_from_raw_parts(data: NonNull<T>, len: usize) -> Self {
|
||||||
|
|
|
@ -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
|
/// [`NonNull::dangling()`]: ptr::NonNull::dangling
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[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]
|
#[must_use]
|
||||||
#[rustc_diagnostic_item = "slice_from_raw_parts_mut"]
|
#[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] {
|
pub const unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] {
|
||||||
|
|
|
@ -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
|
/// character (`'a'`), byte character (`b'a'`), an integer or floating point number
|
||||||
/// with or without a suffix (`1`, `1u8`, `2.3`, `2.3f32`).
|
/// 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.
|
/// Boolean literals like `true` and `false` do not belong here, they are `Ident`s.
|
||||||
|
|
|
@ -2382,8 +2382,6 @@ pub trait BufRead: Read {
|
||||||
/// about Ferris from a binary string, skipping the fun fact:
|
/// about Ferris from a binary string, skipping the fun fact:
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(bufread_skip_until)]
|
|
||||||
///
|
|
||||||
/// use std::io::{self, BufRead};
|
/// use std::io::{self, BufRead};
|
||||||
///
|
///
|
||||||
/// let mut cursor = io::Cursor::new(b"Ferris\0Likes long walks on the beach\0Crustacean\0");
|
/// 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!(num_bytes, 11);
|
||||||
/// assert_eq!(animal, b"Crustacean\0");
|
/// 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> {
|
fn skip_until(&mut self, byte: u8) -> Result<usize> {
|
||||||
skip_until(self, byte)
|
skip_until(self, byte)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1996,11 +1996,22 @@ fn resolution_failure(
|
||||||
&diag_info,
|
&diag_info,
|
||||||
);
|
);
|
||||||
|
|
||||||
format!(
|
if let Some(disambiguator) = disambiguator
|
||||||
"this link resolves to {}, which is not in the {} namespace",
|
&& !matches!(disambiguator, Disambiguator::Namespace(..))
|
||||||
item(res),
|
{
|
||||||
expected_ns.descr()
|
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 {
|
if let Some(span) = sp {
|
||||||
|
|
|
@ -86,6 +86,7 @@ mod issue9612 {
|
||||||
util();
|
util();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unconditional_panic)]
|
||||||
fn util() {
|
fn util() {
|
||||||
let _a: u8 = 4.try_into().unwrap();
|
let _a: u8 = 4.try_into().unwrap();
|
||||||
let _a: u8 = 5.try_into().expect("");
|
let _a: u8 = 5.try_into().expect("");
|
||||||
|
|
|
@ -86,6 +86,7 @@ mod issue9612 {
|
||||||
util();
|
util();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unconditional_panic)]
|
||||||
fn util() {
|
fn util() {
|
||||||
let _a: u8 = 4.try_into().unwrap();
|
let _a: u8 = 4.try_into().unwrap();
|
||||||
let _a: u8 = 5.try_into().expect("");
|
let _a: u8 = 5.try_into().expect("");
|
||||||
|
|
|
@ -274,7 +274,7 @@ LL | let _ = &boxed_slice[1];
|
||||||
| ~~~~~~~~~~~~~~~
|
| ~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
error: called `.get().unwrap()` on a slice
|
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();
|
LL | let _ = Box::new([0]).get(1).unwrap();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
@ -70,6 +70,7 @@ fn main() {
|
||||||
mod issue9909 {
|
mod issue9909 {
|
||||||
#![allow(clippy::identity_op, clippy::unwrap_used, dead_code)]
|
#![allow(clippy::identity_op, clippy::unwrap_used, dead_code)]
|
||||||
|
|
||||||
|
#[allow(unconditional_panic)]
|
||||||
fn reduced() {
|
fn reduced() {
|
||||||
let f = &[1, 2, 3];
|
let f = &[1, 2, 3];
|
||||||
|
|
||||||
|
|
|
@ -70,6 +70,7 @@ fn main() {
|
||||||
mod issue9909 {
|
mod issue9909 {
|
||||||
#![allow(clippy::identity_op, clippy::unwrap_used, dead_code)]
|
#![allow(clippy::identity_op, clippy::unwrap_used, dead_code)]
|
||||||
|
|
||||||
|
#[allow(unconditional_panic)]
|
||||||
fn reduced() {
|
fn reduced() {
|
||||||
let f = &[1, 2, 3];
|
let f = &[1, 2, 3];
|
||||||
|
|
||||||
|
|
|
@ -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
|
= help: consider using `expect()` to provide a better panic message
|
||||||
|
|
||||||
error: called `.get().unwrap()` on a slice
|
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();
|
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
|
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();
|
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
|
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();
|
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
|
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();
|
LL | let b = rest.get_mut(linidx(j, k) - linidx(i, k) - 1).unwrap();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
@ -74,7 +74,7 @@ error: unresolved link to `m`
|
||||||
--> $DIR/disambiguator-mismatch.rs:52:14
|
--> $DIR/disambiguator-mismatch.rs:52:14
|
||||||
|
|
|
|
||||||
LL | /// Link to [m()]
|
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
|
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
|
--> $DIR/disambiguator-mismatch.rs:83:14
|
||||||
|
|
|
|
||||||
LL | /// Link to [fn@std]
|
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@`
|
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
|
--> $DIR/disambiguator-mismatch.rs:93:14
|
||||||
|
|
|
|
||||||
LL | /// Link to [field@S::A]
|
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@`
|
help: to link to the variant, prefix with `variant@`
|
||||||
|
|
|
|
||||||
|
|
|
@ -98,7 +98,7 @@ pub trait T {
|
||||||
/// [m()]
|
/// [m()]
|
||||||
//~^ ERROR unresolved link
|
//~^ ERROR unresolved link
|
||||||
//~| HELP to link to the macro
|
//~| HELP to link to the macro
|
||||||
//~| NOTE not in the value namespace
|
//~| NOTE not a function
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! m {
|
macro_rules! m {
|
||||||
() => {};
|
() => {};
|
||||||
|
|
|
@ -104,7 +104,7 @@ error: unresolved link to `S`
|
||||||
--> $DIR/errors.rs:68:6
|
--> $DIR/errors.rs:68:6
|
||||||
|
|
|
|
||||||
LL | /// [S!]
|
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@`
|
help: to link to the struct, prefix with `struct@`
|
||||||
|
|
|
|
||||||
|
@ -158,7 +158,7 @@ error: unresolved link to `m`
|
||||||
--> $DIR/errors.rs:98:6
|
--> $DIR/errors.rs:98:6
|
||||||
|
|
|
|
||||||
LL | /// [m()]
|
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
|
help: to link to the macro, add an exclamation mark
|
||||||
|
|
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ error: unresolved link to `Clone`
|
||||||
--> $DIR/issue-110495-suffix-with-space.rs:3:6
|
--> $DIR/issue-110495-suffix-with-space.rs:3:6
|
||||||
|
|
|
|
||||||
LL | //! [Clone ()].
|
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
|
note: the lint level is defined here
|
||||||
--> $DIR/issue-110495-suffix-with-space.rs:2:9
|
--> $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
|
--> $DIR/issue-110495-suffix-with-space.rs:5:7
|
||||||
|
|
|
|
||||||
LL | //! [`Clone ()`].
|
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@`
|
help: to link to the trait, prefix with `trait@`
|
||||||
|
|
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ error: unresolved link to `Clone`
|
||||||
--> $DIR/weird-syntax.rs:27:9
|
--> $DIR/weird-syntax.rs:27:9
|
||||||
|
|
|
|
||||||
LL | /// [ `Clone ()` ]
|
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@`
|
help: to link to the trait, prefix with `trait@`
|
||||||
|
|
|
|
||||||
|
@ -52,7 +52,7 @@ error: unresolved link to `Clone`
|
||||||
--> $DIR/weird-syntax.rs:30:7
|
--> $DIR/weird-syntax.rs:30:7
|
||||||
|
|
|
|
||||||
LL | /// [`Clone ()` ]
|
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@`
|
help: to link to the trait, prefix with `trait@`
|
||||||
|
|
|
|
||||||
|
@ -64,7 +64,7 @@ error: unresolved link to `Clone`
|
||||||
--> $DIR/weird-syntax.rs:33:9
|
--> $DIR/weird-syntax.rs:33:9
|
||||||
|
|
|
|
||||||
LL | /// [ `Clone ()`]
|
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@`
|
help: to link to the trait, prefix with `trait@`
|
||||||
|
|
|
|
||||||
|
@ -76,7 +76,7 @@ error: unresolved link to `Clone`
|
||||||
--> $DIR/weird-syntax.rs:36:9
|
--> $DIR/weird-syntax.rs:36:9
|
||||||
|
|
|
|
||||||
LL | /// [```Clone ()```]
|
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@`
|
help: to link to the trait, prefix with `trait@`
|
||||||
|
|
|
|
||||||
|
@ -88,7 +88,7 @@ error: unresolved link to `Clone`
|
||||||
--> $DIR/weird-syntax.rs:42:13
|
--> $DIR/weird-syntax.rs:42:13
|
||||||
|
|
|
|
||||||
LL | /// [ ``` Clone () ``` ]
|
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@`
|
help: to link to the trait, prefix with `trait@`
|
||||||
|
|
|
|
||||||
|
@ -122,7 +122,7 @@ error: unresolved link to `Clone`
|
||||||
--> $DIR/weird-syntax.rs:74:9
|
--> $DIR/weird-syntax.rs:74:9
|
||||||
|
|
|
|
||||||
LL | /// [x][Clone()]
|
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@`
|
help: to link to the trait, prefix with `trait@`
|
||||||
|
|
|
|
||||||
|
@ -134,7 +134,7 @@ error: unresolved link to `Clone`
|
||||||
--> $DIR/weird-syntax.rs:77:9
|
--> $DIR/weird-syntax.rs:77:9
|
||||||
|
|
|
|
||||||
LL | /// [x][Clone ()]
|
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@`
|
help: to link to the trait, prefix with `trait@`
|
||||||
|
|
|
|
||||||
|
@ -176,7 +176,7 @@ error: unresolved link to `Clone`
|
||||||
--> $DIR/weird-syntax.rs:97:9
|
--> $DIR/weird-syntax.rs:97:9
|
||||||
|
|
|
|
||||||
LL | /// [w](Clone\(\))
|
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@`
|
help: to link to the trait, prefix with `trait@`
|
||||||
|
|
|
|
||||||
|
@ -188,7 +188,7 @@ error: unresolved link to `Clone`
|
||||||
--> $DIR/weird-syntax.rs:103:9
|
--> $DIR/weird-syntax.rs:103:9
|
||||||
|
|
|
|
||||||
LL | /// [w](Clone())
|
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@`
|
help: to link to the trait, prefix with `trait@`
|
||||||
|
|
|
|
||||||
|
@ -256,7 +256,7 @@ error: unresolved link to `Clone`
|
||||||
--> $DIR/weird-syntax.rs:132:9
|
--> $DIR/weird-syntax.rs:132:9
|
||||||
|
|
|
|
||||||
LL | /// The [cln][] link here will produce a plain text suggestion
|
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
|
= help: to link to the trait, prefix with `trait@`: trait@Clone
|
||||||
|
|
||||||
|
|
|
@ -1,24 +1,33 @@
|
||||||
//@ check-pass
|
//@ check-pass
|
||||||
//@ignore-test
|
|
||||||
|
|
||||||
// Currently ignored due to self reborrowing not being implemented for Pin
|
|
||||||
|
|
||||||
#![feature(pin_ergonomics)]
|
#![feature(pin_ergonomics)]
|
||||||
#![allow(incomplete_features)]
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
|
|
||||||
struct Foo;
|
pub struct Foo;
|
||||||
|
|
||||||
impl Foo {
|
impl Foo {
|
||||||
fn foo(self: Pin<&mut Self>) {
|
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();
|
||||||
x.foo(); // for this to work we need to automatically reborrow,
|
x.foo(); // for this to work we need to automatically reborrow,
|
||||||
// as if the user had written `x.as_mut().foo()`.
|
// 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() {}
|
fn main() {}
|
||||||
|
|
|
@ -4,6 +4,11 @@ use std::pin::Pin;
|
||||||
|
|
||||||
struct Foo;
|
struct Foo;
|
||||||
|
|
||||||
|
impl Foo {
|
||||||
|
fn foo(self: Pin<&mut Self>) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn foo(_: Pin<&mut Foo>) {
|
fn foo(_: Pin<&mut Foo>) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,4 +17,9 @@ fn bar(mut x: Pin<&mut Foo>) {
|
||||||
foo(x); //~ ERROR use of moved value: `x`
|
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() {}
|
fn main() {}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0382]: use of moved value: `x`
|
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>) {
|
LL | fn bar(mut x: Pin<&mut Foo>) {
|
||||||
| ----- move occurs because `x` has type `Pin<&mut Foo>`, which does not implement the `Copy` trait
|
| ----- 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
|
| ^ value used here after move
|
||||||
|
|
|
|
||||||
note: consider changing this parameter type in function `foo` to borrow instead if owning the value isn't necessary
|
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>) {
|
LL | fn foo(_: Pin<&mut Foo>) {
|
||||||
| --- ^^^^^^^^^^^^^ this parameter takes ownership of the value
|
| --- ^^^^^^^^^^^^^ this parameter takes ownership of the value
|
||||||
| |
|
| |
|
||||||
| in this function
|
| 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`.
|
For more information about this error, try `rustc --explain E0382`.
|
||||||
|
|
8
tests/ui/lint/unconditional_panic_promoted.rs
Normal file
8
tests/ui/lint/unconditional_panic_promoted.rs
Normal 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]
|
||||||
|
}
|
10
tests/ui/lint/unconditional_panic_promoted.stderr
Normal file
10
tests/ui/lint/unconditional_panic_promoted.stderr
Normal 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
|
||||||
|
|
74
tests/ui/traits/missing-for-type-in-impl.e2015.stderr
Normal file
74
tests/ui/traits/missing-for-type-in-impl.e2015.stderr
Normal 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`.
|
31
tests/ui/traits/missing-for-type-in-impl.e2021.stderr
Normal file
31
tests/ui/traits/missing-for-type-in-impl.e2021.stderr
Normal 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`.
|
22
tests/ui/traits/missing-for-type-in-impl.rs
Normal file
22
tests/ui/traits/missing-for-type-in-impl.rs
Normal 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);
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
|
@ -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`.
|
|
@ -13,7 +13,7 @@ trait SuperGeneric<'a> {
|
||||||
}
|
}
|
||||||
trait AnyGeneric<'a>: SuperGeneric<'a> {}
|
trait AnyGeneric<'a>: SuperGeneric<'a> {}
|
||||||
trait FixedGeneric1<'a>: SuperGeneric<'a, Assoc2 = &'a u8> {}
|
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 FixedHrtb: for<'a> SuperGeneric<'a, Assoc2 = &'a u8> {}
|
||||||
trait AnyDifferentBinders: for<'a> SuperGeneric<'a, Assoc2 = &'a u8> + Super {}
|
trait AnyDifferentBinders: for<'a> SuperGeneric<'a, Assoc2 = &'a u8> + Super {}
|
||||||
trait FixedDifferentBinders: for<'a> SuperGeneric<'a, Assoc2 = &'a u8> + Super<Assoc = u8> {}
|
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_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_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_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_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_fixed_hrtb(x: &dyn FixedHrtb) { x } //~ERROR mismatched types
|
||||||
fn dyn_any_different_binders(x: &dyn AnyDifferentBinders<Assoc = u8>) { x } //~ERROR mismatched types
|
fn dyn_any_different_binders(x: &dyn AnyDifferentBinders<Assoc = u8>) { x } //~ERROR mismatched types
|
||||||
|
|
|
@ -106,17 +106,6 @@ LL | fn dyn_fixed_generic1(x: &dyn for<'a> FixedGeneric1<'a>) { x }
|
||||||
= note: expected unit type `()`
|
= note: expected unit type `()`
|
||||||
found reference `&dyn for<'a> FixedGeneric1<'a>`
|
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
|
error[E0308]: mismatched types
|
||||||
--> $DIR/pretty.rs:36:79
|
--> $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 `()`
|
= note: expected unit type `()`
|
||||||
found reference `&dyn HasGat<u8, Assoc<bool> = ()>`
|
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`.
|
For more information about this error, try `rustc --explain E0308`.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue