Skip to content

Commit d30c392

Browse files
committed
Auto merge of rust-lang#131275 - workingjubilee:rollup-4yxqio3, r=workingjubilee
Rollup of 9 pull requests Successful merges: - rust-lang#129517 (Compute array length from type for unconditional panic lint. ) - rust-lang#130367 (Check elaborated projections from dyn don't mention unconstrained late bound lifetimes) - rust-lang#130403 (Stabilize `const_slice_from_raw_parts_mut`) - rust-lang#130633 (Add support for reborrowing pinned method receivers) - rust-lang#131105 (update `Literal`'s intro) - rust-lang#131194 (Fix needless_lifetimes in stable_mir) - rust-lang#131260 (rustdoc: cleaner errors on disambiguator/namespace mismatches) - rust-lang#131267 (Stabilize `BufRead::skip_until`) - rust-lang#131273 (Account for `impl Trait {` when `impl Trait for Type {` was intended) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 495f75a + 08689af commit d30c392

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+559
-94
lines changed

compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs

+64-4
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use rustc_middle::ty::{
1313
use rustc_span::{ErrorGuaranteed, Span};
1414
use rustc_trait_selection::error_reporting::traits::report_dyn_incompatibility;
1515
use rustc_trait_selection::traits::{self, hir_ty_lowering_dyn_compatibility_violations};
16+
use rustc_type_ir::elaborate::ClauseWithSupertraitSpan;
1617
use smallvec::{SmallVec, smallvec};
1718
use tracing::{debug, instrument};
1819

@@ -124,16 +125,19 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
124125
.into_iter()
125126
.filter(|(trait_ref, _)| !tcx.trait_is_auto(trait_ref.def_id()));
126127

127-
for (base_trait_ref, span) in regular_traits_refs_spans {
128+
for (base_trait_ref, original_span) in regular_traits_refs_spans {
128129
let base_pred: ty::Predicate<'tcx> = base_trait_ref.upcast(tcx);
129-
for pred in traits::elaborate(tcx, [base_pred]).filter_only_self() {
130+
for ClauseWithSupertraitSpan { pred, original_span, supertrait_span } in
131+
traits::elaborate(tcx, [ClauseWithSupertraitSpan::new(base_pred, original_span)])
132+
.filter_only_self()
133+
{
130134
debug!("observing object predicate `{pred:?}`");
131135

132136
let bound_predicate = pred.kind();
133137
match bound_predicate.skip_binder() {
134138
ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
135139
let pred = bound_predicate.rebind(pred);
136-
associated_types.entry(span).or_default().extend(
140+
associated_types.entry(original_span).or_default().extend(
137141
tcx.associated_items(pred.def_id())
138142
.in_definition_order()
139143
.filter(|item| item.kind == ty::AssocKind::Type)
@@ -172,8 +176,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
172176
// the discussion in #56288 for alternatives.
173177
if !references_self {
174178
// Include projections defined on supertraits.
175-
projection_bounds.push((pred, span));
179+
projection_bounds.push((pred, original_span));
176180
}
181+
182+
self.check_elaborated_projection_mentions_input_lifetimes(
183+
pred,
184+
original_span,
185+
supertrait_span,
186+
);
177187
}
178188
_ => (),
179189
}
@@ -360,6 +370,56 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
360370

361371
Ty::new_dynamic(tcx, existential_predicates, region_bound, representation)
362372
}
373+
374+
/// Check that elaborating the principal of a trait ref doesn't lead to projections
375+
/// that are unconstrained. This can happen because an otherwise unconstrained
376+
/// *type variable* can be substituted with a type that has late-bound regions. See
377+
/// `elaborated-predicates-unconstrained-late-bound.rs` for a test.
378+
fn check_elaborated_projection_mentions_input_lifetimes(
379+
&self,
380+
pred: ty::PolyProjectionPredicate<'tcx>,
381+
span: Span,
382+
supertrait_span: Span,
383+
) {
384+
let tcx = self.tcx();
385+
386+
// Find any late-bound regions declared in `ty` that are not
387+
// declared in the trait-ref or assoc_item. These are not well-formed.
388+
//
389+
// Example:
390+
//
391+
// for<'a> <T as Iterator>::Item = &'a str // <-- 'a is bad
392+
// for<'a> <T as FnMut<(&'a u32,)>>::Output = &'a str // <-- 'a is ok
393+
let late_bound_in_projection_term =
394+
tcx.collect_constrained_late_bound_regions(pred.map_bound(|pred| pred.projection_term));
395+
let late_bound_in_term =
396+
tcx.collect_referenced_late_bound_regions(pred.map_bound(|pred| pred.term));
397+
debug!(?late_bound_in_projection_term);
398+
debug!(?late_bound_in_term);
399+
400+
// FIXME: point at the type params that don't have appropriate lifetimes:
401+
// struct S1<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F);
402+
// ---- ---- ^^^^^^^
403+
// NOTE(associated_const_equality): This error should be impossible to trigger
404+
// with associated const equality constraints.
405+
self.validate_late_bound_regions(
406+
late_bound_in_projection_term,
407+
late_bound_in_term,
408+
|br_name| {
409+
let item_name = tcx.item_name(pred.projection_def_id());
410+
struct_span_code_err!(
411+
self.dcx(),
412+
span,
413+
E0582,
414+
"binding for associated type `{}` references {}, \
415+
which does not appear in the trait input types",
416+
item_name,
417+
br_name
418+
)
419+
.with_span_label(supertrait_span, "due to this supertrait")
420+
},
421+
);
422+
}
363423
}
364424

365425
fn replace_dummy_self_with_error<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(

compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs

+10-7
Original file line numberDiff line numberDiff line change
@@ -108,17 +108,20 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
108108
let tcx = self.tcx();
109109
let parent_id = tcx.hir().get_parent_item(self_ty.hir_id).def_id;
110110
if let hir::Node::Item(hir::Item {
111-
kind:
112-
hir::ItemKind::Impl(hir::Impl {
113-
self_ty: impl_self_ty,
114-
of_trait: Some(of_trait_ref),
115-
generics,
116-
..
117-
}),
111+
kind: hir::ItemKind::Impl(hir::Impl { self_ty: impl_self_ty, of_trait, generics, .. }),
118112
..
119113
}) = tcx.hir_node_by_def_id(parent_id)
120114
&& self_ty.hir_id == impl_self_ty.hir_id
121115
{
116+
let Some(of_trait_ref) = of_trait else {
117+
diag.span_suggestion_verbose(
118+
impl_self_ty.span.shrink_to_hi(),
119+
"you might have intended to implement this trait for a given type",
120+
format!(" for /* Type */"),
121+
Applicability::HasPlaceholders,
122+
);
123+
return;
124+
};
122125
if !of_trait_ref.trait_def_id().is_some_and(|def_id| def_id.is_local()) {
123126
return;
124127
}

compiler/rustc_hir_typeck/src/method/confirm.rs

+17
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,23 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
235235
target,
236236
});
237237
}
238+
239+
Some(probe::AutorefOrPtrAdjustment::ReborrowPin(mutbl)) => {
240+
let region = self.next_region_var(infer::Autoref(self.span));
241+
242+
target = match target.kind() {
243+
ty::Adt(pin, args) if self.tcx.is_lang_item(pin.did(), hir::LangItem::Pin) => {
244+
let inner_ty = match args[0].expect_ty().kind() {
245+
ty::Ref(_, ty, _) => *ty,
246+
_ => bug!("Expected a reference type for argument to Pin"),
247+
};
248+
Ty::new_pinned_ref(self.tcx, region, inner_ty, mutbl)
249+
}
250+
_ => bug!("Cannot adjust receiver type for reborrowing pin of {target:?}"),
251+
};
252+
253+
adjustments.push(Adjustment { kind: Adjust::ReborrowPin(region, mutbl), target });
254+
}
238255
None => {}
239256
}
240257

compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs

+26-6
Original file line numberDiff line numberDiff line change
@@ -121,16 +121,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
121121
mutbl.ref_prefix_str()
122122
}
123123
Some(probe::AutorefOrPtrAdjustment::ToConstPtr) | None => "",
124+
Some(probe::AutorefOrPtrAdjustment::ReborrowPin(mutbl)) => match mutbl {
125+
hir::Mutability::Mut => "Pin<&mut ",
126+
hir::Mutability::Not => "Pin<&",
127+
},
124128
};
125129
if let Ok(self_expr) = self.sess().source_map().span_to_snippet(self_expr.span)
126130
{
127-
let self_adjusted = if let Some(probe::AutorefOrPtrAdjustment::ToConstPtr) =
131+
let mut self_adjusted =
132+
if let Some(probe::AutorefOrPtrAdjustment::ToConstPtr) =
133+
pick.autoref_or_ptr_adjustment
134+
{
135+
format!("{derefs}{self_expr} as *const _")
136+
} else {
137+
format!("{autoref}{derefs}{self_expr}")
138+
};
139+
140+
if let Some(probe::AutorefOrPtrAdjustment::ReborrowPin(_)) =
128141
pick.autoref_or_ptr_adjustment
129142
{
130-
format!("{derefs}{self_expr} as *const _")
131-
} else {
132-
format!("{autoref}{derefs}{self_expr}")
133-
};
143+
self_adjusted.push('>');
144+
}
134145

