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 7 pull requests #111481

Closed
wants to merge 19 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
2198fae
Make `NonUseContext::AscribeUserTy` carry `ty::Variance`
obeis May 8, 2023
b64e911
Add test.
cjgillot May 10, 2023
d0d4e02
Iteratively replace pointers.
cjgillot May 10, 2023
aeac555
Do not see through copies of mutable pointers.
cjgillot May 10, 2023
9fb1c73
Avoid shadowing.
cjgillot May 10, 2023
a2fe993
Only warn single-use lifetime when the binders match.
cjgillot May 10, 2023
ccd8ad7
Note base types of coercion
compiler-errors May 11, 2023
eadf3bb
Update cargo
heiher May 11, 2023
616fb42
Update browser-ui-test version to 0.16.0
GuillaumeGomez May 10, 2023
0630283
Migrate to 0.16.0 browser-ui-test version
GuillaumeGomez May 10, 2023
8e55400
Convert some GUI tests color checks to use original format
GuillaumeGomez May 11, 2023
cac7e42
Fix backtrace normalization in ice-bug-report-url.rs
uweigand May 10, 2023
7e311dd
Rollup merge of #111366 - obeis:ascribe-user-type-variance, r=lcnr
matthiaskrgr May 11, 2023
62e894f
Rollup merge of #111439 - uweigand:backtrace-normalize, r=compiler-er…
matthiaskrgr May 11, 2023
d0b342c
Rollup merge of #111441 - cjgillot:issue-111422, r=JakobDegen
matthiaskrgr May 11, 2023
7a674e4
Rollup merge of #111444 - cjgillot:issue-111400, r=oli-obk
matthiaskrgr May 11, 2023
beb1ff8
Rollup merge of #111451 - compiler-errors:note-cast-origin, r=b-naber
matthiaskrgr May 11, 2023
fe37a72
Rollup merge of #111456 - loongarch-rs:bump-cargo, r=weihanglo
matthiaskrgr May 11, 2023
8971878
Rollup merge of #111459 - GuillaumeGomez:update-browser-ui-test, r=no…
matthiaskrgr May 11, 2023
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
2 changes: 1 addition & 1 deletion compiler/rustc_borrowck/src/def_use.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ pub fn categorize(context: PlaceContext) -> Option<DefUse> {
// `PlaceMention` and `AscribeUserType` both evaluate the place, which must not
// contain dangling references.
PlaceContext::NonMutatingUse(NonMutatingUseContext::PlaceMention) |
PlaceContext::NonUse(NonUseContext::AscribeUserTy) |
PlaceContext::NonUse(NonUseContext::AscribeUserTy(_)) |

PlaceContext::MutatingUse(MutatingUseContext::AddressOf) |
PlaceContext::NonMutatingUse(NonMutatingUseContext::AddressOf) |
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_borrowck/src/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -777,7 +777,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
Inspect | Copy | Move | PlaceMention | SharedBorrow | ShallowBorrow | UniqueBorrow
| AddressOf | Projection,
) => ty::Covariant,
PlaceContext::NonUse(AscribeUserTy) => ty::Covariant,
PlaceContext::NonUse(AscribeUserTy(variance)) => variance,
}
}

Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_middle/src/mir/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@

use crate::mir::*;
use crate::ty::subst::SubstsRef;
use crate::ty::{CanonicalUserTypeAnnotation, Ty};
use crate::ty::{self, CanonicalUserTypeAnnotation, Ty};
use rustc_span::Span;

