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 8 pull requests #121227

Merged
merged 23 commits into from
Feb 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
75af3c5
coverage: Regression test for a span extraction inconsistency
Zalathar Feb 15, 2024
cd9021e
coverage: Discard spans that fill the entire function body
Zalathar Feb 15, 2024
b49bd0b
Add examples to document the return type of `select_nth_unstable`, `s…
Takashiidobe Feb 16, 2024
3250e95
Add a simple extension trait derive
compiler-errors Feb 13, 2024
9c25823
Use extension trait derive
compiler-errors Feb 13, 2024
a9dbf63
Move trait into attr so it's greppable
compiler-errors Feb 14, 2024
f624d55
Nits
compiler-errors Feb 16, 2024
4b732c9
Let rustbot ping me on changes to match lowering
Nadrieril Feb 16, 2024
6c7827c
Add myself to review rotation
Nadrieril Feb 16, 2024
d855ca0
Ensure `./configure` works when `configure.py` path contains spaces
beetrees Feb 16, 2024
6a671bd
Give the `assume` intrinsic a fallback body
oli-obk Feb 16, 2024
dd40a80
Give the (`un`)`likely` intrinsics fallback bodies
oli-obk Feb 16, 2024
4071938
Use a hardcoded constant instead of calling OpenProcessToken.
smmalis37 Dec 17, 2023
3b63ede
Remove cfg_attr
smmalis37 Feb 16, 2024
340f8aa
const_mut_refs: allow mutable refs to statics
RalfJung Feb 11, 2024
5f21609
Rollup merge of #119032 - smmalis37:patch-1, r=ChrisDenton
Nadrieril Feb 17, 2024
f70f13a
Rollup merge of #120932 - RalfJung:mut-ptr-to-static, r=oli-obk
Nadrieril Feb 17, 2024
5ff9022
Rollup merge of #121059 - compiler-errors:extension, r=davidtwco,Nils…
Nadrieril Feb 17, 2024
c7701ba
Rollup merge of #121135 - Zalathar:no-whole-body-span, r=wesleywiser
Nadrieril Feb 17, 2024
f3d9abc
Rollup merge of #121187 - Takashiidobe:takashi/examples-for-quicksele…
Nadrieril Feb 17, 2024
ac619c0
Rollup merge of #121191 - Nadrieril:ping, r=compiler-errors
Nadrieril Feb 17, 2024
936b666
Rollup merge of #121192 - oli-obk:intrinsics2.0, r=WaffleLapkin
Nadrieril Feb 17, 2024
e266a12
Rollup merge of #121197 - beetrees:configure-quotes, r=Nilstrieb
Nadrieril Feb 17, 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
13 changes: 3 additions & 10 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
use rustc_hir::def_id::{LocalDefId, LocalDefIdMap, CRATE_DEF_ID, LOCAL_CRATE};
use rustc_hir::{ConstArg, GenericArg, ItemLocalMap, ParamName, TraitCandidate};
use rustc_index::{Idx, IndexSlice, IndexVec};
use rustc_macros::extension;
use rustc_middle::span_bug;
use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
use rustc_session::parse::{add_feature_diagnostics, feature_err};
Expand Down Expand Up @@ -190,16 +191,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
}

trait ResolverAstLoweringExt {
fn legacy_const_generic_args(&self, expr: &Expr) -> Option<Vec<usize>>;
fn get_partial_res(&self, id: NodeId) -> Option<PartialRes>;
fn get_import_res(&self, id: NodeId) -> PerNS<Option<Res<NodeId>>>;
fn get_label_res(&self, id: NodeId) -> Option<NodeId>;
fn get_lifetime_res(&self, id: NodeId) -> Option<LifetimeRes>;
fn take_extra_lifetime_params(&mut self, id: NodeId) -> Vec<(Ident, NodeId, LifetimeRes)>;
}

impl ResolverAstLoweringExt for ResolverAstLowering {
#[extension(trait ResolverAstLoweringExt)]
impl ResolverAstLowering {
fn legacy_const_generic_args(&self, expr: &Expr) -> Option<Vec<usize>> {
if let ExprKind::Path(None, path) = &expr.kind {
// Don't perform legacy const generics rewriting if the path already
Expand Down
15 changes: 3 additions & 12 deletions compiler/rustc_borrowck/src/facts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::location::{LocationIndex, LocationTable};
use crate::BorrowIndex;
use polonius_engine::AllFacts as PoloniusFacts;
use polonius_engine::Atom;
use rustc_macros::extension;
use rustc_middle::mir::Local;
use rustc_middle::ty::{RegionVid, TyCtxt};
use rustc_mir_dataflow::move_paths::MovePathIndex;
Expand All @@ -24,20 +25,10 @@ impl polonius_engine::FactTypes for RustcFacts {

pub type AllFacts = PoloniusFacts<RustcFacts>;

pub(crate) trait AllFactsExt {
#[extension(pub(crate) trait AllFactsExt)]
impl AllFacts {
/// Returns `true` if there is a need to gather `AllFacts` given the
/// current `-Z` flags.
fn enabled(tcx: TyCtxt<'_>) -> bool;

fn write_to_dir(
&self,
dir: impl AsRef<Path>,
location_table: &LocationTable,
) -> Result<(), Box<dyn Error>>;
}

impl AllFactsExt for AllFacts {
/// Return
fn enabled(tcx: TyCtxt<'_>) -> bool {
tcx.sess.opts.unstable_opts.nll_facts
|| tcx.sess.opts.unstable_opts.polonius.is_legacy_enabled()
Expand Down
14 changes: 3 additions & 11 deletions compiler/rustc_borrowck/src/place_ext.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,16 @@
use crate::borrow_set::LocalsStateAtExit;
use rustc_hir as hir;
use rustc_macros::extension;
use rustc_middle::mir::ProjectionElem;
use rustc_middle::mir::{Body, Mutability, Place};
use rustc_middle::ty::{self, TyCtxt};

/// Extension methods for the `Place` type.
pub trait PlaceExt<'tcx> {
#[extension(pub trait PlaceExt<'tcx>)]
impl<'tcx> Place<'tcx> {
/// Returns `true` if we can safely ignore borrows of this place.
/// This is true whenever there is no action that the user can do
/// to the place `self` that would invalidate the borrow. This is true
/// for borrows of raw pointer dereferents as well as shared references.
fn ignore_borrow(
&self,
tcx: TyCtxt<'tcx>,
body: &Body<'tcx>,
locals_state_at_exit: &LocalsStateAtExit,
) -> bool;
}

impl<'tcx> PlaceExt<'tcx> for Place<'tcx> {
fn ignore_borrow(
&self,
tcx: TyCtxt<'tcx>,
Expand Down
12 changes: 3 additions & 9 deletions compiler/rustc_borrowck/src/region_infer/opaque_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use rustc_hir::OpaqueTyOrigin;
use rustc_infer::infer::InferCtxt;
use rustc_infer::infer::TyCtxtInferExt as _;
use rustc_infer::traits::{Obligation, ObligationCause};
use rustc_macros::extension;
use rustc_middle::traits::DefiningAnchor;
use rustc_middle::ty::visit::TypeVisitableExt;
use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable};
Expand Down Expand Up @@ -225,15 +226,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
}
}

pub trait InferCtxtExt<'tcx> {
fn infer_opaque_definition_from_instantiation(
&self,
opaque_type_key: OpaqueTypeKey<'tcx>,
instantiated_ty: OpaqueHiddenType<'tcx>,
) -> Ty<'tcx>;
}

impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
#[extension(pub trait InferCtxtExt<'tcx>)]
impl<'tcx> InferCtxt<'tcx> {
/// Given the fully resolved, instantiated type for an opaque
/// type, i.e., the value of an inference variable like C1 or C2
/// (*), computes the "definition type" for an opaque type
Expand Down
24 changes: 3 additions & 21 deletions compiler/rustc_borrowck/src/universal_regions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use rustc_hir::lang_items::LangItem;
use rustc_hir::BodyOwnerKind;
use rustc_index::IndexVec;
use rustc_infer::infer::NllRegionVariableOrigin;
use rustc_macros::extension;
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{self, InlineConstArgs, InlineConstArgsParts, RegionVid, Ty, TyCtxt};
Expand Down Expand Up @@ -793,27 +794,8 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
}
}

trait InferCtxtExt<'tcx> {
fn replace_free_regions_with_nll_infer_vars<T>(
&self,
origin: NllRegionVariableOrigin,
value: T,
) -> T
where
T: TypeFoldable<TyCtxt<'tcx>>;

fn replace_bound_regions_with_nll_infer_vars<T>(
&self,
origin: NllRegionVariableOrigin,
all_outlive_scope: LocalDefId,
value: ty::Binder<'tcx, T>,
indices: &mut UniversalRegionIndices<'tcx>,
) -> T
where
T: TypeFoldable<TyCtxt<'tcx>>;
}

impl<'cx, 'tcx> InferCtxtExt<'tcx> for BorrowckInferCtxt<'cx, 'tcx> {
#[extension(trait InferCtxtExt<'tcx>)]
impl<'cx, 'tcx> BorrowckInferCtxt<'cx, 'tcx> {
#[instrument(skip(self), level = "debug")]
fn replace_free_regions_with_nll_infer_vars<T>(
&self,
Expand Down
37 changes: 33 additions & 4 deletions compiler/rustc_const_eval/src/transform/check_consts/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
visitor.visit_ty(ty);
}

fn check_mut_borrow(&mut self, local: Local, kind: hir::BorrowKind) {
fn check_mut_borrow(&mut self, place: &Place<'_>, kind: hir::BorrowKind) {
match self.const_kind() {
// In a const fn all borrows are transient or point to the places given via
// references in the arguments (so we already checked them with
Expand All @@ -355,10 +355,19 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
// to mutable memory.
hir::ConstContext::ConstFn => self.check_op(ops::TransientMutBorrow(kind)),
_ => {
// For indirect places, we are not creating a new permanent borrow, it's just as
// transient as the already existing one. For reborrowing references this is handled
// at the top of `visit_rvalue`, but for raw pointers we handle it here.
// Pointers/references to `static mut` and cases where the `*` is not the first
// projection also end up here.
// Locals with StorageDead do not live beyond the evaluation and can
// thus safely be borrowed without being able to be leaked to the final
// value of the constant.
if self.local_has_storage_dead(local) {
// Note: This is only sound if every local that has a `StorageDead` has a
// `StorageDead` in every control flow path leading to a `return` terminator.
// The good news is that interning will detect if any unexpected mutable
// pointer slips through.
if place.is_indirect() || self.local_has_storage_dead(place.local) {
self.check_op(ops::TransientMutBorrow(kind));
} else {
self.check_op(ops::MutBorrow(kind));
Expand Down Expand Up @@ -390,6 +399,11 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
trace!("visit_rvalue: rvalue={:?} location={:?}", rvalue, location);

// Special-case reborrows to be more like a copy of a reference.
// FIXME: this does not actually handle all reborrows. It only detects cases where `*` is the outermost
// projection of the borrowed place, it skips deref'ing raw pointers and it skips `static`.
// All those cases are handled below with shared/mutable borrows.
// Once `const_mut_refs` is stable, we should be able to entirely remove this special case.
// (`const_refs_to_cell` is not needed, we already allow all borrows of indirect places anyway.)
match *rvalue {
Rvalue::Ref(_, kind, place) => {
if let Some(reborrowed_place_ref) = place_as_reborrow(self.tcx, self.body, place) {
Expand Down Expand Up @@ -460,7 +474,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {

if !is_allowed {
self.check_mut_borrow(
place.local,
place,
if matches!(rvalue, Rvalue::Ref(..)) {
hir::BorrowKind::Ref
} else {
Expand All @@ -478,7 +492,14 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
place.as_ref(),
);

if borrowed_place_has_mut_interior {
// If the place is indirect, this is basically a reborrow. We have a reborrow
// special case above, but for raw pointers and pointers/references to `static` and
// when the `*` is not the first projection, `place_as_reborrow` does not recognize
// them as such, so we end up here. This should probably be considered a
// `TransientCellBorrow` (we consider the equivalent mutable case a
// `TransientMutBorrow`), but such reborrows got accidentally stabilized already and
// it is too much of a breaking change to take back.
if borrowed_place_has_mut_interior && !place.is_indirect() {
match self.const_kind() {
// In a const fn all borrows are transient or point to the places given via
// references in the arguments (so we already checked them with
Expand All @@ -495,6 +516,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
// final value.
// Note: This is only sound if every local that has a `StorageDead` has a
// `StorageDead` in every control flow path leading to a `return` terminator.
// The good news is that interning will detect if any unexpected mutable
// pointer slips through.
if self.local_has_storage_dead(place.local) {
self.check_op(ops::TransientCellBorrow);
} else {
Expand Down Expand Up @@ -948,6 +971,12 @@ fn place_as_reborrow<'tcx>(
) -> Option<PlaceRef<'tcx>> {
match place.as_ref().last_projection() {
Some((place_base, ProjectionElem::Deref)) => {
// FIXME: why do statics and raw pointers get excluded here? This makes
// some code involving mutable pointers unstable, but it is unclear
// why that code is treated differently from mutable references.
// Once TransientMutBorrow and TransientCellBorrow are stable,
// this can probably be cleaned up without any behavioral changes.

// A borrow of a `static` also looks like `&(*_1)` in the MIR, but `_1` is a `const`
// that points to the allocation for the static. Don't treat these as reborrows.
if body.local_decls[place_base.local].is_ref_to_static() {
Expand Down
24 changes: 24 additions & 0 deletions compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,13 @@ pub trait Qualif {
adt: AdtDef<'tcx>,
args: GenericArgsRef<'tcx>,
) -> bool;

/// Returns `true` if this `Qualif` behaves sructurally for pointers and references:
/// the pointer/reference qualifies if and only if the pointee qualifies.
///
/// (This is currently `false` for all our instances, but that may change in the future. Also,
/// by keeping it abstract, the handling of `Deref` in `in_place` becomes more clear.)
fn deref_structural<'tcx>(cx: &ConstCx<'_, 'tcx>) -> bool;
}

/// Constant containing interior mutability (`UnsafeCell<T>`).
Expand Down Expand Up @@ -103,6 +110,10 @@ impl Qualif for HasMutInterior {
// It arises structurally for all other types.
adt.is_unsafe_cell()
}

fn deref_structural<'tcx>(_cx: &ConstCx<'_, 'tcx>) -> bool {
false
}
}

/// Constant containing an ADT that implements `Drop`.
Expand Down Expand Up @@ -131,6 +142,10 @@ impl Qualif for NeedsDrop {
) -> bool {
adt.has_dtor(cx.tcx)
}

fn deref_structural<'tcx>(_cx: &ConstCx<'_, 'tcx>) -> bool {
false
}
}

/// Constant containing an ADT that implements non-const `Drop`.
Expand Down Expand Up @@ -210,6 +225,10 @@ impl Qualif for NeedsNonConstDrop {
) -> bool {
adt.has_non_const_dtor(cx.tcx)
}

fn deref_structural<'tcx>(_cx: &ConstCx<'_, 'tcx>) -> bool {
false
}
}

// FIXME: Use `mir::visit::Visitor` for the `in_*` functions if/when it supports early return.
Expand Down Expand Up @@ -303,6 +322,11 @@ where
return false;
}

if matches!(elem, ProjectionElem::Deref) && !Q::deref_structural(cx) {
// We have to assume that this qualifies.
return true;
}

place = place_base;
}

Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_hir_analysis/src/check/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -407,9 +407,9 @@ pub fn check_intrinsic_type(
}
sym::float_to_int_unchecked => (2, 0, vec![param(0)], param(1)),

sym::assume => (0, 0, vec![tcx.types.bool], Ty::new_unit(tcx)),
sym::likely => (0, 0, vec![tcx.types.bool], tcx.types.bool),
sym::unlikely => (0, 0, vec![tcx.types.bool], tcx.types.bool),
sym::assume => (0, 1, vec![tcx.types.bool], Ty::new_unit(tcx)),
sym::likely => (0, 1, vec![tcx.types.bool], tcx.types.bool),
sym::unlikely => (0, 1, vec![tcx.types.bool], tcx.types.bool),

sym::read_via_copy => (1, 0, vec![Ty::new_imm_ptr(tcx, param(0))], param(0)),
sym::write_via_move => {
Expand Down
14 changes: 3 additions & 11 deletions compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::LocalDefId;
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{GenericArg, GenericParam, GenericParamKind, HirIdMap, LifetimeName, Node};
use rustc_macros::extension;
use rustc_middle::bug;
use rustc_middle::hir::nested_filter;
use rustc_middle::middle::resolve_bound_vars::*;
Expand All @@ -27,17 +28,8 @@ use std::fmt;

use crate::errors;

trait RegionExt {
fn early(param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg);

fn late(index: u32, param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg);

fn id(&self) -> Option<DefId>;

fn shifted(self, amount: u32) -> ResolvedArg;
}

impl RegionExt for ResolvedArg {
#[extension(trait RegionExt)]
impl ResolvedArg {
fn early(param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg) {
debug!("ResolvedArg::early: def_id={:?}", param.def_id);
(param.def_id, ResolvedArg::EarlyBound(param.def_id.to_def_id()))
Expand Down
26 changes: 6 additions & 20 deletions compiler/rustc_infer/src/infer/canonical/instantiate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,37 +13,23 @@ use rustc_middle::ty::{self, TyCtxt};

/// FIXME(-Znext-solver): This or public because it is shared with the
/// new trait solver implementation. We should deduplicate canonicalization.
pub trait CanonicalExt<'tcx, V> {
#[extension(pub trait CanonicalExt<'tcx, V>)]
impl<'tcx, V> Canonical<'tcx, V> {
/// Instantiate the wrapped value, replacing each canonical value
/// with the value given in `var_values`.
fn instantiate(&self, tcx: TyCtxt<'tcx>, var_values: &CanonicalVarValues<'tcx>) -> V
where
V: TypeFoldable<TyCtxt<'tcx>>;
V: TypeFoldable<TyCtxt<'tcx>>,
{
self.instantiate_projected(tcx, var_values, |value| value.clone())
}

/// Allows one to apply a instantiation to some subset of
/// `self.value`. Invoke `projection_fn` with `self.value` to get
/// a value V that is expressed in terms of the same canonical
/// variables bound in `self` (usually this extracts from subset
/// of `self`). Apply the instantiation `var_values` to this value
/// V, replacing each of the canonical variables.
fn instantiate_projected<T>(
&self,
tcx: TyCtxt<'tcx>,
var_values: &CanonicalVarValues<'tcx>,
projection_fn: impl FnOnce(&V) -> T,
) -> T
where
T: TypeFoldable<TyCtxt<'tcx>>;
}

impl<'tcx, V> CanonicalExt<'tcx, V> for Canonical<'tcx, V> {
fn instantiate(&self, tcx: TyCtxt<'tcx>, var_values: &CanonicalVarValues<'tcx>) -> V
where
V: TypeFoldable<TyCtxt<'tcx>>,
{
self.instantiate_projected(tcx, var_values, |value| value.clone())
}

fn instantiate_projected<T>(
&self,
tcx: TyCtxt<'tcx>,
Expand Down
Loading
Loading