135146
lint.span_suggestion(
136147
sp,
@@ -400,6 +411,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
400411
let autoref = match pick.autoref_or_ptr_adjustment {
401412
Some(probe::AutorefOrPtrAdjustment::Autoref { mutbl, .. }) => mutbl.ref_prefix_str(),
402413
Some(probe::AutorefOrPtrAdjustment::ToConstPtr) | None => "",
414+
Some(probe::AutorefOrPtrAdjustment::ReborrowPin(mutbl)) => match mutbl {
415+
hir::Mutability::Mut => "Pin<&mut ",
416+
hir::Mutability::Not => "Pin<&",
417+
},
403418
};
404419

405420
let (expr_text, precise) = if let Some(expr_text) = expr
@@ -412,14 +427,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
412427
("(..)".to_string(), false)
413428
};
414429

415-
let adjusted_text = if let Some(probe::AutorefOrPtrAdjustment::ToConstPtr) =
430+
let mut adjusted_text = if let Some(probe::AutorefOrPtrAdjustment::ToConstPtr) =
416431
pick.autoref_or_ptr_adjustment
417432
{
418433
format!("{derefs}{expr_text} as *const _")
419434
} else {
420435
format!("{autoref}{derefs}{expr_text}")
421436
};
422437

438+
if let Some(probe::AutorefOrPtrAdjustment::ReborrowPin(_)) = pick.autoref_or_ptr_adjustment
439+
{
440+
adjusted_text.push('>');
441+
}
442+
423443
(adjusted_text, precise)
424444
}
425445
}