macro_rules! make_mir_visitor {
Expand Down Expand Up @@ -782,12 +782,12 @@ macro_rules! make_mir_visitor {

fn super_ascribe_user_ty(&mut self,
place: & $($mutability)? Place<'tcx>,
_variance: $(& $mutability)? ty::Variance,
variance: $(& $mutability)? ty::Variance,
user_ty: & $($mutability)? UserTypeProjection,
location: Location) {
self.visit_place(
place,
PlaceContext::NonUse(NonUseContext::AscribeUserTy),
PlaceContext::NonUse(NonUseContext::AscribeUserTy($(* &$mutability *)? variance)),
location
);
self.visit_user_type_projection(user_ty);
Expand Down Expand Up @@ -1320,7 +1320,7 @@ pub enum NonUseContext {
/// Ending a storage live range.
StorageDead,
/// User type annotation assertions for NLL.
AscribeUserTy,
AscribeUserTy(ty::Variance),
/// The data of a user variable, for debug info.
VarDebugInfo,
}
Expand Down
3 changes: 0 additions & 3 deletions compiler/rustc_middle/src/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,9 +281,6 @@ pub enum ObligationCauseCode<'tcx> {
/// A type like `Box<Foo<'a> + 'b>` is WF only if `'b: 'a`.
ObjectTypeBound(Ty<'tcx>, ty::Region<'tcx>),

/// Obligation incurred due to an object cast.
ObjectCastObligation(/* Concrete type */ Ty<'tcx>, /* Object type */ Ty<'tcx>),

/// Obligation incurred due to a coercion.
Coercion {
source: Ty<'tcx>,
Expand Down
90 changes: 60 additions & 30 deletions compiler/rustc_mir_transform/src/ref_prop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,9 @@ fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let ssa = SsaLocals::new(body);

let mut replacer = compute_replacement(tcx, body, &ssa);
debug!(?replacer.targets, ?replacer.allowed_replacements, ?replacer.storage_to_remove);
debug!(?replacer.targets);
debug!(?replacer.allowed_replacements);
debug!(?replacer.storage_to_remove);

replacer.visit_body_preserves_cfg(body);

Expand Down Expand Up @@ -190,8 +192,11 @@ fn compute_replacement<'tcx>(
continue;
}

// Whether the current local is subject to the uniqueness rule.
let needs_unique = ty.is_mutable_ptr();

// If this a mutable reference that we cannot fully replace, mark it as unknown.
if ty.is_mutable_ptr() && !fully_replacable_locals.contains(local) {
if needs_unique && !fully_replacable_locals.contains(local) {
debug!("not fully replaceable");
continue;
}
Expand All @@ -203,32 +208,33 @@ fn compute_replacement<'tcx>(
// have been visited before.
Rvalue::Use(Operand::Copy(place) | Operand::Move(place))
| Rvalue::CopyForDeref(place) => {
if let Some(rhs) = place.as_local() {
if let Some(rhs) = place.as_local() && ssa.is_ssa(rhs) {
let target = targets[rhs];
if matches!(target, Value::Pointer(..)) {
// Only see through immutable reference and pointers, as we do not know yet if
// mutable references are fully replaced.
if !needs_unique && matches!(target, Value::Pointer(..)) {
targets[local] = target;
} else if ssa.is_ssa(rhs) {
let refmut = body.local_decls[rhs].ty.is_mutable_ptr();
targets[local] = Value::Pointer(tcx.mk_place_deref(rhs.into()), refmut);
} else {
targets[local] = Value::Pointer(tcx.mk_place_deref(rhs.into()), needs_unique);
}
}
}
Rvalue::Ref(_, _, place) | Rvalue::AddressOf(_, place) => {
let mut place = *place;
// Try to see through `place` in order to collapse reborrow chains.
if place.projection.first() == Some(&PlaceElem::Deref)
&& let Value::Pointer(target, refmut) = targets[place.local]
&& let Value::Pointer(target, inner_needs_unique) = targets[place.local]
// Only see through immutable reference and pointers, as we do not know yet if
// mutable references are fully replaced.
&& !refmut
&& !inner_needs_unique
// Only collapse chain if the pointee is definitely live.
&& can_perform_opt(target, location)
{
place = target.project_deeper(&place.projection[1..], tcx);
}
assert_ne!(place.local, local);
if is_constant_place(place) {
targets[local] = Value::Pointer(place, ty.is_mutable_ptr());
targets[local] = Value::Pointer(place, needs_unique);
}
}
// We do not know what to do, so keep as not-a-pointer.
Expand Down Expand Up @@ -276,16 +282,35 @@ fn compute_replacement<'tcx>(
return;
}

if let Value::Pointer(target, refmut) = self.targets[place.local]
&& place.projection.first() == Some(&PlaceElem::Deref)
{
let perform_opt = (self.can_perform_opt)(target, loc);
if perform_opt {
self.allowed_replacements.insert((target.local, loc));
} else if refmut {
// This mutable reference is not fully replacable, so drop it.
self.targets[place.local] = Value::Unknown;
if place.projection.first() != Some(&PlaceElem::Deref) {
// This is not a dereference, nothing to do.
return;
}

let mut place = place.as_ref();
loop {
if let Value::Pointer(target, needs_unique) = self.targets[place.local] {
let perform_opt = (self.can_perform_opt)(target, loc);
debug!(?place, ?target, ?needs_unique, ?perform_opt);

// This a reborrow chain, recursively allow the replacement.
//
// This also allows to detect cases where `target.local` is not replacable,
// and mark it as such.
if let &[PlaceElem::Deref] = &target.projection[..] {
assert!(perform_opt);
self.allowed_replacements.insert((target.local, loc));
place.local = target.local;
continue;
} else if perform_opt {
self.allowed_replacements.insert((target.local, loc));
} else if needs_unique {
// This mutable reference is not fully replacable, so drop it.
self.targets[place.local] = Value::Unknown;
}
}

break;
}
}
}
Expand Down Expand Up @@ -326,18 +351,23 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> {
}

fn visit_place(&mut self, place: &mut Place<'tcx>, ctxt: PlaceContext, loc: Location) {
if let Value::Pointer(target, _) = self.targets[place.local]
&& place.projection.first() == Some(&PlaceElem::Deref)
{
let perform_opt = matches!(ctxt, PlaceContext::NonUse(_))
|| self.allowed_replacements.contains(&(target.local, loc));

if perform_opt {
*place = target.project_deeper(&place.projection[1..], self.tcx);
self.any_replacement = true;
if place.projection.first() != Some(&PlaceElem::Deref) {
return;
}

loop {
if let Value::Pointer(target, _) = self.targets[place.local] {
let perform_opt = matches!(ctxt, PlaceContext::NonUse(_))
|| self.allowed_replacements.contains(&(target.local, loc));

if perform_opt {
*place = target.project_deeper(&place.projection[1..], self.tcx);
self.any_replacement = true;
continue;
}
}
} else {
self.super_place(place, ctxt, loc);

break;
}
}

Expand Down
16 changes: 11 additions & 5 deletions compiler/rustc_resolve/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1482,7 +1482,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
if let Some(&(_, res)) = rib.bindings.get(&normalized_ident) {
self.record_lifetime_res(lifetime.id, res, LifetimeElisionCandidate::Named);

if let LifetimeRes::Param { param, .. } = res {
if let LifetimeRes::Param { param, binder } = res {
match self.lifetime_uses.entry(param) {
Entry::Vacant(v) => {
debug!("First use of {:?} at {:?}", res, ident.span);
Expand All @@ -1496,10 +1496,16 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
LifetimeRibKind::Item
| LifetimeRibKind::AnonymousReportError
| LifetimeRibKind::ElisionFailure => Some(LifetimeUseSet::Many),
// An anonymous lifetime is legal here, go ahead.
LifetimeRibKind::AnonymousCreateParameter { .. } => {
Some(LifetimeUseSet::One { use_span: ident.span, use_ctxt })
}
// An anonymous lifetime is legal here, and bound to the right
// place, go ahead.
LifetimeRibKind::AnonymousCreateParameter {
binder: anon_binder,
..
} => Some(if binder == anon_binder {
LifetimeUseSet::One { use_span: ident.span, use_ctxt }
} else {
LifetimeUseSet::Many
}),
// Only report if eliding the lifetime would have the same
// semantics.
LifetimeRibKind::Elided(r) => Some(if res == r {
Expand Down
16 changes: 12 additions & 4 deletions compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -797,9 +797,17 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
err.span_label(span, explanation);
}

if let ObligationCauseCode::ObjectCastObligation(concrete_ty, obj_ty) = obligation.cause.code().peel_derives() &&
Some(trait_ref.def_id()) == self.tcx.lang_items().sized_trait() {
self.suggest_borrowing_for_object_cast(&mut err, &root_obligation, *concrete_ty, *obj_ty);
if let ObligationCauseCode::Coercion { source, target } =
*obligation.cause.code().peel_derives()
{
if Some(trait_ref.def_id()) == self.tcx.lang_items().sized_trait() {
self.suggest_borrowing_for_object_cast(
&mut err,
&root_obligation,
source,
target,
);
}
}

let UnsatisfiedConst(unsatisfied_const) = self
Expand Down Expand Up @@ -1510,7 +1518,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
| ObligationCauseCode::BindingObligation(_, _)
| ObligationCauseCode::ExprItemObligation(..)
| ObligationCauseCode::ExprBindingObligation(..)
| ObligationCauseCode::ObjectCastObligation(..)
| ObligationCauseCode::Coercion { .. }
| ObligationCauseCode::OpaqueType
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1442,8 +1442,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
err: &mut Diagnostic,
obligation: &PredicateObligation<'tcx>,
self_ty: Ty<'tcx>,
object_ty: Ty<'tcx>,
target_ty: Ty<'tcx>,
) {
let ty::Ref(_, object_ty, hir::Mutability::Not) = target_ty.kind() else { return; };
let ty::Dynamic(predicates, _, ty::Dyn) = object_ty.kind() else { return; };
let self_ref_ty = self.tcx.mk_imm_ref(self.tcx.lifetimes.re_erased, self_ty);

Expand All @@ -1458,7 +1459,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
err.span_suggestion(
obligation.cause.span.shrink_to_lo(),
format!(
"consider borrowing the value, since `&{self_ty}` can be coerced into `{object_ty}`"
"consider borrowing the value, since `&{self_ty}` can be coerced into `{target_ty}`"
),
"&",
Applicability::MaybeIncorrect,
Expand Down Expand Up @@ -2851,30 +2852,27 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
err.span_note(tcx.def_span(item_def_id), descr);
}
}
ObligationCauseCode::ObjectCastObligation(concrete_ty, object_ty) => {
let (concrete_ty, concrete_file) =
self.tcx.short_ty_string(self.resolve_vars_if_possible(concrete_ty));
let (object_ty, object_file) =
self.tcx.short_ty_string(self.resolve_vars_if_possible(object_ty));
ObligationCauseCode::Coercion { source, target } => {
let (source, source_file) =
self.tcx.short_ty_string(self.resolve_vars_if_possible(source));
let (target, target_file) =
self.tcx.short_ty_string(self.resolve_vars_if_possible(target));
err.note(with_forced_trimmed_paths!(format!(
"required for the cast from `{concrete_ty}` to the object type `{object_ty}`",
"required for the cast from `{source}` to `{target}`",
)));
if let Some(file) = concrete_file {
if let Some(file) = source_file {
err.note(format!(
"the full name for the casted type has been written to '{}'",
"the full name for the source type has been written to '{}'",
file.display(),
));
}
if let Some(file) = object_file {
if let Some(file) = target_file {
err.note(format!(
"the full name for the object type has been written to '{}'",
"the full name for the target type has been written to '{}'",
file.display(),
));
}
}
ObligationCauseCode::Coercion { source: _, target } => {
err.note(format!("required by cast to type `{}`", self.ty_to_string(target)));
}
ObligationCauseCode::RepeatElementCopy { is_const_fn } => {
err.note(
"the `Copy` trait is required because this value will be copied for each element of the array",
Expand Down
Loading