Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
20 changes: 8 additions & 12 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1557,12 +1557,10 @@ impl Expr {
}

match &self.kind {
ExprKind::Closure(closure) => {
match closure.fn_decl.output {
FnRetTy::Default(_) => ExprPrecedence::Jump,
FnRetTy::Ty(_) => prefix_attrs_precedence(&self.attrs),
}
}
ExprKind::Closure(closure) => match closure.fn_decl.output {
FnRetTy::Default(_) => ExprPrecedence::Jump,
FnRetTy::Ty(_) => prefix_attrs_precedence(&self.attrs),
},

ExprKind::Break(_ /*label*/, value)
| ExprKind::Ret(value)
Expand All @@ -1584,18 +1582,16 @@ impl Expr {
ExprKind::Binary(op, ..) => op.node.precedence(),
ExprKind::Cast(..) => ExprPrecedence::Cast,

ExprKind::Assign(..) |
ExprKind::AssignOp(..) => ExprPrecedence::Assign,
ExprKind::Assign(..) | ExprKind::AssignOp(..) => ExprPrecedence::Assign,

// Unary, prefix
ExprKind::AddrOf(..)
ExprKind::AddrOf(..) => ExprPrecedence::Prefix,

// Here `let pats = expr` has `let pats =` as a "unary" prefix of `expr`.
// However, this is not exactly right. When `let _ = a` is the LHS of a binop we
// need parens sometimes. E.g. we can print `(let _ = a) && b` as `let _ = a && b`
// but we need to print `(let _ = a) < b` as-is with parens.
| ExprKind::Let(..)
| ExprKind::Move(..)
| ExprKind::Unary(..) => ExprPrecedence::Prefix,
ExprKind::Let(..) | ExprKind::Move(..) | ExprKind::Unary(..) => ExprPrecedence::Prefix,

// Need parens if and only if there are prefix attributes.
ExprKind::Array(_)
Expand Down
47 changes: 23 additions & 24 deletions compiler/rustc_ast/src/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -688,10 +688,10 @@ impl Token {
Lifetime(..) | // labeled loop
Pound => true, // expression attributes
OpenInvisible(InvisibleOrigin::MetaVar(
MetaVarKind::Block |
MetaVarKind::Expr { .. } |
MetaVarKind::Literal |
MetaVarKind::Path
MetaVarKind::Block
| MetaVarKind::Expr { .. }
| MetaVarKind::Literal
| MetaVarKind::Path,
)) => true,
_ => false,
}
Expand All @@ -717,12 +717,12 @@ impl Token {
Shl => true, // path (double UFCS)
Or => matches!(pat_kind, PatWithOr), // leading vert `|` or-pattern
OpenInvisible(InvisibleOrigin::MetaVar(
MetaVarKind::Expr { .. } |
MetaVarKind::Literal |
MetaVarKind::Meta { .. } |
MetaVarKind::Pat(_) |
MetaVarKind::Path |
MetaVarKind::Ty { .. }
MetaVarKind::Expr { .. }
| MetaVarKind::Literal
| MetaVarKind::Meta { .. }
| MetaVarKind::Pat(_)
| MetaVarKind::Path
| MetaVarKind::Ty { .. },
)) => true,
_ => false,
}
Expand All @@ -733,20 +733,19 @@ impl Token {
match self.uninterpolate().kind {
Ident(name, is_raw) =>
ident_can_begin_type(name, self.span, is_raw), // type name or keyword
OpenParen | // tuple
OpenBracket | // array
Bang | // never
Star | // raw pointer
And | // reference
AndAnd | // double reference
Question | // maybe bound in trait object
Lifetime(..) | // lifetime bound in trait object
Lt | Shl | // associated path
PathSep => true, // global path
OpenInvisible(InvisibleOrigin::MetaVar(
MetaVarKind::Ty { .. } |
MetaVarKind::Path
)) => true,
OpenParen // tuple
| OpenBracket // array
| Bang // never
| Star // raw pointer
| And // reference
| AndAnd // double reference
| Question // maybe bound in trait object
| Lifetime(..) // lifetime bound in trait object
| Lt | Shl // associated path
| PathSep => true, // global path
OpenInvisible(InvisibleOrigin::MetaVar(MetaVarKind::Ty { .. } | MetaVarKind::Path)) => {
true
}
// For anonymous structs or unions, which only appear in specific positions
// (type of struct fields or union fields), we don't consider them as regular types
_ => false,
Expand Down
7 changes: 2 additions & 5 deletions compiler/rustc_borrowck/src/def_use.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,7 @@ pub(crate) fn categorize(context: PlaceContext) -> Option<DefUse> {
PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect) |
PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) |
PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) |
PlaceContext::MutatingUse(MutatingUseContext::Retag) =>
Some(DefUse::Use),
PlaceContext::MutatingUse(MutatingUseContext::Retag) => Some(DefUse::Use),

///////////////////////////////////////////////////////////////////////////
// DROP USES
Expand All @@ -70,9 +69,7 @@ pub(crate) fn categorize(context: PlaceContext) -> Option<DefUse> {
// call to `std::mem::drop()`). For the purposes of NLL,
// uses in drop are special because `#[may_dangle]`
// attributes can affect whether lifetimes must be live.

PlaceContext::MutatingUse(MutatingUseContext::Drop) =>
Some(DefUse::Drop),
PlaceContext::MutatingUse(MutatingUseContext::Drop) => Some(DefUse::Drop),

// Debug info is neither def nor use.
PlaceContext::NonUse(NonUseContext::VarDebugInfo) => None,
Expand Down
45 changes: 26 additions & 19 deletions compiler/rustc_borrowck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -833,19 +833,21 @@ impl<'a, 'tcx> ResultsVisitor<'tcx, Borrowck<'a, 'tcx>> for MirBorrowckCtxt<'a,
NonDivergingIntrinsic::CopyNonOverlapping(..) => span_bug!(
span,
"Unexpected CopyNonOverlapping, should only appear after lower_intrinsics",
)
}
),
},
// Only relevant for mir typeck
StatementKind::AscribeUserType(..)
StatementKind::AscribeUserType(..) => {}
// Only relevant for liveness and unsafeck
| StatementKind::PlaceMention(..)
StatementKind::PlaceMention(..) => {}
// Doesn't have any language semantics
| StatementKind::Coverage(..)
StatementKind::Coverage(..) => {}
// These do not actually affect borrowck
| StatementKind::ConstEvalCounter
| StatementKind::StorageLive(..) => {}
StatementKind::ConstEvalCounter | StatementKind::StorageLive(..) => {}
// This does not affect borrowck
StatementKind::BackwardIncompatibleDropHint { place, reason: BackwardIncompatibleDropReason::Edition2024 } => {
StatementKind::BackwardIncompatibleDropHint {
place,
reason: BackwardIncompatibleDropReason::Edition2024,
} => {
self.check_backward_incompatible_drop(location, **place, state);
}
StatementKind::StorageDead(local) => {
Expand All @@ -857,8 +859,7 @@ impl<'a, 'tcx> ResultsVisitor<'tcx, Borrowck<'a, 'tcx>> for MirBorrowckCtxt<'a,
state,
);
}
StatementKind::Nop
| StatementKind::SetDiscriminant { .. } => {
StatementKind::Nop | StatementKind::SetDiscriminant { .. } => {
bug!("Statement not allowed in this MIR phase")
}
}
Expand Down Expand Up @@ -2238,15 +2239,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
// None case => assigning to `x` does not require `x` be initialized.
for (place_base, elem) in place.iter_projections().rev() {
match elem {
ProjectionElem::Index(_/*operand*/) |
ProjectionElem::OpaqueCast(_) |
ProjectionElem::ConstantIndex { .. } |
ProjectionElem::Index(_/*operand*/)
| ProjectionElem::OpaqueCast(_)
// assigning to P[i] requires P to be valid.
ProjectionElem::Downcast(_/*adt_def*/, _/*variant_idx*/) =>
| ProjectionElem::ConstantIndex { .. }
// assigning to (P->variant) is okay if assigning to `P` is okay
//
// FIXME: is this true even if P is an adt with a dtor?
{ }
| ProjectionElem::Downcast(_/*adt_def*/, _/*variant_idx*/) =>
{}
Comment on lines 2244 to +2250
Copy link
Copy Markdown
Contributor

@mejrs mejrs May 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are all these and the P[i] comments in the right place? Looks like they're below the arms they're talking about.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved them around to where I think they belong (both comments were shifted one down).


ProjectionElem::UnwrapUnsafeBinder(_) => {
check_parent_of_field(self, location, place_base, span, state);
Expand All @@ -2255,8 +2256,11 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
// assigning to (*P) requires P to be initialized
ProjectionElem::Deref => {
self.check_if_full_path_is_moved(
location, InitializationRequiringAction::Use,
(place_base, span), state);
location,
InitializationRequiringAction::Use,
(place_base, span),
state,
);
// (base initialized; no need to
// recur further)
break;
Expand All @@ -2275,8 +2279,11 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
match base_ty.kind() {
ty::Adt(def, _) if def.has_dtor(tcx) => {
self.check_if_path_or_subpath_is_moved(
location, InitializationRequiringAction::Assignment,
(place_base, span), state);
location,
InitializationRequiringAction::Assignment,
(place_base, span),
state,
);

// (base initialized; no need to
// recur further)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LoanInvalidationsGenerator<'a, 'tcx> {
StatementKind::Intrinsic(NonDivergingIntrinsic::Assume(op)) => {
self.consume_operand(location, op);
}
StatementKind::Intrinsic(NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping {
src,
dst,
count,
})) => {
StatementKind::Intrinsic(NonDivergingIntrinsic::CopyNonOverlapping(
CopyNonOverlapping { src, dst, count },
)) => {
self.consume_operand(location, src);
self.consume_operand(location, dst);
self.consume_operand(location, count);
Expand Down
33 changes: 23 additions & 10 deletions compiler/rustc_codegen_ssa/src/mir/rvalue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -454,13 +454,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
OperandValue::Pair(lldata, llextra)
}
mir::CastKind::PointerCoercion(
PointerCoercion::MutToConstPointer | PointerCoercion::ArrayToPointer, _
PointerCoercion::MutToConstPointer | PointerCoercion::ArrayToPointer,
_,
) => {
bug!("{kind:?} is for borrowck, and should never appear in codegen");
}
mir::CastKind::PtrToPtr
if bx.cx().is_backend_scalar_pair(operand.layout) =>
{
mir::CastKind::PtrToPtr if bx.cx().is_backend_scalar_pair(operand.layout) => {
if let OperandValue::Pair(data_ptr, meta) = operand.val {
if bx.cx().is_backend_scalar_pair(cast) {
OperandValue::Pair(data_ptr, meta)
Expand All @@ -483,7 +482,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
// path as the other integer-to-X casts.
| mir::CastKind::PointerWithExposedProvenance => {
let imm = operand.immediate();
let abi::BackendRepr::Scalar(from_scalar) = operand.layout.backend_repr else {
let abi::BackendRepr::Scalar(from_scalar) = operand.layout.backend_repr
else {
bug!("Found non-scalar for operand {operand:?}");
};
let from_backend_ty = bx.cx().immediate_backend_type(operand.layout);
Expand All @@ -498,11 +498,18 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
bug!("Found non-scalar for cast {cast:?}");
};

self.cast_immediate(bx, imm, from_scalar, from_backend_ty, to_scalar, to_backend_ty)
.map(OperandValue::Immediate)
.unwrap_or_else(|| {
bug!("Unsupported cast of {operand:?} to {cast:?}");
})
self.cast_immediate(
bx,
imm,
from_scalar,
from_backend_ty,
to_scalar,
to_backend_ty,
)
.map(OperandValue::Immediate)
.unwrap_or_else(|| {
bug!("Unsupported cast of {operand:?} to {cast:?}");
})
}
mir::CastKind::Transmute | mir::CastKind::Subtype => {
self.codegen_transmute_operand(bx, operand, cast)
Expand Down Expand Up @@ -553,6 +560,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
move_annotation: None,
}
}

mir::Rvalue::BinaryOp(op, (ref lhs, ref rhs)) => {
Comment on lines +563 to 564
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are the extra blank lines manual or did rustfmt do this? Here and elsewhere.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe these were manual. I did that once to keep consistency throughout a single match expression.

let lhs = self.codegen_operand(bx, lhs);
let rhs = self.codegen_operand(bx, rhs);
Expand Down Expand Up @@ -666,7 +674,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
};
OperandRef { val: OperandValue::Immediate(static_), layout, move_annotation: None }
}

mir::Rvalue::Use(ref operand, _) => self.codegen_operand(bx, operand),

mir::Rvalue::Repeat(ref elem, len_const) => {
// All arrays have `BackendRepr::Memory`, so only the ZST cases
// end up here. Anything else forces the destination local to be
Expand All @@ -682,6 +692,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
move_annotation: None,
}
}

mir::Rvalue::Aggregate(ref kind, ref fields) => {
let (variant_index, active_field_index) = match **kind {
mir::AggregateKind::Adt(_, variant_index, _, _, active_field_index) => {
Expand Down Expand Up @@ -719,12 +730,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
}
}
}

mir::Rvalue::WrapUnsafeBinder(ref operand, binder_ty) => {
let operand = self.codegen_operand(bx, operand);
let binder_ty = self.monomorphize(binder_ty);
let layout = bx.cx().layout_of(binder_ty);
OperandRef { val: operand.val, layout, move_annotation: None }
}

mir::Rvalue::CopyForDeref(_) => bug!("`CopyForDeref` in codegen"),
}
}
Expand Down
31 changes: 17 additions & 14 deletions compiler/rustc_const_eval/src/const_eval/valtrees.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,7 @@ fn const_to_valtree_inner<'tcx>(
// switch to the base type.
place.layout = ecx.layout_of(*base).unwrap();
ensure_sufficient_stack(|| const_to_valtree_inner(ecx, &place, num_nodes))
},

}

ty::RawPtr(_, _) => {
// Not all raw pointers are allowed, as we cannot properly test them for
Expand All @@ -137,23 +136,19 @@ fn const_to_valtree_inner<'tcx>(
// agree with runtime equality tests.
ty::FnPtr(..) => Err(ValTreeCreationError::NonSupportedType(ty)),

ty::Ref(_, _, _) => {
ty::Ref(_, _, _) => {
let derefd_place = ecx.deref_pointer(place).report_err()?;
const_to_valtree_inner(ecx, &derefd_place, num_nodes)
}

ty::Str | ty::Slice(_) | ty::Array(_, _) => {
slice_branches(ecx, place, num_nodes)
}
ty::Str | ty::Slice(_) | ty::Array(_, _) => slice_branches(ecx, place, num_nodes),
// Trait objects are not allowed in type level constants, as we have no concept for
// resolving their backing type, even if we can do that at const eval time. We may
// hypothetically be able to allow `dyn StructuralPartialEq` trait objects in the future,
// but it is unclear if this is useful.
ty::Dynamic(..) => Err(ValTreeCreationError::NonSupportedType(ty)),

ty::Tuple(elem_tys) => {
branches(ecx, place, elem_tys.len(), None, num_nodes)
}
ty::Tuple(elem_tys) => branches(ecx, place, elem_tys.len(), None, num_nodes),

ty::Adt(def, _) => {
if def.is_union() {
Expand All @@ -163,22 +158,30 @@ fn const_to_valtree_inner<'tcx>(
}

let variant = ecx.read_discriminant(place).report_err()?;
branches(ecx, place, def.variant(variant).fields.len(), def.is_enum().then_some(variant), num_nodes)
branches(
ecx,
place,
def.variant(variant).fields.len(),
def.is_enum().then_some(variant),
num_nodes,
)
}

// FIXME(oli-obk): we could look behind opaque types
ty::Alias(..) => Err(ValTreeCreationError::NonSupportedType(ty)),

// FIXME(oli-obk): we can probably encode closures just like structs
ty::Closure(..) => Err(ValTreeCreationError::NonSupportedType(ty)),

ty::Never
| ty::Error(_)
| ty::Foreign(..)
| ty::Infer(ty::FreshIntTy(_))
| ty::Infer(ty::FreshFloatTy(_))
// FIXME(oli-obk): we could look behind opaque types
| ty::Alias(..)
| ty::Param(_)
| ty::Bound(..)
| ty::Placeholder(..)
| ty::Infer(_)
// FIXME(oli-obk): we can probably encode closures just like structs
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Coroutine(..)
| ty::CoroutineWitness(..)
Expand Down
Loading
Loading