compiler/rustc_hir_typeck/src/method/probe.rs

+71-8
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ enum ProbeResult {
136136
/// `mut`), or it has type `*mut T` and we convert it to `*const T`.
137137
#[derive(Debug, PartialEq, Copy, Clone)]
138138
pub(crate) enum AutorefOrPtrAdjustment {
139-
/// Receiver has type `T`, add `&` or `&mut` (it `T` is `mut`), and maybe also "unsize" it.
139+
/// Receiver has type `T`, add `&` or `&mut` (if `T` is `mut`), and maybe also "unsize" it.
140140
/// Unsizing is used to convert a `[T; N]` to `[T]`, which only makes sense when autorefing.
141141
Autoref {
142142
mutbl: hir::Mutability,
@@ -147,13 +147,17 @@ pub(crate) enum AutorefOrPtrAdjustment {
147147
},
148148
/// Receiver has type `*mut T`, convert to `*const T`
149149
ToConstPtr,
150+
151+
/// Reborrow a `Pin<&mut T>` or `Pin<&T>`.
152+
ReborrowPin(hir::Mutability),
150153
}
151154

152155
impl AutorefOrPtrAdjustment {
153156
fn get_unsize(&self) -> bool {
154157
match self {
155158
AutorefOrPtrAdjustment::Autoref { mutbl: _, unsize } => *unsize,
156159
AutorefOrPtrAdjustment::ToConstPtr => false,
160+
AutorefOrPtrAdjustment::ReborrowPin(_) => false,
157161
}
158162
}
159163
}
@@ -1103,6 +1107,13 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
11031107
unstable_candidates.as_deref_mut(),
11041108
)
11051109
})
1110+
.or_else(|| {
1111+
self.pick_reborrow_pin_method(
1112+
step,
1113+
self_ty,
1114+
unstable_candidates.as_deref_mut(),
1115+
)
1116+
})
11061117
})
11071118
})
11081119
}
@@ -1127,13 +1138,28 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
11271138
r.map(|mut pick| {
11281139
pick.autoderefs = step.autoderefs;
11291140

1130-
// Insert a `&*` or `&mut *` if this is a reference type:
1131-
if let ty::Ref(_, _, mutbl) = *step.self_ty.value.value.kind() {
1132-
pick.autoderefs += 1;
1133-
pick.autoref_or_ptr_adjustment = Some(AutorefOrPtrAdjustment::Autoref {
1134-
mutbl,
1135-
unsize: pick.autoref_or_ptr_adjustment.is_some_and(|a| a.get_unsize()),
1136-
})
1141+
match *step.self_ty.value.value.kind() {
1142+
// Insert a `&*` or `&mut *` if this is a reference type:
1143+
ty::Ref(_, _, mutbl) => {
1144+
pick.autoderefs += 1;
1145+
pick.autoref_or_ptr_adjustment = Some(AutorefOrPtrAdjustment::Autoref {
1146+
mutbl,
1147+
unsize: pick.autoref_or_ptr_adjustment.is_some_and(|a| a.get_unsize()),
1148+
})
1149+
}
1150+
1151+
ty::Adt(def, args)
1152+
if self.tcx.features().pin_ergonomics
1153+
&& self.tcx.is_lang_item(def.did(), hir::LangItem::Pin) =>
1154+
{
1155+
// make sure this is a pinned reference (and not a `Pin<Box>` or something)
1156+
if let ty::Ref(_, _, mutbl) = args[0].expect_ty().kind() {
1157+
pick.autoref_or_ptr_adjustment =
1158+
Some(AutorefOrPtrAdjustment::ReborrowPin(*mutbl));
1159+
}
1160+
}
1161+
1162+
_ => (),
11371163
}
11381164

11391165
pick
@@ -1164,6 +1190,43 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
11641190
})
11651191
}
11661192

