Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 9 pull requests #131275

Merged
merged 22 commits into from
Oct 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
97fbcf6
Allow reborrowing Pin<&mut Self>
eholk Sep 20, 2024
3dfb30c
Allow reborrowing pinned self methods
eholk Sep 20, 2024
30ff400
update `Literal`'s intro
slanterns Oct 1, 2024
9b52fb5
Split out method receivers in feature gate test
eholk Oct 1, 2024
0dc250c
Stabilize `const_slice_from_raw_parts_mut`
eduardosm Sep 15, 2024
8918a9d
Fix needless_lifetimes in stable_mir
practicalrs Oct 3, 2024
3686e59
rustdoc: cleaner errors on disambiguator/namespace mismatches
notriddle Oct 4, 2024
e08002f
Stabilize `BufRead::skip_until`
okaneco Oct 4, 2024
ae5f58d
Check elaborated projections from dyn don't mention unconstrained lat…
compiler-errors Sep 14, 2024
fd7ee48
Elaborate supertrait span correctly to label the error better
compiler-errors Sep 14, 2024
e057c43
Account for `impl Trait {` when `impl Trait for Type {` was intended
estebank Oct 4, 2024
6b67c46
Compute array length from type for unconditional panic.
cjgillot Aug 24, 2024
479779d
Bless clippy.
cjgillot Aug 25, 2024
f09e5a7
Rollup merge of #129517 - cjgillot:known-panic-array, r=pnkfelix
workingjubilee Oct 5, 2024
9510c73
Rollup merge of #130367 - compiler-errors:super-unconstrained, r=spas…
workingjubilee Oct 5, 2024
49c6d78
Rollup merge of #130403 - eduardosm:stabilize-const_slice_from_raw_pa…
workingjubilee Oct 5, 2024
68de7d1
Rollup merge of #130633 - eholk:pin-reborrow-self, r=compiler-errors
workingjubilee Oct 5, 2024
5bad4e9
Rollup merge of #131105 - slanterns:literal_c_str, r=petrochenkov
workingjubilee Oct 5, 2024
bc2f732
Rollup merge of #131194 - practicalrs:fix_needless_lifetimes, r=celinval
workingjubilee Oct 5, 2024
f66aa60
Rollup merge of #131260 - notriddle:notriddle/disambiguator-error, r=…
workingjubilee Oct 5, 2024
3078b23
Rollup merge of #131267 - okaneco:bufread_skip_until, r=tgross35
workingjubilee Oct 5, 2024
08689af
Rollup merge of #131273 - estebank:issue-131051, r=compiler-errors
workingjubilee Oct 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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,
);
}
_ => (),
}
Expand Down Expand Up @@ -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>>>(
Expand Down
17 changes: 10 additions & 7 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
17 changes: 17 additions & 0 deletions compiler/rustc_hir_typeck/src/method/confirm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 => {}
}

Expand Down
32 changes: 26 additions & 6 deletions compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand All @@ -412,14 +427,19 @@ 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 _")
} else {
format!("{autoref}{derefs}{expr_text}")
};

if let Some(probe::AutorefOrPtrAdjustment::ReborrowPin(_)) = pick.autoref_or_ptr_adjustment
{
adjusted_text.push('>');
}

(adjusted_text, precise)
}
}
79 changes: 71 additions & 8 deletions compiler/rustc_hir_typeck/src/method/probe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -147,13 +147,17 @@ 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 {
fn get_unsize(&self) -> bool {
match self {
AutorefOrPtrAdjustment::Autoref { mutbl: _, unsize } => *unsize,
AutorefOrPtrAdjustment::ToConstPtr => false,
AutorefOrPtrAdjustment::ReborrowPin(_) => false,
}
}
}
Expand Down Expand Up @@ -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(),
)
})
})
})
}
Expand All @@ -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
Expand Down Expand Up @@ -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.
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_middle/src/ty/predicate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
10 changes: 10 additions & 0 deletions compiler/rustc_middle/src/ty/sty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
16 changes: 9 additions & 7 deletions compiler/rustc_mir_transform/src/known_panics_lint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
Expand Down
Loading
Loading