1193+
/// Looks for applicable methods if we reborrow a `Pin<&mut T>` as a `Pin<&T>`.
1194+
#[instrument(level = "debug", skip(self, step, unstable_candidates))]
1195+
fn pick_reborrow_pin_method(
1196+
&self,
1197+
step: &CandidateStep<'tcx>,
1198+
self_ty: Ty<'tcx>,
1199+
unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>,
1200+
) -> Option<PickResult<'tcx>> {
1201+
if !self.tcx.features().pin_ergonomics {
1202+
return None;
1203+
}
1204+
1205+
// make sure self is a Pin<&mut T>
1206+
let inner_ty = match self_ty.kind() {
1207+
ty::Adt(def, args) if self.tcx.is_lang_item(def.did(), hir::LangItem::Pin) => {
1208+
match args[0].expect_ty().kind() {
1209+
ty::Ref(_, ty, hir::Mutability::Mut) => *ty,
1210+
_ => {
1211+
return None;
1212+
}
1213+
}
1214+
}
1215+
_ => return None,
1216+
};
1217+
1218+
let region = self.tcx.lifetimes.re_erased;
1219+
let autopin_ty = Ty::new_pinned_ref(self.tcx, region, inner_ty, hir::Mutability::Not);
1220+
self.pick_method(autopin_ty, unstable_candidates).map(|r| {
1221+
r.map(|mut pick| {
1222+
pick.autoderefs = step.autoderefs;
1223+
pick.autoref_or_ptr_adjustment =
1224+
Some(AutorefOrPtrAdjustment::ReborrowPin(hir::Mutability::Not));
1225+
pick
1226+
})
1227+
})
1228+
}
1229+
11671230
/// If `self_ty` is `*mut T` then this picks `*const T` methods. The reason why we have a
11681231
/// special case for this is because going from `*mut T` to `*const T` with autoderefs and
11691232
/// autorefs would require dereferencing the pointer, which is not safe.

compiler/rustc_middle/src/ty/predicate.rs

+4
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,10 @@ pub struct Clause<'tcx>(
179179
);
180180

181181
impl<'tcx> rustc_type_ir::inherent::Clause<TyCtxt<'tcx>> for Clause<'tcx> {
182+
fn as_predicate(self) -> Predicate<'tcx> {
183+
self.as_predicate()
184+
}
185+
182186
fn instantiate_supertrait(self, tcx: TyCtxt<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>) -> Self {
183187
self.instantiate_supertrait(tcx, trait_ref)
184188
}

compiler/rustc_middle/src/ty/sty.rs

+10
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,16 @@ impl<'tcx> Ty<'tcx> {
584584
Ty::new_ref(tcx, r, ty, hir::Mutability::Not)
585585
}
586586

587+
pub fn new_pinned_ref(
588+
tcx: TyCtxt<'tcx>,
589+
r: Region<'tcx>,
590+
ty: Ty<'tcx>,
591+
mutbl: ty::Mutability,
592+
) -> Ty<'tcx> {
593+
let pin = tcx.adt_def(tcx.require_lang_item(LangItem::Pin, None));
594+
Ty::new_adt(tcx, pin, tcx.mk_args(&[Ty::new_ref(tcx, r, ty, mutbl).into()]))
595+
}
596+
587597
#[inline]
588598
pub fn new_ptr(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, mutbl: ty::Mutability) -> Ty<'tcx> {
589599
Ty::new(tcx, ty::RawPtr(ty, mutbl))

compiler/rustc_mir_transform/src/known_panics_lint.rs

+9-7
Original file line numberDiff line numberDiff line change
@@ -600,13 +600,15 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
600600
}
601601

602602
Len(place) => {
603-
let len = match self.get_const(place)? {
604-
Value::Immediate(src) => src.len(&self.ecx).discard_err()?,
605-
Value::Aggregate { fields, .. } => fields.len() as u64,
606-
Value::Uninit => match place.ty(self.local_decls(), self.tcx).ty.kind() {
607-
ty::Array(_, n) => n.try_eval_target_usize(self.tcx, self.param_env)?,
608-
_ => return None,
609-
},
603+
let len = if let ty::Array(_, n) = place.ty(self.local_decls(), self.tcx).ty.kind()
604+
{
605+
n.try_eval_target_usize(self.tcx, self.param_env)?
606+
} else {
607+
match self.get_const(place)? {
608+
Value::Immediate(src) => src.len(&self.ecx).discard_err()?,
609+
Value::Aggregate { fields, .. } => fields.len() as u64,
610+
Value::Uninit => return None,
611+
}
610612
};
611613
ImmTy::from_scalar(Scalar::from_target_usize(len, self), layout).into()
612614
}

0 commit comments

Comments
 (0)