Auto merge of rust-lang/rust#112049 - Kobzol:pgo-omit-benchmarks, r=<try>
[do not merge] CI experiments
Various CI experiments for try/dist builds.
r? @ghost
diff --git a/RELEASES.md b/RELEASES.md
index 40ddba6..5446562 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -670,13 +670,6 @@
- [Support `target.<triple>.rustdocflags` officially](https://github.com/rust-lang/cargo/pull/13197/)
- [Stabilize global cache data tracking](https://github.com/rust-lang/cargo/pull/13492/)
-<a id="1.78.0-Misc"></a>
-
-Misc
-----
-
-- [rustdoc: add `--test-builder-wrapper` arg to support wrappers such as RUSTC_WRAPPER when building doctests](https://github.com/rust-lang/rust/pull/114651/)
-
<a id="1.78.0-Compatibility-Notes"></a>
Compatibility Notes
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 44bb44c..a09aa9e 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -23,7 +23,7 @@
use crate::ptr::P;
use crate::token::{self, Token};
use crate::tokenstream::*;
-use crate::visit::{AssocCtxt, BoundKind};
+use crate::visit::{AssocCtxt, BoundKind, FnCtxt};
pub trait ExpectOne<A: Array> {
fn expect_one(self, err: &'static str) -> A::Item;
@@ -37,7 +37,16 @@ fn expect_one(self, err: &'static str) -> A::Item {
}
pub trait WalkItemKind {
- fn walk(&mut self, span: Span, id: NodeId, visitor: &mut impl MutVisitor);
+ type Ctxt;
+ fn walk(
+ &mut self,
+ span: Span,
+ id: NodeId,
+ ident: &mut Ident,
+ visibility: &mut Visibility,
+ ctxt: Self::Ctxt,
+ visitor: &mut impl MutVisitor,
+ );
}
pub trait MutVisitor: Sized {
@@ -114,9 +123,9 @@ fn visit_fn_header(&mut self, header: &mut FnHeader) {
fn flat_map_assoc_item(
&mut self,
i: P<AssocItem>,
- _ctxt: AssocCtxt,
+ ctxt: AssocCtxt,
) -> SmallVec<[P<AssocItem>; 1]> {
- walk_flat_map_item(self, i)
+ walk_flat_map_assoc_item(self, i, ctxt)
}
fn visit_fn_decl(&mut self, d: &mut P<FnDecl>) {
@@ -880,7 +889,7 @@ fn walk_coroutine_kind<T: MutVisitor>(vis: &mut T, coroutine_kind: &mut Coroutin
fn walk_fn<T: MutVisitor>(vis: &mut T, kind: FnKind<'_>) {
match kind {
- FnKind::Fn(FnSig { header, decl, span }, generics, body) => {
+ FnKind::Fn(_ctxt, _ident, FnSig { header, decl, span }, _visibility, generics, body) => {
// Identifier and visibility are visited as a part of the item.
vis.visit_fn_header(header);
vis.visit_generics(generics);
@@ -890,8 +899,9 @@ fn walk_fn<T: MutVisitor>(vis: &mut T, kind: FnKind<'_>) {
}
vis.visit_span(span);
}
- FnKind::Closure(binder, decl, body) => {
+ FnKind::Closure(binder, coroutine_kind, decl, body) => {
vis.visit_closure_binder(binder);
+ coroutine_kind.as_mut().map(|coroutine_kind| vis.visit_coroutine_kind(coroutine_kind));
vis.visit_fn_decl(decl);
vis.visit_expr(body);
}
@@ -1079,17 +1089,29 @@ pub fn walk_block<T: MutVisitor>(vis: &mut T, block: &mut P<Block>) {
vis.visit_span(span);
}
-pub fn walk_item_kind(
- kind: &mut impl WalkItemKind,
+pub fn walk_item_kind<K: WalkItemKind>(
+ kind: &mut K,
span: Span,
id: NodeId,
+ ident: &mut Ident,
+ visibility: &mut Visibility,
+ ctxt: K::Ctxt,
vis: &mut impl MutVisitor,
) {
- kind.walk(span, id, vis)
+ kind.walk(span, id, ident, visibility, ctxt, vis)
}
impl WalkItemKind for ItemKind {
- fn walk(&mut self, span: Span, id: NodeId, vis: &mut impl MutVisitor) {
+ type Ctxt = ();
+ fn walk(
+ &mut self,
+ span: Span,
+ id: NodeId,
+ ident: &mut Ident,
+ visibility: &mut Visibility,
+ _ctxt: Self::Ctxt,
+ vis: &mut impl MutVisitor,
+ ) {
match self {
ItemKind::ExternCrate(_orig_name) => {}
ItemKind::Use(use_tree) => vis.visit_use_tree(use_tree),
@@ -1102,7 +1124,11 @@ fn walk(&mut self, span: Span, id: NodeId, vis: &mut impl MutVisitor) {
}
ItemKind::Fn(box Fn { defaultness, generics, sig, body }) => {
visit_defaultness(vis, defaultness);
- vis.visit_fn(FnKind::Fn(sig, generics, body), span, id);
+ vis.visit_fn(
+ FnKind::Fn(FnCtxt::Free, ident, sig, visibility, generics, body),
+ span,
+ id,
+ );
}
ItemKind::Mod(safety, mod_kind) => {
visit_safety(vis, safety);
@@ -1201,14 +1227,27 @@ fn walk(&mut self, span: Span, id: NodeId, vis: &mut impl MutVisitor) {
}
impl WalkItemKind for AssocItemKind {
- fn walk(&mut self, span: Span, id: NodeId, visitor: &mut impl MutVisitor) {
+ type Ctxt = AssocCtxt;
+ fn walk(
+ &mut self,
+ span: Span,
+ id: NodeId,
+ ident: &mut Ident,
+ visibility: &mut Visibility,
+ ctxt: Self::Ctxt,
+ visitor: &mut impl MutVisitor,
+ ) {
match self {
AssocItemKind::Const(item) => {
visit_const_item(item, visitor);
}
AssocItemKind::Fn(box Fn { defaultness, generics, sig, body }) => {
visit_defaultness(visitor, defaultness);
- visitor.visit_fn(FnKind::Fn(sig, generics, body), span, id);
+ visitor.visit_fn(
+ FnKind::Fn(FnCtxt::Assoc(ctxt), ident, sig, visibility, generics, body),
+ span,
+ id,
+ );
}
AssocItemKind::Type(box TyAlias {
defaultness,
@@ -1288,24 +1327,40 @@ pub fn walk_crate<T: MutVisitor>(vis: &mut T, krate: &mut Crate) {
vis.visit_span(inject_use_span);
}
-/// Mutates one item, returning the item again.
-pub fn walk_flat_map_item<K: WalkItemKind>(
+pub fn walk_flat_map_item<K: WalkItemKind<Ctxt = ()>>(
+ visitor: &mut impl MutVisitor,
+ item: P<Item<K>>,
+) -> SmallVec<[P<Item<K>>; 1]> {
+ walk_flat_map_assoc_item(visitor, item, ())
+}
+
+pub fn walk_flat_map_assoc_item<K: WalkItemKind>(
visitor: &mut impl MutVisitor,
mut item: P<Item<K>>,
+ ctxt: K::Ctxt,
) -> SmallVec<[P<Item<K>>; 1]> {
let Item { ident, attrs, id, kind, vis, span, tokens } = item.deref_mut();
visitor.visit_id(id);
visit_attrs(visitor, attrs);
visitor.visit_vis(vis);
visitor.visit_ident(ident);
- kind.walk(*span, *id, visitor);
+ kind.walk(*span, *id, ident, vis, ctxt, visitor);
visit_lazy_tts(visitor, tokens);
visitor.visit_span(span);
smallvec![item]
}
impl WalkItemKind for ForeignItemKind {
- fn walk(&mut self, span: Span, id: NodeId, visitor: &mut impl MutVisitor) {
+ type Ctxt = ();
+ fn walk(
+ &mut self,
+ span: Span,
+ id: NodeId,
+ ident: &mut Ident,
+ visibility: &mut Visibility,
+ _ctxt: Self::Ctxt,
+ visitor: &mut impl MutVisitor,
+ ) {
match self {
ForeignItemKind::Static(box StaticItem { ty, mutability: _, expr, safety: _ }) => {
visitor.visit_ty(ty);
@@ -1313,7 +1368,11 @@ fn walk(&mut self, span: Span, id: NodeId, visitor: &mut impl MutVisitor) {
}
ForeignItemKind::Fn(box Fn { defaultness, generics, sig, body }) => {
visit_defaultness(visitor, defaultness);
- visitor.visit_fn(FnKind::Fn(sig, generics, body), span, id);
+ visitor.visit_fn(
+ FnKind::Fn(FnCtxt::Foreign, ident, sig, visibility, generics, body),
+ span,
+ id,
+ );
}
ForeignItemKind::TyAlias(box TyAlias {
defaultness,
@@ -1522,9 +1581,8 @@ pub fn walk_expr<T: MutVisitor>(vis: &mut T, Expr { kind, id, span, attrs, token
fn_arg_span,
}) => {
visit_constness(vis, constness);
- coroutine_kind.as_mut().map(|coroutine_kind| vis.visit_coroutine_kind(coroutine_kind));
vis.visit_capture_by(capture_clause);
- vis.visit_fn(FnKind::Closure(binder, fn_decl, body), *span, *id);
+ vis.visit_fn(FnKind::Closure(binder, coroutine_kind, fn_decl, body), *span, *id);
vis.visit_span(fn_decl_span);
vis.visit_span(fn_arg_span);
}
@@ -1785,8 +1843,20 @@ fn dummy() -> Self {
#[derive(Debug)]
pub enum FnKind<'a> {
/// E.g., `fn foo()`, `fn foo(&self)`, or `extern "Abi" fn foo()`.
- Fn(&'a mut FnSig, &'a mut Generics, &'a mut Option<P<Block>>),
+ Fn(
+ FnCtxt,
+ &'a mut Ident,
+ &'a mut FnSig,
+ &'a mut Visibility,
+ &'a mut Generics,
+ &'a mut Option<P<Block>>,
+ ),
/// E.g., `|x, y| body`.
- Closure(&'a mut ClosureBinder, &'a mut P<FnDecl>, &'a mut P<Expr>),
+ Closure(
+ &'a mut ClosureBinder,
+ &'a mut Option<CoroutineKind>,
+ &'a mut P<FnDecl>,
+ &'a mut P<Expr>,
+ ),
}
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index ef6f126..3500c21 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -66,7 +66,7 @@ pub fn descr(self) -> &'static str {
#[derive(Copy, Clone, Debug)]
pub enum FnKind<'a> {
/// E.g., `fn foo()`, `fn foo(&self)`, or `extern "Abi" fn foo()`.
- Fn(FnCtxt, Ident, &'a FnSig, &'a Visibility, &'a Generics, Option<&'a Block>),
+ Fn(FnCtxt, &'a Ident, &'a FnSig, &'a Visibility, &'a Generics, &'a Option<P<Block>>),
/// E.g., `|x, y| body`.
Closure(&'a ClosureBinder, &'a Option<CoroutineKind>, &'a FnDecl, &'a Expr),
@@ -112,11 +112,15 @@ pub enum LifetimeCtxt {
GenericArg,
}
-pub trait WalkItemKind: Sized {
+pub trait WalkItemKind {
+ type Ctxt;
fn walk<'a, V: Visitor<'a>>(
&'a self,
- item: &'a Item<Self>,
- ctxt: AssocCtxt,
+ span: Span,
+ id: NodeId,
+ ident: &'a Ident,
+ visibility: &'a Visibility,
+ ctxt: Self::Ctxt,
visitor: &mut V,
) -> V::Result;
}
@@ -340,16 +344,19 @@ pub fn walk_trait_ref<'a, V: Visitor<'a>>(visitor: &mut V, trait_ref: &'a TraitR
}
impl WalkItemKind for ItemKind {
+ type Ctxt = ();
fn walk<'a, V: Visitor<'a>>(
&'a self,
- item: &'a Item<Self>,
- _ctxt: AssocCtxt,
+ span: Span,
+ id: NodeId,
+ ident: &'a Ident,
+ vis: &'a Visibility,
+ _ctxt: Self::Ctxt,
visitor: &mut V,
) -> V::Result {
- let Item { id, span, vis, ident, .. } = item;
match self {
ItemKind::ExternCrate(_rename) => {}
- ItemKind::Use(use_tree) => try_visit!(visitor.visit_use_tree(use_tree, *id, false)),
+ ItemKind::Use(use_tree) => try_visit!(visitor.visit_use_tree(use_tree, id, false)),
ItemKind::Static(box StaticItem { ty, safety: _, mutability: _, expr }) => {
try_visit!(visitor.visit_ty(ty));
visit_opt!(visitor, visit_expr, expr);
@@ -360,8 +367,8 @@ fn walk<'a, V: Visitor<'a>>(
visit_opt!(visitor, visit_expr, expr);
}
ItemKind::Fn(box Fn { defaultness: _, generics, sig, body }) => {
- let kind = FnKind::Fn(FnCtxt::Free, *ident, sig, vis, generics, body.as_deref());
- try_visit!(visitor.visit_fn(kind, *span, *id));
+ let kind = FnKind::Fn(FnCtxt::Free, ident, sig, vis, generics, body);
+ try_visit!(visitor.visit_fn(kind, span, id));
}
ItemKind::Mod(_unsafety, mod_kind) => match mod_kind {
ModKind::Loaded(items, _inline, _inner_span) => {
@@ -418,7 +425,7 @@ fn walk<'a, V: Visitor<'a>>(
walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
}
ItemKind::MacCall(mac) => try_visit!(visitor.visit_mac_call(mac)),
- ItemKind::MacroDef(ts) => try_visit!(visitor.visit_mac_def(ts, *id)),
+ ItemKind::MacroDef(ts) => try_visit!(visitor.visit_mac_def(ts, id)),
ItemKind::Delegation(box Delegation {
id,
qself,
@@ -434,7 +441,7 @@ fn walk<'a, V: Visitor<'a>>(
}
ItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => {
try_visit!(walk_qself(visitor, qself));
- try_visit!(visitor.visit_path(prefix, *id));
+ try_visit!(visitor.visit_path(prefix, id));
if let Some(suffixes) = suffixes {
for (ident, rename) in suffixes {
visitor.visit_ident(ident);
@@ -452,9 +459,9 @@ fn walk<'a, V: Visitor<'a>>(
pub fn walk_item<'a, V: Visitor<'a>>(
visitor: &mut V,
- item: &'a Item<impl WalkItemKind>,
+ item: &'a Item<impl WalkItemKind<Ctxt = ()>>,
) -> V::Result {
- walk_assoc_item(visitor, item, AssocCtxt::Trait /*ignored*/)
+ walk_assoc_item(visitor, item, ())
}
pub fn walk_enum_def<'a, V: Visitor<'a>>(
@@ -684,20 +691,23 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) -> V::Res
}
impl WalkItemKind for ForeignItemKind {
+ type Ctxt = ();
fn walk<'a, V: Visitor<'a>>(
&'a self,
- item: &'a Item<Self>,
- _ctxt: AssocCtxt,
+ span: Span,
+ id: NodeId,
+ ident: &'a Ident,
+ vis: &'a Visibility,
+ _ctxt: Self::Ctxt,
visitor: &mut V,
) -> V::Result {
- let &Item { id, span, ident, ref vis, .. } = item;
match self {
ForeignItemKind::Static(box StaticItem { ty, mutability: _, expr, safety: _ }) => {
try_visit!(visitor.visit_ty(ty));
visit_opt!(visitor, visit_expr, expr);
}
ForeignItemKind::Fn(box Fn { defaultness: _, generics, sig, body }) => {
- let kind = FnKind::Fn(FnCtxt::Foreign, ident, sig, vis, generics, body.as_deref());
+ let kind = FnKind::Fn(FnCtxt::Foreign, ident, sig, vis, generics, body);
try_visit!(visitor.visit_fn(kind, span, id));
}
ForeignItemKind::TyAlias(box TyAlias {
@@ -850,13 +860,16 @@ pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>) -> V::Resu
}
impl WalkItemKind for AssocItemKind {
+ type Ctxt = AssocCtxt;
fn walk<'a, V: Visitor<'a>>(
&'a self,
- item: &'a Item<Self>,
- ctxt: AssocCtxt,
+ span: Span,
+ id: NodeId,
+ ident: &'a Ident,
+ vis: &'a Visibility,
+ ctxt: Self::Ctxt,
visitor: &mut V,
) -> V::Result {
- let &Item { id, span, ident, ref vis, .. } = item;
match self {
AssocItemKind::Const(box ConstItem { defaultness: _, generics, ty, expr }) => {
try_visit!(visitor.visit_generics(generics));
@@ -864,8 +877,7 @@ fn walk<'a, V: Visitor<'a>>(
visit_opt!(visitor, visit_expr, expr);
}
AssocItemKind::Fn(box Fn { defaultness: _, generics, sig, body }) => {
- let kind =
- FnKind::Fn(FnCtxt::Assoc(ctxt), ident, sig, vis, generics, body.as_deref());
+ let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), ident, sig, vis, generics, body);
try_visit!(visitor.visit_fn(kind, span, id));
}
AssocItemKind::Type(box TyAlias {
@@ -913,16 +925,16 @@ fn walk<'a, V: Visitor<'a>>(
}
}
-pub fn walk_assoc_item<'a, V: Visitor<'a>>(
+pub fn walk_assoc_item<'a, V: Visitor<'a>, K: WalkItemKind>(
visitor: &mut V,
- item: &'a Item<impl WalkItemKind>,
- ctxt: AssocCtxt,
+ item: &'a Item<K>,
+ ctxt: K::Ctxt,
) -> V::Result {
- let Item { id: _, span: _, ident, vis, attrs, kind, tokens: _ } = item;
+ let Item { id, span, ident, vis, attrs, kind, tokens: _ } = item;
walk_list!(visitor, visit_attribute, attrs);
try_visit!(visitor.visit_vis(vis));
try_visit!(visitor.visit_ident(ident));
- try_visit!(kind.walk(item, ctxt, visitor));
+ try_visit!(kind.walk(*span, *id, ident, vis, ctxt, visitor));
V::Result::output()
}
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index dee4858..07a6f4e 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -946,8 +946,7 @@ fn visit_item(&mut self, item: &'a Item) {
self.visit_vis(&item.vis);
self.visit_ident(&item.ident);
- let kind =
- FnKind::Fn(FnCtxt::Free, item.ident, sig, &item.vis, generics, body.as_deref());
+ let kind = FnKind::Fn(FnCtxt::Free, &item.ident, sig, &item.vis, generics, body);
self.visit_fn(kind, item.span, item.id);
walk_list!(self, visit_attribute, &item.attrs);
return; // Avoid visiting again.
@@ -1476,14 +1475,8 @@ fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
{
self.visit_vis(&item.vis);
self.visit_ident(&item.ident);
- let kind = FnKind::Fn(
- FnCtxt::Assoc(ctxt),
- item.ident,
- sig,
- &item.vis,
- generics,
- body.as_deref(),
- );
+ let kind =
+ FnKind::Fn(FnCtxt::Assoc(ctxt), &item.ident, sig, &item.vis, generics, body);
walk_list!(self, visit_attribute, &item.attrs);
self.visit_fn(kind, item.span, item.id);
}
diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs
index d832dec..7adc7a8 100644
--- a/compiler/rustc_borrowck/src/dataflow.rs
+++ b/compiler/rustc_borrowck/src/dataflow.rs
@@ -1,93 +1,171 @@
+use std::fmt;
+
use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::graph;
use rustc_index::bit_set::BitSet;
-use rustc_middle::mir::{self, BasicBlock, Body, Location, Place, TerminatorEdges};
+use rustc_middle::mir::{
+ self, BasicBlock, Body, CallReturnPlaces, Location, Place, TerminatorEdges,
+};
use rustc_middle::ty::{RegionVid, TyCtxt};
use rustc_mir_dataflow::fmt::DebugWithContext;
use rustc_mir_dataflow::impls::{EverInitializedPlaces, MaybeUninitializedPlaces};
-use rustc_mir_dataflow::{Analysis, Forward, GenKill, Results, ResultsVisitable};
+use rustc_mir_dataflow::{Analysis, GenKill, JoinSemiLattice, SwitchIntEdgeEffects};
use tracing::debug;
use crate::{BorrowSet, PlaceConflictBias, PlaceExt, RegionInferenceContext, places_conflict};
-/// The results of the dataflow analyses used by the borrow checker.
-pub(crate) struct BorrowckResults<'a, 'tcx> {
- pub(crate) borrows: Results<'tcx, Borrows<'a, 'tcx>>,
- pub(crate) uninits: Results<'tcx, MaybeUninitializedPlaces<'a, 'tcx>>,
- pub(crate) ever_inits: Results<'tcx, EverInitializedPlaces<'a, 'tcx>>,
+// This analysis is different to most others. Its results aren't computed with
+// `iterate_to_fixpoint`, but are instead composed from the results of three sub-analyses that are
+// computed individually with `iterate_to_fixpoint`.
+pub(crate) struct Borrowck<'a, 'tcx> {
+ pub(crate) borrows: Borrows<'a, 'tcx>,
+ pub(crate) uninits: MaybeUninitializedPlaces<'a, 'tcx>,
+ pub(crate) ever_inits: EverInitializedPlaces<'a, 'tcx>,
+}
+
+impl<'a, 'tcx> Analysis<'tcx> for Borrowck<'a, 'tcx> {
+ type Domain = BorrowckDomain<'a, 'tcx>;
+
+ const NAME: &'static str = "borrowck";
+
+ fn bottom_value(&self, body: &mir::Body<'tcx>) -> Self::Domain {
+ BorrowckDomain {
+ borrows: self.borrows.bottom_value(body),
+ uninits: self.uninits.bottom_value(body),
+ ever_inits: self.ever_inits.bottom_value(body),
+ }
+ }
+
+ fn initialize_start_block(&self, _body: &mir::Body<'tcx>, _state: &mut Self::Domain) {
+ // This is only reachable from `iterate_to_fixpoint`, which this analysis doesn't use.
+ unreachable!();
+ }
+
+ fn apply_before_statement_effect(
+ &mut self,
+ state: &mut Self::Domain,
+ stmt: &mir::Statement<'tcx>,
+ loc: Location,
+ ) {
+ self.borrows.apply_before_statement_effect(&mut state.borrows, stmt, loc);
+ self.uninits.apply_before_statement_effect(&mut state.uninits, stmt, loc);
+ self.ever_inits.apply_before_statement_effect(&mut state.ever_inits, stmt, loc);
+ }
+
+ fn apply_statement_effect(
+ &mut self,
+ state: &mut Self::Domain,
+ stmt: &mir::Statement<'tcx>,
+ loc: Location,
+ ) {
+ self.borrows.apply_statement_effect(&mut state.borrows, stmt, loc);
+ self.uninits.apply_statement_effect(&mut state.uninits, stmt, loc);
+ self.ever_inits.apply_statement_effect(&mut state.ever_inits, stmt, loc);
+ }
+
+ fn apply_before_terminator_effect(
+ &mut self,
+ state: &mut Self::Domain,
+ term: &mir::Terminator<'tcx>,
+ loc: Location,
+ ) {
+ self.borrows.apply_before_terminator_effect(&mut state.borrows, term, loc);
+ self.uninits.apply_before_terminator_effect(&mut state.uninits, term, loc);
+ self.ever_inits.apply_before_terminator_effect(&mut state.ever_inits, term, loc);
+ }
+
+ fn apply_terminator_effect<'mir>(
+ &mut self,
+ state: &mut Self::Domain,
+ term: &'mir mir::Terminator<'tcx>,
+ loc: Location,
+ ) -> TerminatorEdges<'mir, 'tcx> {
+ self.borrows.apply_terminator_effect(&mut state.borrows, term, loc);
+ self.uninits.apply_terminator_effect(&mut state.uninits, term, loc);
+ self.ever_inits.apply_terminator_effect(&mut state.ever_inits, term, loc);
+
+ // This return value doesn't matter. It's only used by `iterate_to_fixpoint`, which this
+ // analysis doesn't use.
+ TerminatorEdges::None
+ }
+
+ fn apply_call_return_effect(
+ &mut self,
+ _state: &mut Self::Domain,
+ _block: BasicBlock,
+ _return_places: CallReturnPlaces<'_, 'tcx>,
+ ) {
+ // This is only reachable from `iterate_to_fixpoint`, which this analysis doesn't use.
+ unreachable!();
+ }
+
+ fn apply_switch_int_edge_effects(
+ &mut self,
+ _block: BasicBlock,
+ _discr: &mir::Operand<'tcx>,
+ _apply_edge_effects: &mut impl SwitchIntEdgeEffects<Self::Domain>,
+ ) {
+ // This is only reachable from `iterate_to_fixpoint`, which this analysis doesn't use.
+ unreachable!();
+ }
+}
+
+impl JoinSemiLattice for BorrowckDomain<'_, '_> {
+ fn join(&mut self, _other: &Self) -> bool {
+ // This is only reachable from `iterate_to_fixpoint`, which this analysis doesn't use.
+ unreachable!();
+ }
+}
+
+impl<'tcx, C> DebugWithContext<C> for BorrowckDomain<'_, 'tcx>
+where
+ C: rustc_mir_dataflow::move_paths::HasMoveData<'tcx>,
+{
+ fn fmt_with(&self, ctxt: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.write_str("borrows: ")?;
+ self.borrows.fmt_with(ctxt, f)?;
+ f.write_str(" uninits: ")?;
+ self.uninits.fmt_with(ctxt, f)?;
+ f.write_str(" ever_inits: ")?;
+ self.ever_inits.fmt_with(ctxt, f)?;
+ Ok(())
+ }
+
+ fn fmt_diff_with(&self, old: &Self, ctxt: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ if self == old {
+ return Ok(());
+ }
+
+ if self.borrows != old.borrows {
+ f.write_str("borrows: ")?;
+ self.borrows.fmt_diff_with(&old.borrows, ctxt, f)?;
+ f.write_str("\n")?;
+ }
+
+ if self.uninits != old.uninits {
+ f.write_str("uninits: ")?;
+ self.uninits.fmt_diff_with(&old.uninits, ctxt, f)?;
+ f.write_str("\n")?;
+ }
+
+ if self.ever_inits != old.ever_inits {
+ f.write_str("ever_inits: ")?;
+ self.ever_inits.fmt_diff_with(&old.ever_inits, ctxt, f)?;
+ f.write_str("\n")?;
+ }
+
+ Ok(())
+ }
}
/// The transient state of the dataflow analyses used by the borrow checker.
-#[derive(Debug)]
+#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) struct BorrowckDomain<'a, 'tcx> {
pub(crate) borrows: <Borrows<'a, 'tcx> as Analysis<'tcx>>::Domain,
pub(crate) uninits: <MaybeUninitializedPlaces<'a, 'tcx> as Analysis<'tcx>>::Domain,
pub(crate) ever_inits: <EverInitializedPlaces<'a, 'tcx> as Analysis<'tcx>>::Domain,
}
-impl<'a, 'tcx> ResultsVisitable<'tcx> for BorrowckResults<'a, 'tcx> {
- type Direction = Forward;
- type Domain = BorrowckDomain<'a, 'tcx>;
-
- fn bottom_value(&self, body: &mir::Body<'tcx>) -> Self::Domain {
- BorrowckDomain {
- borrows: self.borrows.analysis.bottom_value(body),
- uninits: self.uninits.analysis.bottom_value(body),
- ever_inits: self.ever_inits.analysis.bottom_value(body),
- }
- }
-
- fn reset_to_block_entry(&self, state: &mut Self::Domain, block: BasicBlock) {
- state.borrows.clone_from(self.borrows.entry_set_for_block(block));
- state.uninits.clone_from(self.uninits.entry_set_for_block(block));
- state.ever_inits.clone_from(self.ever_inits.entry_set_for_block(block));
- }
-
- fn reconstruct_before_statement_effect(
- &mut self,
- state: &mut Self::Domain,
- stmt: &mir::Statement<'tcx>,
- loc: Location,
- ) {
- self.borrows.analysis.apply_before_statement_effect(&mut state.borrows, stmt, loc);
- self.uninits.analysis.apply_before_statement_effect(&mut state.uninits, stmt, loc);
- self.ever_inits.analysis.apply_before_statement_effect(&mut state.ever_inits, stmt, loc);
- }
-
- fn reconstruct_statement_effect(
- &mut self,
- state: &mut Self::Domain,
- stmt: &mir::Statement<'tcx>,
- loc: Location,
- ) {
- self.borrows.analysis.apply_statement_effect(&mut state.borrows, stmt, loc);
- self.uninits.analysis.apply_statement_effect(&mut state.uninits, stmt, loc);
- self.ever_inits.analysis.apply_statement_effect(&mut state.ever_inits, stmt, loc);
- }
-
- fn reconstruct_before_terminator_effect(
- &mut self,
- state: &mut Self::Domain,
- term: &mir::Terminator<'tcx>,
- loc: Location,
- ) {
- self.borrows.analysis.apply_before_terminator_effect(&mut state.borrows, term, loc);
- self.uninits.analysis.apply_before_terminator_effect(&mut state.uninits, term, loc);
- self.ever_inits.analysis.apply_before_terminator_effect(&mut state.ever_inits, term, loc);
- }
-
- fn reconstruct_terminator_effect(
- &mut self,
- state: &mut Self::Domain,
- term: &mir::Terminator<'tcx>,
- loc: Location,
- ) {
- self.borrows.analysis.apply_terminator_effect(&mut state.borrows, term, loc);
- self.uninits.analysis.apply_terminator_effect(&mut state.uninits, term, loc);
- self.ever_inits.analysis.apply_terminator_effect(&mut state.ever_inits, term, loc);
- }
-}
-
rustc_index::newtype_index! {
#[orderable]
#[debug_format = "bw{}"]
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 454fd14..129a306 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -27,7 +27,7 @@
};
use rustc_middle::ty::print::PrintTraitRefExt as _;
use rustc_middle::ty::{
- self, ClauseKind, PredicateKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor, Upcast,
+ self, PredicateKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor, Upcast,
suggest_constraining_type_params,
};
use rustc_middle::util::CallKind;
@@ -649,11 +649,11 @@ fn suggest_borrow_generic_arg(
) -> Option<ty::Mutability> {
let tcx = self.infcx.tcx;
let sig = tcx.fn_sig(callee_did).instantiate_identity().skip_binder();
- let clauses = tcx.predicates_of(callee_did).instantiate_identity(self.infcx.tcx).predicates;
+ let clauses = tcx.predicates_of(callee_did);
// First, is there at least one method on one of `param`'s trait bounds?
// This keeps us from suggesting borrowing the argument to `mem::drop`, e.g.
- if !clauses.iter().any(|clause| {
+ if !clauses.instantiate_identity(tcx).predicates.iter().any(|clause| {
clause.as_trait_clause().is_some_and(|tc| {
tc.self_ty().skip_binder().is_param(param.index)
&& tc.polarity() == ty::PredicatePolarity::Positive
@@ -682,8 +682,12 @@ fn suggest_borrow_generic_arg(
// Normalize before comparing to see through type aliases and projections.
let old_ty = ty::EarlyBinder::bind(ty).instantiate(tcx, generic_args);
let new_ty = ty::EarlyBinder::bind(ty).instantiate(tcx, new_args);
- if let Ok(old_ty) = tcx.try_normalize_erasing_regions(self.param_env, old_ty)
- && let Ok(new_ty) = tcx.try_normalize_erasing_regions(self.param_env, new_ty)
+ if let Ok(old_ty) =
+ tcx.try_normalize_erasing_regions(self.infcx.typing_env(self.param_env), old_ty)
+ && let Ok(new_ty) = tcx.try_normalize_erasing_regions(
+ self.infcx.typing_env(self.param_env),
+ new_ty,
+ )
{
old_ty == new_ty
} else {
@@ -700,23 +704,19 @@ fn suggest_borrow_generic_arg(
return false;
}
- // Test the callee's predicates, substituting a reference in for the self ty
- // in bounds on `param`.
- clauses.iter().all(|&clause| {
- let clause_for_ref = clause.kind().map_bound(|kind| match kind {
- ClauseKind::Trait(c) if c.self_ty().is_param(param.index) => {
- ClauseKind::Trait(c.with_self_ty(tcx, ref_ty))
- }
- ClauseKind::Projection(c) if c.self_ty().is_param(param.index) => {
- ClauseKind::Projection(c.with_self_ty(tcx, ref_ty))
- }
- _ => kind,
- });
+ // Test the callee's predicates, substituting in `ref_ty` for the moved argument type.
+ clauses.instantiate(tcx, new_args).predicates.iter().all(|&(mut clause)| {
+ // Normalize before testing to see through type aliases and projections.
+ if let Ok(normalized) =
+ tcx.try_normalize_erasing_regions(self.infcx.typing_env(self.param_env), clause)
+ {
+ clause = normalized;
+ }
self.infcx.predicate_must_hold_modulo_regions(&Obligation::new(
tcx,
ObligationCause::dummy(),
self.param_env,
- ty::EarlyBinder::bind(clause_for_ref).instantiate(tcx, generic_args),
+ clause,
))
})
}) {
@@ -3837,11 +3837,16 @@ fn explain_deref_coercion(&mut self, loan: &BorrowData<'tcx>, err: &mut Diag<'_>
if tcx.is_diagnostic_item(sym::deref_method, method_did) {
let deref_target =
tcx.get_diagnostic_item(sym::deref_target).and_then(|deref_target| {
- Instance::try_resolve(tcx, self.param_env, deref_target, method_args)
- .transpose()
+ Instance::try_resolve(
+ tcx,
+ self.infcx.typing_env(self.param_env),
+ deref_target,
+ method_args,
+ )
+ .transpose()
});
if let Some(Ok(instance)) = deref_target {
- let deref_target_ty = instance.ty(tcx, self.param_env);
+ let deref_target_ty = instance.ty(tcx, self.infcx.typing_env(self.param_env));
err.note(format!("borrow occurs due to deref coercion to `{deref_target_ty}`"));
err.span_note(tcx.def_span(instance.def_id()), "deref defined here");
}
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index 0797bb4..6c63da8 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -864,7 +864,7 @@ pub(super) fn move_spans(
let kind = call_kind(
self.infcx.tcx,
- self.param_env,
+ self.infcx.typing_env(self.param_env),
method_did,
method_args,
*fn_span,
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index 807b5576..d4660d8 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -952,7 +952,7 @@ fn maybe_suggest_constrain_dyn_trait_impl(
if let Ok(Some(instance)) = ty::Instance::try_resolve(
tcx,
- self.param_env,
+ self.infcx.typing_env(self.param_env),
*fn_did,
self.infcx.resolve_vars_if_possible(args),
) {
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 657e6e0..7eaf265 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -36,13 +36,13 @@
use rustc_middle::query::Providers;
use rustc_middle::ty::{self, ParamEnv, RegionVid, TyCtxt, TypingMode};
use rustc_middle::{bug, span_bug};
-use rustc_mir_dataflow::Analysis;
use rustc_mir_dataflow::impls::{
EverInitializedPlaces, MaybeInitializedPlaces, MaybeUninitializedPlaces,
};
use rustc_mir_dataflow::move_paths::{
InitIndex, InitLocation, LookupResult, MoveData, MoveOutIndex, MovePathIndex,
};
+use rustc_mir_dataflow::{Analysis, EntrySets, Results, ResultsVisitor, visit_results};
use rustc_session::lint::builtin::UNUSED_MUT;
use rustc_span::{Span, Symbol};
use smallvec::SmallVec;
@@ -50,7 +50,7 @@
use crate::borrow_set::{BorrowData, BorrowSet};
use crate::consumers::{BodyWithBorrowckFacts, ConsumerOptions};
-use crate::dataflow::{BorrowIndex, BorrowckDomain, BorrowckResults, Borrows};
+use crate::dataflow::{BorrowIndex, Borrowck, BorrowckDomain, Borrows};
use crate::diagnostics::{AccessKind, IllegalMoveOriginKind, MoveError, RegionName};
use crate::location::LocationTable;
use crate::nll::PoloniusOutput;
@@ -221,6 +221,10 @@ fn do_mir_borrowck<'tcx>(
consumer_options,
);
+ // `flow_inits` is large, so we drop it as soon as possible. This reduces
+ // peak memory usage significantly on some benchmarks.
+ drop(flow_inits);
+
// Dump MIR results into a file, if that is enabled. This let us
// write unit-tests, as well as helping with debugging.
nll::dump_nll_mir(&infcx, body, ®ioncx, &opt_closure_req, &borrow_set);
@@ -229,27 +233,6 @@ fn do_mir_borrowck<'tcx>(
// information.
nll::dump_annotation(&infcx, body, ®ioncx, &opt_closure_req, &opaque_type_values, diags);
- // The various `flow_*` structures can be large. We drop `flow_inits` here
- // so it doesn't overlap with the others below. This reduces peak memory
- // usage significantly on some benchmarks.
- drop(flow_inits);
-
- let flow_borrows = Borrows::new(tcx, body, ®ioncx, &borrow_set).iterate_to_fixpoint(
- tcx,
- body,
- Some("borrowck"),
- );
- let flow_uninits = MaybeUninitializedPlaces::new(tcx, body, &move_data).iterate_to_fixpoint(
- tcx,
- body,
- Some("borrowck"),
- );
- let flow_ever_inits = EverInitializedPlaces::new(body, &move_data).iterate_to_fixpoint(
- tcx,
- body,
- Some("borrowck"),
- );
-
let movable_coroutine =
// The first argument is the coroutine type passed by value
if let Some(local) = body.local_decls.raw.get(1)
@@ -334,16 +317,11 @@ fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
// Compute and report region errors, if any.
mbcx.report_region_errors(nll_errors);
- let mut results = BorrowckResults {
- ever_inits: flow_ever_inits,
- uninits: flow_uninits,
- borrows: flow_borrows,
- };
-
- rustc_mir_dataflow::visit_results(
+ let mut flow_results = get_flow_results(tcx, body, &move_data, &borrow_set, ®ioncx);
+ visit_results(
body,
traversal::reverse_postorder(body).map(|(bb, _)| bb),
- &mut results,
+ &mut flow_results,
&mut mbcx,
);
@@ -426,6 +404,47 @@ fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
(result, body_with_facts)
}
+fn get_flow_results<'a, 'tcx>(
+ tcx: TyCtxt<'tcx>,
+ body: &'a Body<'tcx>,
+ move_data: &'a MoveData<'tcx>,
+ borrow_set: &'a BorrowSet<'tcx>,
+ regioncx: &RegionInferenceContext<'tcx>,
+) -> Results<'tcx, Borrowck<'a, 'tcx>> {
+ // We compute these three analyses individually, but them combine them into
+ // a single results so that `mbcx` can visit them all together.
+ let borrows = Borrows::new(tcx, body, regioncx, borrow_set).iterate_to_fixpoint(
+ tcx,
+ body,
+ Some("borrowck"),
+ );
+ let uninits = MaybeUninitializedPlaces::new(tcx, body, move_data).iterate_to_fixpoint(
+ tcx,
+ body,
+ Some("borrowck"),
+ );
+ let ever_inits = EverInitializedPlaces::new(body, move_data).iterate_to_fixpoint(
+ tcx,
+ body,
+ Some("borrowck"),
+ );
+
+ let analysis = Borrowck {
+ borrows: borrows.analysis,
+ uninits: uninits.analysis,
+ ever_inits: ever_inits.analysis,
+ };
+
+ assert_eq!(borrows.entry_sets.len(), uninits.entry_sets.len());
+ assert_eq!(borrows.entry_sets.len(), ever_inits.entry_sets.len());
+ let entry_sets: EntrySets<'_, Borrowck<'_, '_>> =
+ itertools::izip!(borrows.entry_sets, uninits.entry_sets, ever_inits.entry_sets)
+ .map(|(borrows, uninits, ever_inits)| BorrowckDomain { borrows, uninits, ever_inits })
+ .collect();
+
+ Results { analysis, entry_sets }
+}
+
pub(crate) struct BorrowckInferCtxt<'tcx> {
pub(crate) infcx: InferCtxt<'tcx>,
pub(crate) reg_var_to_origin: RefCell<FxIndexMap<ty::RegionVid, RegionCtxt>>,
@@ -588,14 +607,10 @@ struct MirBorrowckCtxt<'a, 'infcx, 'tcx> {
// 2. loans made in overlapping scopes do not conflict
// 3. assignments do not affect things loaned out as immutable
// 4. moves do not affect things loaned out in any way
-impl<'a, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'a, 'tcx, R>
- for MirBorrowckCtxt<'a, '_, 'tcx>
-{
- type Domain = BorrowckDomain<'a, 'tcx>;
-
+impl<'a, 'tcx> ResultsVisitor<'a, 'tcx, Borrowck<'a, 'tcx>> for MirBorrowckCtxt<'a, '_, 'tcx> {
fn visit_statement_before_primary_effect(
&mut self,
- _results: &mut R,
+ _results: &mut Results<'tcx, Borrowck<'a, 'tcx>>,
state: &BorrowckDomain<'a, 'tcx>,
stmt: &'a Statement<'tcx>,
location: Location,
@@ -667,7 +682,7 @@ fn visit_statement_before_primary_effect(
fn visit_terminator_before_primary_effect(
&mut self,
- _results: &mut R,
+ _results: &mut Results<'tcx, Borrowck<'a, 'tcx>>,
state: &BorrowckDomain<'a, 'tcx>,
term: &'a Terminator<'tcx>,
loc: Location,
@@ -780,7 +795,7 @@ fn visit_terminator_before_primary_effect(
fn visit_terminator_after_primary_effect(
&mut self,
- _results: &mut R,
+ _results: &mut Results<'tcx, Borrowck<'a, 'tcx>>,
state: &BorrowckDomain<'a, 'tcx>,
term: &'a Terminator<'tcx>,
loc: Location,
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 0fe6a4b..ac02196 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -1527,7 +1527,9 @@ fn check_call_dest(
// The signature in this call can reference region variables,
// so erase them before calling a query.
let output_ty = self.tcx().erase_regions(sig.output());
- if !output_ty.is_privately_uninhabited(self.tcx(), self.param_env) {
+ if !output_ty
+ .is_privately_uninhabited(self.tcx(), self.infcx.typing_env(self.param_env))
+ {
span_mirbug!(self, term, "call to converging function {:?} w/o dest", sig);
}
}
diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs
index f419c1e..e7ee6b4 100644
--- a/compiler/rustc_builtin_macros/src/cfg_eval.rs
+++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs
@@ -204,10 +204,10 @@ fn flat_map_generic_param(
fn flat_map_assoc_item(
&mut self,
item: P<ast::AssocItem>,
- _ctxt: AssocCtxt,
+ ctxt: AssocCtxt,
) -> SmallVec<[P<ast::AssocItem>; 1]> {
let item = configure!(self, item);
- mut_visit::walk_flat_map_item(self, item)
+ mut_visit::walk_flat_map_assoc_item(self, item, ctxt)
}
fn flat_map_foreign_item(
diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs
index 9534845..ba5d343 100644
--- a/compiler/rustc_builtin_macros/src/test_harness.rs
+++ b/compiler/rustc_builtin_macros/src/test_harness.rs
@@ -144,7 +144,15 @@ fn visit_crate(&mut self, c: &mut ast::Crate) {
item.kind
{
let prev_tests = mem::take(&mut self.tests);
- walk_item_kind(&mut item.kind, item.span, item.id, self);
+ walk_item_kind(
+ &mut item.kind,
+ item.span,
+ item.id,
+ &mut item.ident,
+ &mut item.vis,
+ (),
+ self,
+ );
self.add_test_cases(item.id, span, prev_tests);
} else {
// But in those cases, we emit a lint to warn the user of these missing tests.
diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
index f647ee3..7dd2139 100644
--- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
@@ -376,7 +376,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
let instance = if let ty::FnDef(def_id, fn_args) = *func.layout().ty.kind() {
let instance = ty::Instance::expect_resolve(
fx.tcx,
- ty::ParamEnv::reveal_all(),
+ ty::TypingEnv::fully_monomorphized(),
def_id,
fn_args,
source_info.span,
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index da3818c..1b91d25 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -666,7 +666,7 @@ fn codegen_stmt<'tcx>(
let func_ref = fx.get_function_ref(
Instance::resolve_for_fn_ptr(
fx.tcx,
- ParamEnv::reveal_all(),
+ ty::TypingEnv::fully_monomorphized(),
def_id,
args,
)
@@ -841,14 +841,18 @@ fn is_wide_ptr<'tcx>(fx: &FunctionCx<'_, '_, 'tcx>, ty: Ty<'tcx>) -> bool {
lval.write_cvalue(fx, CValue::by_val(operand, box_layout));
}
Rvalue::NullaryOp(ref null_op, ty) => {
- assert!(lval.layout().ty.is_sized(fx.tcx, ParamEnv::reveal_all()));
+ assert!(lval.layout().ty.is_sized(fx.tcx, ty::ParamEnv::reveal_all()));
let layout = fx.layout_of(fx.monomorphize(ty));
let val = match null_op {
NullOp::SizeOf => layout.size.bytes(),
NullOp::AlignOf => layout.align.abi.bytes(),
NullOp::OffsetOf(fields) => fx
.tcx
- .offset_of_subfield(ParamEnv::reveal_all(), layout, fields.iter())
+ .offset_of_subfield(
+ ty::TypingEnv::fully_monomorphized(),
+ layout,
+ fields.iter(),
+ )
.bytes(),
NullOp::UbChecks => {
let val = fx.tcx.sess.ub_checks();
diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs
index 27e71b9..add081b 100644
--- a/compiler/rustc_codegen_cranelift/src/common.rs
+++ b/compiler/rustc_codegen_cranelift/src/common.rs
@@ -103,11 +103,11 @@ fn clif_pair_type_from_ty<'tcx>(
/// Is a pointer to this type a wide ptr?
pub(crate) fn has_ptr_meta<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
- if ty.is_sized(tcx, ParamEnv::reveal_all()) {
+ if ty.is_sized(tcx, ty::ParamEnv::reveal_all()) {
return false;
}
- let tail = tcx.struct_tail_for_codegen(ty, ParamEnv::reveal_all());
+ let tail = tcx.struct_tail_for_codegen(ty, ty::TypingEnv::fully_monomorphized());
match tail.kind() {
ty::Foreign(..) => false,
ty::Str | ty::Slice(..) | ty::Dynamic(..) => true,
@@ -339,9 +339,9 @@ fn data_layout(&self) -> &rustc_abi::TargetDataLayout {
}
}
-impl<'tcx> layout::HasParamEnv<'tcx> for FunctionCx<'_, '_, 'tcx> {
- fn param_env(&self) -> ParamEnv<'tcx> {
- ParamEnv::reveal_all()
+impl<'tcx> layout::HasTypingEnv<'tcx> for FunctionCx<'_, '_, 'tcx> {
+ fn typing_env(&self) -> ty::TypingEnv<'tcx> {
+ ty::TypingEnv::fully_monomorphized()
}
}
@@ -358,7 +358,7 @@ pub(crate) fn monomorphize<T>(&self, value: T) -> T
{
self.instance.instantiate_mir_and_normalize_erasing_regions(
self.tcx,
- ty::ParamEnv::reveal_all(),
+ ty::TypingEnv::fully_monomorphized(),
ty::EarlyBinder::bind(value),
)
}
@@ -497,9 +497,9 @@ fn data_layout(&self) -> &rustc_abi::TargetDataLayout {
}
}
-impl<'tcx> layout::HasParamEnv<'tcx> for RevealAllLayoutCx<'tcx> {
- fn param_env(&self) -> ParamEnv<'tcx> {
- ParamEnv::reveal_all()
+impl<'tcx> layout::HasTypingEnv<'tcx> for RevealAllLayoutCx<'tcx> {
+ fn typing_env(&self) -> ty::TypingEnv<'tcx> {
+ ty::TypingEnv::fully_monomorphized()
}
}
diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs
index ab78584..5311547 100644
--- a/compiler/rustc_codegen_cranelift/src/constant.rs
+++ b/compiler/rustc_codegen_cranelift/src/constant.rs
@@ -78,7 +78,7 @@ pub(crate) fn eval_mir_constant<'tcx>(
let cv = fx.monomorphize(constant.const_);
// This cannot fail because we checked all required_consts in advance.
let val = cv
- .eval(fx.tcx, ty::ParamEnv::reveal_all(), constant.span)
+ .eval(fx.tcx, ty::TypingEnv::fully_monomorphized(), constant.span)
.expect("erroneous constant missed by mono item collection");
(val, cv.ty())
}
@@ -265,8 +265,13 @@ fn data_id_for_static(
assert!(!definition);
assert!(!tcx.is_mutable_static(def_id));
- let ty = instance.ty(tcx, ParamEnv::reveal_all());
- let align = tcx.layout_of(ParamEnv::reveal_all().and(ty)).unwrap().align.pref.bytes();
+ let ty = instance.ty(tcx, ty::TypingEnv::fully_monomorphized());
+ let align = tcx
+ .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty))
+ .unwrap()
+ .align
+ .pref
+ .bytes();
let linkage = if import_linkage == rustc_middle::mir::mono::Linkage::ExternalWeak
|| import_linkage == rustc_middle::mir::mono::Linkage::WeakAny
diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs
index 9025ea9..f3a8623 100644
--- a/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs
@@ -210,7 +210,7 @@ pub(crate) fn define_function<'tcx>(
type_names::push_generic_params(
tcx,
- tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), args),
+ tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), args),
&mut name,
);
@@ -275,8 +275,10 @@ pub(crate) fn define_static<'tcx>(
let span = tcx.def_span(def_id);
let (file_id, line, _column) = self.get_span_loc(tcx, span, span);
- let static_type = Instance::mono(tcx, def_id).ty(tcx, ty::ParamEnv::reveal_all());
- let static_layout = tcx.layout_of(ty::ParamEnv::reveal_all().and(static_type)).unwrap();
+ let static_type = Instance::mono(tcx, def_id).ty(tcx, ty::TypingEnv::fully_monomorphized());
+ let static_layout = tcx
+ .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(static_type))
+ .unwrap();
// FIXME use the actual type layout
let type_id = self.debug_type(tcx, type_dbg, static_type);
diff --git a/compiler/rustc_codegen_cranelift/src/inline_asm.rs b/compiler/rustc_codegen_cranelift/src/inline_asm.rs
index a3f816f..0df1a30 100644
--- a/compiler/rustc_codegen_cranelift/src/inline_asm.rs
+++ b/compiler/rustc_codegen_cranelift/src/inline_asm.rs
@@ -92,7 +92,7 @@ pub(crate) fn codegen_inline_asm_terminator<'tcx>(
if let ty::FnDef(def_id, args) = *const_.ty().kind() {
let instance = ty::Instance::resolve_for_fn_ptr(
fx.tcx,
- ty::ParamEnv::reveal_all(),
+ ty::TypingEnv::fully_monomorphized(),
def_id,
args,
)
@@ -227,11 +227,11 @@ pub(crate) fn codegen_naked_asm<'tcx>(
InlineAsmOperand::Const { ref value } => {
let cv = instance.instantiate_mir_and_normalize_erasing_regions(
tcx,
- ty::ParamEnv::reveal_all(),
+ ty::TypingEnv::fully_monomorphized(),
ty::EarlyBinder::bind(value.const_),
);
let const_value = cv
- .eval(tcx, ty::ParamEnv::reveal_all(), value.span)
+ .eval(tcx, ty::TypingEnv::fully_monomorphized(), value.span)
.expect("erroneous constant missed by mono item collection");
let value = rustc_codegen_ssa::common::asm_const_to_str(
@@ -250,13 +250,13 @@ pub(crate) fn codegen_naked_asm<'tcx>(
let const_ = instance.instantiate_mir_and_normalize_erasing_regions(
tcx,
- ty::ParamEnv::reveal_all(),
+ ty::TypingEnv::fully_monomorphized(),
ty::EarlyBinder::bind(value.const_),
);
if let ty::FnDef(def_id, args) = *const_.ty().kind() {
let instance = ty::Instance::resolve_for_fn_ptr(
tcx,
- ty::ParamEnv::reveal_all(),
+ ty::TypingEnv::fully_monomorphized(),
def_id,
args,
)
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
index 1e2e41b..c663f6f 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
@@ -20,7 +20,7 @@ macro_rules! intrinsic_args {
use cranelift_codegen::ir::AtomicRmwOp;
use rustc_middle::ty;
use rustc_middle::ty::GenericArgsRef;
-use rustc_middle::ty::layout::{HasParamEnv, ValidityRequirement};
+use rustc_middle::ty::layout::ValidityRequirement;
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
use rustc_span::source_map::Spanned;
use rustc_span::symbol::{Symbol, sym};
@@ -453,11 +453,6 @@ fn codegen_regular_intrinsic_call<'tcx>(
fx.bcx.ins().trap(TrapCode::user(2).unwrap());
return Ok(());
}
- sym::likely | sym::unlikely => {
- intrinsic_args!(fx, args => (a); intrinsic);
-
- ret.write_cvalue(fx, a);
- }
sym::breakpoint => {
intrinsic_args!(fx, args => (); intrinsic);
@@ -687,7 +682,10 @@ fn codegen_regular_intrinsic_call<'tcx>(
if let Some(requirement) = requirement {
let do_panic = !fx
.tcx
- .check_validity_requirement((requirement, fx.param_env().and(ty)))
+ .check_validity_requirement((
+ requirement,
+ ty::TypingEnv::fully_monomorphized().as_query_input(ty),
+ ))
.expect("expect to have layout during codegen");
if do_panic {
@@ -746,7 +744,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
let const_val = fx
.tcx
- .const_eval_instance(ParamEnv::reveal_all(), instance, source_info.span)
+ .const_eval_instance(ty::ParamEnv::reveal_all(), instance, source_info.span)
.unwrap();
let val = crate::constant::codegen_const_value(fx, const_val, ret.layout().ty);
ret.write_cvalue(fx, val);
@@ -1267,6 +1265,11 @@ fn codegen_regular_intrinsic_call<'tcx>(
);
}
+ sym::cold_path => {
+ // This is a no-op. The intrinsic is just a hint to the optimizer.
+ // We still have an impl here to avoid it being turned into a call.
+ }
+
// Unimplemented intrinsics must have a fallback body. The fallback body is obtained
// by converting the `InstanceKind::Intrinsic` to an `InstanceKind::Item`.
_ => {
diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs
index b506b1f..e6f6ae3 100644
--- a/compiler/rustc_codegen_cranelift/src/lib.rs
+++ b/compiler/rustc_codegen_cranelift/src/lib.rs
@@ -98,7 +98,7 @@ mod prelude {
pub(crate) use rustc_middle::mir::{self, *};
pub(crate) use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
pub(crate) use rustc_middle::ty::{
- self, FloatTy, Instance, InstanceKind, IntTy, ParamEnv, Ty, TyCtxt, UintTy,
+ self, FloatTy, Instance, InstanceKind, IntTy, Ty, TyCtxt, UintTy,
};
pub(crate) use rustc_span::Span;
diff --git a/compiler/rustc_codegen_cranelift/src/main_shim.rs b/compiler/rustc_codegen_cranelift/src/main_shim.rs
index df92bc5..2ee4ff5 100644
--- a/compiler/rustc_codegen_cranelift/src/main_shim.rs
+++ b/compiler/rustc_codegen_cranelift/src/main_shim.rs
@@ -49,7 +49,7 @@ fn create_entry_fn(
// regions must appear in the argument
// listing.
let main_ret_ty = tcx.normalize_erasing_regions(
- ty::ParamEnv::reveal_all(),
+ ty::TypingEnv::fully_monomorphized(),
main_ret_ty.no_bound_vars().unwrap(),
);
@@ -113,7 +113,7 @@ fn create_entry_fn(
.unwrap();
let report = Instance::expect_resolve(
tcx,
- ParamEnv::reveal_all(),
+ ty::TypingEnv::fully_monomorphized(),
report.def_id,
tcx.mk_args(&[GenericArg::from(main_ret_ty)]),
DUMMY_SP,
@@ -139,7 +139,7 @@ fn create_entry_fn(
let start_def_id = tcx.require_lang_item(LangItem::Start, None);
let start_instance = Instance::expect_resolve(
tcx,
- ParamEnv::reveal_all(),
+ ty::TypingEnv::fully_monomorphized(),
start_def_id,
tcx.mk_args(&[main_ret_ty.into()]),
DUMMY_SP,
diff --git a/compiler/rustc_codegen_cranelift/src/unsize.rs b/compiler/rustc_codegen_cranelift/src/unsize.rs
index 3369343..2843e5b 100644
--- a/compiler/rustc_codegen_cranelift/src/unsize.rs
+++ b/compiler/rustc_codegen_cranelift/src/unsize.rs
@@ -3,6 +3,7 @@
//! [`PointerCoercion::Unsize`]: `rustc_middle::ty::adjustment::PointerCoercion::Unsize`
use rustc_codegen_ssa::base::validate_trivial_unsize;
+use rustc_middle::ty::layout::HasTypingEnv;
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
use crate::base::codegen_panic_nounwind;
@@ -23,7 +24,7 @@ pub(crate) fn unsized_info<'tcx>(
old_info: Option<Value>,
) -> Value {
let (source, target) =
- fx.tcx.struct_lockstep_tails_for_codegen(source, target, ParamEnv::reveal_all());
+ fx.tcx.struct_lockstep_tails_for_codegen(source, target, fx.typing_env());
match (&source.kind(), &target.kind()) {
(&ty::Array(_, len), &ty::Slice(_)) => fx.bcx.ins().iconst(
fx.pointer_type,
diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs
index 900d7e6..6676e68 100644
--- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs
+++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs
@@ -4,6 +4,7 @@
use cranelift_codegen::ir::immediates::Offset32;
use cranelift_frontend::Variable;
use rustc_middle::ty::FnSig;
+use rustc_middle::ty::layout::HasTypingEnv;
use crate::prelude::*;
@@ -884,19 +885,17 @@ pub(crate) fn assert_assignable<'tcx>(
assert_assignable(fx, *a, *b, limit - 1);
}
(ty::FnPtr(..), ty::FnPtr(..)) => {
- let from_sig = fx.tcx.normalize_erasing_late_bound_regions(
- ParamEnv::reveal_all(),
- from_ty.fn_sig(fx.tcx),
- );
+ let from_sig = fx
+ .tcx
+ .normalize_erasing_late_bound_regions(fx.typing_env(), from_ty.fn_sig(fx.tcx));
let FnSig {
inputs_and_output: types_from,
c_variadic: c_variadic_from,
safety: unsafety_from,
abi: abi_from,
} = from_sig;
- let to_sig = fx
- .tcx
- .normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), to_ty.fn_sig(fx.tcx));
+ let to_sig =
+ fx.tcx.normalize_erasing_late_bound_regions(fx.typing_env(), to_ty.fn_sig(fx.tcx));
let FnSig {
inputs_and_output: types_to,
c_variadic: c_variadic_to,
@@ -932,9 +931,8 @@ pub(crate) fn assert_assignable<'tcx>(
(&ty::Dynamic(from_traits, _, _from_kind), &ty::Dynamic(to_traits, _, _to_kind)) => {
// FIXME(dyn-star): Do the right thing with DynKinds
for (from, to) in from_traits.iter().zip(to_traits) {
- let from =
- fx.tcx.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), from);
- let to = fx.tcx.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), to);
+ let from = fx.tcx.normalize_erasing_late_bound_regions(fx.typing_env(), from);
+ let to = fx.tcx.normalize_erasing_late_bound_regions(fx.typing_env(), to);
assert_eq!(
from, to,
"Can't write trait object of incompatible traits {:?} to place with traits {:?}\n\n{:#?}",
diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs
index e6ae7cf..9a14232 100644
--- a/compiler/rustc_codegen_gcc/src/builder.rs
+++ b/compiler/rustc_codegen_gcc/src/builder.rs
@@ -24,9 +24,9 @@
use rustc_middle::bug;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
use rustc_middle::ty::layout::{
- FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, HasTyCtxt, LayoutError, LayoutOfHelpers,
+ FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasTyCtxt, HasTypingEnv, LayoutError, LayoutOfHelpers,
};
-use rustc_middle::ty::{Instance, ParamEnv, Ty, TyCtxt};
+use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
use rustc_span::Span;
use rustc_span::def_id::DefId;
use rustc_target::abi::call::FnAbi;
@@ -2319,9 +2319,9 @@ fn get_static(&mut self, def_id: DefId) -> RValue<'gcc> {
}
}
-impl<'tcx> HasParamEnv<'tcx> for Builder<'_, '_, 'tcx> {
- fn param_env(&self) -> ParamEnv<'tcx> {
- self.cx.param_env()
+impl<'tcx> HasTypingEnv<'tcx> for Builder<'_, '_, 'tcx> {
+ fn typing_env(&self) -> ty::TypingEnv<'tcx> {
+ self.cx.typing_env()
}
}
diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs
index 07c7a54..6dc2f4e 100644
--- a/compiler/rustc_codegen_gcc/src/consts.rs
+++ b/compiler/rustc_codegen_gcc/src/consts.rs
@@ -215,7 +215,7 @@ pub fn get_static(&self, def_id: DefId) -> LValue<'gcc> {
let gcc_type = if nested {
self.type_i8()
} else {
- let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all());
+ let ty = instance.ty(self.tcx, ty::TypingEnv::fully_monomorphized());
self.layout_of(ty).gcc_type(self)
};
diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs
index 707b359..3846d02 100644
--- a/compiler/rustc_codegen_gcc/src/context.rs
+++ b/compiler/rustc_codegen_gcc/src/context.rs
@@ -11,10 +11,10 @@
use rustc_middle::mir::mono::CodegenUnit;
use rustc_middle::span_bug;
use rustc_middle::ty::layout::{
- FnAbiError, FnAbiOf, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, HasTyCtxt, LayoutError,
+ FnAbiError, FnAbiOf, FnAbiOfHelpers, FnAbiRequest, HasTyCtxt, HasTypingEnv, LayoutError,
LayoutOfHelpers,
};
-use rustc_middle::ty::{self, Instance, ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt};
+use rustc_middle::ty::{self, Instance, PolyExistentialTraitRef, Ty, TyCtxt};
use rustc_session::Session;
use rustc_span::source_map::respan;
use rustc_span::{DUMMY_SP, Span};
@@ -144,7 +144,9 @@ pub fn new(
supports_f128_type: bool,
) -> Self {
let create_type = |ctype, rust_type| {
- let layout = tcx.layout_of(ParamEnv::reveal_all().and(rust_type)).unwrap();
+ let layout = tcx
+ .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(rust_type))
+ .unwrap();
let align = layout.align.abi.bytes();
#[cfg(feature = "master")]
{
@@ -459,7 +461,7 @@ fn eh_personality(&self) -> RValue<'gcc> {
Some(def_id) if !wants_msvc_seh(self.sess()) => {
let instance = ty::Instance::expect_resolve(
tcx,
- ty::ParamEnv::reveal_all(),
+ self.typing_env(),
def_id,
ty::List::empty(),
DUMMY_SP,
@@ -583,9 +585,9 @@ fn handle_fn_abi_err(
}
}
-impl<'tcx, 'gcc> HasParamEnv<'tcx> for CodegenCx<'gcc, 'tcx> {
- fn param_env(&self) -> ParamEnv<'tcx> {
- ParamEnv::reveal_all()
+impl<'tcx, 'gcc> HasTypingEnv<'tcx> for CodegenCx<'gcc, 'tcx> {
+ fn typing_env(&self) -> ty::TypingEnv<'tcx> {
+ ty::TypingEnv::fully_monomorphized()
}
}
diff --git a/compiler/rustc_codegen_gcc/src/int.rs b/compiler/rustc_codegen_gcc/src/int.rs
index 5ca440f..02b760d 100644
--- a/compiler/rustc_codegen_gcc/src/int.rs
+++ b/compiler/rustc_codegen_gcc/src/int.rs
@@ -5,7 +5,7 @@
use gccjit::{BinaryOp, ComparisonOp, FunctionType, Location, RValue, ToRValue, Type, UnaryOp};
use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
use rustc_codegen_ssa::traits::{BackendTypes, BaseTypeCodegenMethods, BuilderMethods, OverflowOp};
-use rustc_middle::ty::{ParamEnv, Ty};
+use rustc_middle::ty::{self, Ty};
use rustc_target::abi::Endian;
use rustc_target::abi::call::{ArgAbi, ArgAttributes, Conv, FnAbi, PassMode};
use rustc_target::spec;
@@ -380,7 +380,10 @@ pub fn operation_with_overflow(
let overflow_field = self.context.new_field(self.location, self.bool_type, "overflow");
let ret_ty = Ty::new_tup(self.tcx, &[self.tcx.types.i128, self.tcx.types.bool]);
- let layout = self.tcx.layout_of(ParamEnv::reveal_all().and(ret_ty)).unwrap();
+ let layout = self
+ .tcx
+ .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ret_ty))
+ .unwrap();
let arg_abi = ArgAbi { layout, mode: PassMode::Direct(ArgAttributes::new()) };
let mut fn_abi = FnAbi {
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
index b0298a3..69326f4 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
@@ -21,7 +21,7 @@
use rustc_middle::bug;
use rustc_middle::ty::layout::LayoutOf;
#[cfg(feature = "master")]
-use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt};
+use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, HasTypingEnv};
use rustc_middle::ty::{self, Instance, Ty};
use rustc_span::{Span, Symbol, sym};
use rustc_target::abi::HasDataLayout;
@@ -107,7 +107,7 @@ fn codegen_intrinsic_call(
span: Span,
) -> Result<(), Instance<'tcx>> {
let tcx = self.tcx;
- let callee_ty = instance.ty(tcx, ty::ParamEnv::reveal_all());
+ let callee_ty = instance.ty(tcx, self.typing_env());
let (def_id, fn_args) = match *callee_ty.kind() {
ty::FnDef(def_id, fn_args) => (def_id, fn_args),
@@ -115,7 +115,7 @@ fn codegen_intrinsic_call(
};
let sig = callee_ty.fn_sig(tcx);
- let sig = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), sig);
+ let sig = tcx.normalize_erasing_late_bound_regions(self.typing_env(), sig);
let arg_tys = sig.inputs();
let ret_ty = sig.output();
let name = tcx.item_name(def_id);
@@ -139,8 +139,6 @@ fn codegen_intrinsic_call(
&args.iter().map(|arg| arg.immediate()).collect::<Vec<_>>(),
)
}
- sym::likely => self.expect(args[0].immediate(), true),
- sym::unlikely => self.expect(args[0].immediate(), false),
sym::is_val_statically_known => {
let a = args[0].immediate();
let builtin = self.context.get_builtin_function("__builtin_constant_p");
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
index 43dbfaf..604678a9 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
@@ -55,8 +55,10 @@ macro_rules! require_simd {
}
let tcx = bx.tcx();
- let sig =
- tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), callee_ty.fn_sig(tcx));
+ let sig = tcx.normalize_erasing_late_bound_regions(
+ ty::TypingEnv::fully_monomorphized(),
+ callee_ty.fn_sig(tcx),
+ );
let arg_tys = sig.inputs();
if name == sym::simd_select_bitmask {
@@ -478,7 +480,7 @@ macro_rules! require_simd {
match *in_elem.kind() {
ty::RawPtr(p_ty, _) => {
let metadata = p_ty.ptr_metadata_ty(bx.tcx, |ty| {
- bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty)
+ bx.tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), ty)
});
require!(metadata.is_unit(), InvalidMonomorphization::CastWidePointer {
span,
@@ -493,7 +495,7 @@ macro_rules! require_simd {
match *out_elem.kind() {
ty::RawPtr(p_ty, _) => {
let metadata = p_ty.ptr_metadata_ty(bx.tcx, |ty| {
- bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty)
+ bx.tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), ty)
});
require!(metadata.is_unit(), InvalidMonomorphization::CastWidePointer {
span,
diff --git a/compiler/rustc_codegen_gcc/src/mono_item.rs b/compiler/rustc_codegen_gcc/src/mono_item.rs
index b7b282b..239902d 100644
--- a/compiler/rustc_codegen_gcc/src/mono_item.rs
+++ b/compiler/rustc_codegen_gcc/src/mono_item.rs
@@ -6,7 +6,7 @@
use rustc_middle::bug;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::mir::mono::{Linkage, Visibility};
-use rustc_middle::ty::layout::{FnAbiOf, LayoutOf};
+use rustc_middle::ty::layout::{FnAbiOf, HasTypingEnv, LayoutOf};
use rustc_middle::ty::{self, Instance, TypeVisitableExt};
use crate::context::CodegenCx;
@@ -27,11 +27,8 @@ fn predefine_static(
let DefKind::Static { nested, .. } = self.tcx.def_kind(def_id) else { bug!() };
// Nested statics do not have a type, so pick a dummy type and let `codegen_static` figure out
// the gcc type from the actual evaluated initializer.
- let ty = if nested {
- self.tcx.types.unit
- } else {
- instance.ty(self.tcx, ty::ParamEnv::reveal_all())
- };
+ let ty =
+ if nested { self.tcx.types.unit } else { instance.ty(self.tcx, self.typing_env()) };
let gcc_type = self.layout_of(ty).gcc_type(self);
let is_tls = attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL);
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index ac76b78..b5bb763 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -14,7 +14,7 @@
use rustc_hir::def_id::DefId;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
use rustc_middle::ty::layout::{
- FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, LayoutError, LayoutOfHelpers,
+ FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasTypingEnv, LayoutError, LayoutOfHelpers,
TyAndLayout,
};
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
@@ -81,9 +81,9 @@ fn tcx(&self) -> TyCtxt<'tcx> {
}
}
-impl<'tcx> ty::layout::HasParamEnv<'tcx> for Builder<'_, '_, 'tcx> {
- fn param_env(&self) -> ty::ParamEnv<'tcx> {
- self.cx.param_env()
+impl<'tcx> ty::layout::HasTypingEnv<'tcx> for Builder<'_, '_, 'tcx> {
+ fn typing_env(&self) -> ty::TypingEnv<'tcx> {
+ self.cx.typing_env()
}
}
@@ -472,7 +472,7 @@ fn atomic_load(
#[instrument(level = "trace", skip(self))]
fn load_operand(&mut self, place: PlaceRef<'tcx, &'ll Value>) -> OperandRef<'tcx, &'ll Value> {
if place.layout.is_unsized() {
- let tail = self.tcx.struct_tail_for_codegen(place.layout.ty, self.param_env());
+ let tail = self.tcx.struct_tail_for_codegen(place.layout.ty, self.typing_env());
if matches!(tail.kind(), ty::Foreign(..)) {
// Unsized locals and, at least conceptually, even unsized arguments must be copied
// around, which requires dynamically determining their size. Therefore, we cannot
diff --git a/compiler/rustc_codegen_llvm/src/callee.rs b/compiler/rustc_codegen_llvm/src/callee.rs
index dcea9d3..e0a2de3 100644
--- a/compiler/rustc_codegen_llvm/src/callee.rs
+++ b/compiler/rustc_codegen_llvm/src/callee.rs
@@ -5,7 +5,7 @@
//! closure.
use rustc_codegen_ssa::common;
-use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt};
+use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, HasTypingEnv};
use rustc_middle::ty::{self, Instance, TypeVisitableExt};
use tracing::debug;
@@ -28,12 +28,7 @@ pub(crate) fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'t
}
let sym = tcx.symbol_name(instance).name;
- debug!(
- "get_fn({:?}: {:?}) => {}",
- instance,
- instance.ty(cx.tcx(), ty::ParamEnv::reveal_all()),
- sym
- );
+ debug!("get_fn({:?}: {:?}) => {}", instance, instance.ty(cx.tcx(), cx.typing_env()), sym);
let fn_abi = cx.fn_abi_of_instance(instance, ty::List::empty());
diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs
index 7ab4f45..6f5ffbb 100644
--- a/compiler/rustc_codegen_llvm/src/consts.rs
+++ b/compiler/rustc_codegen_llvm/src/consts.rs
@@ -13,8 +13,8 @@
read_target_uint,
};
use rustc_middle::mir::mono::MonoItem;
-use rustc_middle::ty::layout::LayoutOf;
-use rustc_middle::ty::{self, Instance};
+use rustc_middle::ty::Instance;
+use rustc_middle::ty::layout::{HasTypingEnv, LayoutOf};
use rustc_middle::{bug, span_bug};
use rustc_session::config::Lto;
use tracing::{debug, instrument, trace};
@@ -244,7 +244,7 @@ pub(crate) fn get_static(&self, def_id: DefId) -> &'ll Value {
let llty = if nested {
self.type_i8()
} else {
- let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all());
+ let ty = instance.ty(self.tcx, self.typing_env());
trace!(?ty);
self.layout_of(ty).llvm_type(self)
};
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index 3a7c7ef..841c110 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -15,7 +15,7 @@
use rustc_middle::middle::codegen_fn_attrs::PatchableFunctionEntry;
use rustc_middle::mir::mono::CodegenUnit;
use rustc_middle::ty::layout::{
- FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, LayoutError, LayoutOfHelpers,
+ FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasTypingEnv, LayoutError, LayoutOfHelpers,
};
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
use rustc_middle::{bug, span_bug};
@@ -658,7 +658,7 @@ fn eh_personality(&self) -> &'ll Value {
let llfn = match tcx.lang_items().eh_personality() {
Some(def_id) if name.is_none() => self.get_fn_addr(ty::Instance::expect_resolve(
tcx,
- ty::ParamEnv::reveal_all(),
+ self.typing_env(),
def_id,
ty::List::empty(),
DUMMY_SP,
@@ -1162,9 +1162,9 @@ fn tcx(&self) -> TyCtxt<'tcx> {
}
}
-impl<'tcx, 'll> HasParamEnv<'tcx> for CodegenCx<'ll, 'tcx> {
- fn param_env(&self) -> ty::ParamEnv<'tcx> {
- ty::ParamEnv::reveal_all()
+impl<'tcx, 'll> HasTypingEnv<'tcx> for CodegenCx<'ll, 'tcx> {
+ fn typing_env(&self) -> ty::TypingEnv<'tcx> {
+ ty::TypingEnv::fully_monomorphized()
}
}
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs
index 0f19094..4a68bde 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs
@@ -6,7 +6,7 @@
use rustc_index::Idx;
use rustc_index::bit_set::BitSet;
use rustc_middle::mir::{Body, SourceScope};
-use rustc_middle::ty::layout::FnAbiOf;
+use rustc_middle::ty::layout::{FnAbiOf, HasTypingEnv};
use rustc_middle::ty::{self, Instance};
use rustc_session::config::DebugInfo;
use rustc_span::BytePos;
@@ -118,7 +118,7 @@ fn make_mir_scope<'ll, 'tcx>(
// if this is moved to `rustc_codegen_ssa::mir::debuginfo`.
let callee = cx.tcx.instantiate_and_normalize_erasing_regions(
instance.args,
- ty::ParamEnv::reveal_all(),
+ cx.typing_env(),
ty::EarlyBinder::bind(callee),
);
debug_context.inlined_function_scopes.entry(callee).or_insert_with(|| {
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index 151923a..ef16e5b 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -11,10 +11,9 @@
use rustc_hir::def::{CtorKind, DefKind};
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_middle::bug;
-use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
+use rustc_middle::ty::layout::{HasTypingEnv, LayoutOf, TyAndLayout};
use rustc_middle::ty::{
- self, AdtKind, CoroutineArgsExt, Instance, ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt,
- Visibility,
+ self, AdtKind, CoroutineArgsExt, Instance, PolyExistentialTraitRef, Ty, TyCtxt, Visibility,
};
use rustc_session::config::{self, DebugInfo, Lto};
use rustc_span::symbol::Symbol;
@@ -301,9 +300,8 @@ fn build_subroutine_type_di_node<'ll, 'tcx>(
.insert(unique_type_id, recursion_marker_type_di_node(cx));
let fn_ty = unique_type_id.expect_ty();
- let signature = cx
- .tcx
- .normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), fn_ty.fn_sig(cx.tcx));
+ let signature =
+ cx.tcx.normalize_erasing_late_bound_regions(cx.typing_env(), fn_ty.fn_sig(cx.tcx));
let signature_di_nodes: SmallVec<_> = iter::once(
// return type
@@ -1109,9 +1107,7 @@ fn build_upvar_field_di_nodes<'ll, 'tcx>(
}
};
- assert!(
- up_var_tys.iter().all(|t| t == cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t))
- );
+ assert!(up_var_tys.iter().all(|t| t == cx.tcx.normalize_erasing_regions(cx.typing_env(), t)));
let capture_names = cx.tcx.closure_saved_names_of_captured_variables(def_id);
let layout = cx.layout_of(closure_or_coroutine_ty);
@@ -1272,8 +1268,7 @@ fn build_generic_type_param_di_nodes<'ll, 'tcx>(
let template_params: SmallVec<_> = iter::zip(args, names)
.filter_map(|(kind, name)| {
kind.as_type().map(|ty| {
- let actual_type =
- cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty);
+ let actual_type = cx.tcx.normalize_erasing_regions(cx.typing_env(), ty);
let actual_type_di_node = type_di_node(cx, actual_type);
let name = name.as_str();
unsafe {
@@ -1341,7 +1336,7 @@ pub(crate) fn build_global_var_di_node<'ll>(
if nested {
return;
}
- let variable_type = Instance::mono(cx.tcx, def_id).ty(cx.tcx, ty::ParamEnv::reveal_all());
+ let variable_type = Instance::mono(cx.tcx, def_id).ty(cx.tcx, cx.typing_env());
let type_di_node = type_di_node(cx, variable_type);
let var_name = tcx.item_name(def_id);
let var_name = var_name.as_str();
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs
index 5120b63..4e46147 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs
@@ -6,7 +6,7 @@
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_macros::HashStable;
use rustc_middle::bug;
-use rustc_middle::ty::{ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt};
+use rustc_middle::ty::{self, PolyExistentialTraitRef, Ty, TyCtxt};
use super::{SmallVec, UNKNOWN_LINE_NUMBER, unknown_file_metadata};
use crate::common::{AsCCharPtr, CodegenCx};
@@ -49,12 +49,15 @@ pub(super) enum UniqueTypeId<'tcx> {
impl<'tcx> UniqueTypeId<'tcx> {
pub(crate) fn for_ty(tcx: TyCtxt<'tcx>, t: Ty<'tcx>) -> Self {
- assert_eq!(t, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t));
+ assert_eq!(t, tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), t));
UniqueTypeId::Ty(t, private::HiddenZst)
}
pub(crate) fn for_enum_variant_part(tcx: TyCtxt<'tcx>, enum_ty: Ty<'tcx>) -> Self {
- assert_eq!(enum_ty, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), enum_ty));
+ assert_eq!(
+ enum_ty,
+ tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), enum_ty)
+ );
UniqueTypeId::VariantPart(enum_ty, private::HiddenZst)
}
@@ -63,7 +66,10 @@ pub(crate) fn for_enum_variant_struct_type(
enum_ty: Ty<'tcx>,
variant_idx: VariantIdx,
) -> Self {
- assert_eq!(enum_ty, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), enum_ty));
+ assert_eq!(
+ enum_ty,
+ tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), enum_ty)
+ );
UniqueTypeId::VariantStructType(enum_ty, variant_idx, private::HiddenZst)
}
@@ -72,7 +78,10 @@ pub(crate) fn for_enum_variant_struct_type_wrapper(
enum_ty: Ty<'tcx>,
variant_idx: VariantIdx,
) -> Self {
- assert_eq!(enum_ty, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), enum_ty));
+ assert_eq!(
+ enum_ty,
+ tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), enum_ty)
+ );
UniqueTypeId::VariantStructTypeCppLikeWrapper(enum_ty, variant_idx, private::HiddenZst)
}
@@ -81,10 +90,13 @@ pub(crate) fn for_vtable_ty(
self_type: Ty<'tcx>,
implemented_trait: Option<PolyExistentialTraitRef<'tcx>>,
) -> Self {
- assert_eq!(self_type, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), self_type));
+ assert_eq!(
+ self_type,
+ tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), self_type)
+ );
assert_eq!(
implemented_trait,
- tcx.normalize_erasing_regions(ParamEnv::reveal_all(), implemented_trait)
+ tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), implemented_trait)
);
UniqueTypeId::VTableTy(self_type, implemented_trait, private::HiddenZst)
}
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
index 89492e4..4b650b0 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
@@ -15,8 +15,8 @@
use rustc_hir::def_id::{DefId, DefIdMap};
use rustc_index::IndexVec;
use rustc_middle::mir;
-use rustc_middle::ty::layout::LayoutOf;
-use rustc_middle::ty::{self, GenericArgsRef, Instance, ParamEnv, Ty, TypeVisitableExt};
+use rustc_middle::ty::layout::{HasTypingEnv, LayoutOf};
+use rustc_middle::ty::{self, GenericArgsRef, Instance, Ty, TypeVisitableExt};
use rustc_session::Session;
use rustc_session::config::{self, DebugInfo};
use rustc_span::symbol::Symbol;
@@ -344,7 +344,7 @@ fn dbg_scope_fn(
type_names::push_generic_params(
tcx,
- tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), args),
+ tcx.normalize_erasing_regions(self.typing_env(), args),
&mut name,
);
@@ -481,8 +481,7 @@ fn get_template_parameters<'ll, 'tcx>(
iter::zip(args, names)
.filter_map(|(kind, name)| {
kind.as_type().map(|ty| {
- let actual_type =
- cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty);
+ let actual_type = cx.tcx.normalize_erasing_regions(cx.typing_env(), ty);
let actual_type_metadata = type_di_node(cx, actual_type);
let name = name.as_str();
unsafe {
@@ -526,7 +525,7 @@ fn get_containing_scope<'ll, 'tcx>(
if cx.tcx.trait_id_of_impl(impl_def_id).is_none() {
let impl_self_ty = cx.tcx.instantiate_and_normalize_erasing_regions(
instance.args,
- ty::ParamEnv::reveal_all(),
+ cx.typing_env(),
cx.tcx.type_of(impl_def_id),
);
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs b/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs
index 960487ada..6e84129 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs
@@ -1,7 +1,7 @@
// Utility Functions.
use rustc_hir::def_id::DefId;
-use rustc_middle::ty::layout::{HasParamEnv, LayoutOf};
+use rustc_middle::ty::layout::{HasTypingEnv, LayoutOf};
use rustc_middle::ty::{self, Ty};
use tracing::trace;
@@ -62,7 +62,7 @@ pub(crate) fn wide_pointer_kind<'ll, 'tcx>(
cx: &CodegenCx<'ll, 'tcx>,
pointee_ty: Ty<'tcx>,
) -> Option<WidePtrKind> {
- let pointee_tail_ty = cx.tcx.struct_tail_for_codegen(pointee_ty, cx.param_env());
+ let pointee_tail_ty = cx.tcx.struct_tail_for_codegen(pointee_ty, cx.typing_env());
let layout = cx.layout_of(pointee_tail_ty);
trace!(
"wide_pointer_kind: {:?} has layout {:?} (is_unsized? {})",
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index e9c687d..da7f94e 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -10,7 +10,7 @@
use rustc_codegen_ssa::traits::*;
use rustc_hir as hir;
use rustc_middle::mir::BinOp;
-use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, LayoutOf};
+use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, HasTypingEnv, LayoutOf};
use rustc_middle::ty::{self, GenericArgsRef, Ty};
use rustc_middle::{bug, span_bug};
use rustc_span::{Span, Symbol, sym};
@@ -163,14 +163,14 @@ fn codegen_intrinsic_call(
span: Span,
) -> Result<(), ty::Instance<'tcx>> {
let tcx = self.tcx;
- let callee_ty = instance.ty(tcx, ty::ParamEnv::reveal_all());
+ let callee_ty = instance.ty(tcx, self.typing_env());
let ty::FnDef(def_id, fn_args) = *callee_ty.kind() else {
bug!("expected fn item type, found {}", callee_ty);
};
let sig = callee_ty.fn_sig(tcx);
- let sig = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), sig);
+ let sig = tcx.normalize_erasing_late_bound_regions(self.typing_env(), sig);
let arg_tys = sig.inputs();
let ret_ty = sig.output();
let name = tcx.item_name(def_id);
@@ -192,7 +192,6 @@ fn codegen_intrinsic_call(
Some(instance),
)
}
- sym::likely => self.expect(args[0].immediate(), true),
sym::is_val_statically_known => {
let intrinsic_type = args[0].layout.immediate_llvm_type(self.cx);
let kind = self.type_kind(intrinsic_type);
@@ -213,7 +212,6 @@ fn codegen_intrinsic_call(
self.const_bool(false)
}
}
- sym::unlikely => self.expect(args[0].immediate(), false),
sym::select_unpredictable => {
let cond = args[0].immediate();
assert_eq!(args[1].layout, args[2].layout);
@@ -1154,8 +1152,7 @@ macro_rules! require_simd {
}
let tcx = bx.tcx();
- let sig =
- tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), callee_ty.fn_sig(tcx));
+ let sig = tcx.normalize_erasing_late_bound_regions(bx.typing_env(), callee_ty.fn_sig(tcx));
let arg_tys = sig.inputs();
// Sanity-check: all vector arguments must be immediates.
@@ -2189,7 +2186,7 @@ macro_rules! bitwise_red {
match in_elem.kind() {
ty::RawPtr(p_ty, _) => {
let metadata = p_ty.ptr_metadata_ty(bx.tcx, |ty| {
- bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty)
+ bx.tcx.normalize_erasing_regions(bx.typing_env(), ty)
});
require!(metadata.is_unit(), InvalidMonomorphization::CastWidePointer {
span,
@@ -2204,7 +2201,7 @@ macro_rules! bitwise_red {
match out_elem.kind() {
ty::RawPtr(p_ty, _) => {
let metadata = p_ty.ptr_metadata_ty(bx.tcx, |ty| {
- bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty)
+ bx.tcx.normalize_erasing_regions(bx.typing_env(), ty)
});
require!(metadata.is_unit(), InvalidMonomorphization::CastWidePointer {
span,
diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs
index ea8857b..33789c6 100644
--- a/compiler/rustc_codegen_llvm/src/mono_item.rs
+++ b/compiler/rustc_codegen_llvm/src/mono_item.rs
@@ -3,7 +3,7 @@
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_middle::bug;
use rustc_middle::mir::mono::{Linkage, Visibility};
-use rustc_middle::ty::layout::{FnAbiOf, LayoutOf};
+use rustc_middle::ty::layout::{FnAbiOf, HasTypingEnv, LayoutOf};
use rustc_middle::ty::{self, Instance, TypeVisitableExt};
use rustc_session::config::CrateType;
use rustc_target::spec::RelocModel;
@@ -26,11 +26,8 @@ fn predefine_static(
let DefKind::Static { nested, .. } = self.tcx.def_kind(def_id) else { bug!() };
// Nested statics do not have a type, so pick a dummy type and let `codegen_static` figure
// out the llvm type from the actual evaluated initializer.
- let ty = if nested {
- self.tcx.types.unit
- } else {
- instance.ty(self.tcx, ty::ParamEnv::reveal_all())
- };
+ let ty =
+ if nested { self.tcx.types.unit } else { instance.ty(self.tcx, self.typing_env()) };
let llty = self.layout_of(ty).llvm_type(self);
let g = self.define_global(symbol_name, llty).unwrap_or_else(|| {
diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
index 850d368..d9152c5 100644
--- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
+++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
@@ -595,8 +595,10 @@ pub(crate) fn linking_symbol_name_for_instance_in_crate<'tcx>(
let (conv, args) = instance
.map(|i| {
- tcx.fn_abi_of_instance(ty::ParamEnv::reveal_all().and((i, ty::List::empty())))
- .unwrap_or_else(|_| bug!("fn_abi_of_instance({i:?}) failed"))
+ tcx.fn_abi_of_instance(
+ ty::TypingEnv::fully_monomorphized().as_query_input((i, ty::List::empty())),
+ )
+ .unwrap_or_else(|_| bug!("fn_abi_of_instance({i:?}) failed"))
})
.map(|fnabi| (fnabi.conv, &fnabi.args[..]))
.unwrap_or((Conv::Rust, &[]));
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index ef95ab9..c8b3b30 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -21,7 +21,7 @@
use rustc_middle::mir::BinOp;
use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem};
use rustc_middle::query::Providers;
-use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout};
+use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutOf, TyAndLayout};
use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypingMode};
use rustc_session::Session;
use rustc_session::config::{self, CrateType, EntryFnType, OptLevel, OutputType};
@@ -165,7 +165,7 @@ fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
) -> Bx::Value {
let cx = bx.cx();
let (source, target) =
- cx.tcx().struct_lockstep_tails_for_codegen(source, target, bx.param_env());
+ cx.tcx().struct_lockstep_tails_for_codegen(source, target, bx.typing_env());
match (source.kind(), target.kind()) {
(&ty::Array(_, len), &ty::Slice(_)) => cx.const_usize(
len.try_to_target_usize(cx.tcx()).expect("expected monomorphic const in codegen"),
@@ -466,10 +466,9 @@ fn create_entry_fn<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
// late-bound regions, since late-bound
// regions must appear in the argument
// listing.
- let main_ret_ty = cx.tcx().normalize_erasing_regions(
- ty::ParamEnv::reveal_all(),
- main_ret_ty.no_bound_vars().unwrap(),
- );
+ let main_ret_ty = cx
+ .tcx()
+ .normalize_erasing_regions(cx.typing_env(), main_ret_ty.no_bound_vars().unwrap());
let Some(llfn) = cx.declare_c_main(llfty) else {
// FIXME: We should be smart and show a better diagnostic here.
@@ -495,7 +494,7 @@ fn create_entry_fn<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
let start_def_id = cx.tcx().require_lang_item(LangItem::Start, None);
let start_instance = ty::Instance::expect_resolve(
cx.tcx(),
- ty::ParamEnv::reveal_all(),
+ cx.typing_env(),
start_def_id,
cx.tcx().mk_args(&[main_ret_ty.into()]),
DUMMY_SP,
diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
index 27bc585..6c4f6d3 100644
--- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
+++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
@@ -21,9 +21,7 @@
use rustc_hir::{CoroutineDesugaring, CoroutineKind, CoroutineSource, Mutability};
use rustc_middle::bug;
use rustc_middle::ty::layout::{IntegerExt, TyAndLayout};
-use rustc_middle::ty::{
- self, ExistentialProjection, GenericArgKind, GenericArgsRef, ParamEnv, Ty, TyCtxt,
-};
+use rustc_middle::ty::{self, ExistentialProjection, GenericArgKind, GenericArgsRef, Ty, TyCtxt};
use smallvec::SmallVec;
use crate::debuginfo::wants_c_like_enum_debuginfo;
@@ -82,7 +80,7 @@ fn push_debuginfo_type_name<'tcx>(
ty::Adt(def, args) => {
// `layout_for_cpp_like_fallback` will be `Some` if we want to use the fallback encoding.
let layout_for_cpp_like_fallback = if cpp_like_debuginfo && def.is_enum() {
- match tcx.layout_of(ParamEnv::reveal_all().and(t)) {
+ match tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(t)) {
Ok(layout) => {
if !wants_c_like_enum_debuginfo(tcx, layout) {
Some(layout)
@@ -248,8 +246,10 @@ fn push_debuginfo_type_name<'tcx>(
};
if let Some(principal) = trait_data.principal() {
- let principal =
- tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), principal);
+ let principal = tcx.normalize_erasing_late_bound_regions(
+ ty::TypingEnv::fully_monomorphized(),
+ principal,
+ );
push_item_name(tcx, principal.def_id, qualified, output);
let principal_has_generic_params =
push_generic_params_internal(tcx, principal.args, output, visited);
@@ -350,8 +350,10 @@ fn push_debuginfo_type_name<'tcx>(
return;
}
- let sig =
- tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), t.fn_sig(tcx));
+ let sig = tcx.normalize_erasing_late_bound_regions(
+ ty::TypingEnv::fully_monomorphized(),
+ t.fn_sig(tcx),
+ );
if cpp_like_debuginfo {
// Format as a C++ function pointer: return_type (*)(params...)
@@ -415,7 +417,8 @@ fn push_debuginfo_type_name<'tcx>(
// In the case of cpp-like debuginfo, the name additionally gets wrapped inside of
// an artificial `enum2$<>` type, as defined in msvc_enum_fallback().
if cpp_like_debuginfo && t.is_coroutine() {
- let ty_and_layout = tcx.layout_of(ParamEnv::reveal_all().and(t)).unwrap();
+ let ty_and_layout =
+ tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(t)).unwrap();
msvc_enum_fallback(
tcx,
ty_and_layout,
@@ -529,8 +532,8 @@ pub fn compute_debuginfo_vtable_name<'tcx>(
}
if let Some(trait_ref) = trait_ref {
- let trait_ref =
- tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), trait_ref);
+ let trait_ref = tcx
+ .normalize_erasing_late_bound_regions(ty::TypingEnv::fully_monomorphized(), trait_ref);
push_item_name(tcx, trait_ref.def_id, true, &mut vtable_name);
visited.clear();
push_generic_params_internal(tcx, trait_ref.args, &mut vtable_name, &mut visited);
@@ -639,7 +642,7 @@ fn push_generic_params_internal<'tcx>(
output: &mut String,
visited: &mut FxHashSet<Ty<'tcx>>,
) -> bool {
- assert_eq!(args, tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), args));
+ assert_eq!(args, tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), args));
let mut args = args.non_erasable_generics().peekable();
if args.peek().is_none() {
return false;
@@ -678,14 +681,14 @@ fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: ty::Const<'tcx>, output: &mut S
// FIXME: directly extract the bits from a valtree instead of evaluating an
// already evaluated `Const` in order to get the bits.
let bits = ct
- .try_to_bits(tcx, ty::ParamEnv::reveal_all())
+ .try_to_bits(tcx, ty::TypingEnv::fully_monomorphized())
.expect("expected monomorphic const in codegen");
let val = Integer::from_int_ty(&tcx, *ity).size().sign_extend(bits) as i128;
write!(output, "{val}")
}
ty::Uint(_) => {
let val = ct
- .try_to_bits(tcx, ty::ParamEnv::reveal_all())
+ .try_to_bits(tcx, ty::TypingEnv::fully_monomorphized())
.expect("expected monomorphic const in codegen");
write!(output, "{val}")
}
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index 027d803..e3ed12b 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -377,20 +377,32 @@ fn codegen_switchint_terminator(
// If there are two targets (one conditional, one fallback), emit `br` instead of
// `switch`.
let (test_value, target) = target_iter.next().unwrap();
- let lltrue = helper.llbb_with_cleanup(self, target);
- let llfalse = helper.llbb_with_cleanup(self, targets.otherwise());
+ let otherwise = targets.otherwise();
+ let lltarget = helper.llbb_with_cleanup(self, target);
+ let llotherwise = helper.llbb_with_cleanup(self, otherwise);
+ let target_cold = self.cold_blocks[target];
+ let otherwise_cold = self.cold_blocks[otherwise];
+ // If `target_cold == otherwise_cold`, the branches have the same weight
+ // so there is no expectation. If they differ, the `target` branch is expected
+ // when the `otherwise` branch is cold.
+ let expect = if target_cold == otherwise_cold { None } else { Some(otherwise_cold) };
if switch_ty == bx.tcx().types.bool {
// Don't generate trivial icmps when switching on bool.
match test_value {
- 0 => bx.cond_br(discr_value, llfalse, lltrue),
- 1 => bx.cond_br(discr_value, lltrue, llfalse),
+ 0 => {
+ let expect = expect.map(|e| !e);
+ bx.cond_br_with_expect(discr_value, llotherwise, lltarget, expect);
+ }
+ 1 => {
+ bx.cond_br_with_expect(discr_value, lltarget, llotherwise, expect);
+ }
_ => bug!(),
}
} else {
let switch_llty = bx.immediate_backend_type(bx.layout_of(switch_ty));
let llval = bx.const_uint_big(switch_llty, test_value);
let cmp = bx.icmp(IntPredicate::IntEQ, discr_value, llval);
- bx.cond_br(cmp, lltrue, llfalse);
+ bx.cond_br_with_expect(cmp, lltarget, llotherwise, expect);
}
} else if self.cx.sess().opts.optimize == OptLevel::No
&& target_iter.len() == 2
@@ -765,7 +777,7 @@ fn codegen_panic_intrinsic(
let do_panic = !bx
.tcx()
- .check_validity_requirement((requirement, bx.param_env().and(ty)))
+ .check_validity_requirement((requirement, bx.typing_env().as_query_input(ty)))
.expect("expect to have layout during codegen");
let layout = bx.layout_of(ty);
@@ -836,14 +848,8 @@ fn codegen_call_terminator(
let (instance, mut llfn) = match *callee.layout.ty.kind() {
ty::FnDef(def_id, args) => (
Some(
- ty::Instance::expect_resolve(
- bx.tcx(),
- ty::ParamEnv::reveal_all(),
- def_id,
- args,
- fn_span,
- )
- .polymorphize(bx.tcx()),
+ ty::Instance::expect_resolve(bx.tcx(), bx.typing_env(), def_id, args, fn_span)
+ .polymorphize(bx.tcx()),
),
None,
),
@@ -1179,7 +1185,7 @@ fn codegen_asm_terminator(
if let ty::FnDef(def_id, args) = *const_.ty().kind() {
let instance = ty::Instance::resolve_for_fn_ptr(
bx.tcx(),
- ty::ParamEnv::reveal_all(),
+ bx.typing_env(),
def_id,
args,
)
diff --git a/compiler/rustc_codegen_ssa/src/mir/constant.rs b/compiler/rustc_codegen_ssa/src/mir/constant.rs
index 54b9c9c..7676e1e 100644
--- a/compiler/rustc_codegen_ssa/src/mir/constant.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs
@@ -1,6 +1,6 @@
use rustc_abi::BackendRepr;
use rustc_middle::mir::interpret::ErrorHandled;
-use rustc_middle::ty::layout::HasTyCtxt;
+use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv};
use rustc_middle::ty::{self, Ty};
use rustc_middle::{bug, mir, span_bug};
@@ -24,7 +24,7 @@ pub fn eval_mir_constant(&self, constant: &mir::ConstOperand<'tcx>) -> mir::Cons
// `MirUsedCollector` visited all required_consts before codegen began, so if we got here
// there can be no more constants that fail to evaluate.
self.monomorphize(constant.const_)
- .eval(self.cx.tcx(), ty::ParamEnv::reveal_all(), constant.span)
+ .eval(self.cx.tcx(), self.cx.typing_env(), constant.span)
.expect("erroneous constant missed by mono item collection")
}
@@ -57,7 +57,7 @@ fn eval_unevaluated_mir_constant_to_valtree(
other => span_bug!(constant.span, "{other:#?}"),
};
let uv = self.monomorphize(uv);
- self.cx.tcx().const_eval_resolve_for_typeck(ty::ParamEnv::reveal_all(), uv, constant.span)
+ self.cx.tcx().const_eval_resolve_for_typeck(self.cx.typing_env(), uv, constant.span)
}
/// process constant containing SIMD shuffle indices & constant vectors
diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
index c9e38bb..c35d0b9 100644
--- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
@@ -59,14 +59,14 @@ pub fn codegen_intrinsic_call(
llresult: Bx::Value,
span: Span,
) -> Result<(), ty::Instance<'tcx>> {
- let callee_ty = instance.ty(bx.tcx(), ty::ParamEnv::reveal_all());
+ let callee_ty = instance.ty(bx.tcx(), bx.typing_env());
let ty::FnDef(def_id, fn_args) = *callee_ty.kind() else {
bug!("expected fn item type, found {}", callee_ty);
};
let sig = callee_ty.fn_sig(bx.tcx());
- let sig = bx.tcx().normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), sig);
+ let sig = bx.tcx().normalize_erasing_late_bound_regions(bx.typing_env(), sig);
let arg_tys = sig.inputs();
let ret_ty = sig.output();
let name = bx.tcx().item_name(def_id);
@@ -498,6 +498,11 @@ pub fn codegen_intrinsic_call(
}
}
+ sym::cold_path => {
+ // This is a no-op. The intrinsic is just a hint to the optimizer.
+ return Ok(());
+ }
+
_ => {
// Need to use backend-specific things in the implementation.
return bx.codegen_intrinsic_call(instance, fn_abi, args, llresult, span);
diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs
index 20fd089..0cbc5c4 100644
--- a/compiler/rustc_codegen_ssa/src/mir/mod.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs
@@ -4,7 +4,7 @@
use rustc_index::bit_set::BitSet;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::mir::{UnwindTerminateReason, traversal};
-use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, TyAndLayout};
+use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, HasTypingEnv, TyAndLayout};
use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
use rustc_middle::{bug, mir, span_bug};
use rustc_target::callconv::{FnAbi, PassMode};
@@ -91,6 +91,10 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
/// Cached terminate upon unwinding block and its reason
terminate_block: Option<(Bx::BasicBlock, UnwindTerminateReason)>,
+ /// A bool flag for each basic block indicating whether it is a cold block.
+ /// A cold block is a block that is unlikely to be executed at runtime.
+ cold_blocks: IndexVec<mir::BasicBlock, bool>,
+
/// The location where each MIR arg/var/tmp/ret is stored. This is
/// usually an `PlaceRef` representing an alloca, but not always:
/// sometimes we can skip the alloca and just store the value
@@ -124,7 +128,7 @@ pub fn monomorphize<T>(&self, value: T) -> T
debug!("monomorphize: self.instance={:?}", self.instance);
self.instance.instantiate_mir_and_normalize_erasing_regions(
self.cx.tcx(),
- ty::ParamEnv::reveal_all(),
+ self.cx.typing_env(),
ty::EarlyBinder::bind(value),
)
}
@@ -207,6 +211,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
cleanup_kinds,
landing_pads: IndexVec::from_elem(None, &mir.basic_blocks),
funclets: IndexVec::from_fn_n(|_| None, mir.basic_blocks.len()),
+ cold_blocks: find_cold_blocks(cx.tcx(), mir),
locals: locals::Locals::empty(),
debug_context,
per_local_var_debug_info: None,
@@ -477,3 +482,39 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
args
}
+
+fn find_cold_blocks<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ mir: &mir::Body<'tcx>,
+) -> IndexVec<mir::BasicBlock, bool> {
+ let local_decls = &mir.local_decls;
+
+ let mut cold_blocks: IndexVec<mir::BasicBlock, bool> =
+ IndexVec::from_elem(false, &mir.basic_blocks);
+
+ // Traverse all basic blocks from end of the function to the start.
+ for (bb, bb_data) in traversal::postorder(mir) {
+ let terminator = bb_data.terminator();
+
+ // If a BB ends with a call to a cold function, mark it as cold.
+ if let mir::TerminatorKind::Call { ref func, .. } = terminator.kind
+ && let ty::FnDef(def_id, ..) = *func.ty(local_decls, tcx).kind()
+ && let attrs = tcx.codegen_fn_attrs(def_id)
+ && attrs.flags.contains(CodegenFnAttrFlags::COLD)
+ {
+ cold_blocks[bb] = true;
+ continue;
+ }
+
+ // If all successors of a BB are cold and there's at least one of them, mark this BB as cold
+ let mut succ = terminator.successors();
+ if let Some(first) = succ.next()
+ && cold_blocks[first]
+ && succ.all(|s| cold_blocks[s])
+ {
+ cold_blocks[bb] = true;
+ }
+ }
+
+ cold_blocks
+}
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
index 0e1cd66..f63b2d1 100644
--- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -474,7 +474,7 @@ pub(crate) fn codegen_rvalue_operand(
ty::FnDef(def_id, args) => {
let instance = ty::Instance::resolve_for_fn_ptr(
bx.tcx(),
- ty::ParamEnv::reveal_all(),
+ bx.typing_env(),
def_id,
args,
)
@@ -709,7 +709,7 @@ pub(crate) fn codegen_rvalue_operand(
mir::NullOp::OffsetOf(fields) => {
let val = bx
.tcx()
- .offset_of_subfield(bx.param_env(), layout, fields.iter())
+ .offset_of_subfield(bx.typing_env(), layout, fields.iter())
.bytes();
bx.cx().const_usize(val)
}
@@ -727,7 +727,7 @@ pub(crate) fn codegen_rvalue_operand(
mir::Rvalue::ThreadLocalRef(def_id) => {
assert!(bx.cx().tcx().is_static(def_id));
- let layout = bx.layout_of(bx.cx().tcx().static_ptr_ty(def_id));
+ let layout = bx.layout_of(bx.cx().tcx().static_ptr_ty(def_id, bx.typing_env()));
let static_ = if !def_id.is_local() && bx.cx().tcx().needs_thread_local_shim(def_id)
{
let instance = ty::Instance {
diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs
index 74cd522..b0138ac 100644
--- a/compiler/rustc_codegen_ssa/src/traits/builder.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs
@@ -84,6 +84,26 @@ fn cond_br(
then_llbb: Self::BasicBlock,
else_llbb: Self::BasicBlock,
);
+
+ // Conditional with expectation.
+ //
+ // This function is opt-in for back ends.
+ //
+ // The default implementation calls `self.expect()` before emiting the branch
+ // by calling `self.cond_br()`
+ fn cond_br_with_expect(
+ &mut self,
+ mut cond: Self::Value,
+ then_llbb: Self::BasicBlock,
+ else_llbb: Self::BasicBlock,
+ expect: Option<bool>,
+ ) {
+ if let Some(expect) = expect {
+ cond = self.expect(cond, expect);
+ }
+ self.cond_br(cond, then_llbb, else_llbb)
+ }
+
fn switch(
&mut self,
v: Self::Value,
diff --git a/compiler/rustc_codegen_ssa/src/traits/type_.rs b/compiler/rustc_codegen_ssa/src/traits/type_.rs
index 44ba226..3810c60 100644
--- a/compiler/rustc_codegen_ssa/src/traits/type_.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/type_.rs
@@ -1,6 +1,6 @@
use rustc_abi::{AddressSpace, Float, Integer};
use rustc_middle::bug;
-use rustc_middle::ty::layout::{HasTyCtxt, TyAndLayout};
+use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, TyAndLayout};
use rustc_middle::ty::{self, Ty};
use rustc_target::callconv::{ArgAbi, CastTarget, FnAbi, Reg};
@@ -41,7 +41,7 @@ pub trait BaseTypeCodegenMethods<'tcx>: BackendTypes {
}
pub trait DerivedTypeCodegenMethods<'tcx>:
- BaseTypeCodegenMethods<'tcx> + MiscCodegenMethods<'tcx> + HasTyCtxt<'tcx>
+ BaseTypeCodegenMethods<'tcx> + MiscCodegenMethods<'tcx> + HasTyCtxt<'tcx> + HasTypingEnv<'tcx>
{
fn type_int(&self) -> Self::Type {
match &self.sess().target.c_int_width[..] {
@@ -74,7 +74,7 @@ fn type_from_float(&self, f: Float) -> Self::Type {
}
fn type_needs_drop(&self, ty: Ty<'tcx>) -> bool {
- ty.needs_drop(self.tcx(), ty::ParamEnv::reveal_all())
+ ty.needs_drop(self.tcx(), self.typing_env())
}
fn type_is_sized(&self, ty: Ty<'tcx>) -> bool {
@@ -86,12 +86,11 @@ fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool {
}
fn type_has_metadata(&self, ty: Ty<'tcx>) -> bool {
- let param_env = ty::ParamEnv::reveal_all();
- if ty.is_sized(self.tcx(), param_env) {
+ if ty.is_sized(self.tcx(), self.param_env()) {
return false;
}
- let tail = self.tcx().struct_tail_for_codegen(ty, param_env);
+ let tail = self.tcx().struct_tail_for_codegen(ty, self.typing_env());
match tail.kind() {
ty::Foreign(..) => false,
ty::Str | ty::Slice(..) | ty::Dynamic(..) => true,
@@ -101,7 +100,10 @@ fn type_has_metadata(&self, ty: Ty<'tcx>) -> bool {
}
impl<'tcx, T> DerivedTypeCodegenMethods<'tcx> for T where
- Self: BaseTypeCodegenMethods<'tcx> + MiscCodegenMethods<'tcx> + HasTyCtxt<'tcx>
+ Self: BaseTypeCodegenMethods<'tcx>
+ + MiscCodegenMethods<'tcx>
+ + HasTyCtxt<'tcx>
+ + HasTypingEnv<'tcx>
{
}
diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl
index 15027ae..f93f4d3 100644
--- a/compiler/rustc_const_eval/messages.ftl
+++ b/compiler/rustc_const_eval/messages.ftl
@@ -403,7 +403,7 @@
const_eval_unmarked_const_fn_exposed = `{$def_path}` cannot be (indirectly) exposed to stable
.help = either mark the callee as `#[rustc_const_stable_indirect]`, or the caller as `#[rustc_const_unstable]`
const_eval_unmarked_intrinsic_exposed = intrinsic `{$def_path}` cannot be (indirectly) exposed to stable
- .help = mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_intrinsic]` (but this requires team approval)
+ .help = mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_intrinsic_const_stable_indirect]` (but this requires team approval)
const_eval_unreachable = entering unreachable code
const_eval_unreachable_unwind =
diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs
index ffe32ac..8e96d36 100644
--- a/compiler/rustc_const_eval/src/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/check_consts/check.rs
@@ -388,7 +388,7 @@ fn revalidate_conditional_constness(
return false;
}
- let infcx = tcx.infer_ctxt().build(self.body.typing_mode(tcx));
+ let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(self.body.typing_env(tcx));
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
let body_id = self.body.source.def_id().expect_local();
@@ -398,11 +398,8 @@ fn revalidate_conditional_constness(
ty::BoundConstness::Const
}
};
- let const_conditions = ocx.normalize(
- &ObligationCause::misc(call_span, body_id),
- self.param_env,
- const_conditions,
- );
+ let const_conditions =
+ ocx.normalize(&ObligationCause::misc(call_span, body_id), param_env, const_conditions);
ocx.register_obligations(const_conditions.into_iter().map(|(trait_ref, span)| {
Obligation::new(
tcx,
@@ -411,7 +408,7 @@ fn revalidate_conditional_constness(
body_id,
ObligationCauseCode::WhereClause(callee, span),
),
- self.param_env,
+ param_env,
trait_ref.to_host_effect_clause(tcx, host_polarity),
)
}));
@@ -760,7 +757,7 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location
Some(ConstStability { level: StabilityLevel::Stable { .. }, .. }) => {
// All good. Note that a `#[rustc_const_stable]` intrinsic (meaning it
// can be *directly* invoked from stable const code) does not always
- // have the `#[rustc_const_stable_intrinsic]` attribute (which controls
+ // have the `#[rustc_intrinsic_const_stable_indirect]` attribute (which controls
// exposing an intrinsic indirectly); we accept this call anyway.
}
}
diff --git a/compiler/rustc_const_eval/src/check_consts/mod.rs b/compiler/rustc_const_eval/src/check_consts/mod.rs
index ebdd55a..80d3c64 100644
--- a/compiler/rustc_const_eval/src/check_consts/mod.rs
+++ b/compiler/rustc_const_eval/src/check_consts/mod.rs
@@ -24,17 +24,15 @@
pub struct ConstCx<'mir, 'tcx> {
pub body: &'mir mir::Body<'tcx>,
pub tcx: TyCtxt<'tcx>,
- pub param_env: ty::ParamEnv<'tcx>,
+ pub typing_env: ty::TypingEnv<'tcx>,
pub const_kind: Option<hir::ConstContext>,
}
impl<'mir, 'tcx> ConstCx<'mir, 'tcx> {
pub fn new(tcx: TyCtxt<'tcx>, body: &'mir mir::Body<'tcx>) -> Self {
- let def_id = body.source.def_id().expect_local();
- let param_env = tcx.param_env(def_id);
-
+ let typing_env = body.typing_env(tcx);
let const_kind = tcx.hir().body_const_context(body.source.def_id().expect_local());
- ConstCx { body, tcx, param_env, const_kind }
+ ConstCx { body, tcx, typing_env, const_kind }
}
pub(crate) fn dcx(&self) -> DiagCtxtHandle<'tcx> {
diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs
index ca95e42..8ba6b89 100644
--- a/compiler/rustc_const_eval/src/check_consts/ops.rs
+++ b/compiler/rustc_const_eval/src/check_consts/ops.rs
@@ -120,7 +120,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
#[allow(rustc::untranslatable_diagnostic)]
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, _: Span) -> Diag<'tcx> {
let FnCallNonConst { callee, args, span, call_source } = *self;
- let ConstCx { tcx, param_env, .. } = *ccx;
+ let ConstCx { tcx, typing_env, .. } = *ccx;
let caller = ccx.def_id();
let diag_trait = |err, self_ty: Ty<'_>, trait_id| {
@@ -146,13 +146,11 @@ fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, _: Span) -> Diag<'tcx> {
}
}
ty::Adt(..) => {
+ let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env);
let obligation =
Obligation::new(tcx, ObligationCause::dummy(), param_env, trait_ref);
-
- let infcx = tcx.infer_ctxt().build(ccx.body.typing_mode(tcx));
let mut selcx = SelectionContext::new(&infcx);
let implsrc = selcx.select(&obligation);
-
if let Ok(Some(ImplSource::UserDefined(data))) = implsrc {
// FIXME(const_trait_impl) revisit this
if !tcx.is_const_trait_impl(data.impl_def_id) {
@@ -166,7 +164,7 @@ fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, _: Span) -> Diag<'tcx> {
};
let call_kind =
- call_kind(tcx, ccx.param_env, callee, args, span, call_source.from_hir_call(), None);
+ call_kind(tcx, ccx.typing_env, callee, args, span, call_source.from_hir_call(), None);
debug!(?call_kind);
diff --git a/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs b/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs
index 0173a52..f6eb130 100644
--- a/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs
+++ b/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs
@@ -32,17 +32,15 @@ pub fn checking_enabled(ccx: &ConstCx<'_, '_>) -> bool {
/// This is separate from the rest of the const checking logic because it must run after drop
/// elaboration.
pub fn check_live_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mir::Body<'tcx>) {
- let def_id = body.source.def_id().expect_local();
- let const_kind = tcx.hir().body_const_context(def_id);
- if const_kind.is_none() {
+ let ccx = ConstCx::new(tcx, body);
+ if ccx.const_kind.is_none() {
return;
}
- if tcx.has_attr(def_id, sym::rustc_do_not_const_check) {
+ if tcx.has_attr(body.source.def_id(), sym::rustc_do_not_const_check) {
return;
}
- let ccx = ConstCx { body, tcx, const_kind, param_env: tcx.param_env(def_id) };
if !checking_enabled(&ccx) {
return;
}
diff --git a/compiler/rustc_const_eval/src/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/check_consts/qualifs.rs
index 29a0857..bc416ac 100644
--- a/compiler/rustc_const_eval/src/check_consts/qualifs.rs
+++ b/compiler/rustc_const_eval/src/check_consts/qualifs.rs
@@ -106,20 +106,24 @@ fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool {
// Instead we invoke an obligation context manually, and provide the opaque type inference settings
// that allow the trait solver to just error out instead of cycling.
let freeze_def_id = cx.tcx.require_lang_item(LangItem::Freeze, Some(cx.body.span));
-
+ // FIXME(#132279): Once we've got a typing mode which reveals opaque types using the HIR
+ // typeck results without causing query cycles, we should use this here instead of defining
+ // opaque types.
+ let typing_env = ty::TypingEnv {
+ typing_mode: ty::TypingMode::analysis_in_body(
+ cx.tcx,
+ cx.body.source.def_id().expect_local(),
+ ),
+ param_env: cx.typing_env.param_env,
+ };
+ let (infcx, param_env) = cx.tcx.infer_ctxt().build_with_typing_env(typing_env);
+ let ocx = ObligationCtxt::new(&infcx);
let obligation = Obligation::new(
cx.tcx,
ObligationCause::dummy_with_span(cx.body.span),
- cx.param_env,
+ param_env,
ty::TraitRef::new(cx.tcx, freeze_def_id, [ty::GenericArg::from(ty)]),
);
-
- // FIXME(#132279): This should eventually use the already defined hidden types.
- let infcx = cx.tcx.infer_ctxt().build(ty::TypingMode::analysis_in_body(
- cx.tcx,
- cx.body.source.def_id().expect_local(),
- ));
- let ocx = ObligationCtxt::new(&infcx);
ocx.register_obligation(obligation);
let errors = ocx.select_all_or_error();
!errors.is_empty()
@@ -156,7 +160,7 @@ fn in_qualifs(qualifs: &ConstQualifs) -> bool {
}
fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool {
- ty.needs_drop(cx.tcx, cx.param_env)
+ ty.needs_drop(cx.tcx, cx.typing_env)
}
fn in_adt_inherently<'tcx>(
diff --git a/compiler/rustc_const_eval/src/check_consts/resolver.rs b/compiler/rustc_const_eval/src/check_consts/resolver.rs
index 74eb6b3..03624a2 100644
--- a/compiler/rustc_const_eval/src/check_consts/resolver.rs
+++ b/compiler/rustc_const_eval/src/check_consts/resolver.rs
@@ -120,7 +120,10 @@ fn ref_allows_mutation(&self, kind: mir::BorrowKind, place: mir::Place<'tcx>) ->
///
/// [rust-lang/unsafe-code-guidelines#134]: https://github.com/rust-lang/unsafe-code-guidelines/issues/134
fn shared_borrow_allows_mutation(&self, place: mir::Place<'tcx>) -> bool {
- !place.ty(self.ccx.body, self.ccx.tcx).ty.is_freeze(self.ccx.tcx, self.ccx.param_env)
+ !place
+ .ty(self.ccx.body, self.ccx.tcx)
+ .ty
+ .is_freeze(self.ccx.tcx, self.ccx.typing_env.param_env)
}
}
diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
index a430d9d..ca3ee67 100644
--- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
@@ -221,7 +221,7 @@ pub(super) fn op_to_const<'tcx>(
let pointee_ty = imm.layout.ty.builtin_deref(false).unwrap(); // `false` = no raw ptrs
debug_assert!(
matches!(
- ecx.tcx.struct_tail_for_codegen(pointee_ty, ecx.param_env).kind(),
+ ecx.tcx.struct_tail_for_codegen(pointee_ty, ecx.typing_env()).kind(),
ty::Str | ty::Slice(..),
),
"`ConstValue::Slice` is for slice-tailed types only, but got {}",
@@ -280,11 +280,13 @@ pub fn eval_to_const_value_raw_provider<'tcx>(
// opaque types. This is needed for trivial things like `size_of`, but also for using associated
// types that are not specified in the opaque type.
assert_eq!(key.param_env.reveal(), Reveal::All);
+ let typing_env =
+ ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env: key.param_env };
// We call `const_eval` for zero arg intrinsics, too, in order to cache their value.
// Catch such calls and evaluate them instead of trying to load a constant's MIR.
if let ty::InstanceKind::Intrinsic(def_id) = key.value.instance.def {
- let ty = key.value.instance.ty(tcx, key.param_env);
+ let ty = key.value.instance.ty(tcx, typing_env);
let ty::FnDef(_, args) = ty.kind() else {
bug!("intrinsic with type {:?}", ty);
};
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index 62115ae..19c3195 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -249,9 +249,10 @@ fn hook_special_const_fn(
} else if self.tcx.is_lang_item(def_id, LangItem::PanicFmt) {
// For panic_fmt, call const_panic_fmt instead.
let const_def_id = self.tcx.require_lang_item(LangItem::ConstPanicFmt, None);
+ // FIXME(@lcnr): why does this use an empty env if we've got a `param_env` right here.
let new_instance = ty::Instance::expect_resolve(
*self.tcx,
- ty::ParamEnv::reveal_all(),
+ ty::TypingEnv::fully_monomorphized(),
const_def_id,
instance.args,
self.cur_span(),
@@ -263,6 +264,12 @@ fn hook_special_const_fn(
}
/// See documentation on the `ptr_guaranteed_cmp` intrinsic.
+ /// Returns `2` if the result is unknown.
+ /// Returns `1` if the pointers are guaranteed equal.
+ /// Returns `0` if the pointers are guaranteed inequal.
+ ///
+ /// Note that this intrinsic is exposed on stable for comparison with null. In other words, any
+ /// change to this function that affects comparison with null is insta-stable!
fn guaranteed_cmp(&mut self, a: Scalar, b: Scalar) -> InterpResult<'tcx, u8> {
interp_ok(match (a, b) {
// Comparisons between integers are always known.
diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs
index ea88b2e..64bedea 100644
--- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs
+++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs
@@ -2,6 +2,7 @@
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId};
use rustc_middle::ty::layout::{LayoutCx, LayoutOf, TyAndLayout};
+use rustc_middle::ty::solve::Reveal;
use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt};
use rustc_middle::{bug, mir};
use rustc_span::DUMMY_SP;
@@ -281,8 +282,9 @@ pub fn valtree_to_const_value<'tcx>(
// the `ValTree` and using `place_projection` and `place_field` to
// create inner `MPlace`s which are filled recursively.
// FIXME Does this need an example?
-
let (param_env, ty) = param_env_ty.into_parts();
+ debug_assert_eq!(param_env.reveal(), Reveal::All);
+ let typing_env = ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env };
match *ty.kind() {
ty::FnDef(..) => {
@@ -302,11 +304,12 @@ pub fn valtree_to_const_value<'tcx>(
let mut ecx =
mk_eval_cx_to_read_const_val(tcx, DUMMY_SP, param_env, CanAccessMutGlobal::No);
let imm = valtree_to_ref(&mut ecx, valtree, inner_ty);
- let imm = ImmTy::from_immediate(imm, tcx.layout_of(param_env_ty).unwrap());
+ let imm =
+ ImmTy::from_immediate(imm, tcx.layout_of(typing_env.as_query_input(ty)).unwrap());
op_to_const(&ecx, &imm.into(), /* for diagnostics */ false)
}
ty::Tuple(_) | ty::Array(_, _) | ty::Adt(..) => {
- let layout = tcx.layout_of(param_env_ty).unwrap();
+ let layout = tcx.layout_of(typing_env.as_query_input(ty)).unwrap();
if layout.is_zst() {
// Fast path to avoid some allocations.
return mir::ConstValue::ZeroSized;
@@ -319,7 +322,7 @@ pub fn valtree_to_const_value<'tcx>(
let branches = valtree.unwrap_branch();
// Find the non-ZST field. (There can be aligned ZST!)
for (i, &inner_valtree) in branches.iter().enumerate() {
- let field = layout.field(&LayoutCx::new(tcx, param_env), i);
+ let field = layout.field(&LayoutCx::new(tcx, typing_env), i);
if !field.is_zst() {
return valtree_to_const_value(tcx, param_env.and(field.ty), inner_valtree);
}
diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs
index ef0902e..6cfe4b2 100644
--- a/compiler/rustc_const_eval/src/interpret/call.rs
+++ b/compiler/rustc_const_eval/src/interpret/call.rs
@@ -215,7 +215,7 @@ fn layout_compat(
// Even if `ty` is normalized, the search for the unsized tail will project
// to fields, which can yield non-normalized types. So we need to provide a
// normalization function.
- let normalize = |ty| self.tcx.normalize_erasing_regions(self.param_env, ty);
+ let normalize = |ty| self.tcx.normalize_erasing_regions(self.typing_env(), ty);
ty.ptr_metadata_ty(*self.tcx, normalize)
};
return interp_ok(meta_ty(caller) == meta_ty(callee));
@@ -652,35 +652,35 @@ pub(super) fn init_fn_call(
};
// Obtain the underlying trait we are working on, and the adjusted receiver argument.
- let (trait_, dyn_ty, adjusted_recv) = if let ty::Dynamic(data, _, ty::DynStar) =
- receiver_place.layout.ty.kind()
- {
- let recv = self.unpack_dyn_star(&receiver_place, data)?;
+ let (trait_, dyn_ty, adjusted_recv) =
+ if let ty::Dynamic(data, _, ty::DynStar) = receiver_place.layout.ty.kind() {
+ let recv = self.unpack_dyn_star(&receiver_place, data)?;
- (data.principal(), recv.layout.ty, recv.ptr())
- } else {
- // Doesn't have to be a `dyn Trait`, but the unsized tail must be `dyn Trait`.
- // (For that reason we also cannot use `unpack_dyn_trait`.)
- let receiver_tail =
- self.tcx.struct_tail_for_codegen(receiver_place.layout.ty, self.param_env);
- let ty::Dynamic(receiver_trait, _, ty::Dyn) = receiver_tail.kind() else {
- span_bug!(
- self.cur_span(),
- "dynamic call on non-`dyn` type {}",
- receiver_tail
- )
+ (data.principal(), recv.layout.ty, recv.ptr())
+ } else {
+ // Doesn't have to be a `dyn Trait`, but the unsized tail must be `dyn Trait`.
+ // (For that reason we also cannot use `unpack_dyn_trait`.)
+ let receiver_tail = self
+ .tcx
+ .struct_tail_for_codegen(receiver_place.layout.ty, self.typing_env());
+ let ty::Dynamic(receiver_trait, _, ty::Dyn) = receiver_tail.kind() else {
+ span_bug!(
+ self.cur_span(),
+ "dynamic call on non-`dyn` type {}",
+ receiver_tail
+ )
+ };
+ assert!(receiver_place.layout.is_unsized());
+
+ // Get the required information from the vtable.
+ let vptr = receiver_place.meta().unwrap_meta().to_pointer(self)?;
+ let dyn_ty = self.get_ptr_vtable_ty(vptr, Some(receiver_trait))?;
+
+ // It might be surprising that we use a pointer as the receiver even if this
+ // is a by-val case; this works because by-val passing of an unsized `dyn
+ // Trait` to a function is actually desugared to a pointer.
+ (receiver_trait.principal(), dyn_ty, receiver_place.ptr())
};
- assert!(receiver_place.layout.is_unsized());
-
- // Get the required information from the vtable.
- let vptr = receiver_place.meta().unwrap_meta().to_pointer(self)?;
- let dyn_ty = self.get_ptr_vtable_ty(vptr, Some(receiver_trait))?;
-
- // It might be surprising that we use a pointer as the receiver even if this
- // is a by-val case; this works because by-val passing of an unsized `dyn
- // Trait` to a function is actually desugared to a pointer.
- (receiver_trait.principal(), dyn_ty, receiver_place.ptr())
- };
// Now determine the actual method to call. Usually we use the easy way of just
// looking up the method at index `idx`.
@@ -704,7 +704,7 @@ pub(super) fn init_fn_call(
let concrete_method = Instance::expect_resolve_for_vtable(
tcx,
- self.param_env,
+ self.typing_env(),
def_id,
instance.args.rebase_onto(tcx, trait_def_id, concrete_trait_ref.args),
self.cur_span(),
diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs
index 4955905..2d1bb5c 100644
--- a/compiler/rustc_const_eval/src/interpret/cast.rs
+++ b/compiler/rustc_const_eval/src/interpret/cast.rs
@@ -83,7 +83,7 @@ pub fn cast(
ty::FnDef(def_id, args) => {
let instance = ty::Instance::resolve_for_fn_ptr(
*self.tcx,
- self.param_env,
+ self.typing_env(),
def_id,
args,
)
@@ -384,7 +384,7 @@ fn unsize_into_ptr(
) -> InterpResult<'tcx> {
// A<Struct> -> A<Trait> conversion
let (src_pointee_ty, dest_pointee_ty) =
- self.tcx.struct_lockstep_tails_for_codegen(source_ty, cast_ty, self.param_env);
+ self.tcx.struct_lockstep_tails_for_codegen(source_ty, cast_ty, self.typing_env());
match (src_pointee_ty.kind(), dest_pointee_ty.kind()) {
(&ty::Array(_, length), &ty::Slice(_)) => {
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index ff6d5b2..70a696e 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -10,9 +10,7 @@
use rustc_middle::ty::layout::{
self, FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers, TyAndLayout,
};
-use rustc_middle::ty::{
- self, GenericArgsRef, ParamEnv, Ty, TyCtxt, TypeFoldable, TypingMode, Variance,
-};
+use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypeFoldable, TypingEnv, Variance};
use rustc_middle::{mir, span_bug};
use rustc_session::Limit;
use rustc_span::Span;
@@ -65,12 +63,12 @@ fn tcx(&self) -> TyCtxt<'tcx> {
}
}
-impl<'tcx, M> layout::HasParamEnv<'tcx> for InterpCx<'tcx, M>
+impl<'tcx, M> layout::HasTypingEnv<'tcx> for InterpCx<'tcx, M>
where
M: Machine<'tcx>,
{
- fn param_env(&self) -> ty::ParamEnv<'tcx> {
- self.param_env
+ fn typing_env(&self) -> ty::TypingEnv<'tcx> {
+ self.typing_env()
}
}
@@ -116,8 +114,7 @@ fn handle_fn_abi_err(
/// This test should be symmetric, as it is primarily about layout compatibility.
pub(super) fn mir_assign_valid_types<'tcx>(
tcx: TyCtxt<'tcx>,
- typing_mode: TypingMode<'tcx>,
- param_env: ParamEnv<'tcx>,
+ typing_env: TypingEnv<'tcx>,
src: TyAndLayout<'tcx>,
dest: TyAndLayout<'tcx>,
) -> bool {
@@ -125,7 +122,7 @@ pub(super) fn mir_assign_valid_types<'tcx>(
// all normal lifetimes are erased, higher-ranked types with their
// late-bound lifetimes are still around and can lead to type
// differences.
- if util::relate_types(tcx, typing_mode, param_env, Variance::Covariant, src.ty, dest.ty) {
+ if util::relate_types(tcx, typing_env, Variance::Covariant, src.ty, dest.ty) {
// Make sure the layout is equal, too -- just to be safe. Miri really
// needs layout equality. For performance reason we skip this check when
// the types are equal. Equal types *can* have different layouts when
@@ -145,8 +142,7 @@ pub(super) fn mir_assign_valid_types<'tcx>(
#[cfg_attr(not(debug_assertions), inline(always))]
pub(super) fn from_known_layout<'tcx>(
tcx: TyCtxtAt<'tcx>,
- typing_mode: TypingMode<'tcx>,
- param_env: ParamEnv<'tcx>,
+ typing_env: TypingEnv<'tcx>,
known_layout: Option<TyAndLayout<'tcx>>,
compute: impl FnOnce() -> InterpResult<'tcx, TyAndLayout<'tcx>>,
) -> InterpResult<'tcx, TyAndLayout<'tcx>> {
@@ -155,13 +151,7 @@ pub(super) fn from_known_layout<'tcx>(
Some(known_layout) => {
if cfg!(debug_assertions) {
let check_layout = compute()?;
- if !mir_assign_valid_types(
- tcx.tcx,
- typing_mode,
- param_env,
- check_layout,
- known_layout,
- ) {
+ if !mir_assign_valid_types(tcx.tcx, typing_env, check_layout, known_layout) {
span_bug!(
tcx.span,
"expected type differs from actual type.\nexpected: {}\nactual: {}",
@@ -211,9 +201,11 @@ pub fn new(
}
}
- pub fn typing_mode(&self) -> TypingMode<'tcx> {
+ /// During CTFE we're always in `PostAnalysis` mode.
+ #[inline(always)]
+ pub fn typing_env(&self) -> ty::TypingEnv<'tcx> {
debug_assert_eq!(self.param_env.reveal(), Reveal::All);
- TypingMode::PostAnalysis
+ ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env: self.param_env }
}
/// Returns the span of the currently executed statement/terminator.
@@ -304,13 +296,13 @@ pub(super) fn instantiate_from_frame_and_normalize_erasing_regions<
.instance
.try_instantiate_mir_and_normalize_erasing_regions(
*self.tcx,
- self.param_env,
+ self.typing_env(),
ty::EarlyBinder::bind(value),
)
.map_err(|_| ErrorHandled::TooGeneric(self.cur_span()))
}
- /// The `args` are assumed to already be in our interpreter "universe" (param_env).
+ /// The `args` are assumed to already be in our interpreter "universe".
pub(super) fn resolve(
&self,
def: DefId,
@@ -319,7 +311,7 @@ pub(super) fn resolve(
trace!("resolve: {:?}, {:#?}", def, args);
trace!("param_env: {:#?}", self.param_env);
trace!("args: {:#?}", args);
- match ty::Instance::try_resolve(*self.tcx, self.param_env, def, args) {
+ match ty::Instance::try_resolve(*self.tcx, self.typing_env(), def, args) {
Ok(Some(instance)) => interp_ok(instance),
Ok(None) => throw_inval!(TooGeneric),
@@ -328,7 +320,7 @@ pub(super) fn resolve(
}
}
- /// Check if the two things are equal in the current param_env, using an infctx to get proper
+ /// Check if the two things are equal in the current param_env, using an infcx to get proper
/// equality checks.
#[instrument(level = "trace", skip(self), ret)]
pub(super) fn eq_in_param_env<T>(&self, a: T, b: T) -> bool
@@ -340,14 +332,14 @@ pub(super) fn eq_in_param_env<T>(&self, a: T, b: T) -> bool
return true;
}
// Slow path: spin up an inference context to check if these traits are sufficiently equal.
- let infcx = self.tcx.infer_ctxt().build(self.typing_mode());
+ let (infcx, param_env) = self.tcx.infer_ctxt().build_with_typing_env(self.typing_env());
let ocx = ObligationCtxt::new(&infcx);
let cause = ObligationCause::dummy_with_span(self.cur_span());
// equate the two trait refs after normalization
- let a = ocx.normalize(&cause, self.param_env, a);
- let b = ocx.normalize(&cause, self.param_env, b);
+ let a = ocx.normalize(&cause, param_env, a);
+ let b = ocx.normalize(&cause, param_env, b);
- if let Err(terr) = ocx.eq(&cause, self.param_env, a, b) {
+ if let Err(terr) = ocx.eq(&cause, param_env, a, b) {
trace!(?terr);
return false;
}
@@ -572,7 +564,7 @@ pub fn eval_global(
let val = if self.tcx.is_static(gid.instance.def_id()) {
let alloc_id = self.tcx.reserve_and_set_static_alloc(gid.instance.def_id());
- let ty = instance.ty(self.tcx.tcx, self.param_env);
+ let ty = instance.ty(self.tcx.tcx, self.typing_env());
mir::ConstAlloc { alloc_id, ty }
} else {
self.ctfe_query(|tcx| tcx.eval_to_allocation_raw(self.param_env.and(gid)))?
@@ -587,7 +579,7 @@ pub fn eval_mir_constant(
layout: Option<TyAndLayout<'tcx>>,
) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
M::eval_mir_constant(self, *val, span, layout, |ecx, val, span, layout| {
- let const_val = val.eval(*ecx.tcx, ecx.param_env, span).map_err(|err| {
+ let const_val = val.eval(*ecx.tcx, ecx.typing_env(), span).map_err(|err| {
if M::ALL_CONSTS_ARE_PRECHECKED {
match err {
ErrorHandled::TooGeneric(..) => {},
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
index c7a56a8..c8859ab 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
@@ -40,6 +40,7 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>(
) -> InterpResult<'tcx, ConstValue<'tcx>> {
let tp_ty = args.type_at(0);
let name = tcx.item_name(def_id);
+ let typing_env = ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env };
interp_ok(match name {
sym::type_name => {
ensure_monomorphic_enough(tcx, tp_ty)?;
@@ -48,11 +49,13 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>(
}
sym::needs_drop => {
ensure_monomorphic_enough(tcx, tp_ty)?;
- ConstValue::from_bool(tp_ty.needs_drop(tcx, param_env))
+ ConstValue::from_bool(tp_ty.needs_drop(tcx, typing_env))
}
sym::pref_align_of => {
// Correctly handles non-monomorphic calls, so there is no need for ensure_monomorphic_enough.
- let layout = tcx.layout_of(param_env.and(tp_ty)).map_err(|e| err_inval!(Layout(*e)))?;
+ let layout = tcx
+ .layout_of(typing_env.as_query_input(tp_ty))
+ .map_err(|e| err_inval!(Layout(*e)))?;
ConstValue::from_target_usize(layout.align.pref.bytes(), &tcx)
}
sym::type_id => {
@@ -355,7 +358,7 @@ pub fn eval_intrinsic(
let should_panic = !self
.tcx
- .check_validity_requirement((requirement, self.param_env.and(ty)))
+ .check_validity_requirement((requirement, self.typing_env().as_query_input(ty)))
.map_err(|_| err_inval!(TooGeneric))?;
if should_panic {
diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs
index 09635c9..07566e9 100644
--- a/compiler/rustc_const_eval/src/interpret/memory.rs
+++ b/compiler/rustc_const_eval/src/interpret/memory.rs
@@ -859,7 +859,7 @@ pub fn get_alloc_info(&self, id: AllocId) -> AllocInfo {
// # Global allocations
if let Some(global_alloc) = self.tcx.try_get_global_alloc(id) {
- let (size, align) = global_alloc.size_and_align(*self.tcx, self.param_env);
+ let (size, align) = global_alloc.size_and_align(*self.tcx, self.typing_env());
let mutbl = global_alloc.mutability(*self.tcx, self.param_env);
let kind = match global_alloc {
GlobalAlloc::Static { .. } | GlobalAlloc::Memory { .. } => AllocKind::LiveData,
diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs
index a130ae8..0157e6c2 100644
--- a/compiler/rustc_const_eval/src/interpret/operand.rs
+++ b/compiler/rustc_const_eval/src/interpret/operand.rs
@@ -8,7 +8,7 @@
use rustc_abi::{BackendRepr, HasDataLayout, Size};
use rustc_hir::def::Namespace;
use rustc_middle::mir::interpret::ScalarSizeMismatch;
-use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt, LayoutOf, TyAndLayout};
+use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutOf, TyAndLayout};
use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter};
use rustc_middle::ty::{ConstInt, ScalarInt, Ty, TyCtxt};
use rustc_middle::{bug, mir, span_bug, ty};
@@ -297,21 +297,25 @@ pub fn from_int(i: impl Into<i128>, layout: TyAndLayout<'tcx>) -> Self {
#[inline]
pub fn from_bool(b: bool, tcx: TyCtxt<'tcx>) -> Self {
- let layout = tcx.layout_of(ty::ParamEnv::reveal_all().and(tcx.types.bool)).unwrap();
+ let layout = tcx
+ .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(tcx.types.bool))
+ .unwrap();
Self::from_scalar(Scalar::from_bool(b), layout)
}
#[inline]
pub fn from_ordering(c: std::cmp::Ordering, tcx: TyCtxt<'tcx>) -> Self {
let ty = tcx.ty_ordering_enum(None);
- let layout = tcx.layout_of(ty::ParamEnv::reveal_all().and(ty)).unwrap();
+ let layout =
+ tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)).unwrap();
Self::from_scalar(Scalar::from_i8(c as i8), layout)
}
pub fn from_pair(a: Self, b: Self, tcx: TyCtxt<'tcx>) -> Self {
let layout = tcx
.layout_of(
- ty::ParamEnv::reveal_all().and(Ty::new_tup(tcx, &[a.layout.ty, b.layout.ty])),
+ ty::TypingEnv::fully_monomorphized()
+ .as_query_input(Ty::new_tup(tcx, &[a.layout.ty, b.layout.ty])),
)
.unwrap();
Self::from_scalar_pair(a.to_scalar(), b.to_scalar(), layout)
@@ -341,7 +345,7 @@ pub fn to_const_int(self) -> ConstInt {
#[inline]
#[cfg_attr(debug_assertions, track_caller)] // only in debug builds due to perf (see #98980)
- pub fn to_pair(self, cx: &(impl HasTyCtxt<'tcx> + HasParamEnv<'tcx>)) -> (Self, Self) {
+ pub fn to_pair(self, cx: &(impl HasTyCtxt<'tcx> + HasTypingEnv<'tcx>)) -> (Self, Self) {
let layout = self.layout;
let (val0, val1) = self.to_scalar_pair();
(
@@ -773,8 +777,7 @@ pub fn eval_place_to_op(
)?;
if !mir_assign_valid_types(
*self.tcx,
- self.typing_mode(),
- self.param_env,
+ self.typing_env(),
self.layout_of(normalized_place_ty)?,
op.layout,
) {
@@ -833,9 +836,7 @@ pub(crate) fn const_val_to_op(
})
};
let layout =
- from_known_layout(self.tcx, self.typing_mode(), self.param_env, layout, || {
- self.layout_of(ty).into()
- })?;
+ from_known_layout(self.tcx, self.typing_env(), layout, || self.layout_of(ty).into())?;
let imm = match val_val {
mir::ConstValue::Indirect { alloc_id, offset } => {
// This is const data, no mutation allowed.
diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs
index fbc85d3..201f1b5 100644
--- a/compiler/rustc_const_eval/src/interpret/operator.rs
+++ b/compiler/rustc_const_eval/src/interpret/operator.rs
@@ -533,7 +533,7 @@ pub fn nullary_op(
}
OffsetOf(fields) => {
let val =
- self.tcx.offset_of_subfield(self.param_env, layout, fields.iter()).bytes();
+ self.tcx.offset_of_subfield(self.typing_env(), layout, fields.iter()).bytes();
ImmTy::from_uint(val, usize_layout())
}
UbChecks => ImmTy::from_bool(M::ub_checks(self)?, *self.tcx),
diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs
index cc8d1db..13fcccc 100644
--- a/compiler/rustc_const_eval/src/interpret/place.rs
+++ b/compiler/rustc_const_eval/src/interpret/place.rs
@@ -540,8 +540,7 @@ pub fn eval_place(
)?;
if !mir_assign_valid_types(
*self.tcx,
- self.typing_mode(),
- self.param_env,
+ self.typing_env(),
self.layout_of(normalized_place_ty)?,
place.layout,
) {
@@ -871,13 +870,8 @@ fn copy_op_no_validate(
) -> InterpResult<'tcx> {
// We do NOT compare the types for equality, because well-typed code can
// actually "transmute" `&mut T` to `&T` in an assignment without a cast.
- let layout_compat = mir_assign_valid_types(
- *self.tcx,
- self.typing_mode(),
- self.param_env,
- src.layout(),
- dest.layout(),
- );
+ let layout_compat =
+ mir_assign_valid_types(*self.tcx, self.typing_env(), src.layout(), dest.layout());
if !allow_transmute && !layout_compat {
span_bug!(
self.cur_span(),
diff --git a/compiler/rustc_const_eval/src/interpret/stack.rs b/compiler/rustc_const_eval/src/interpret/stack.rs
index 50c0446..037c1a2 100644
--- a/compiler/rustc_const_eval/src/interpret/stack.rs
+++ b/compiler/rustc_const_eval/src/interpret/stack.rs
@@ -379,7 +379,7 @@ pub(crate) fn push_stack_frame_raw(
for &const_ in body.required_consts() {
let c =
self.instantiate_from_current_frame_and_normalize_erasing_regions(const_.const_)?;
- c.eval(*self.tcx, self.param_env, const_.span).map_err(|err| {
+ c.eval(*self.tcx, self.typing_env(), const_.span).map_err(|err| {
err.emit_note(*self.tcx);
err
})?;
@@ -596,13 +596,12 @@ pub(super) fn layout_of_local(
return interp_ok(layout);
}
- let layout =
- from_known_layout(self.tcx, self.typing_mode(), self.param_env, layout, || {
- let local_ty = frame.body.local_decls[local].ty;
- let local_ty =
- self.instantiate_from_frame_and_normalize_erasing_regions(frame, local_ty)?;
- self.layout_of(local_ty).into()
- })?;
+ let layout = from_known_layout(self.tcx, self.typing_env(), layout, || {
+ let local_ty = frame.body.local_decls[local].ty;
+ let local_ty =
+ self.instantiate_from_frame_and_normalize_erasing_regions(frame, local_ty)?;
+ self.layout_of(local_ty).into()
+ })?;
// Layouts of locals are requested a lot, so we cache them.
state.layout.set(Some(layout));
diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs
index 18cff2c..d452524 100644
--- a/compiler/rustc_const_eval/src/interpret/step.rs
+++ b/compiler/rustc_const_eval/src/interpret/step.rs
@@ -418,7 +418,8 @@ fn eval_callee_and_args(
.collect::<InterpResult<'tcx, Vec<_>>>()?;
let fn_sig_binder = func.layout.ty.fn_sig(*self.tcx);
- let fn_sig = self.tcx.normalize_erasing_late_bound_regions(self.param_env, fn_sig_binder);
+ let fn_sig =
+ self.tcx.normalize_erasing_late_bound_regions(self.typing_env(), fn_sig_binder);
let extra_args = &args[fn_sig.inputs().len()..];
let extra_args =
self.tcx.mk_type_list_from_iter(extra_args.iter().map(|arg| arg.layout().ty));
diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs
index 3a68db9..005b430 100644
--- a/compiler/rustc_const_eval/src/interpret/validity.rs
+++ b/compiler/rustc_const_eval/src/interpret/validity.rs
@@ -448,7 +448,7 @@ fn check_wide_ptr_meta(
meta: MemPlaceMeta<M::Provenance>,
pointee: TyAndLayout<'tcx>,
) -> InterpResult<'tcx> {
- let tail = self.ecx.tcx.struct_tail_for_codegen(pointee.ty, self.ecx.param_env);
+ let tail = self.ecx.tcx.struct_tail_for_codegen(pointee.ty, self.ecx.typing_env());
match tail.kind() {
ty::Dynamic(data, _, ty::Dyn) => {
let vtable = meta.unwrap_meta().to_pointer(self.ecx)?;
@@ -568,7 +568,7 @@ fn check_safe_pointer(
throw_validation_failure!(self.path, DanglingPtrUseAfterFree { ptr_kind });
};
let (size, _align) =
- global_alloc.size_and_align(*self.ecx.tcx, self.ecx.param_env);
+ global_alloc.size_and_align(*self.ecx.tcx, self.ecx.typing_env());
if let GlobalAlloc::Static(did) = global_alloc {
let DefKind::Static { nested, .. } = self.ecx.tcx.def_kind(did) else {
@@ -955,7 +955,7 @@ fn union_data_range<'e>(
) -> Cow<'e, RangeSet> {
assert!(layout.ty.is_union());
assert!(layout.is_sized(), "there are no unsized unions");
- let layout_cx = LayoutCx::new(*ecx.tcx, ecx.param_env);
+ let layout_cx = LayoutCx::new(*ecx.tcx, ecx.typing_env());
return M::cached_union_data_range(ecx, layout.ty, || {
let mut out = RangeSet(Vec::new());
union_data_range_uncached(&layout_cx, layout, Size::ZERO, &mut out);
diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs
index 0490195..527236b 100644
--- a/compiler/rustc_const_eval/src/lib.rs
+++ b/compiler/rustc_const_eval/src/lib.rs
@@ -47,7 +47,7 @@ pub fn provide(providers: &mut Providers) {
providers.hooks.try_destructure_mir_constant_for_user_output =
const_eval::try_destructure_mir_constant_for_user_output;
providers.valtree_to_const_val = |tcx, (ty, valtree)| {
- const_eval::valtree_to_const_value(tcx, ty::ParamEnv::empty().and(ty), valtree)
+ const_eval::valtree_to_const_value(tcx, ty::ParamEnv::reveal_all().and(ty), valtree)
};
providers.check_validity_requirement = |tcx, (init_kind, param_env_and_ty)| {
util::check_validity_requirement(tcx, init_kind, param_env_and_ty)
diff --git a/compiler/rustc_const_eval/src/util/alignment.rs b/compiler/rustc_const_eval/src/util/alignment.rs
index 6fa7d36..9507b24 100644
--- a/compiler/rustc_const_eval/src/util/alignment.rs
+++ b/compiler/rustc_const_eval/src/util/alignment.rs
@@ -9,7 +9,7 @@
pub fn is_disaligned<'tcx, L>(
tcx: TyCtxt<'tcx>,
local_decls: &L,
- param_env: ty::ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
place: Place<'tcx>,
) -> bool
where
@@ -22,8 +22,8 @@ pub fn is_disaligned<'tcx, L>(
};
let ty = place.ty(local_decls, tcx).ty;
- let unsized_tail = || tcx.struct_tail_for_codegen(ty, param_env);
- match tcx.layout_of(param_env.and(ty)) {
+ let unsized_tail = || tcx.struct_tail_for_codegen(ty, typing_env);
+ match tcx.layout_of(typing_env.as_query_input(ty)) {
Ok(layout)
if layout.align.abi <= pack
&& (layout.is_sized()
diff --git a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
index f743525..1afc910 100644
--- a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
+++ b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
@@ -3,7 +3,7 @@
use rustc_middle::ty::layout::{
HasTyCtxt, LayoutCx, LayoutError, LayoutOf, TyAndLayout, ValidityRequirement,
};
-use rustc_middle::ty::{ParamEnvAnd, Ty, TyCtxt};
+use rustc_middle::ty::{PseudoCanonicalInput, Ty, TyCtxt};
use crate::const_eval::{CanAccessMutGlobal, CheckAlignment, CompileTimeMachine};
use crate::interpret::{InterpCx, MemoryKind};
@@ -23,16 +23,16 @@
pub fn check_validity_requirement<'tcx>(
tcx: TyCtxt<'tcx>,
kind: ValidityRequirement,
- param_env_and_ty: ParamEnvAnd<'tcx, Ty<'tcx>>,
+ input: PseudoCanonicalInput<'tcx, Ty<'tcx>>,
) -> Result<bool, &'tcx LayoutError<'tcx>> {
- let layout = tcx.layout_of(param_env_and_ty)?;
+ let layout = tcx.layout_of(input)?;
// There is nothing strict or lax about inhabitedness.
if kind == ValidityRequirement::Inhabited {
return Ok(!layout.is_uninhabited());
}
- let layout_cx = LayoutCx::new(tcx, param_env_and_ty.param_env);
+ let layout_cx = LayoutCx::new(tcx, input.typing_env);
if kind == ValidityRequirement::Uninit || tcx.sess.opts.unstable_opts.strict_init_checks {
check_validity_requirement_strict(layout, &layout_cx, kind)
} else {
@@ -49,7 +49,7 @@ fn check_validity_requirement_strict<'tcx>(
) -> Result<bool, &'tcx LayoutError<'tcx>> {
let machine = CompileTimeMachine::new(CanAccessMutGlobal::No, CheckAlignment::Error);
- let mut cx = InterpCx::new(cx.tcx(), rustc_span::DUMMY_SP, cx.param_env, machine);
+ let mut cx = InterpCx::new(cx.tcx(), rustc_span::DUMMY_SP, cx.typing_env.param_env, machine);
let allocated = cx
.allocate(ty, MemoryKind::Machine(crate::const_eval::MemoryKind::Heap))
diff --git a/compiler/rustc_const_eval/src/util/compare_types.rs b/compiler/rustc_const_eval/src/util/compare_types.rs
index 0cf27d3..9eed1a2 100644
--- a/compiler/rustc_const_eval/src/util/compare_types.rs
+++ b/compiler/rustc_const_eval/src/util/compare_types.rs
@@ -5,18 +5,17 @@
use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::traits::ObligationCause;
-use rustc_middle::ty::{ParamEnv, Ty, TyCtxt, TypingMode, Variance};
+use rustc_middle::ty::{Ty, TyCtxt, TypingEnv, Variance};
use rustc_trait_selection::traits::ObligationCtxt;
/// Returns whether `src` is a subtype of `dest`, i.e. `src <: dest`.
pub fn sub_types<'tcx>(
tcx: TyCtxt<'tcx>,
- typing_mode: TypingMode<'tcx>,
- param_env: ParamEnv<'tcx>,
+ typing_env: TypingEnv<'tcx>,
src: Ty<'tcx>,
dest: Ty<'tcx>,
) -> bool {
- relate_types(tcx, typing_mode, param_env, Variance::Covariant, src, dest)
+ relate_types(tcx, typing_env, Variance::Covariant, src, dest)
}
/// Returns whether `src` is a subtype of `dest`, i.e. `src <: dest`.
@@ -26,8 +25,7 @@ pub fn sub_types<'tcx>(
/// because we want to check for type equality.
pub fn relate_types<'tcx>(
tcx: TyCtxt<'tcx>,
- typing_mode: TypingMode<'tcx>,
- param_env: ParamEnv<'tcx>,
+ typing_env: TypingEnv<'tcx>,
variance: Variance,
src: Ty<'tcx>,
dest: Ty<'tcx>,
@@ -36,8 +34,7 @@ pub fn relate_types<'tcx>(
return true;
}
- let mut builder = tcx.infer_ctxt().ignoring_regions();
- let infcx = builder.build(typing_mode);
+ let (infcx, param_env) = tcx.infer_ctxt().ignoring_regions().build_with_typing_env(typing_env);
let ocx = ObligationCtxt::new(&infcx);
let cause = ObligationCause::dummy();
let src = ocx.normalize(&cause, param_env, src);
diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs
index bede4c4..65d5861 100644
--- a/compiler/rustc_data_structures/src/lib.rs
+++ b/compiler/rustc_data_structures/src/lib.rs
@@ -21,6 +21,7 @@
#![feature(auto_traits)]
#![feature(cfg_match)]
#![feature(core_intrinsics)]
+#![feature(dropck_eyepatch)]
#![feature(extend_one)]
#![feature(file_buffered)]
#![feature(hash_raw_entry)]
@@ -78,6 +79,7 @@
pub mod transitive_relation;
pub mod unhash;
pub mod unord;
+pub mod vec_cache;
pub mod work_queue;
mod atomic_ref;
diff --git a/compiler/rustc_data_structures/src/vec_cache.rs b/compiler/rustc_data_structures/src/vec_cache.rs
new file mode 100644
index 0000000..eb251b5
--- /dev/null
+++ b/compiler/rustc_data_structures/src/vec_cache.rs
@@ -0,0 +1,324 @@
+//! VecCache maintains a mapping from K -> (V, I) pairing. K and I must be roughly u32-sized, and V
+//! must be Copy.
+//!
+//! VecCache supports efficient concurrent put/get across the key space, with write-once semantics
+//! (i.e., a given key can only be put once). Subsequent puts will panic.
+//!
+//! This is currently used for query caching.
+
+use std::fmt::Debug;
+use std::marker::PhantomData;
+use std::sync::atomic::{AtomicPtr, AtomicU32, AtomicUsize, Ordering};
+
+use rustc_index::Idx;
+
+struct Slot<V> {
+ // We never construct &Slot<V> so it's fine for this to not be in an UnsafeCell.
+ value: V,
+ // This is both an index and a once-lock.
+ //
+ // 0: not yet initialized.
+ // 1: lock held, initializing.
+ // 2..u32::MAX - 2: initialized.
+ index_and_lock: AtomicU32,
+}
+
+/// This uniquely identifies a single `Slot<V>` entry in the buckets map, and provides accessors for
+/// either getting the value or putting a value.
+#[derive(Copy, Clone, Debug)]
+struct SlotIndex {
+ // the index of the bucket in VecCache (0 to 20)
+ bucket_idx: usize,
+ // number of entries in that bucket
+ entries: usize,
+ // the index of the slot within the bucket
+ index_in_bucket: usize,
+}
+
+// This makes sure the counts are consistent with what we allocate, precomputing each bucket a
+// compile-time. Visiting all powers of two is enough to hit all the buckets.
+//
+// We confirm counts are accurate in the slot_index_exhaustive test.
+const ENTRIES_BY_BUCKET: [usize; 21] = {
+ let mut entries = [0; 21];
+ let mut key = 0;
+ loop {
+ let si = SlotIndex::from_index(key);
+ entries[si.bucket_idx] = si.entries;
+ if key == 0 {
+ key = 1;
+ } else if key == (1 << 31) {
+ break;
+ } else {
+ key <<= 1;
+ }
+ }
+ entries
+};
+
+impl SlotIndex {
+ // This unpacks a flat u32 index into identifying which bucket it belongs to and the offset
+ // within that bucket. As noted in the VecCache docs, buckets double in size with each index.
+ // Typically that would mean 31 buckets (2^0 + 2^1 ... + 2^31 = u32::MAX - 1), but to reduce
+ // the size of the VecCache struct and avoid uselessly small allocations, we instead have the
+ // first bucket have 2**12 entries. To simplify the math, the second bucket also 2**12 entries,
+ // and buckets double from there.
+ //
+ // We assert that [0, 2**32 - 1] uniquely map through this function to individual, consecutive
+ // slots (see `slot_index_exhaustive` in tests).
+ #[inline]
+ const fn from_index(idx: u32) -> Self {
+ let mut bucket = match idx.checked_ilog2() {
+ Some(x) => x as usize,
+ None => 0,
+ };
+ let entries;
+ let running_sum;
+ if bucket <= 11 {
+ entries = 1 << 12;
+ running_sum = 0;
+ bucket = 0;
+ } else {
+ entries = 1 << bucket;
+ running_sum = entries;
+ bucket = bucket - 11;
+ }
+ SlotIndex { bucket_idx: bucket, entries, index_in_bucket: idx as usize - running_sum }
+ }
+
+ // SAFETY: Buckets must be managed solely by functions here (i.e., get/put on SlotIndex) and
+ // `self` comes from SlotIndex::from_index
+ #[inline]
+ unsafe fn get<V: Copy>(&self, buckets: &[AtomicPtr<Slot<V>>; 21]) -> Option<(V, u32)> {
+ // SAFETY: `bucket_idx` is ilog2(u32).saturating_sub(11), which is at most 21, i.e.,
+ // in-bounds of buckets. See `from_index` for computation.
+ let bucket = unsafe { buckets.get_unchecked(self.bucket_idx) };
+ let ptr = bucket.load(Ordering::Acquire);
+ // Bucket is not yet initialized: then we obviously won't find this entry in that bucket.
+ if ptr.is_null() {
+ return None;
+ }
+ assert!(self.index_in_bucket < self.entries);
+ // SAFETY: `bucket` was allocated (so <= isize in total bytes) to hold `entries`, so this
+ // must be inbounds.
+ let slot = unsafe { ptr.add(self.index_in_bucket) };
+
+ // SAFETY: initialized bucket has zeroed all memory within the bucket, so we are valid for
+ // AtomicU32 access.
+ let index_and_lock = unsafe { &(*slot).index_and_lock };
+ let current = index_and_lock.load(Ordering::Acquire);
+ let index = match current {
+ 0 => return None,
+ // Treat "initializing" as actually just not initialized at all.
+ // The only reason this is a separate state is that `complete` calls could race and
+ // we can't allow that, but from load perspective there's no difference.
+ 1 => return None,
+ _ => current - 2,
+ };
+
+ // SAFETY:
+ // * slot is a valid pointer (buckets are always valid for the index we get).
+ // * value is initialized since we saw a >= 2 index above.
+ // * `V: Copy`, so safe to read.
+ let value = unsafe { (*slot).value };
+ Some((value, index))
+ }
+
+ fn bucket_ptr<V>(&self, bucket: &AtomicPtr<Slot<V>>) -> *mut Slot<V> {
+ let ptr = bucket.load(Ordering::Acquire);
+ if ptr.is_null() { self.initialize_bucket(bucket) } else { ptr }
+ }
+
+ #[cold]
+ fn initialize_bucket<V>(&self, bucket: &AtomicPtr<Slot<V>>) -> *mut Slot<V> {
+ static LOCK: std::sync::Mutex<()> = std::sync::Mutex::new(());
+
+ // If we are initializing the bucket, then acquire a global lock.
+ //
+ // This path is quite cold, so it's cheap to use a global lock. This ensures that we never
+ // have multiple allocations for the same bucket.
+ let _allocator_guard = LOCK.lock().unwrap_or_else(|e| e.into_inner());
+
+ let ptr = bucket.load(Ordering::Acquire);
+
+ // OK, now under the allocator lock, if we're still null then it's definitely us that will
+ // initialize this bucket.
+ if ptr.is_null() {
+ let bucket_layout =
+ std::alloc::Layout::array::<Slot<V>>(self.entries as usize).unwrap();
+ // This is more of a sanity check -- this code is very cold, so it's safe to pay a
+ // little extra cost here.
+ assert!(bucket_layout.size() > 0);
+ // SAFETY: Just checked that size is non-zero.
+ let allocated = unsafe { std::alloc::alloc_zeroed(bucket_layout).cast::<Slot<V>>() };
+ if allocated.is_null() {
+ std::alloc::handle_alloc_error(bucket_layout);
+ }
+ bucket.store(allocated, Ordering::Release);
+ allocated
+ } else {
+ // Otherwise some other thread initialized this bucket after we took the lock. In that
+ // case, just return early.
+ ptr
+ }
+ }
+
+ /// Returns true if this successfully put into the map.
+ #[inline]
+ fn put<V>(&self, buckets: &[AtomicPtr<Slot<V>>; 21], value: V, extra: u32) -> bool {
+ // SAFETY: `bucket_idx` is ilog2(u32).saturating_sub(11), which is at most 21, i.e.,
+ // in-bounds of buckets.
+ let bucket = unsafe { buckets.get_unchecked(self.bucket_idx) };
+ let ptr = self.bucket_ptr(bucket);
+
+ assert!(self.index_in_bucket < self.entries);
+ // SAFETY: `bucket` was allocated (so <= isize in total bytes) to hold `entries`, so this
+ // must be inbounds.
+ let slot = unsafe { ptr.add(self.index_in_bucket) };
+
+ // SAFETY: initialized bucket has zeroed all memory within the bucket, so we are valid for
+ // AtomicU32 access.
+ let index_and_lock = unsafe { &(*slot).index_and_lock };
+ match index_and_lock.compare_exchange(0, 1, Ordering::AcqRel, Ordering::Acquire) {
+ Ok(_) => {
+ // We have acquired the initialization lock. It is our job to write `value` and
+ // then set the lock to the real index.
+
+ unsafe {
+ (&raw mut (*slot).value).write(value);
+ }
+
+ index_and_lock.store(extra.checked_add(2).unwrap(), Ordering::Release);
+
+ true
+ }
+
+ // Treat "initializing" as the caller's fault. Callers are responsible for ensuring that
+ // there are no races on initialization. In the compiler's current usage for query
+ // caches, that's the "active query map" which ensures each query actually runs once
+ // (even if concurrently started).
+ Err(1) => panic!("caller raced calls to put()"),
+
+ // This slot was already populated. Also ignore, currently this is the same as
+ // "initializing".
+ Err(_) => false,
+ }
+ }
+}
+
+pub struct VecCache<K: Idx, V, I> {
+ // Entries per bucket:
+ // Bucket 0: 4096 2^12
+ // Bucket 1: 4096 2^12
+ // Bucket 2: 8192
+ // Bucket 3: 16384
+ // ...
+ // Bucket 19: 1073741824
+ // Bucket 20: 2147483648
+ // The total number of entries if all buckets are initialized is u32::MAX-1.
+ buckets: [AtomicPtr<Slot<V>>; 21],
+
+ // In the compiler's current usage these are only *read* during incremental and self-profiling.
+ // They are an optimization over iterating the full buckets array.
+ present: [AtomicPtr<Slot<()>>; 21],
+ len: AtomicUsize,
+
+ key: PhantomData<(K, I)>,
+}
+
+impl<K: Idx, V, I> Default for VecCache<K, V, I> {
+ fn default() -> Self {
+ VecCache {
+ buckets: Default::default(),
+ key: PhantomData,
+ len: Default::default(),
+ present: Default::default(),
+ }
+ }
+}
+
+// SAFETY: No access to `V` is made.
+unsafe impl<K: Idx, #[may_dangle] V, I> Drop for VecCache<K, V, I> {
+ fn drop(&mut self) {
+ // We have unique ownership, so no locks etc. are needed. Since `K` and `V` are both `Copy`,
+ // we are also guaranteed to just need to deallocate any large arrays (not iterate over
+ // contents).
+ //
+ // Confirm no need to deallocate invidual entries. Note that `V: Copy` is asserted on
+ // insert/lookup but not necessarily construction, primarily to avoid annoyingly propagating
+ // the bounds into struct definitions everywhere.
+ assert!(!std::mem::needs_drop::<K>());
+ assert!(!std::mem::needs_drop::<V>());
+
+ for (idx, bucket) in self.buckets.iter().enumerate() {
+ let bucket = bucket.load(Ordering::Acquire);
+ if !bucket.is_null() {
+ let layout = std::alloc::Layout::array::<Slot<V>>(ENTRIES_BY_BUCKET[idx]).unwrap();
+ unsafe {
+ std::alloc::dealloc(bucket.cast(), layout);
+ }
+ }
+ }
+
+ for (idx, bucket) in self.present.iter().enumerate() {
+ let bucket = bucket.load(Ordering::Acquire);
+ if !bucket.is_null() {
+ let layout = std::alloc::Layout::array::<Slot<()>>(ENTRIES_BY_BUCKET[idx]).unwrap();
+ unsafe {
+ std::alloc::dealloc(bucket.cast(), layout);
+ }
+ }
+ }
+ }
+}
+
+impl<K, V, I> VecCache<K, V, I>
+where
+ K: Eq + Idx + Copy + Debug,
+ V: Copy,
+ I: Idx + Copy,
+{
+ #[inline(always)]
+ pub fn lookup(&self, key: &K) -> Option<(V, I)> {
+ let key = u32::try_from(key.index()).unwrap();
+ let slot_idx = SlotIndex::from_index(key);
+ match unsafe { slot_idx.get(&self.buckets) } {
+ Some((value, idx)) => Some((value, I::new(idx as usize))),
+ None => None,
+ }
+ }
+
+ #[inline]
+ pub fn complete(&self, key: K, value: V, index: I) {
+ let key = u32::try_from(key.index()).unwrap();
+ let slot_idx = SlotIndex::from_index(key);
+ if slot_idx.put(&self.buckets, value, index.index() as u32) {
+ let present_idx = self.len.fetch_add(1, Ordering::Relaxed);
+ let slot = SlotIndex::from_index(present_idx as u32);
+ // We should always be uniquely putting due to `len` fetch_add returning unique values.
+ assert!(slot.put(&self.present, (), key));
+ }
+ }
+
+ pub fn iter(&self, f: &mut dyn FnMut(&K, &V, I)) {
+ for idx in 0..self.len.load(Ordering::Acquire) {
+ let key = SlotIndex::from_index(idx as u32);
+ match unsafe { key.get(&self.present) } {
+ // This shouldn't happen in our current usage (iter is really only
+ // used long after queries are done running), but if we hit this in practice it's
+ // probably fine to just break early.
+ None => unreachable!(),
+ Some(((), key)) => {
+ let key = K::new(key as usize);
+ // unwrap() is OK: present entries are always written only after we put the real
+ // entry.
+ let value = self.lookup(&key).unwrap();
+ f(&key, &value.0, value.1);
+ }
+ }
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests;
diff --git a/compiler/rustc_data_structures/src/vec_cache/tests.rs b/compiler/rustc_data_structures/src/vec_cache/tests.rs
new file mode 100644
index 0000000..a05f274
--- /dev/null
+++ b/compiler/rustc_data_structures/src/vec_cache/tests.rs
@@ -0,0 +1,95 @@
+use super::*;
+
+#[test]
+#[cfg(not(miri))]
+fn vec_cache_empty() {
+ let cache: VecCache<u32, u32, u32> = VecCache::default();
+ for key in 0..u32::MAX {
+ assert!(cache.lookup(&key).is_none());
+ }
+}
+
+#[test]
+fn vec_cache_insert_and_check() {
+ let cache: VecCache<u32, u32, u32> = VecCache::default();
+ cache.complete(0, 1, 2);
+ assert_eq!(cache.lookup(&0), Some((1, 2)));
+}
+
+#[test]
+fn sparse_inserts() {
+ let cache: VecCache<u32, u8, u32> = VecCache::default();
+ let end = if cfg!(target_pointer_width = "64") && cfg!(target_os = "linux") {
+ // For paged memory, 64-bit systems we should be able to sparsely allocate all of the pages
+ // needed for these inserts cheaply (without needing to actually have gigabytes of resident
+ // memory).
+ 31
+ } else {
+ // Otherwise, still run the test but scaled back:
+ //
+ // Each slot is 5 bytes, so 2^25 entries (on non-virtual memory systems, like e.g. Windows) will
+ // mean 160 megabytes of allocated memory. Going beyond that is probably not reasonable for
+ // tests.
+ 25
+ };
+ for shift in 0..end {
+ let key = 1u32 << shift;
+ cache.complete(key, shift, key);
+ assert_eq!(cache.lookup(&key), Some((shift, key)));
+ }
+}
+
+#[test]
+fn concurrent_stress_check() {
+ let cache: VecCache<u32, u32, u32> = VecCache::default();
+ std::thread::scope(|s| {
+ for idx in 0..100 {
+ let cache = &cache;
+ s.spawn(move || {
+ cache.complete(idx, idx, idx);
+ });
+ }
+ });
+
+ for idx in 0..100 {
+ assert_eq!(cache.lookup(&idx), Some((idx, idx)));
+ }
+}
+
+#[test]
+fn slot_entries_table() {
+ assert_eq!(ENTRIES_BY_BUCKET, [
+ 4096, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304,
+ 8388608, 16777216, 33554432, 67108864, 134217728, 268435456, 536870912, 1073741824,
+ 2147483648
+ ]);
+}
+
+#[test]
+#[cfg(not(miri))]
+fn slot_index_exhaustive() {
+ let mut buckets = [0u32; 21];
+ for idx in 0..=u32::MAX {
+ buckets[SlotIndex::from_index(idx).bucket_idx] += 1;
+ }
+ let mut prev = None::<SlotIndex>;
+ for idx in 0..=u32::MAX {
+ let slot_idx = SlotIndex::from_index(idx);
+ if let Some(p) = prev {
+ if p.bucket_idx == slot_idx.bucket_idx {
+ assert_eq!(p.index_in_bucket + 1, slot_idx.index_in_bucket);
+ } else {
+ assert_eq!(slot_idx.index_in_bucket, 0);
+ }
+ } else {
+ assert_eq!(idx, 0);
+ assert_eq!(slot_idx.index_in_bucket, 0);
+ assert_eq!(slot_idx.bucket_idx, 0);
+ }
+
+ assert_eq!(buckets[slot_idx.bucket_idx], slot_idx.entries as u32);
+ assert_eq!(ENTRIES_BY_BUCKET[slot_idx.bucket_idx], slot_idx.entries, "{}", idx);
+
+ prev = Some(slot_idx);
+ }
+}
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index 04ac789..9178646 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -1303,7 +1303,7 @@ fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
fragment.make_trait_items()
}
fn walk_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
- walk_flat_map_item(visitor, self.wrapped)
+ walk_flat_map_assoc_item(visitor, self.wrapped, AssocCtxt::Trait)
}
fn is_mac_call(&self) -> bool {
matches!(self.wrapped.kind, AssocItemKind::MacCall(..))
@@ -1344,7 +1344,7 @@ fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
fragment.make_impl_items()
}
fn walk_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
- walk_flat_map_item(visitor, self.wrapped)
+ walk_flat_map_assoc_item(visitor, self.wrapped, AssocCtxt::Impl)
}
fn is_mac_call(&self) -> bool {
matches!(self.wrapped.kind, AssocItemKind::MacCall(..))
diff --git a/compiler/rustc_expand/src/placeholders.rs b/compiler/rustc_expand/src/placeholders.rs
index 610c69e..90206b1 100644
--- a/compiler/rustc_expand/src/placeholders.rs
+++ b/compiler/rustc_expand/src/placeholders.rs
@@ -286,7 +286,7 @@ fn flat_map_assoc_item(
AssocCtxt::Impl => it.make_impl_items(),
}
}
- _ => walk_flat_map_item(self, item),
+ _ => walk_flat_map_assoc_item(self, item, ctxt),
}
}
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index a4820ba..ce2b47e 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -838,7 +838,7 @@ pub struct BuiltinAttribute {
template!(Word), WarnFollowing, EncodeCrossCrate::No, IMPL_DETAIL,
),
rustc_attr!(
- rustc_const_stable_intrinsic, Normal,
+ rustc_intrinsic_const_stable_indirect, Normal,
template!(Word), WarnFollowing, EncodeCrossCrate::No, IMPL_DETAIL,
),
gated!(
diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs
index 9f42d3e..5d27b8f 100644
--- a/compiler/rustc_feature/src/lib.rs
+++ b/compiler/rustc_feature/src/lib.rs
@@ -74,14 +74,19 @@ pub fn from_environment(krate: Option<&str>) -> Self {
// Returns whether `krate` should be counted as unstable
let is_unstable_crate =
|var: &str| krate.is_some_and(|name| var.split(',').any(|new_krate| new_krate == name));
- // `true` if we should enable unstable features for bootstrapping.
- let bootstrap =
- std::env::var("RUSTC_BOOTSTRAP").is_ok_and(|var| var == "1" || is_unstable_crate(&var));
- match (disable_unstable_features, bootstrap) {
- (_, true) => UnstableFeatures::Cheat,
- (true, _) => UnstableFeatures::Disallow,
- (false, _) => UnstableFeatures::Allow,
+
+ let bootstrap = std::env::var("RUSTC_BOOTSTRAP").ok();
+ if let Some(val) = bootstrap.as_deref() {
+ match val {
+ val if val == "1" || is_unstable_crate(val) => return UnstableFeatures::Cheat,
+ // Hypnotize ourselves so that we think we are a stable compiler and thus don't
+ // allow any unstable features.
+ "-1" => return UnstableFeatures::Disallow,
+ _ => {}
+ }
}
+
+ if disable_unstable_features { UnstableFeatures::Disallow } else { UnstableFeatures::Allow }
}
pub fn is_nightly_build(&self) -> bool {
diff --git a/compiler/rustc_feature/src/tests.rs b/compiler/rustc_feature/src/tests.rs
index 50433e4..cc0e1f3 100644
--- a/compiler/rustc_feature/src/tests.rs
+++ b/compiler/rustc_feature/src/tests.rs
@@ -18,6 +18,16 @@ fn rustc_bootstrap_parsing() {
assert!(!is_bootstrap("x,y,z", Some("a")));
assert!(!is_bootstrap("x,y,z", None));
- // this is technically a breaking change, but there are no stability guarantees for RUSTC_BOOTSTRAP
+ // `RUSTC_BOOTSTRAP=0` is not recognized.
assert!(!is_bootstrap("0", None));
+
+ // `RUSTC_BOOTSTRAP=-1` is force-stable, no unstable features allowed.
+ let is_force_stable = |krate| {
+ std::env::set_var("RUSTC_BOOTSTRAP", "-1");
+ matches!(UnstableFeatures::from_environment(krate), UnstableFeatures::Disallow)
+ };
+ assert!(is_force_stable(None));
+ // Does not support specifying any crate.
+ assert!(is_force_stable(Some("x")));
+ assert!(is_force_stable(Some("x,y,z")));
}
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 8326d00..a67a577 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -54,7 +54,7 @@ pub struct EnabledLangFeature {
pub stable_since: Option<Symbol>,
}
-/// Information abhout an enabled library feature.
+/// Information about an enabled library feature.
#[derive(Debug, Copy, Clone)]
pub struct EnabledLibFeature {
pub gate_name: Symbol,
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index 6e8ba51..64a30e6 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -448,6 +448,11 @@
.note = add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate
.feedback_note = we are soliciting feedback, see issue #121718 <https://github.com/rust-lang/rust/issues/121718> for more information
+hir_analysis_rpitit_refined_lifetimes = impl trait in impl method captures fewer lifetimes than in trait
+ .suggestion = modify the `use<..>` bound to capture the same lifetimes that the trait does
+ .note = add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate
+ .feedback_note = we are soliciting feedback, see issue #121718 <https://github.com/rust-lang/rust/issues/121718> for more information
+
hir_analysis_self_in_impl_self =
`Self` is not valid in the self type of an impl block
.note = replace `Self` with a different type
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 3080d8b..cf8c81c 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -21,8 +21,7 @@
use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
use rustc_middle::ty::util::{Discr, InspectCoroutineFields, IntTypeExt};
use rustc_middle::ty::{
- AdtDef, GenericArgKind, ParamEnv, RegionKind, TypeSuperVisitable, TypeVisitable,
- TypeVisitableExt,
+ AdtDef, GenericArgKind, RegionKind, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
};
use rustc_session::lint::builtin::UNINHABITED_STATIC;
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
@@ -114,15 +113,15 @@ fn allowed_union_field<'tcx>(
}
}
- let param_env = tcx.param_env(item_def_id);
+ let typing_env = ty::TypingEnv::non_body_analysis(tcx, item_def_id);
for field in &def.non_enum_variant().fields {
- let Ok(field_ty) = tcx.try_normalize_erasing_regions(param_env, field.ty(tcx, args))
+ let Ok(field_ty) = tcx.try_normalize_erasing_regions(typing_env, field.ty(tcx, args))
else {
tcx.dcx().span_delayed_bug(span, "could not normalize field type");
continue;
};
- if !allowed_union_field(field_ty, tcx, param_env) {
+ if !allowed_union_field(field_ty, tcx, typing_env.param_env) {
let (field_span, ty_span) = match tcx.hir().get_if_local(field.did) {
// We are currently checking the type this field came from, so it must be local.
Some(Node::Field(field)) => (field.span, field.ty.span),
@@ -137,7 +136,7 @@ fn allowed_union_field<'tcx>(
note: (),
});
return false;
- } else if field_ty.needs_drop(tcx, param_env) {
+ } else if field_ty.needs_drop(tcx, typing_env) {
// This should never happen. But we can get here e.g. in case of name resolution errors.
tcx.dcx()
.span_delayed_bug(span, "we should never accept maybe-dropping union fields");
@@ -158,7 +157,7 @@ fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) {
// reason to allow any statics to be uninhabited.
let ty = tcx.type_of(def_id).instantiate_identity();
let span = tcx.def_span(def_id);
- let layout = match tcx.layout_of(ParamEnv::reveal_all().and(ty)) {
+ let layout = match tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)) {
Ok(l) => l,
// Foreign statics that overflow their allowed size should emit an error
Err(LayoutError::SizeOverflow(_))
@@ -237,7 +236,10 @@ pub(super) fn check_opaque_for_cycles<'tcx>(
// And also look for cycle errors in the layout of coroutines.
if let Err(&LayoutError::Cycle(guar)) =
- tcx.layout_of(tcx.param_env(def_id).and(Ty::new_opaque(tcx, def_id.to_def_id(), args)))
+ tcx.layout_of(
+ ty::TypingEnv::post_analysis(tcx, def_id.to_def_id())
+ .as_query_input(Ty::new_opaque(tcx, def_id.to_def_id(), args)),
+ )
{
return Err(guar);
}
@@ -1307,8 +1309,8 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
// "known" respecting #[non_exhaustive] attributes.
let field_infos = adt.all_fields().map(|field| {
let ty = field.ty(tcx, GenericArgs::identity_for_item(tcx, field.did));
- let param_env = tcx.param_env(field.did);
- let layout = tcx.layout_of(param_env.and(ty));
+ let typing_env = ty::TypingEnv::non_body_analysis(tcx, field.did);
+ let layout = tcx.layout_of(typing_env.as_query_input(ty));
// We are currently checking the type this field came from, so it must be local
let span = tcx.hir().span_if_local(field.did).unwrap();
let trivial = layout.is_ok_and(|layout| layout.is_1zst());
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
index 646c104..25ba52b 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
@@ -1,6 +1,7 @@
+use itertools::Itertools as _;
use rustc_data_structures::fx::FxIndexSet;
use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_lint_defs::builtin::{REFINING_IMPL_TRAIT_INTERNAL, REFINING_IMPL_TRAIT_REACHABLE};
@@ -75,6 +76,8 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>(
let mut trait_bounds = vec![];
// Bounds that we find on the RPITITs in the impl signature.
let mut impl_bounds = vec![];
+ // Pairs of trait and impl opaques.
+ let mut pairs = vec![];
for trait_projection in collector.types.into_iter().rev() {
let impl_opaque_args = trait_projection.args.rebase_onto(tcx, trait_m.def_id, impl_m_args);
@@ -121,6 +124,8 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>(
tcx.explicit_item_bounds(impl_opaque.def_id)
.iter_instantiated_copied(tcx, impl_opaque.args),
));
+
+ pairs.push((trait_projection, impl_opaque));
}
let hybrid_preds = tcx
@@ -212,6 +217,39 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>(
return;
}
}
+
+ // Make sure that the RPITIT doesn't capture fewer regions than
+ // the trait definition. We hard-error if it captures *more*, since that
+ // is literally unrepresentable in the type system; however, we may be
+ // promising stronger outlives guarantees if we capture *fewer* regions.
+ for (trait_projection, impl_opaque) in pairs {
+ let impl_variances = tcx.variances_of(impl_opaque.def_id);
+ let impl_captures: FxIndexSet<_> = impl_opaque
+ .args
+ .iter()
+ .zip_eq(impl_variances)
+ .filter(|(_, v)| **v == ty::Invariant)
+ .map(|(arg, _)| arg)
+ .collect();
+
+ let trait_variances = tcx.variances_of(trait_projection.def_id);
+ let mut trait_captures = FxIndexSet::default();
+ for (arg, variance) in trait_projection.args.iter().zip_eq(trait_variances) {
+ if *variance != ty::Invariant {
+ continue;
+ }
+ arg.visit_with(&mut CollectParams { params: &mut trait_captures });
+ }
+
+ if !trait_captures.iter().all(|arg| impl_captures.contains(arg)) {
+ report_mismatched_rpitit_captures(
+ tcx,
+ impl_opaque.def_id.expect_local(),
+ trait_captures,
+ is_internal,
+ );
+ }
+ }
}
struct ImplTraitInTraitCollector<'tcx> {
@@ -342,3 +380,65 @@ fn fold_binder<T>(&mut self, t: ty::Binder<'tcx, T>) -> ty::Binder<'tcx, T>
self.tcx.anonymize_bound_vars(t)
}
}
+
+struct CollectParams<'a, 'tcx> {
+ params: &'a mut FxIndexSet<ty::GenericArg<'tcx>>,
+}
+impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for CollectParams<'_, 'tcx> {
+ fn visit_ty(&mut self, ty: Ty<'tcx>) {
+ if let ty::Param(_) = ty.kind() {
+ self.params.insert(ty.into());
+ } else {
+ ty.super_visit_with(self);
+ }
+ }
+ fn visit_region(&mut self, r: ty::Region<'tcx>) {
+ match r.kind() {
+ ty::ReEarlyParam(_) | ty::ReLateParam(_) => {
+ self.params.insert(r.into());
+ }
+ _ => {}
+ }
+ }
+ fn visit_const(&mut self, ct: ty::Const<'tcx>) {
+ if let ty::ConstKind::Param(_) = ct.kind() {
+ self.params.insert(ct.into());
+ } else {
+ ct.super_visit_with(self);
+ }
+ }
+}
+
+fn report_mismatched_rpitit_captures<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ impl_opaque_def_id: LocalDefId,
+ mut trait_captured_args: FxIndexSet<ty::GenericArg<'tcx>>,
+ is_internal: bool,
+) {
+ let Some(use_bound_span) =
+ tcx.hir_node_by_def_id(impl_opaque_def_id).expect_opaque_ty().bounds.iter().find_map(
+ |bound| match *bound {
+ rustc_hir::GenericBound::Use(_, span) => Some(span),
+ hir::GenericBound::Trait(_) | hir::GenericBound::Outlives(_) => None,
+ },
+ )
+ else {
+ // I have no idea when you would ever undercapture without a `use<..>`.
+ tcx.dcx().delayed_bug("expected use<..> to undercapture in an impl opaque");
+ return;
+ };
+
+ trait_captured_args
+ .sort_by_cached_key(|arg| !matches!(arg.unpack(), ty::GenericArgKind::Lifetime(_)));
+ let suggestion = format!("use<{}>", trait_captured_args.iter().join(", "));
+
+ tcx.emit_node_span_lint(
+ if is_internal { REFINING_IMPL_TRAIT_INTERNAL } else { REFINING_IMPL_TRAIT_REACHABLE },
+ tcx.local_def_id_to_hir_id(impl_opaque_def_id),
+ use_bound_span,
+ crate::errors::ReturnPositionImplTraitInTraitRefinedLifetimes {
+ suggestion_span: use_bound_span,
+ suggestion,
+ },
+ );
+}
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index cb954b0..3e33120 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -109,9 +109,8 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -
| sym::three_way_compare
| sym::discriminant_value
| sym::type_id
- | sym::likely
- | sym::unlikely
| sym::select_unpredictable
+ | sym::cold_path
| sym::ptr_guaranteed_cmp
| sym::minnumf16
| sym::minnumf32
@@ -489,9 +488,8 @@ 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], tcx.types.unit),
- sym::likely => (0, 0, vec![tcx.types.bool], tcx.types.bool),
- sym::unlikely => (0, 0, vec![tcx.types.bool], tcx.types.bool),
sym::select_unpredictable => (1, 0, vec![tcx.types.bool, param(0), param(0)], param(0)),
+ sym::cold_path => (0, 0, vec![], tcx.types.unit),
sym::read_via_copy => (1, 0, vec![Ty::new_imm_ptr(tcx, param(0))], param(0)),
sym::write_via_move => {
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 1802f00..20bc34b 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -1126,7 +1126,7 @@ fn check_type_defn<'tcx>(
let ty = tcx.type_of(variant.tail().did).instantiate_identity();
let ty = tcx.erase_regions(ty);
assert!(!ty.has_infer());
- ty.needs_drop(tcx, tcx.param_env(item.owner_id))
+ ty.needs_drop(tcx, wfcx.infcx.typing_env(wfcx.param_env))
}
};
// All fields (except for possibly the last) should be sized.
@@ -1281,7 +1281,8 @@ fn check_item_type(
UnsizedHandling::Forbid => true,
UnsizedHandling::Allow => false,
UnsizedHandling::AllowIfForeignTail => {
- let tail = tcx.struct_tail_for_codegen(item_ty, wfcx.param_env);
+ let tail =
+ tcx.struct_tail_for_codegen(item_ty, wfcx.infcx.typing_env(wfcx.param_env));
!matches!(tail.kind(), ty::Foreign(_))
}
};
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
index 5ff5237..c2ad618 100644
--- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -259,7 +259,9 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<()
let ty_a = field.ty(tcx, args_a);
let ty_b = field.ty(tcx, args_b);
- if let Ok(layout) = tcx.layout_of(param_env.and(ty_a)) {
+ if let Ok(layout) =
+ tcx.layout_of(infcx.typing_env(param_env).as_query_input(ty_a))
+ {
if layout.is_1zst() {
// ignore 1-ZST fields
return false;
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index cc55f57..b4b3ef3 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -177,6 +177,7 @@ enum Scope<'a> {
LateBoundary {
s: ScopeRef<'a>,
what: &'static str,
+ deny_late_regions: bool,
},
Root {
@@ -234,9 +235,11 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
.field("s", &"..")
.finish(),
Scope::TraitRefBoundary { s: _ } => f.debug_struct("TraitRefBoundary").finish(),
- Scope::LateBoundary { s: _, what } => {
- f.debug_struct("LateBoundary").field("what", what).finish()
- }
+ Scope::LateBoundary { s: _, what, deny_late_regions } => f
+ .debug_struct("LateBoundary")
+ .field("what", what)
+ .field("deny_late_regions", deny_late_regions)
+ .finish(),
Scope::Root { opt_parent_item } => {
f.debug_struct("Root").field("opt_parent_item", &opt_parent_item).finish()
}
@@ -573,17 +576,11 @@ fn visit_opaque_ty(&mut self, opaque: &'tcx rustc_hir::OpaqueTy<'tcx>) {
// give, we will reverse the IndexMap after early captures.
let mut late_depth = 0;
let mut scope = self.scope;
- let mut crossed_late_boundary = None;
let mut opaque_capture_scopes = vec![(opaque.def_id, &captures)];
loop {
match *scope {
Scope::Binder { ref bound_vars, scope_type, s, .. } => {
for (&original_lifetime, &def) in bound_vars.iter().rev() {
- if let ResolvedArg::LateBound(..) = def
- && crossed_late_boundary.is_some()
- {
- continue;
- }
if let DefKind::LifetimeParam = self.tcx.def_kind(original_lifetime) {
let def = def.shifted(late_depth);
let ident = lifetime_ident(original_lifetime);
@@ -624,12 +621,8 @@ fn visit_opaque_ty(&mut self, opaque: &'tcx rustc_hir::OpaqueTy<'tcx>) {
Scope::ObjectLifetimeDefault { s, .. }
| Scope::Supertrait { s, .. }
- | Scope::TraitRefBoundary { s, .. } => {
- scope = s;
- }
-
- Scope::LateBoundary { s, what, .. } => {
- crossed_late_boundary = Some(what);
+ | Scope::TraitRefBoundary { s, .. }
+ | Scope::LateBoundary { s, .. } => {
scope = s;
}
}
@@ -640,7 +633,16 @@ fn visit_opaque_ty(&mut self, opaque: &'tcx rustc_hir::OpaqueTy<'tcx>) {
let scope = Scope::Opaque { captures: &captures, def_id: opaque.def_id, s: self.scope };
self.with(scope, |this| {
let scope = Scope::TraitRefBoundary { s: this.scope };
- this.with(scope, |this| intravisit::walk_opaque_ty(this, opaque))
+ this.with(scope, |this| {
+ let scope = Scope::LateBoundary {
+ s: this.scope,
+ what: "nested `impl Trait`",
+ // We can capture late-bound regions; we just don't duplicate
+ // lifetime or const params, so we can't allow those.
+ deny_late_regions: false,
+ };
+ this.with(scope, |this| intravisit::walk_opaque_ty(this, opaque))
+ })
});
let captures = captures.into_inner().into_iter().collect();
@@ -997,9 +999,12 @@ fn visit_poly_trait_ref(&mut self, trait_ref: &'tcx hir::PolyTraitRef<'tcx>) {
}
fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) {
- self.with(Scope::LateBoundary { s: self.scope, what: "constant" }, |this| {
- intravisit::walk_anon_const(this, c);
- });
+ self.with(
+ Scope::LateBoundary { s: self.scope, what: "constant", deny_late_regions: true },
+ |this| {
+ intravisit::walk_anon_const(this, c);
+ },
+ );
}
fn visit_generic_param(&mut self, p: &'tcx GenericParam<'tcx>) {
@@ -1291,8 +1296,10 @@ fn resolve_lifetime_ref(
scope = s;
}
- Scope::LateBoundary { s, what } => {
- crossed_late_boundary = Some(what);
+ Scope::LateBoundary { s, what, deny_late_regions } => {
+ if deny_late_regions {
+ crossed_late_boundary = Some(what);
+ }
scope = s;
}
}
@@ -1508,7 +1515,7 @@ fn resolve_type_ref(&mut self, param_def_id: LocalDefId, hir_id: HirId) {
scope = s;
}
- Scope::LateBoundary { s, what } => {
+ Scope::LateBoundary { s, what, deny_late_regions: _ } => {
crossed_late_boundary = Some(what);
scope = s;
}
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index a92a5e4..07d3273 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -1153,6 +1153,16 @@ pub(crate) struct ReturnPositionImplTraitInTraitRefined<'tcx> {
pub return_ty: Ty<'tcx>,
}
+#[derive(LintDiagnostic)]
+#[diag(hir_analysis_rpitit_refined_lifetimes)]
+#[note]
+#[note(hir_analysis_feedback_note)]
+pub(crate) struct ReturnPositionImplTraitInTraitRefinedLifetimes {
+ #[suggestion(applicability = "maybe-incorrect", code = "{suggestion}")]
+ pub suggestion_span: Span,
+ pub suggestion: String,
+}
+
#[derive(Diagnostic)]
#[diag(hir_analysis_inherent_ty_outside, code = E0390)]
#[help]
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs
index 92f38a7..3947193 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs
@@ -3,7 +3,7 @@
use rustc_hir::{self as hir, HirId};
use rustc_middle::bug;
use rustc_middle::ty::layout::LayoutError;
-use rustc_middle::ty::{self, ParamEnv, TyCtxt};
+use rustc_middle::ty::{self, TyCtxt};
use crate::errors;
@@ -130,7 +130,7 @@ fn is_valid_cmse_inputs<'tcx>(
let fn_sig = tcx.instantiate_bound_regions_with_erased(fn_sig);
for (index, ty) in fn_sig.inputs().iter().enumerate() {
- let layout = tcx.layout_of(ParamEnv::reveal_all().and(*ty))?;
+ let layout = tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(*ty))?;
let align = layout.layout.align().abi.bytes();
let size = layout.layout.size().bytes();
@@ -158,8 +158,10 @@ fn is_valid_cmse_output<'tcx>(
// this type is only used for layout computation, which does not rely on regions
let fn_sig = tcx.instantiate_bound_regions_with_erased(fn_sig);
+ let typing_env = ty::TypingEnv::fully_monomorphized();
+
let mut ret_ty = fn_sig.output();
- let layout = tcx.layout_of(ParamEnv::reveal_all().and(ret_ty))?;
+ let layout = tcx.layout_of(typing_env.as_query_input(ret_ty))?;
let size = layout.layout.size().bytes();
if size <= 4 {
@@ -182,7 +184,7 @@ fn is_valid_cmse_output<'tcx>(
for variant_def in adt_def.variants() {
for field_def in variant_def.fields.iter() {
let ty = field_def.ty(tcx, args);
- let layout = tcx.layout_of(ParamEnv::reveal_all().and(ty))?;
+ let layout = tcx.layout_of(typing_env.as_query_input(ty))?;
if !layout.layout.is_1zst() {
ret_ty = ty;
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 3549935..1610848 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -2357,8 +2357,10 @@ fn report_private_fields(
// Only assoc fns that return `Self`
let fn_sig = self.tcx.fn_sig(item.def_id).skip_binder();
let ret_ty = fn_sig.output();
- let ret_ty =
- self.tcx.normalize_erasing_late_bound_regions(self.param_env, ret_ty);
+ let ret_ty = self.tcx.normalize_erasing_late_bound_regions(
+ self.typing_env(self.param_env),
+ ret_ty,
+ );
if !self.can_eq(self.param_env, ret_ty, adt_ty) {
return None;
}
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 919e837..c4c4c2f 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -2648,15 +2648,7 @@ pub(crate) fn suggest_deref_or_ref(
}
let make_sugg = |expr: &Expr<'_>, span: Span, sugg: &str| {
- let needs_parens = match expr.kind {
- // parenthesize if needed (Issue #46756)
- hir::ExprKind::Cast(_, _) | hir::ExprKind::Binary(_, _, _) => true,
- // parenthesize borrows of range literals (Issue #54505)
- _ if is_range_literal(expr) => true,
- _ => false,
- };
-
- if needs_parens {
+ if self.needs_parentheses(expr) {
(
vec![
(span.shrink_to_lo(), format!("{prefix}{sugg}(")),
@@ -2869,6 +2861,19 @@ pub(crate) fn suggest_deref_or_ref(
return None;
}
+ if self.needs_parentheses(expr) {
+ return Some((
+ vec![
+ (span, format!("{suggestion}(")),
+ (expr.span.shrink_to_hi(), ")".to_string()),
+ ],
+ message,
+ Applicability::MachineApplicable,
+ true,
+ false,
+ ));
+ }
+
return Some((
vec![(span, suggestion)],
message,
@@ -2897,6 +2902,16 @@ fn is_else_if_block(&self, expr: &hir::Expr<'_>) -> bool {
false
}
+ fn needs_parentheses(&self, expr: &hir::Expr<'_>) -> bool {
+ match expr.kind {
+ // parenthesize if needed (Issue #46756)
+ hir::ExprKind::Cast(_, _) | hir::ExprKind::Binary(_, _, _) => true,
+ // parenthesize borrows of range literals (Issue #54505)
+ _ if is_range_literal(expr) => true,
+ _ => false,
+ }
+ }
+
pub(crate) fn suggest_cast(
&self,
err: &mut Diag<'_>,
diff --git a/compiler/rustc_hir_typeck/src/intrinsicck.rs b/compiler/rustc_hir_typeck/src/intrinsicck.rs
index a754f7f..789530d 100644
--- a/compiler/rustc_hir_typeck/src/intrinsicck.rs
+++ b/compiler/rustc_hir_typeck/src/intrinsicck.rs
@@ -46,7 +46,7 @@ pub(crate) fn check_transmute(&self, from: Ty<'tcx>, to: Ty<'tcx>, hir_id: HirId
let span = tcx.hir().span(hir_id);
let normalize = |ty| {
let ty = self.resolve_vars_if_possible(ty);
- self.tcx.normalize_erasing_regions(self.param_env, ty)
+ self.tcx.normalize_erasing_regions(self.typing_env(self.param_env), ty)
};
let from = normalize(from);
let to = normalize(to);
@@ -62,7 +62,7 @@ pub(crate) fn check_transmute(&self, from: Ty<'tcx>, to: Ty<'tcx>, hir_id: HirId
return;
}
- let skel = |ty| SizeSkeleton::compute(ty, tcx, self.param_env);
+ let skel = |ty| SizeSkeleton::compute(ty, tcx, self.typing_env(self.param_env));
let sk_from = skel(from);
let sk_to = skel(to);
trace!(?sk_from, ?sk_to);
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index 175fca3..d50eff0 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -1257,7 +1257,11 @@ fn compute_2229_migrations_for_drop(
) -> Option<FxIndexSet<UpvarMigrationInfo>> {
let ty = self.resolve_vars_if_possible(self.node_ty(var_hir_id));
- if !ty.has_significant_drop(self.tcx, self.tcx.param_env(closure_def_id)) {
+ // FIXME(#132279): Using `non_body_analysis` here feels wrong.
+ if !ty.has_significant_drop(
+ self.tcx,
+ ty::TypingEnv::non_body_analysis(self.tcx, closure_def_id),
+ ) {
debug!("does not have significant drop");
return None;
}
@@ -1535,8 +1539,13 @@ fn has_significant_drop_outside_of_captures(
base_path_ty: Ty<'tcx>,
captured_by_move_projs: Vec<&[Projection<'tcx>]>,
) -> bool {
- let needs_drop =
- |ty: Ty<'tcx>| ty.has_significant_drop(self.tcx, self.tcx.param_env(closure_def_id));
+ // FIXME(#132279): Using `non_body_analysis` here feels wrong.
+ let needs_drop = |ty: Ty<'tcx>| {
+ ty.has_significant_drop(
+ self.tcx,
+ ty::TypingEnv::non_body_analysis(self.tcx, closure_def_id),
+ )
+ };
let is_drop_defined_for_ty = |ty: Ty<'tcx>| {
let drop_trait = self.tcx.require_lang_item(hir::LangItem::Drop, Some(closure_span));
diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index 391e640..8694800 100644
--- a/compiler/rustc_hir_typeck/src/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -881,6 +881,8 @@ fn cx(&self) -> TyCtxt<'tcx> {
}
fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
- self.tcx.try_normalize_erasing_regions(self.param_env, ct).unwrap_or(ct)
+ self.tcx
+ .try_normalize_erasing_regions(ty::TypingEnv::from_param_env(self.param_env), ct)
+ .unwrap_or(ct)
}
}
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 12df4a1..b29dc7f 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -38,7 +38,8 @@
use rustc_middle::ty::visit::TypeVisitableExt;
use rustc_middle::ty::{
self, ConstVid, FloatVid, GenericArg, GenericArgKind, GenericArgs, GenericArgsRef,
- GenericParamDefKind, InferConst, IntVid, Ty, TyCtxt, TyVid, TypingMode,
+ GenericParamDefKind, InferConst, IntVid, PseudoCanonicalInput, Ty, TyCtxt, TyVid,
+ TypeVisitable, TypingEnv, TypingMode,
};
use rustc_span::Span;
use rustc_span::symbol::Symbol;
@@ -565,6 +566,13 @@ pub fn build_with_canonical<T>(
(infcx, value, args)
}
+ pub fn build_with_typing_env(
+ mut self,
+ TypingEnv { typing_mode, param_env }: TypingEnv<'tcx>,
+ ) -> (InferCtxt<'tcx>, ty::ParamEnv<'tcx>) {
+ (self.build(typing_mode), param_env)
+ }
+
pub fn build(&mut self, typing_mode: TypingMode<'tcx>) -> InferCtxt<'tcx> {
let InferCtxtBuilder { tcx, considering_regions, skip_leak_check, next_trait_solver } =
*self;
@@ -1278,6 +1286,42 @@ pub fn create_next_universe(&self) -> ty::UniverseIndex {
u
}
+ /// Extract [`ty::TypingMode`] of this inference context to get a `TypingEnv`
+ /// which contains the necessary information to use the trait system without
+ /// using canonicalization or carrying this inference context around.
+ pub fn typing_env(&self, param_env: ty::ParamEnv<'tcx>) -> ty::TypingEnv<'tcx> {
+ let typing_mode = match self.typing_mode(param_env) {
+ ty::TypingMode::Coherence => ty::TypingMode::Coherence,
+ // FIXME(#132279): This erases the `defining_opaque_types` as it isn't possible
+ // to handle them without proper canonicalization. This means we may cause cycle
+ // errors and fail to reveal opaques while inside of bodies. We should rename this
+ // function and require explicit comments on all use-sites in the future.
+ ty::TypingMode::Analysis { defining_opaque_types: _ } => {
+ TypingMode::non_body_analysis()
+ }
+ ty::TypingMode::PostAnalysis => ty::TypingMode::PostAnalysis,
+ };
+ ty::TypingEnv { typing_mode, param_env }
+ }
+
+ /// Similar to [`Self::canonicalize_query`], except that it returns
+ /// a [`PseudoCanonicalInput`] and requires both the `value` and the
+ /// `param_env` to not contain any inference variables or placeholders.
+ pub fn pseudo_canonicalize_query<V>(
+ &self,
+ param_env: ty::ParamEnv<'tcx>,
+ value: V,
+ ) -> PseudoCanonicalInput<'tcx, V>
+ where
+ V: TypeVisitable<TyCtxt<'tcx>>,
+ {
+ debug_assert!(!value.has_infer());
+ debug_assert!(!value.has_placeholders());
+ debug_assert!(!param_env.has_infer());
+ debug_assert!(!param_env.has_placeholders());
+ self.typing_env(param_env).as_query_input(value)
+ }
+
/// The returned function is used in a fast path. If it returns `true` the variable is
/// unchanged, `false` indicates that the status is unknown.
#[inline]
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 130f3cb..f6366ec 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -2485,7 +2485,7 @@ fn variant_find_init_error<'tcx>(
});
// Check if this ADT has a constrained layout (like `NonNull` and friends).
- if let Ok(layout) = cx.tcx.layout_of(cx.param_env.and(ty)) {
+ if let Ok(layout) = cx.tcx.layout_of(cx.typing_env().as_query_input(ty)) {
if let BackendRepr::Scalar(scalar) | BackendRepr::ScalarPair(scalar, _) =
&layout.backend_repr
{
@@ -2521,7 +2521,7 @@ fn ty_find_init_error<'tcx>(
ty: Ty<'tcx>,
init: InitKind,
) -> Option<InitError> {
- let ty = cx.tcx.try_normalize_erasing_regions(cx.param_env, ty).unwrap_or(ty);
+ let ty = cx.tcx.try_normalize_erasing_regions(cx.typing_env(), ty).unwrap_or(ty);
use rustc_type_ir::TyKind::*;
match ty.kind() {
@@ -2568,7 +2568,7 @@ fn ty_find_init_error<'tcx>(
let definitely_inhabited = match variant
.inhabited_predicate(cx.tcx, *adt_def)
.instantiate(cx.tcx, args)
- .apply_any_module(cx.tcx, cx.param_env)
+ .apply_any_module(cx.tcx, cx.typing_env())
{
// Entirely skip uninhabited variants.
Some(false) => return None,
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index aa7ec26..6eec32b 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -19,7 +19,7 @@
use rustc_middle::middle::privacy::EffectiveVisibilities;
use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout};
use rustc_middle::ty::print::{PrintError, PrintTraitRefExt as _, Printer, with_no_trimmed_paths};
-use rustc_middle::ty::{self, GenericArg, RegisteredTools, Ty, TyCtxt, TypingMode};
+use rustc_middle::ty::{self, GenericArg, RegisteredTools, Ty, TyCtxt, TypingEnv, TypingMode};
use rustc_session::lint::{
BuiltinLintDiag, FutureIncompatibleInfo, Level, Lint, LintBuffer, LintExpectationId, LintId,
};
@@ -708,6 +708,10 @@ pub fn typing_mode(&self) -> TypingMode<'tcx> {
TypingMode::non_body_analysis()
}
+ pub fn typing_env(&self) -> TypingEnv<'tcx> {
+ TypingEnv { typing_mode: self.typing_mode(), param_env: self.param_env }
+ }
+
/// Gets the type-checking results for the current body,
/// or `None` if outside a body.
pub fn maybe_typeck_results(&self) -> Option<&'tcx ty::TypeckResults<'tcx>> {
@@ -906,7 +910,7 @@ pub fn get_associated_type(
.find_by_name_and_kind(tcx, Ident::from_str(name), ty::AssocKind::Type, trait_id)
.and_then(|assoc| {
let proj = Ty::new_projection(tcx, assoc.def_id, [self_ty]);
- tcx.try_normalize_erasing_regions(self.param_env, proj).ok()
+ tcx.try_normalize_erasing_regions(self.typing_env(), proj).ok()
})
}
@@ -1010,10 +1014,10 @@ fn tcx(&self) -> TyCtxt<'tcx> {
}
}
-impl<'tcx> ty::layout::HasParamEnv<'tcx> for LateContext<'tcx> {
+impl<'tcx> ty::layout::HasTypingEnv<'tcx> for LateContext<'tcx> {
#[inline]
- fn param_env(&self) -> ty::ParamEnv<'tcx> {
- self.param_env
+ fn typing_env(&self) -> ty::TypingEnv<'tcx> {
+ self.typing_env()
}
}
diff --git a/compiler/rustc_lint/src/for_loops_over_fallibles.rs b/compiler/rustc_lint/src/for_loops_over_fallibles.rs
index cf68e41..dbc920e 100644
--- a/compiler/rustc_lint/src/for_loops_over_fallibles.rs
+++ b/compiler/rustc_lint/src/for_loops_over_fallibles.rs
@@ -166,7 +166,7 @@ fn suggest_question_mark<'tcx>(
}
let ty = args.type_at(0);
- let infcx = cx.tcx.infer_ctxt().build(cx.typing_mode());
+ let (infcx, param_env) = cx.tcx.infer_ctxt().build_with_typing_env(cx.typing_env());
let ocx = ObligationCtxt::new(&infcx);
let body_def_id = cx.tcx.hir().body_owner_def_id(body_id);
@@ -175,7 +175,7 @@ fn suggest_question_mark<'tcx>(
ocx.register_bound(
cause,
- cx.param_env,
+ param_env,
// Erase any region vids from the type, which may not be resolved
infcx.tcx.erase_regions(ty),
into_iterator_did,
diff --git a/compiler/rustc_lint/src/foreign_modules.rs b/compiler/rustc_lint/src/foreign_modules.rs
index 394ea79..45b1882 100644
--- a/compiler/rustc_lint/src/foreign_modules.rs
+++ b/compiler/rustc_lint/src/foreign_modules.rs
@@ -131,7 +131,7 @@ fn check_foreign_item<'tcx>(&mut self, tcx: TyCtxt<'tcx>, this_fi: hir::ForeignI
// Check that the declarations match.
if !structurally_same_type(
tcx,
- tcx.param_env(this_fi.owner_id),
+ ty::TypingEnv::non_body_analysis(tcx, this_fi.owner_id),
existing_decl_ty,
this_decl_ty,
types::CItemKind::Declaration,
@@ -205,18 +205,18 @@ fn get_relevant_span(tcx: TyCtxt<'_>, fi: hir::OwnerId) -> Span {
/// with the same members (as the declarations shouldn't clash).
fn structurally_same_type<'tcx>(
tcx: TyCtxt<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
a: Ty<'tcx>,
b: Ty<'tcx>,
ckind: types::CItemKind,
) -> bool {
let mut seen_types = UnordSet::default();
- let result = structurally_same_type_impl(&mut seen_types, tcx, param_env, a, b, ckind);
+ let result = structurally_same_type_impl(&mut seen_types, tcx, typing_env, a, b, ckind);
if cfg!(debug_assertions) && result {
// Sanity-check: must have same ABI, size and alignment.
// `extern` blocks cannot be generic, so we'll always get a layout here.
- let a_layout = tcx.layout_of(param_env.and(a)).unwrap();
- let b_layout = tcx.layout_of(param_env.and(b)).unwrap();
+ let a_layout = tcx.layout_of(typing_env.as_query_input(a)).unwrap();
+ let b_layout = tcx.layout_of(typing_env.as_query_input(b)).unwrap();
assert_eq!(a_layout.backend_repr, b_layout.backend_repr);
assert_eq!(a_layout.size, b_layout.size);
assert_eq!(a_layout.align, b_layout.align);
@@ -227,7 +227,7 @@ fn structurally_same_type<'tcx>(
fn structurally_same_type_impl<'tcx>(
seen_types: &mut UnordSet<(Ty<'tcx>, Ty<'tcx>)>,
tcx: TyCtxt<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
a: Ty<'tcx>,
b: Ty<'tcx>,
ckind: types::CItemKind,
@@ -303,7 +303,7 @@ fn structurally_same_type_impl<'tcx>(
structurally_same_type_impl(
seen_types,
tcx,
- param_env,
+ typing_env,
tcx.type_of(a_did).instantiate(tcx, a_gen_args),
tcx.type_of(b_did).instantiate(tcx, b_gen_args),
ckind,
@@ -315,23 +315,23 @@ fn structurally_same_type_impl<'tcx>(
// For arrays, we also check the length.
a_len == b_len
&& structurally_same_type_impl(
- seen_types, tcx, param_env, *a_ty, *b_ty, ckind,
+ seen_types, tcx, typing_env, *a_ty, *b_ty, ckind,
)
}
(Slice(a_ty), Slice(b_ty)) => {
- structurally_same_type_impl(seen_types, tcx, param_env, *a_ty, *b_ty, ckind)
+ structurally_same_type_impl(seen_types, tcx, typing_env, *a_ty, *b_ty, ckind)
}
(RawPtr(a_ty, a_mutbl), RawPtr(b_ty, b_mutbl)) => {
a_mutbl == b_mutbl
&& structurally_same_type_impl(
- seen_types, tcx, param_env, *a_ty, *b_ty, ckind,
+ seen_types, tcx, typing_env, *a_ty, *b_ty, ckind,
)
}
(Ref(_a_region, a_ty, a_mut), Ref(_b_region, b_ty, b_mut)) => {
// For structural sameness, we don't need the region to be same.
a_mut == b_mut
&& structurally_same_type_impl(
- seen_types, tcx, param_env, *a_ty, *b_ty, ckind,
+ seen_types, tcx, typing_env, *a_ty, *b_ty, ckind,
)
}
(FnDef(..), FnDef(..)) => {
@@ -346,12 +346,12 @@ fn structurally_same_type_impl<'tcx>(
(a_sig.abi, a_sig.safety, a_sig.c_variadic)
== (b_sig.abi, b_sig.safety, b_sig.c_variadic)
&& a_sig.inputs().iter().eq_by(b_sig.inputs().iter(), |a, b| {
- structurally_same_type_impl(seen_types, tcx, param_env, *a, *b, ckind)
+ structurally_same_type_impl(seen_types, tcx, typing_env, *a, *b, ckind)
})
&& structurally_same_type_impl(
seen_types,
tcx,
- param_env,
+ typing_env,
a_sig.output(),
b_sig.output(),
ckind,
@@ -379,14 +379,14 @@ fn structurally_same_type_impl<'tcx>(
// An Adt and a primitive or pointer type. This can be FFI-safe if non-null
// enum layout optimisation is being applied.
(Adt(..), _) if is_primitive_or_pointer(b) => {
- if let Some(a_inner) = types::repr_nullable_ptr(tcx, param_env, a, ckind) {
+ if let Some(a_inner) = types::repr_nullable_ptr(tcx, typing_env, a, ckind) {
a_inner == b
} else {
false
}
}
(_, Adt(..)) if is_primitive_or_pointer(a) => {
- if let Some(b_inner) = types::repr_nullable_ptr(tcx, param_env, b, ckind) {
+ if let Some(b_inner) = types::repr_nullable_ptr(tcx, typing_env, b, ckind) {
b_inner == a
} else {
false
diff --git a/compiler/rustc_lint/src/if_let_rescope.rs b/compiler/rustc_lint/src/if_let_rescope.rs
index afcfbeb..0e87466 100644
--- a/compiler/rustc_lint/src/if_let_rescope.rs
+++ b/compiler/rustc_lint/src/if_let_rescope.rs
@@ -368,7 +368,7 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Self::Result {
.cx
.typeck_results()
.expr_ty(expr)
- .has_significant_drop(self.cx.tcx, self.cx.param_env)
+ .has_significant_drop(self.cx.tcx, self.cx.typing_env())
{
return ControlFlow::Break(expr.span);
}
diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs
index 2f338f4..38c38b5 100644
--- a/compiler/rustc_lint/src/internal.rs
+++ b/compiler/rustc_lint/src/internal.rs
@@ -103,7 +103,8 @@ fn typeck_results_of_method_fn<'tcx>(
impl LateLintPass<'_> for QueryStability {
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
let Some((span, def_id, args)) = typeck_results_of_method_fn(cx, expr) else { return };
- if let Ok(Some(instance)) = ty::Instance::try_resolve(cx.tcx, cx.param_env, def_id, args) {
+ if let Ok(Some(instance)) = ty::Instance::try_resolve(cx.tcx, cx.typing_env(), def_id, args)
+ {
let def_id = instance.def_id();
if cx.tcx.has_attr(def_id, sym::rustc_lint_query_instability) {
cx.emit_span_lint(POTENTIAL_QUERY_INSTABILITY, span, QueryInstability {
@@ -544,7 +545,7 @@ fn diagnostic_outside_of_impl<'cx>(
) {
// Is the callee marked with `#[rustc_lint_diagnostics]`?
let Some(inst) =
- ty::Instance::try_resolve(cx.tcx, cx.param_env, def_id, fn_gen_args).ok().flatten()
+ ty::Instance::try_resolve(cx.tcx, cx.typing_env(), def_id, fn_gen_args).ok().flatten()
else {
return;
};
diff --git a/compiler/rustc_lint/src/let_underscore.rs b/compiler/rustc_lint/src/let_underscore.rs
index abee9ee..9e4e833 100644
--- a/compiler/rustc_lint/src/let_underscore.rs
+++ b/compiler/rustc_lint/src/let_underscore.rs
@@ -128,7 +128,7 @@ fn check_local(&mut self, cx: &LateContext<'_>, local: &hir::LetStmt<'_>) {
// If the type has a trivial Drop implementation, then it doesn't
// matter that we drop the value immediately.
- if !ty.needs_drop(cx.tcx, cx.param_env) {
+ if !ty.needs_drop(cx.tcx, cx.typing_env()) {
return;
}
// Lint for patterns like `mutex.lock()`, which returns `Result<MutexGuard, _>` as well.
diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs
index cf25ec9..36b1ff5 100644
--- a/compiler/rustc_lint/src/non_fmt_panic.rs
+++ b/compiler/rustc_lint/src/non_fmt_panic.rs
@@ -157,15 +157,17 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
Some(ty_def) if cx.tcx.is_lang_item(ty_def.did(), LangItem::String),
);
- let infcx = cx.tcx.infer_ctxt().build(cx.typing_mode());
+ let (infcx, param_env) = cx.tcx.infer_ctxt().build_with_typing_env(cx.typing_env());
let suggest_display = is_str
- || cx.tcx.get_diagnostic_item(sym::Display).is_some_and(|t| {
- infcx.type_implements_trait(t, [ty], cx.param_env).may_apply()
- });
+ || cx
+ .tcx
+ .get_diagnostic_item(sym::Display)
+ .is_some_and(|t| infcx.type_implements_trait(t, [ty], param_env).may_apply());
let suggest_debug = !suggest_display
- && cx.tcx.get_diagnostic_item(sym::Debug).is_some_and(|t| {
- infcx.type_implements_trait(t, [ty], cx.param_env).may_apply()
- });
+ && cx
+ .tcx
+ .get_diagnostic_item(sym::Debug)
+ .is_some_and(|t| infcx.type_implements_trait(t, [ty], param_env).may_apply());
let suggest_panic_any = !is_str && panic == sym::std_panic_macro;
diff --git a/compiler/rustc_lint/src/noop_method_call.rs b/compiler/rustc_lint/src/noop_method_call.rs
index 4890a93..76dc96a 100644
--- a/compiler/rustc_lint/src/noop_method_call.rs
+++ b/compiler/rustc_lint/src/noop_method_call.rs
@@ -94,9 +94,9 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
let args = cx
.tcx
- .normalize_erasing_regions(cx.param_env, cx.typeck_results().node_args(expr.hir_id));
+ .normalize_erasing_regions(cx.typing_env(), cx.typeck_results().node_args(expr.hir_id));
// Resolve the trait method instance.
- let Ok(Some(i)) = ty::Instance::try_resolve(cx.tcx, cx.param_env, did, args) else {
+ let Ok(Some(i)) = ty::Instance::try_resolve(cx.tcx, cx.typing_env(), did, args) else {
return;
};
// (Re)check that it implements the noop diagnostic.
diff --git a/compiler/rustc_lint/src/tail_expr_drop_order.rs b/compiler/rustc_lint/src/tail_expr_drop_order.rs
index 8976305..19763ce 100644
--- a/compiler/rustc_lint/src/tail_expr_drop_order.rs
+++ b/compiler/rustc_lint/src/tail_expr_drop_order.rs
@@ -103,7 +103,7 @@ fn check_fn_or_closure<'tcx>(
if matches!(fn_kind, hir::intravisit::FnKind::Closure) {
for &capture in cx.tcx.closure_captures(def_id) {
if matches!(capture.info.capture_kind, ty::UpvarCapture::ByValue)
- && capture.place.ty().has_significant_drop(cx.tcx, cx.param_env)
+ && capture.place.ty().has_significant_drop(cx.tcx, cx.typing_env())
{
locals.push(capture.var_ident.span);
}
@@ -113,7 +113,7 @@ fn check_fn_or_closure<'tcx>(
if cx
.typeck_results()
.node_type(param.hir_id)
- .has_significant_drop(cx.tcx, cx.param_env)
+ .has_significant_drop(cx.tcx, cx.typing_env())
{
locals.push(param.span);
}
@@ -158,7 +158,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LocalCollector<'a, 'tcx> {
fn visit_pat(&mut self, pat: &'tcx Pat<'tcx>) {
if let PatKind::Binding(_binding_mode, id, ident, pat) = pat.kind {
let ty = self.cx.typeck_results().node_type(id);
- if ty.has_significant_drop(self.cx.tcx, self.cx.param_env) {
+ if ty.has_significant_drop(self.cx.tcx, self.cx.typing_env()) {
self.locals.push(ident.span);
}
if let Some(pat) = pat {
@@ -234,7 +234,10 @@ fn expr_generates_nonlocal_droppy_value(&self, expr: &Expr<'tcx>) -> bool {
if Self::expr_eventually_point_into_local(expr) {
return false;
}
- self.cx.typeck_results().expr_ty(expr).has_significant_drop(self.cx.tcx, self.cx.param_env)
+ self.cx
+ .typeck_results()
+ .expr_ty(expr)
+ .has_significant_drop(self.cx.tcx, self.cx.typing_env())
}
}
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index be70149..2e6cb99 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -613,10 +613,11 @@ pub(crate) fn transparent_newtype_field<'a, 'tcx>(
tcx: TyCtxt<'tcx>,
variant: &'a ty::VariantDef,
) -> Option<&'a ty::FieldDef> {
- let param_env = tcx.param_env(variant.def_id);
+ let typing_env = ty::TypingEnv::non_body_analysis(tcx, variant.def_id);
variant.fields.iter().find(|field| {
let field_ty = tcx.type_of(field.did).instantiate_identity();
- let is_1zst = tcx.layout_of(param_env.and(field_ty)).is_ok_and(|layout| layout.is_1zst());
+ let is_1zst =
+ tcx.layout_of(typing_env.as_query_input(field_ty)).is_ok_and(|layout| layout.is_1zst());
!is_1zst
})
}
@@ -624,11 +625,11 @@ pub(crate) fn transparent_newtype_field<'a, 'tcx>(
/// Is type known to be non-null?
fn ty_is_known_nonnull<'tcx>(
tcx: TyCtxt<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
ty: Ty<'tcx>,
mode: CItemKind,
) -> bool {
- let ty = tcx.try_normalize_erasing_regions(param_env, ty).unwrap_or(ty);
+ let ty = tcx.try_normalize_erasing_regions(typing_env, ty).unwrap_or(ty);
match ty.kind() {
ty::FnPtr(..) => true,
@@ -649,7 +650,7 @@ fn ty_is_known_nonnull<'tcx>(
def.variants()
.iter()
.filter_map(|variant| transparent_newtype_field(tcx, variant))
- .any(|field| ty_is_known_nonnull(tcx, param_env, field.ty(tcx, args), mode))
+ .any(|field| ty_is_known_nonnull(tcx, typing_env, field.ty(tcx, args), mode))
}
_ => false,
}
@@ -659,10 +660,10 @@ fn ty_is_known_nonnull<'tcx>(
/// If the type passed in was not scalar, returns None.
fn get_nullable_type<'tcx>(
tcx: TyCtxt<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
ty: Ty<'tcx>,
) -> Option<Ty<'tcx>> {
- let ty = tcx.try_normalize_erasing_regions(param_env, ty).unwrap_or(ty);
+ let ty = tcx.try_normalize_erasing_regions(typing_env, ty).unwrap_or(ty);
Some(match *ty.kind() {
ty::Adt(field_def, field_args) => {
@@ -679,7 +680,7 @@ fn get_nullable_type<'tcx>(
.expect("No non-zst fields in transparent type.")
.ty(tcx, field_args)
};
- return get_nullable_type(tcx, param_env, inner_field_ty);
+ return get_nullable_type(tcx, typing_env, inner_field_ty);
}
ty::Int(ty) => Ty::new_int(tcx, ty),
ty::Uint(ty) => Ty::new_uint(tcx, ty),
@@ -708,10 +709,10 @@ fn get_nullable_type<'tcx>(
/// - Does not have the `#[non_exhaustive]` attribute.
fn is_niche_optimization_candidate<'tcx>(
tcx: TyCtxt<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
ty: Ty<'tcx>,
) -> bool {
- if tcx.layout_of(param_env.and(ty)).is_ok_and(|layout| !layout.is_1zst()) {
+ if tcx.layout_of(typing_env.as_query_input(ty)).is_ok_and(|layout| !layout.is_1zst()) {
return false;
}
@@ -734,7 +735,7 @@ fn is_niche_optimization_candidate<'tcx>(
/// `core::ptr::NonNull`, and `#[repr(transparent)]` newtypes.
pub(crate) fn repr_nullable_ptr<'tcx>(
tcx: TyCtxt<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
ty: Ty<'tcx>,
ckind: CItemKind,
) -> Option<Ty<'tcx>> {
@@ -747,9 +748,9 @@ pub(crate) fn repr_nullable_ptr<'tcx>(
let ty1 = field1.ty(tcx, args);
let ty2 = field2.ty(tcx, args);
- if is_niche_optimization_candidate(tcx, param_env, ty1) {
+ if is_niche_optimization_candidate(tcx, typing_env, ty1) {
ty2
- } else if is_niche_optimization_candidate(tcx, param_env, ty2) {
+ } else if is_niche_optimization_candidate(tcx, typing_env, ty2) {
ty1
} else {
return None;
@@ -760,20 +761,20 @@ pub(crate) fn repr_nullable_ptr<'tcx>(
_ => return None,
};
- if !ty_is_known_nonnull(tcx, param_env, field_ty, ckind) {
+ if !ty_is_known_nonnull(tcx, typing_env, field_ty, ckind) {
return None;
}
// At this point, the field's type is known to be nonnull and the parent enum is Option-like.
// If the computed size for the field and the enum are different, the nonnull optimization isn't
// being applied (and we've got a problem somewhere).
- let compute_size_skeleton = |t| SizeSkeleton::compute(t, tcx, param_env).ok();
+ let compute_size_skeleton = |t| SizeSkeleton::compute(t, tcx, typing_env).ok();
if !compute_size_skeleton(ty)?.same_size(compute_size_skeleton(field_ty)?) {
bug!("improper_ctypes: Option nonnull optimization not applied?");
}
// Return the nullable type this Option-like enum can be safely represented with.
- let field_ty_layout = tcx.layout_of(param_env.and(field_ty));
+ let field_ty_layout = tcx.layout_of(typing_env.as_query_input(field_ty));
if field_ty_layout.is_err() && !field_ty.has_non_region_param() {
bug!("should be able to compute the layout of non-polymorphic type");
}
@@ -784,10 +785,10 @@ pub(crate) fn repr_nullable_ptr<'tcx>(
WrappingRange { start: 0, end }
if end == field_ty_scalar.size(&tcx).unsigned_int_max() - 1 =>
{
- return Some(get_nullable_type(tcx, param_env, field_ty).unwrap());
+ return Some(get_nullable_type(tcx, typing_env, field_ty).unwrap());
}
WrappingRange { start: 1, .. } => {
- return Some(get_nullable_type(tcx, param_env, field_ty).unwrap());
+ return Some(get_nullable_type(tcx, typing_env, field_ty).unwrap());
}
WrappingRange { start, end } => {
unreachable!("Unhandled start and end range: ({}, {})", start, end)
@@ -825,7 +826,7 @@ fn check_field_type_for_ffi(
let field_ty = self
.cx
.tcx
- .try_normalize_erasing_regions(self.cx.param_env, field_ty)
+ .try_normalize_erasing_regions(self.cx.typing_env(), field_ty)
.unwrap_or(field_ty);
self.check_type_for_ffi(acc, field_ty)
}
@@ -988,7 +989,7 @@ fn check_type_for_ffi(
{
// Special-case types like `Option<extern fn()>` and `Result<extern fn(), ()>`
if let Some(ty) =
- repr_nullable_ptr(self.cx.tcx, self.cx.param_env, ty, self.mode)
+ repr_nullable_ptr(self.cx.tcx, self.cx.typing_env(), ty, self.mode)
{
return self.check_type_for_ffi(acc, ty);
}
@@ -1196,7 +1197,7 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
if let Some(ty) = self
.cx
.tcx
- .try_normalize_erasing_regions(self.cx.param_env, ty)
+ .try_normalize_erasing_regions(self.cx.typing_env(), ty)
.unwrap_or(ty)
.visit_with(&mut ProhibitOpaqueTypes)
.break_value()
@@ -1220,7 +1221,7 @@ fn check_type_for_ffi_and_report_errors(
return;
}
- let ty = self.cx.tcx.try_normalize_erasing_regions(self.cx.param_env, ty).unwrap_or(ty);
+ let ty = self.cx.tcx.try_normalize_erasing_regions(self.cx.typing_env(), ty).unwrap_or(ty);
// C doesn't really support passing arrays by value - the only way to pass an array by value
// is through a struct. So, first test that the top level isn't an array, and then
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index 6c13127..5ec920d 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -272,7 +272,7 @@ fn is_ty_must_use<'tcx>(
|| !ty.is_inhabited_from(
cx.tcx,
cx.tcx.parent_module(expr.hir_id).to_def_id(),
- cx.param_env,
+ cx.typing_env(),
)
{
return Some(MustUsePath::Suppressed);
@@ -556,7 +556,7 @@ fn check_stmt(&mut self, cx: &LateContext<'_>, s: &hir::Stmt<'_>) {
if let hir::StmtKind::Semi(expr) = s.kind {
if let hir::ExprKind::Path(_) = expr.kind {
let ty = cx.typeck_results().expr_ty(expr);
- if ty.needs_drop(cx.tcx, cx.param_env) {
+ if ty.needs_drop(cx.tcx, cx.typing_env()) {
let sub = if let Ok(snippet) = cx.sess().source_map().span_to_snippet(expr.span)
{
PathStatementDropSub::Suggestion { span: s.span, snippet }
diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs
index 493db49..ace4689 100644
--- a/compiler/rustc_metadata/src/native_libs.rs
+++ b/compiler/rustc_metadata/src/native_libs.rs
@@ -6,7 +6,7 @@
use rustc_attr as attr;
use rustc_data_structures::fx::FxHashSet;
use rustc_middle::query::LocalCrate;
-use rustc_middle::ty::{List, ParamEnv, ParamEnvAnd, Ty, TyCtxt};
+use rustc_middle::ty::{self, List, Ty, TyCtxt};
use rustc_session::Session;
use rustc_session::config::CrateType;
use rustc_session::cstore::{
@@ -613,7 +613,7 @@ fn i686_arg_list_size(&self, item: DefId) -> usize {
.map(|ty| {
let layout = self
.tcx
- .layout_of(ParamEnvAnd { param_env: ParamEnv::empty(), value: ty })
+ .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty))
.expect("layout")
.layout;
// In both stdcall and fastcall, we always round up the argument size to the
diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs
index e6b3629..94d1302 100644
--- a/compiler/rustc_middle/src/middle/stability.rs
+++ b/compiler/rustc_middle/src/middle/stability.rs
@@ -10,7 +10,6 @@
use rustc_data_structures::unord::UnordMap;
use rustc_errors::{Applicability, Diag, EmissionGuarantee};
use rustc_feature::GateIssue;
-use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdMap};
use rustc_hir::{self as hir, HirId};
use rustc_macros::{Decodable, Encodable, HashStable, Subdiagnostic};
@@ -24,7 +23,7 @@
use tracing::debug;
pub use self::StabilityLevel::*;
-use crate::ty::{self, TyCtxt};
+use crate::ty::TyCtxt;
#[derive(PartialEq, Clone, Copy, Debug)]
pub enum StabilityLevel {
@@ -273,22 +272,6 @@ pub enum EvalResult {
Unmarked,
}
-// See issue #38412.
-fn skip_stability_check_due_to_privacy(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
- if tcx.def_kind(def_id) == DefKind::TyParam {
- // Have no visibility, considered public for the purpose of this check.
- return false;
- }
- match tcx.visibility(def_id) {
- // Must check stability for `pub` items.
- ty::Visibility::Public => false,
-
- // These are not visible outside crate; therefore
- // stability markers are irrelevant, if even present.
- ty::Visibility::Restricted(..) => true,
- }
-}
-
// See issue #83250.
fn suggestion_for_allocator_api(
tcx: TyCtxt<'_>,
@@ -407,11 +390,6 @@ pub fn eval_stability_allow_unstable(
def_id, span, stability
);
- // Issue #38412: private items lack stability markers.
- if skip_stability_check_due_to_privacy(self, def_id) {
- return EvalResult::Allow;
- }
-
match stability {
Some(Stability {
level: attr::Unstable { reason, issue, is_soft, implied_by },
@@ -495,11 +473,6 @@ pub fn eval_default_body_stability(self, def_id: DefId, span: Span) -> EvalResul
"body stability: inspecting def_id={def_id:?} span={span:?} of stability={stability:?}"
);
- // Issue #38412: private items lack stability markers.
- if skip_stability_check_due_to_privacy(self, def_id) {
- return EvalResult::Allow;
- }
-
match stability {
Some(DefaultBodyStability {
level: attr::Unstable { reason, issue, is_soft, .. },
diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs
index f956353..a513703 100644
--- a/compiler/rustc_middle/src/mir/consts.rs
+++ b/compiler/rustc_middle/src/mir/consts.rs
@@ -102,10 +102,11 @@ pub fn try_to_target_usize(&self, tcx: TyCtxt<'tcx>) -> Option<u64> {
pub fn try_to_bits_for_ty(
&self,
tcx: TyCtxt<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
ty: Ty<'tcx>,
) -> Option<u128> {
- let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size;
+ let size =
+ tcx.layout_of(typing_env.with_reveal_all_normalized(tcx).as_query_input(ty)).ok()?.size;
self.try_to_bits(size)
}
@@ -314,7 +315,7 @@ pub fn try_to_bool(self) -> Option<bool> {
pub fn eval(
self,
tcx: TyCtxt<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
span: Span,
) -> Result<ConstValue<'tcx>, ErrorHandled> {
match self {
@@ -333,7 +334,7 @@ pub fn eval(
}
Const::Unevaluated(uneval, _) => {
// FIXME: We might want to have a `try_eval`-like function on `Unevaluated`
- tcx.const_eval_resolve(param_env, uneval, span)
+ tcx.const_eval_resolve(typing_env, uneval, span)
}
Const::Val(val, _) => Ok(val),
}
@@ -343,7 +344,7 @@ pub fn eval(
pub fn try_eval_scalar(
self,
tcx: TyCtxt<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
) -> Option<Scalar> {
if let Const::Ty(_, c) = self
&& let ty::ConstKind::Value(ty, val) = c.kind()
@@ -354,7 +355,7 @@ pub fn try_eval_scalar(
// pointer here, which valtrees don't represent.)
Some(val.unwrap_leaf().into())
} else {
- self.eval(tcx, param_env, DUMMY_SP).ok()?.try_to_scalar()
+ self.eval(tcx, typing_env, DUMMY_SP).ok()?.try_to_scalar()
}
}
@@ -362,23 +363,29 @@ pub fn try_eval_scalar(
pub fn try_eval_scalar_int(
self,
tcx: TyCtxt<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
) -> Option<ScalarInt> {
- self.try_eval_scalar(tcx, param_env)?.try_to_scalar_int().ok()
+ self.try_eval_scalar(tcx, typing_env)?.try_to_scalar_int().ok()
}
#[inline]
- pub fn try_eval_bits(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Option<u128> {
- let int = self.try_eval_scalar_int(tcx, param_env)?;
- let size =
- tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(self.ty())).ok()?.size;
+ pub fn try_eval_bits(
+ &self,
+ tcx: TyCtxt<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
+ ) -> Option<u128> {
+ let int = self.try_eval_scalar_int(tcx, typing_env)?;
+ let size = tcx
+ .layout_of(typing_env.with_reveal_all_normalized(tcx).as_query_input(self.ty()))
+ .ok()?
+ .size;
Some(int.to_bits(size))
}
/// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type.
#[inline]
- pub fn eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> u128 {
- self.try_eval_bits(tcx, param_env)
+ pub fn eval_bits(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> u128 {
+ self.try_eval_bits(tcx, typing_env)
.unwrap_or_else(|| bug!("expected bits of {:#?}, got {:#?}", self.ty(), self))
}
@@ -386,21 +393,21 @@ pub fn eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> u128
pub fn try_eval_target_usize(
self,
tcx: TyCtxt<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
) -> Option<u64> {
- Some(self.try_eval_scalar_int(tcx, param_env)?.to_target_usize(tcx))
+ Some(self.try_eval_scalar_int(tcx, typing_env)?.to_target_usize(tcx))
}
#[inline]
/// Panics if the value cannot be evaluated or doesn't contain a valid `usize`.
- pub fn eval_target_usize(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> u64 {
- self.try_eval_target_usize(tcx, param_env)
+ pub fn eval_target_usize(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> u64 {
+ self.try_eval_target_usize(tcx, typing_env)
.unwrap_or_else(|| bug!("expected usize, got {:#?}", self))
}
#[inline]
- pub fn try_eval_bool(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Option<bool> {
- self.try_eval_scalar_int(tcx, param_env)?.try_into().ok()
+ pub fn try_eval_bool(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> Option<bool> {
+ self.try_eval_scalar_int(tcx, typing_env)?.try_into().ok()
}
#[inline]
@@ -411,17 +418,16 @@ pub fn from_value(val: ConstValue<'tcx>, ty: Ty<'tcx>) -> Self {
pub fn from_bits(
tcx: TyCtxt<'tcx>,
bits: u128,
- param_env_ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
+ typing_env: ty::TypingEnv<'tcx>,
+ ty: Ty<'tcx>,
) -> Self {
let size = tcx
- .layout_of(param_env_ty)
- .unwrap_or_else(|e| {
- bug!("could not compute layout for {:?}: {:?}", param_env_ty.value, e)
- })
+ .layout_of(typing_env.as_query_input(ty))
+ .unwrap_or_else(|e| bug!("could not compute layout for {ty:?}: {e:?}"))
.size;
let cv = ConstValue::Scalar(Scalar::from_uint(bits, size));
- Self::Val(cv, param_env_ty.value)
+ Self::Val(cv, ty)
}
#[inline]
@@ -438,7 +444,8 @@ pub fn zero_sized(ty: Ty<'tcx>) -> Self {
pub fn from_usize(tcx: TyCtxt<'tcx>, n: u64) -> Self {
let ty = tcx.types.usize;
- Self::from_bits(tcx, n as u128, ty::ParamEnv::empty().and(ty))
+ let typing_env = ty::TypingEnv::fully_monomorphized();
+ Self::from_bits(tcx, n as u128, typing_env, ty)
}
#[inline]
diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs
index f225ad9..c4b0e6e 100644
--- a/compiler/rustc_middle/src/mir/interpret/mod.rs
+++ b/compiler/rustc_middle/src/mir/interpret/mod.rs
@@ -351,7 +351,11 @@ pub fn mutability(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Mutabi
}
}
- pub fn size_and_align(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> (Size, Align) {
+ pub fn size_and_align(
+ &self,
+ tcx: TyCtxt<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
+ ) -> (Size, Align) {
match self {
GlobalAlloc::Static(def_id) => {
let DefKind::Static { nested, .. } = tcx.def_kind(def_id) else {
@@ -374,7 +378,7 @@ pub fn size_and_align(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> (S
.type_of(def_id)
.no_bound_vars()
.expect("statics should not have generic parameters");
- let layout = tcx.layout_of(param_env.and(ty)).unwrap();
+ let layout = tcx.layout_of(typing_env.as_query_input(ty)).unwrap();
assert!(layout.is_sized());
(layout.size, layout.align.abi)
}
diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs
index 2ecf1d0..7092f87 100644
--- a/compiler/rustc_middle/src/mir/interpret/queries.rs
+++ b/compiler/rustc_middle/src/mir/interpret/queries.rs
@@ -58,7 +58,7 @@ pub fn const_eval_poly_to_alloc(self, def_id: DefId) -> EvalToAllocationRawResul
#[instrument(level = "debug", skip(self))]
pub fn const_eval_resolve(
self,
- param_env: ty::ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
ct: mir::UnevaluatedConst<'tcx>,
span: Span,
) -> EvalToConstValueResult<'tcx> {
@@ -72,14 +72,11 @@ pub fn const_eval_resolve(
bug!("did not expect inference variables here");
}
- match ty::Instance::try_resolve(
- self, param_env,
- // FIXME: maybe have a separate version for resolving mir::UnevaluatedConst?
- ct.def, ct.args,
- ) {
+ // FIXME: maybe have a separate version for resolving mir::UnevaluatedConst?
+ match ty::Instance::try_resolve(self, typing_env, ct.def, ct.args) {
Ok(Some(instance)) => {
let cid = GlobalId { instance, promoted: ct.promoted };
- self.const_eval_global_id(param_env, cid, span)
+ self.const_eval_global_id(typing_env.param_env, cid, span)
}
// For errors during resolution, we deliberately do not point at the usage site of the constant,
// since for these errors the place the constant is used shouldn't matter.
@@ -91,7 +88,7 @@ pub fn const_eval_resolve(
#[instrument(level = "debug", skip(self))]
pub fn const_eval_resolve_for_typeck(
self,
- param_env: ty::ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
ct: ty::UnevaluatedConst<'tcx>,
span: Span,
) -> EvalToValTreeResult<'tcx> {
@@ -105,10 +102,10 @@ pub fn const_eval_resolve_for_typeck(
bug!("did not expect inference variables here");
}
- match ty::Instance::try_resolve(self, param_env, ct.def, ct.args) {
+ match ty::Instance::try_resolve(self, typing_env, ct.def, ct.args) {
Ok(Some(instance)) => {
let cid = GlobalId { instance, promoted: None };
- self.const_eval_global_id_for_typeck(param_env, cid, span).inspect(|_| {
+ self.const_eval_global_id_for_typeck(typing_env.param_env, cid, span).inspect(|_| {
// We are emitting the lint here instead of in `is_const_evaluatable`
// as we normalize obligations before checking them, and normalization
// uses this function to evaluate this constant.
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 260c654..425cb05 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -39,7 +39,7 @@
use crate::ty::print::{FmtPrinter, Printer, pretty_print_const, with_no_trimmed_paths};
use crate::ty::visit::TypeVisitableExt;
use crate::ty::{
- self, AdtDef, GenericArg, GenericArgsRef, Instance, InstanceKind, List, Ty, TyCtxt, TypingMode,
+ self, AdtDef, GenericArg, GenericArgsRef, Instance, InstanceKind, List, Ty, TyCtxt, TypingEnv,
UserTypeAnnotationIndex,
};
@@ -452,12 +452,17 @@ pub fn basic_blocks_mut(&mut self) -> &mut IndexVec<BasicBlock, BasicBlockData<'
self.basic_blocks.as_mut()
}
- pub fn typing_mode(&self, _tcx: TyCtxt<'tcx>) -> TypingMode<'tcx> {
+ pub fn typing_env(&self, tcx: TyCtxt<'tcx>) -> TypingEnv<'tcx> {
match self.phase {
- // FIXME(#132279): the MIR is quite clearly inside of a body, so we
- // should instead reveal opaques defined by that body here.
- MirPhase::Built | MirPhase::Analysis(_) => TypingMode::non_body_analysis(),
- MirPhase::Runtime(_) => TypingMode::PostAnalysis,
+ // FIXME(#132279): we should reveal the opaques defined in the body during analysis.
+ MirPhase::Built | MirPhase::Analysis(_) => TypingEnv {
+ typing_mode: ty::TypingMode::non_body_analysis(),
+ param_env: tcx.param_env(self.source.def_id()),
+ },
+ MirPhase::Runtime(_) => TypingEnv {
+ typing_mode: ty::TypingMode::PostAnalysis,
+ param_env: tcx.param_env_reveal_all_normalized(self.source.def_id()),
+ },
}
}
@@ -618,7 +623,7 @@ pub fn is_custom_mir(&self) -> bool {
}
/// If this basic block ends with a [`TerminatorKind::SwitchInt`] for which we can evaluate the
- /// dimscriminant in monomorphization, we return the discriminant bits and the
+ /// discriminant in monomorphization, we return the discriminant bits and the
/// [`SwitchTargets`], just so the caller doesn't also have to match on the terminator.
fn try_const_mono_switchint<'a>(
tcx: TyCtxt<'tcx>,
@@ -627,13 +632,15 @@ fn try_const_mono_switchint<'a>(
) -> Option<(u128, &'a SwitchTargets)> {
// There are two places here we need to evaluate a constant.
let eval_mono_const = |constant: &ConstOperand<'tcx>| {
- let env = ty::ParamEnv::reveal_all();
+ // FIXME(#132279): what is this, why are we using an empty environment with
+ // `RevealAll` here.
+ let typing_env = ty::TypingEnv::fully_monomorphized();
let mono_literal = instance.instantiate_mir_and_normalize_erasing_regions(
tcx,
- env,
+ typing_env,
crate::ty::EarlyBinder::bind(constant.const_),
);
- mono_literal.try_eval_bits(tcx, env)
+ mono_literal.try_eval_bits(tcx, typing_env)
};
let TerminatorKind::SwitchInt { discr, targets } = &block.terminator().kind else {
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs
index d8d99de..244d22d 100644
--- a/compiler/rustc_middle/src/mir/mono.rs
+++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -46,7 +46,7 @@ pub enum InstantiationMode {
LocalCopy,
}
-#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash, HashStable)]
+#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash, HashStable, TyEncodable, TyDecodable)]
pub enum MonoItem<'tcx> {
Fn(Instance<'tcx>),
Static(DefId),
@@ -66,20 +66,7 @@ pub fn is_user_defined(&self) -> bool {
// change NON_INCR_MIN_CGU_SIZE as well.
pub fn size_estimate(&self, tcx: TyCtxt<'tcx>) -> usize {
match *self {
- MonoItem::Fn(instance) => {
- match instance.def {
- // "Normal" functions size estimate: the number of
- // statements, plus one for the terminator.
- InstanceKind::Item(..)
- | InstanceKind::DropGlue(..)
- | InstanceKind::AsyncDropGlueCtorShim(..) => {
- let mir = tcx.instance_mir(instance.def);
- mir.basic_blocks.iter().map(|bb| bb.statements.len() + 1).sum()
- }
- // Other compiler-generated shims size estimate: 1
- _ => 1,
- }
- }
+ MonoItem::Fn(instance) => tcx.size_estimate(instance),
// Conservatively estimate the size of a static declaration or
// assembly item to be 1.
MonoItem::Static(_) | MonoItem::GlobalAsm(_) => 1,
@@ -556,3 +543,21 @@ pub fn build_cgu_name_no_mangle<I, C, S>(
Symbol::intern(&cgu_name)
}
}
+
+/// See module-level docs of `rustc_monomorphize::collector` on some context for "mentioned" items.
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
+pub enum CollectionMode {
+ /// Collect items that are used, i.e., actually needed for codegen.
+ ///
+ /// Which items are used can depend on optimization levels, as MIR optimizations can remove
+ /// uses.
+ UsedItems,
+ /// Collect items that are mentioned. The goal of this mode is that it is independent of
+ /// optimizations: the set of "mentioned" items is computed before optimizations are run.
+ ///
+ /// The exact contents of this set are *not* a stable guarantee. (For instance, it is currently
+ /// computed after drop-elaboration. If we ever do some optimizations even in debug builds, we
+ /// might decide to run them before computing mentioned items.) The key property of this set is
+ /// that it is optimization-independent.
+ MentionedItems,
+}
diff --git a/compiler/rustc_middle/src/mir/statement.rs b/compiler/rustc_middle/src/mir/statement.rs
index 88ed90c..1ce735c 100644
--- a/compiler/rustc_middle/src/mir/statement.rs
+++ b/compiler/rustc_middle/src/mir/statement.rs
@@ -332,9 +332,9 @@ pub fn const_from_scalar(
span: Span,
) -> Operand<'tcx> {
debug_assert!({
- let param_env_and_ty = ty::ParamEnv::empty().and(ty);
+ let typing_env = ty::TypingEnv::fully_monomorphized();
let type_size = tcx
- .layout_of(param_env_and_ty)
+ .layout_of(typing_env.as_query_input(ty))
.unwrap_or_else(|e| panic!("could not compute layout for {ty:?}: {e:?}"))
.size;
let scalar_size = match val {
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index f01ac30..2083279 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -20,7 +20,7 @@
use super::{BasicBlock, Const, Local, UserTypeProjection};
use crate::mir::coverage::CoverageKind;
use crate::ty::adjustment::PointerCoercion;
-use crate::ty::{self, GenericArgsRef, List, Region, Ty, TyCtxt, UserTypeAnnotationIndex};
+use crate::ty::{self, GenericArgsRef, List, Region, Ty, UserTypeAnnotationIndex};
/// Represents the "flavors" of MIR.
///
@@ -100,13 +100,6 @@ pub fn name(&self) -> &'static str {
MirPhase::Runtime(RuntimePhase::Optimized) => "runtime-optimized",
}
}
-
- pub fn param_env<'tcx>(&self, tcx: TyCtxt<'tcx>, body_def_id: DefId) -> ty::ParamEnv<'tcx> {
- match self {
- MirPhase::Built | MirPhase::Analysis(_) => tcx.param_env(body_def_id),
- MirPhase::Runtime(_) => tcx.param_env_reveal_all_normalized(body_def_id),
- }
- }
}
/// See [`MirPhase::Analysis`].
diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs
index 1d4c36e..013847f 100644
--- a/compiler/rustc_middle/src/query/erase.rs
+++ b/compiler/rustc_middle/src/query/erase.rs
@@ -216,6 +216,10 @@ impl<T0, T1> EraseType for (&'_ T0, &'_ [T1]) {
type Result = [u8; size_of::<(&'static (), &'static [()])>()];
}
+impl<T0, T1> EraseType for (&'_ [T0], &'_ [T1]) {
+ type Result = [u8; size_of::<(&'static [()], &'static [()])>()];
+}
+
impl<T0> EraseType for (&'_ T0, Result<(), ErrorGuaranteed>) {
type Result = [u8; size_of::<(&'static (), Result<(), ErrorGuaranteed>)>()];
}
diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs
index fe28ef0..d2fab8e 100644
--- a/compiler/rustc_middle/src/query/keys.rs
+++ b/compiler/rustc_middle/src/query/keys.rs
@@ -2,11 +2,13 @@
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalModDefId, ModDefId};
use rustc_hir::hir_id::{HirId, OwnerId};
+use rustc_query_system::dep_graph::DepNodeIndex;
use rustc_query_system::query::{DefIdCache, DefaultCache, SingleCache, VecCache};
use rustc_span::symbol::{Ident, Symbol};
use rustc_span::{DUMMY_SP, Span};
use crate::infer::canonical::CanonicalQueryInput;
+use crate::mir::mono::CollectionMode;
use crate::ty::fast_reject::SimplifiedType;
use crate::ty::layout::{TyAndLayout, ValidityRequirement};
use crate::ty::{self, GenericArg, GenericArgsRef, Ty, TyCtxt};
@@ -110,7 +112,7 @@ fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
}
impl Key for CrateNum {
- type Cache<V> = VecCache<Self, V>;
+ type Cache<V> = VecCache<Self, V, DepNodeIndex>;
fn default_span(&self, _: TyCtxt<'_>) -> Span {
DUMMY_SP
@@ -127,7 +129,7 @@ fn as_local_key(&self) -> Option<Self::LocalKey> {
}
impl Key for OwnerId {
- type Cache<V> = VecCache<Self, V>;
+ type Cache<V> = VecCache<Self, V, DepNodeIndex>;
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
self.to_def_id().default_span(tcx)
@@ -139,7 +141,7 @@ fn key_as_def_id(&self) -> Option<DefId> {
}
impl Key for LocalDefId {
- type Cache<V> = VecCache<Self, V>;
+ type Cache<V> = VecCache<Self, V, DepNodeIndex>;
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
self.to_def_id().default_span(tcx)
@@ -466,6 +468,18 @@ fn ty_def_id(&self) -> Option<DefId> {
}
}
+impl<'tcx, T: Key> Key for ty::PseudoCanonicalInput<'tcx, T> {
+ type Cache<V> = DefaultCache<Self, V>;
+
+ fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
+ self.value.default_span(tcx)
+ }
+
+ fn ty_def_id(&self) -> Option<DefId> {
+ self.value.ty_def_id()
+ }
+}
+
impl Key for Symbol {
type Cache<V> = DefaultCache<Self, V>;
@@ -574,7 +588,7 @@ fn key_as_def_id(&self) -> Option<DefId> {
}
}
-impl<'tcx> Key for (ValidityRequirement, ty::ParamEnvAnd<'tcx, Ty<'tcx>>) {
+impl<'tcx> Key for (ValidityRequirement, ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) {
type Cache<V> = DefaultCache<Self, V>;
// Just forward to `Ty<'tcx>`
@@ -590,3 +604,11 @@ fn ty_def_id(&self) -> Option<DefId> {
}
}
}
+
+impl<'tcx> Key for (ty::Instance<'tcx>, CollectionMode) {
+ type Cache<V> = DefaultCache<Self, V>;
+
+ fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
+ self.0.default_span(tcx)
+ }
+}
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 4e36688..684d5b6 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -40,6 +40,7 @@
};
use rustc_session::lint::LintExpectationId;
use rustc_span::def_id::LOCAL_CRATE;
+use rustc_span::source_map::Spanned;
use rustc_span::symbol::Symbol;
use rustc_span::{DUMMY_SP, Span};
use rustc_target::spec::PanicStrategy;
@@ -59,7 +60,7 @@
EvalStaticInitializerRawResult, EvalToAllocationRawResult, EvalToConstValueResult,
EvalToValTreeResult, GlobalId, LitToConstError, LitToConstInput,
};
-use crate::mir::mono::CodegenUnit;
+use crate::mir::mono::{CodegenUnit, CollectionMode, MonoItem};
use crate::query::erase::{Erase, erase, restore};
use crate::query::plumbing::{
CyclePlaceholder, DynamicQuery, query_ensure, query_ensure_error_guaranteed, query_get_at,
@@ -80,8 +81,8 @@
use crate::ty::print::{PrintTraitRefExt, describe_as_module};
use crate::ty::util::AlwaysRequiresDrop;
use crate::ty::{
- self, CrateInherentImpls, GenericArg, GenericArgsRef, ParamEnvAnd, Ty, TyCtxt, TyCtxtFeed,
- UnusedGenericParams,
+ self, CrateInherentImpls, GenericArg, GenericArgsRef, PseudoCanonicalInput, Ty, TyCtxt,
+ TyCtxtFeed, UnusedGenericParams,
};
use crate::{dep_graph, mir, thir};
@@ -1340,10 +1341,10 @@
}
query codegen_select_candidate(
- key: (ty::ParamEnv<'tcx>, ty::TraitRef<'tcx>)
+ key: PseudoCanonicalInput<'tcx, ty::TraitRef<'tcx>>
) -> Result<&'tcx ImplSource<'tcx, ()>, CodegenObligationError> {
cache_on_disk_if { true }
- desc { |tcx| "computing candidate for `{}`", key.1 }
+ desc { |tcx| "computing candidate for `{}`", key.value }
}
/// Return all `impl` blocks in the current crate.
@@ -1405,15 +1406,15 @@
desc { "computing whether `{}` is `Unpin`", env.value }
}
/// Query backing `Ty::needs_drop`.
- query needs_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
+ query needs_drop_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool {
desc { "computing whether `{}` needs drop", env.value }
}
/// Query backing `Ty::needs_async_drop`.
- query needs_async_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
+ query needs_async_drop_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool {
desc { "computing whether `{}` needs async drop", env.value }
}
/// Query backing `Ty::has_significant_drop_raw`.
- query has_significant_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
+ query has_significant_drop_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool {
desc { "computing whether `{}` has a significant drop", env.value }
}
@@ -1450,7 +1451,7 @@
/// Computes the layout of a type. Note that this implicitly
/// executes in "reveal all" mode, and will normalize the input type.
query layout_of(
- key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>
+ key: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>
) -> Result<ty::layout::TyAndLayout<'tcx>, &'tcx ty::layout::LayoutError<'tcx>> {
depth_limit
desc { "computing layout of `{}`", key.value }
@@ -1463,7 +1464,7 @@
/// NB: this doesn't handle virtual calls - those should use `fn_abi_of_instance`
/// instead, where the instance is an `InstanceKind::Virtual`.
query fn_abi_of_fn_ptr(
- key: ty::ParamEnvAnd<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>)>
+ key: ty::PseudoCanonicalInput<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>)>
) -> Result<&'tcx rustc_target::callconv::FnAbi<'tcx, Ty<'tcx>>, &'tcx ty::layout::FnAbiError<'tcx>> {
desc { "computing call ABI of `{}` function pointers", key.value.0 }
}
@@ -1474,7 +1475,7 @@
/// NB: that includes virtual calls, which are represented by "direct calls"
/// to an `InstanceKind::Virtual` instance (of `<dyn Trait as Trait>::fn`).
query fn_abi_of_instance(
- key: ty::ParamEnvAnd<'tcx, (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>)>
+ key: ty::PseudoCanonicalInput<'tcx, (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>)>
) -> Result<&'tcx rustc_target::callconv::FnAbi<'tcx, Ty<'tcx>>, &'tcx ty::layout::FnAbiError<'tcx>> {
desc { "computing call ABI of `{}`", key.value.0 }
}
@@ -2087,7 +2088,7 @@
/// Do not call this query directly: invoke `try_normalize_erasing_regions` instead.
query try_normalize_generic_arg_after_erasing_regions(
- goal: ParamEnvAnd<'tcx, GenericArg<'tcx>>
+ goal: PseudoCanonicalInput<'tcx, GenericArg<'tcx>>
) -> Result<GenericArg<'tcx>, NoSolution> {
desc { "normalizing `{}`", goal.value }
}
@@ -2244,7 +2245,7 @@
/// from `Ok(None)` to avoid misleading diagnostics when an error
/// has already been/will be emitted, for the original cause.
query resolve_instance_raw(
- key: ty::ParamEnvAnd<'tcx, (DefId, GenericArgsRef<'tcx>)>
+ key: ty::PseudoCanonicalInput<'tcx, (DefId, GenericArgsRef<'tcx>)>
) -> Result<Option<ty::Instance<'tcx>>, ErrorGuaranteed> {
desc { "resolving instance `{}`", ty::Instance::new(key.value.0, key.value.1) }
}
@@ -2282,7 +2283,7 @@
desc { "computing the backend features for CLI flags" }
}
- query check_validity_requirement(key: (ValidityRequirement, ty::ParamEnvAnd<'tcx, Ty<'tcx>>)) -> Result<bool, &'tcx ty::layout::LayoutError<'tcx>> {
+ query check_validity_requirement(key: (ValidityRequirement, ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>)) -> Result<bool, &'tcx ty::layout::LayoutError<'tcx>> {
desc { "checking validity requirement for `{}`: {}", key.1.value, key.0 }
}
@@ -2339,6 +2340,16 @@
arena_cache
desc { "functions to skip for move-size check" }
}
+
+ query items_of_instance(key: (ty::Instance<'tcx>, CollectionMode)) -> (&'tcx [Spanned<MonoItem<'tcx>>], &'tcx [Spanned<MonoItem<'tcx>>]) {
+ desc { "collecting items used by `{}`", key.0 }
+ cache_on_disk_if { true }
+ }
+
+ query size_estimate(key: ty::Instance<'tcx>) -> usize {
+ desc { "estimating codegen size of `{}`", key }
+ cache_on_disk_if { true }
+ }
}
rustc_query_append! { define_callbacks! }
diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs
index 8b77a4a..3849cb7 100644
--- a/compiler/rustc_middle/src/query/on_disk_cache.rs
+++ b/compiler/rustc_middle/src/query/on_disk_cache.rs
@@ -12,6 +12,7 @@
use rustc_macros::{Decodable, Encodable};
use rustc_middle::dep_graph::{DepNodeIndex, SerializedDepNodeIndex};
use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState};
+use rustc_middle::mir::mono::MonoItem;
use rustc_middle::mir::{self, interpret};
use rustc_middle::ty::codec::{RefDecodable, TyDecoder, TyEncoder};
use rustc_middle::ty::{self, Ty, TyCtxt};
@@ -22,7 +23,7 @@
use rustc_span::hygiene::{
ExpnId, HygieneDecodeContext, HygieneEncodeContext, SyntaxContext, SyntaxContextData,
};
-use rustc_span::source_map::SourceMap;
+use rustc_span::source_map::{SourceMap, Spanned};
use rustc_span::{
BytePos, CachingSourceMapView, ExpnData, ExpnHash, Pos, RelativeBytePos, SourceFile, Span,
SpanDecoder, SpanEncoder, StableSourceFileId, Symbol,
@@ -773,6 +774,13 @@ fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self {
}
}
+impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [Spanned<MonoItem<'tcx>>] {
+ #[inline]
+ fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self {
+ RefDecodable::decode(d)
+ }
+}
+
impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>>
for &'tcx crate::traits::specialization_graph::Graph
{
diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index 45ceb0a..8f26e05 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -905,7 +905,7 @@ pub fn contains(
&self,
value: mir::Const<'tcx>,
tcx: TyCtxt<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
) -> Option<bool> {
use Ordering::*;
debug_assert_eq!(self.ty, value.ty());
@@ -913,10 +913,10 @@ pub fn contains(
let value = PatRangeBoundary::Finite(value);
// For performance, it's important to only do the second comparison if necessary.
Some(
- match self.lo.compare_with(value, ty, tcx, param_env)? {
+ match self.lo.compare_with(value, ty, tcx, typing_env)? {
Less | Equal => true,
Greater => false,
- } && match value.compare_with(self.hi, ty, tcx, param_env)? {
+ } && match value.compare_with(self.hi, ty, tcx, typing_env)? {
Less => true,
Equal => self.end == RangeEnd::Included,
Greater => false,
@@ -929,17 +929,17 @@ pub fn overlaps(
&self,
other: &Self,
tcx: TyCtxt<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
) -> Option<bool> {
use Ordering::*;
debug_assert_eq!(self.ty, other.ty);
// For performance, it's important to only do the second comparison if necessary.
Some(
- match other.lo.compare_with(self.hi, self.ty, tcx, param_env)? {
+ match other.lo.compare_with(self.hi, self.ty, tcx, typing_env)? {
Less => true,
Equal => self.end == RangeEnd::Included,
Greater => false,
- } && match self.lo.compare_with(other.hi, self.ty, tcx, param_env)? {
+ } && match self.lo.compare_with(other.hi, self.ty, tcx, typing_env)? {
Less => true,
Equal => other.end == RangeEnd::Included,
Greater => false,
@@ -985,9 +985,14 @@ pub fn as_finite(self) -> Option<mir::Const<'tcx>> {
Self::NegInfinity | Self::PosInfinity => None,
}
}
- pub fn eval_bits(self, ty: Ty<'tcx>, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> u128 {
+ pub fn eval_bits(
+ self,
+ ty: Ty<'tcx>,
+ tcx: TyCtxt<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
+ ) -> u128 {
match self {
- Self::Finite(value) => value.eval_bits(tcx, param_env),
+ Self::Finite(value) => value.eval_bits(tcx, typing_env),
Self::NegInfinity => {
// Unwrap is ok because the type is known to be numeric.
ty.numeric_min_and_max_as_bits(tcx).unwrap().0
@@ -999,13 +1004,13 @@ pub fn eval_bits(self, ty: Ty<'tcx>, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<
}
}
- #[instrument(skip(tcx, param_env), level = "debug", ret)]
+ #[instrument(skip(tcx, typing_env), level = "debug", ret)]
pub fn compare_with(
self,
other: Self,
ty: Ty<'tcx>,
tcx: TyCtxt<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
) -> Option<Ordering> {
use PatRangeBoundary::*;
match (self, other) {
@@ -1034,8 +1039,8 @@ pub fn compare_with(
_ => {}
}
- let a = self.eval_bits(ty, tcx, param_env);
- let b = other.eval_bits(ty, tcx, param_env);
+ let a = self.eval_bits(ty, tcx, typing_env);
+ let b = other.eval_bits(ty, tcx, typing_env);
match ty.kind() {
ty::Float(ty::FloatTy::F16) => {
diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs
index 0773eb7..79d5670 100644
--- a/compiler/rustc_middle/src/ty/adt.rs
+++ b/compiler/rustc_middle/src/ty/adt.rs
@@ -498,12 +498,13 @@ pub fn eval_explicit_discr(
expr_did: DefId,
) -> Result<Discr<'tcx>, ErrorGuaranteed> {
assert!(self.is_enum());
- let param_env = tcx.param_env(expr_did);
+
let repr_type = self.repr().discr_type();
match tcx.const_eval_poly(expr_did) {
Ok(val) => {
+ let typing_env = ty::TypingEnv::post_analysis(tcx, expr_did);
let ty = repr_type.to_ty(tcx);
- if let Some(b) = val.try_to_bits_for_ty(tcx, param_env, ty) {
+ if let Some(b) = val.try_to_bits_for_ty(tcx, typing_env, ty) {
trace!("discriminants: {} ({:?})", b, repr_type);
Ok(Discr { val: b, ty })
} else {
diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs
index b5358f0..47a84d4 100644
--- a/compiler/rustc_middle/src/ty/codec.rs
+++ b/compiler/rustc_middle/src/ty/codec.rs
@@ -13,9 +13,11 @@
use rustc_abi::{FieldIdx, VariantIdx};
use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def_id::LocalDefId;
+use rustc_middle::mir::mono::MonoItem;
use rustc_middle::ty::TyCtxt;
use rustc_serialize::{Decodable, Encodable};
use rustc_span::Span;
+use rustc_span::source_map::Spanned;
pub use rustc_type_ir::{TyDecoder, TyEncoder};
use crate::arena::ArenaAllocatable;
@@ -397,6 +399,15 @@ fn decode(decoder: &mut D) -> &'tcx Self {
}
}
+impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for [Spanned<MonoItem<'tcx>>] {
+ fn decode(decoder: &mut D) -> &'tcx Self {
+ decoder
+ .interner()
+ .arena
+ .alloc_from_iter((0..decoder.read_usize()).map(|_| Decodable::decode(decoder)))
+ }
+}
+
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D>
for ty::List<ty::BoundVariableKind>
{
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index 5689f3d..3bd09fc 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -9,7 +9,7 @@
use crate::middle::resolve_bound_vars as rbv;
use crate::mir::interpret::{LitToConstInput, Scalar};
-use crate::ty::{self, GenericArgs, ParamEnv, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt};
+use crate::ty::{self, GenericArgs, Ty, TyCtxt, TypeVisitableExt};
mod int;
mod kind;
@@ -330,17 +330,22 @@ fn try_from_lit_or_param(
None
}
- #[inline]
/// Creates a constant with the given integer value and interns it.
- pub fn from_bits(tcx: TyCtxt<'tcx>, bits: u128, ty: ParamEnvAnd<'tcx, Ty<'tcx>>) -> Self {
+ #[inline]
+ pub fn from_bits(
+ tcx: TyCtxt<'tcx>,
+ bits: u128,
+ typing_env: ty::TypingEnv<'tcx>,
+ ty: Ty<'tcx>,
+ ) -> Self {
let size = tcx
- .layout_of(ty)
+ .layout_of(typing_env.as_query_input(ty))
.unwrap_or_else(|e| panic!("could not compute layout for {ty:?}: {e:?}"))
.size;
ty::Const::new_value(
tcx,
ty::ValTree::from_scalar_int(ScalarInt::try_from_uint(bits, size).unwrap()),
- ty.value,
+ ty,
)
}
@@ -353,13 +358,13 @@ pub fn zero_sized(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Self {
#[inline]
/// Creates an interned bool constant.
pub fn from_bool(tcx: TyCtxt<'tcx>, v: bool) -> Self {
- Self::from_bits(tcx, v as u128, ParamEnv::empty().and(tcx.types.bool))
+ Self::from_bits(tcx, v as u128, ty::TypingEnv::fully_monomorphized(), tcx.types.bool)
}
#[inline]
/// Creates an interned usize constant.
pub fn from_target_usize(tcx: TyCtxt<'tcx>, n: u64) -> Self {
- Self::from_bits(tcx, n as u128, ParamEnv::empty().and(tcx.types.usize))
+ Self::from_bits(tcx, n as u128, ty::TypingEnv::fully_monomorphized(), tcx.types.usize)
}
/// Panics if self.kind != ty::ConstKind::Value
@@ -393,15 +398,15 @@ pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> {
self.try_to_valtree()?.0.try_to_target_usize(tcx)
}
- #[inline]
/// Attempts to evaluate the given constant to bits. Can fail to evaluate in the presence of
/// generics (or erroneous code) or if the value can't be represented as bits (e.g. because it
/// contains const generic parameters or pointers).
- pub fn try_to_bits(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<u128> {
+ #[inline]
+ pub fn try_to_bits(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> Option<u128> {
let (scalar, ty) = self.try_to_scalar()?;
let scalar = scalar.try_to_scalar_int().ok()?;
- let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size;
- // if `ty` does not depend on generic parameters, use an empty param_env
+ let input = typing_env.with_reveal_all_normalized(tcx).as_query_input(ty);
+ let size = tcx.layout_of(input).ok()?.size;
Some(scalar.to_bits(size))
}
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 84ac281..2ba1bf2 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -596,8 +596,16 @@ fn coroutine_is_async_gen(self, coroutine_def_id: DefId) -> bool {
self.coroutine_is_async_gen(coroutine_def_id)
}
- fn layout_is_pointer_like(self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool {
- self.layout_of(self.erase_regions(param_env.and(ty)))
+ // We don't use `TypingEnv` here as it's only defined in `rustc_middle` and
+ // `rustc_next_trait_solver` shouldn't have to know about it.
+ fn layout_is_pointer_like(
+ self,
+ typing_mode: ty::TypingMode<'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
+ ty: Ty<'tcx>,
+ ) -> bool {
+ let typing_env = ty::TypingEnv { typing_mode, param_env };
+ self.layout_of(self.erase_regions(typing_env).as_query_input(self.erase_regions(ty)))
.is_ok_and(|layout| layout.layout.is_pointer_like(&self.data_layout))
}
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
index bf741f6..505c727 100644
--- a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
+++ b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
@@ -3,7 +3,7 @@
use tracing::instrument;
use crate::ty::context::TyCtxt;
-use crate::ty::{self, DefId, OpaqueTypeKey, ParamEnv, Ty};
+use crate::ty::{self, DefId, OpaqueTypeKey, Ty, TypingEnv};
/// Represents whether some type is inhabited in a given context.
/// Examples of uninhabited types are `!`, `enum Void {}`, or a struct
@@ -35,8 +35,13 @@ pub enum InhabitedPredicate<'tcx> {
impl<'tcx> InhabitedPredicate<'tcx> {
/// Returns true if the corresponding type is inhabited in the given `ParamEnv` and module.
- pub fn apply(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, module_def_id: DefId) -> bool {
- self.apply_revealing_opaque(tcx, param_env, module_def_id, &|_| None)
+ pub fn apply(
+ self,
+ tcx: TyCtxt<'tcx>,
+ typing_env: TypingEnv<'tcx>,
+ module_def_id: DefId,
+ ) -> bool {
+ self.apply_revealing_opaque(tcx, typing_env, module_def_id, &|_| None)
}
/// Returns true if the corresponding type is inhabited in the given `ParamEnv` and module,
@@ -44,13 +49,13 @@ pub fn apply(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, module_def_id:
pub fn apply_revealing_opaque(
self,
tcx: TyCtxt<'tcx>,
- param_env: ParamEnv<'tcx>,
+ typing_env: TypingEnv<'tcx>,
module_def_id: DefId,
reveal_opaque: &impl Fn(OpaqueTypeKey<'tcx>) -> Option<Ty<'tcx>>,
) -> bool {
let Ok(result) = self.apply_inner::<!>(
tcx,
- param_env,
+ typing_env,
&mut Default::default(),
&|id| Ok(tcx.is_descendant_of(module_def_id, id)),
reveal_opaque,
@@ -59,25 +64,25 @@ pub fn apply_revealing_opaque(
}
/// Same as `apply`, but returns `None` if self contains a module predicate
- pub fn apply_any_module(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<bool> {
- self.apply_inner(tcx, param_env, &mut Default::default(), &|_| Err(()), &|_| None).ok()
+ pub fn apply_any_module(self, tcx: TyCtxt<'tcx>, typing_env: TypingEnv<'tcx>) -> Option<bool> {
+ self.apply_inner(tcx, typing_env, &mut Default::default(), &|_| Err(()), &|_| None).ok()
}
/// Same as `apply`, but `NotInModule(_)` predicates yield `false`. That is,
/// privately uninhabited types are considered always uninhabited.
- pub fn apply_ignore_module(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> bool {
+ pub fn apply_ignore_module(self, tcx: TyCtxt<'tcx>, typing_env: TypingEnv<'tcx>) -> bool {
let Ok(result) =
- self.apply_inner::<!>(tcx, param_env, &mut Default::default(), &|_| Ok(true), &|_| {
+ self.apply_inner::<!>(tcx, typing_env, &mut Default::default(), &|_| Ok(true), &|_| {
None
});
result
}
- #[instrument(level = "debug", skip(tcx, param_env, in_module, reveal_opaque), ret)]
+ #[instrument(level = "debug", skip(tcx, typing_env, in_module, reveal_opaque), ret)]
fn apply_inner<E: std::fmt::Debug>(
self,
tcx: TyCtxt<'tcx>,
- param_env: ParamEnv<'tcx>,
+ typing_env: TypingEnv<'tcx>,
eval_stack: &mut SmallVec<[Ty<'tcx>; 1]>, // for cycle detection
in_module: &impl Fn(DefId) -> Result<bool, E>,
reveal_opaque: &impl Fn(OpaqueTypeKey<'tcx>) -> Option<Ty<'tcx>>,
@@ -94,7 +99,7 @@ fn apply_inner<E: std::fmt::Debug>(
// we have a param_env available, we can do better.
Self::GenericType(t) => {
let normalized_pred = tcx
- .try_normalize_erasing_regions(param_env, t)
+ .try_normalize_erasing_regions(typing_env, t)
.map_or(self, |t| t.inhabited_predicate(tcx));
match normalized_pred {
// We don't have more information than we started with, so consider inhabited.
@@ -107,7 +112,7 @@ fn apply_inner<E: std::fmt::Debug>(
}
eval_stack.push(t);
let ret =
- pred.apply_inner(tcx, param_env, eval_stack, in_module, reveal_opaque);
+ pred.apply_inner(tcx, typing_env, eval_stack, in_module, reveal_opaque);
eval_stack.pop();
ret
}
@@ -126,7 +131,7 @@ fn apply_inner<E: std::fmt::Debug>(
eval_stack.push(t);
let ret = t.inhabited_predicate(tcx).apply_inner(
tcx,
- param_env,
+ typing_env,
eval_stack,
in_module,
reveal_opaque,
@@ -136,10 +141,10 @@ fn apply_inner<E: std::fmt::Debug>(
}
},
Self::And([a, b]) => try_and(a, b, |x| {
- x.apply_inner(tcx, param_env, eval_stack, in_module, reveal_opaque)
+ x.apply_inner(tcx, typing_env, eval_stack, in_module, reveal_opaque)
}),
Self::Or([a, b]) => try_or(a, b, |x| {
- x.apply_inner(tcx, param_env, eval_stack, in_module, reveal_opaque)
+ x.apply_inner(tcx, typing_env, eval_stack, in_module, reveal_opaque)
}),
}
}
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
index dd00db8..4a5f6d8 100644
--- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
+++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
@@ -181,18 +181,18 @@ pub fn is_inhabited_from(
self,
tcx: TyCtxt<'tcx>,
module: DefId,
- param_env: ty::ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
) -> bool {
- self.inhabited_predicate(tcx).apply(tcx, param_env, module)
+ self.inhabited_predicate(tcx).apply(tcx, typing_env, module)
}
/// Returns true if the type is uninhabited without regard to visibility
pub fn is_privately_uninhabited(
self,
tcx: TyCtxt<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
) -> bool {
- !self.inhabited_predicate(tcx).apply_ignore_module(tcx, param_env)
+ !self.inhabited_predicate(tcx).apply_ignore_module(tcx, typing_env)
}
}
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index 0d1c56f..d42b6be 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -178,9 +178,9 @@ pub enum InstanceKind<'tcx> {
impl<'tcx> Instance<'tcx> {
/// Returns the `Ty` corresponding to this `Instance`, with generic instantiations applied and
/// lifetimes erased, allowing a `ParamEnv` to be specified for use during normalization.
- pub fn ty(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Ty<'tcx> {
+ pub fn ty(&self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> Ty<'tcx> {
let ty = tcx.type_of(self.def.def_id());
- tcx.instantiate_and_normalize_erasing_regions(self.args, param_env, ty)
+ tcx.instantiate_and_normalize_erasing_regions(self.args, typing_env, ty)
}
/// Finds a crate that contains a monomorphization of this instance that
@@ -519,7 +519,7 @@ pub fn def_id(&self) -> DefId {
#[instrument(level = "debug", skip(tcx), ret)]
pub fn try_resolve(
tcx: TyCtxt<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
def_id: DefId,
args: GenericArgsRef<'tcx>,
) -> Result<Option<Instance<'tcx>>, ErrorGuaranteed> {
@@ -537,17 +537,14 @@ pub fn try_resolve(
// All regions in the result of this query are erased, so it's
// fine to erase all of the input regions.
-
- // HACK(eddyb) erase regions in `args` first, so that `param_env.and(...)`
- // below is more likely to ignore the bounds in scope (e.g. if the only
- // generic parameters mentioned by `args` were lifetime ones).
+ let typing_env = tcx.erase_regions(typing_env);
let args = tcx.erase_regions(args);
- tcx.resolve_instance_raw(tcx.erase_regions(param_env.and((def_id, args))))
+ tcx.resolve_instance_raw(typing_env.as_query_input((def_id, args)))
}
pub fn expect_resolve(
tcx: TyCtxt<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
def_id: DefId,
args: GenericArgsRef<'tcx>,
span: Span,
@@ -558,7 +555,7 @@ pub fn expect_resolve(
let span_or_local_def_span =
|| if span.is_dummy() && def_id.is_local() { tcx.def_span(def_id) } else { span };
- match ty::Instance::try_resolve(tcx, param_env, def_id, args) {
+ match ty::Instance::try_resolve(tcx, typing_env, def_id, args) {
Ok(Some(instance)) => instance,
Ok(None) => {
let type_length = type_length(args);
@@ -600,7 +597,7 @@ pub fn expect_resolve(
pub fn resolve_for_fn_ptr(
tcx: TyCtxt<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
def_id: DefId,
args: GenericArgsRef<'tcx>,
) -> Option<Instance<'tcx>> {
@@ -608,7 +605,7 @@ pub fn resolve_for_fn_ptr(
// Use either `resolve_closure` or `resolve_for_vtable`
assert!(!tcx.is_closure_like(def_id), "Called `resolve_for_fn_ptr` on closure: {def_id:?}");
let reason = tcx.sess.is_sanitizer_kcfi_enabled().then_some(ReifyReason::FnPtr);
- Instance::try_resolve(tcx, param_env, def_id, args).ok().flatten().map(|mut resolved| {
+ Instance::try_resolve(tcx, typing_env, def_id, args).ok().flatten().map(|mut resolved| {
match resolved.def {
InstanceKind::Item(def) if resolved.def.requires_caller_location(tcx) => {
debug!(" => fn pointer created for function with #[track_caller]");
@@ -648,7 +645,7 @@ pub fn resolve_for_fn_ptr(
pub fn expect_resolve_for_vtable(
tcx: TyCtxt<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
def_id: DefId,
args: GenericArgsRef<'tcx>,
span: Span,
@@ -664,7 +661,7 @@ pub fn expect_resolve_for_vtable(
return Instance { def: InstanceKind::VTableShim(def_id), args };
}
- let mut resolved = Instance::expect_resolve(tcx, param_env, def_id, args, span);
+ let mut resolved = Instance::expect_resolve(tcx, typing_env, def_id, args, span);
let reason = tcx.sess.is_sanitizer_kcfi_enabled().then_some(ReifyReason::Vtable);
match resolved.def {
@@ -743,7 +740,7 @@ pub fn resolve_drop_in_place(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ty::Instance<'t
let args = tcx.mk_args(&[ty.into()]);
Instance::expect_resolve(
tcx,
- ty::ParamEnv::reveal_all(),
+ ty::TypingEnv::fully_monomorphized(),
def_id,
args,
ty.ty_adt_def().and_then(|adt| tcx.hir().span_if_local(adt.did())).unwrap_or(DUMMY_SP),
@@ -755,7 +752,7 @@ pub fn resolve_async_drop_in_place(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ty::Insta
let args = tcx.mk_args(&[ty.into()]);
Instance::expect_resolve(
tcx,
- ty::ParamEnv::reveal_all(),
+ ty::TypingEnv::fully_monomorphized(),
def_id,
args,
ty.ty_adt_def().and_then(|adt| tcx.hir().span_if_local(adt.did())).unwrap_or(DUMMY_SP),
@@ -883,16 +880,16 @@ pub fn instantiate_mir<T>(&self, tcx: TyCtxt<'tcx>, v: EarlyBinder<'tcx, &T>) ->
pub fn instantiate_mir_and_normalize_erasing_regions<T>(
&self,
tcx: TyCtxt<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
v: EarlyBinder<'tcx, T>,
) -> T
where
T: TypeFoldable<TyCtxt<'tcx>>,
{
if let Some(args) = self.args_for_mir_body() {
- tcx.instantiate_and_normalize_erasing_regions(args, param_env, v)
+ tcx.instantiate_and_normalize_erasing_regions(args, typing_env, v)
} else {
- tcx.normalize_erasing_regions(param_env, v.instantiate_identity())
+ tcx.normalize_erasing_regions(typing_env, v.instantiate_identity())
}
}
@@ -901,21 +898,21 @@ pub fn instantiate_mir_and_normalize_erasing_regions<T>(
pub fn try_instantiate_mir_and_normalize_erasing_regions<T>(
&self,
tcx: TyCtxt<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
v: EarlyBinder<'tcx, T>,
) -> Result<T, NormalizationError<'tcx>>
where
T: TypeFoldable<TyCtxt<'tcx>>,
{
if let Some(args) = self.args_for_mir_body() {
- tcx.try_instantiate_and_normalize_erasing_regions(args, param_env, v)
+ tcx.try_instantiate_and_normalize_erasing_regions(args, typing_env, v)
} else {
// We're using `instantiate_identity` as e.g.
// `FnPtrShim` is separately generated for every
// instantiation of the `FnDef`, so the MIR body
// is already instantiated. Any generic parameters it
// contains are generic parameters from the caller.
- tcx.try_normalize_erasing_regions(param_env, v.instantiate_identity())
+ tcx.try_normalize_erasing_regions(typing_env, v.instantiate_identity())
}
}
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index a0eb902..8625a8d 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -297,12 +297,12 @@ fn into_diag_arg(self) -> DiagArgValue {
#[derive(Clone, Copy)]
pub struct LayoutCx<'tcx> {
pub calc: abi::LayoutCalculator<TyCtxt<'tcx>>,
- pub param_env: ty::ParamEnv<'tcx>,
+ pub typing_env: ty::TypingEnv<'tcx>,
}
impl<'tcx> LayoutCx<'tcx> {
- pub fn new(tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self {
- Self { calc: abi::LayoutCalculator::new(tcx), param_env }
+ pub fn new(tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> Self {
+ Self { calc: abi::LayoutCalculator::new(tcx), typing_env }
}
}
@@ -337,12 +337,12 @@ impl<'tcx> SizeSkeleton<'tcx> {
pub fn compute(
ty: Ty<'tcx>,
tcx: TyCtxt<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
) -> Result<SizeSkeleton<'tcx>, &'tcx LayoutError<'tcx>> {
debug_assert!(!ty.has_non_region_infer());
// First try computing a static layout.
- let err = match tcx.layout_of(param_env.and(ty)) {
+ let err = match tcx.layout_of(typing_env.as_query_input(ty)) {
Ok(layout) => {
if layout.is_sized() {
return Ok(SizeSkeleton::Known(layout.size, Some(layout.align.abi)));
@@ -367,7 +367,7 @@ pub fn compute(
let tail = tcx.struct_tail_raw(
pointee,
- |ty| match tcx.try_normalize_erasing_regions(param_env, ty) {
+ |ty| match tcx.try_normalize_erasing_regions(typing_env, ty) {
Ok(ty) => ty,
Err(e) => Ty::new_error_with_message(
tcx,
@@ -402,7 +402,7 @@ pub fn compute(
return Ok(SizeSkeleton::Known(Size::from_bytes(0), None));
}
- match SizeSkeleton::compute(inner, tcx, param_env)? {
+ match SizeSkeleton::compute(inner, tcx, typing_env)? {
// This may succeed because the multiplication of two types may overflow
// but a single size of a nested array will not.
SizeSkeleton::Known(s, a) => {
@@ -432,7 +432,7 @@ pub fn compute(
let i = VariantIdx::from_usize(i);
let fields =
def.variant(i).fields.iter().map(|field| {
- SizeSkeleton::compute(field.ty(tcx, args), tcx, param_env)
+ SizeSkeleton::compute(field.ty(tcx, args), tcx, typing_env)
});
let mut ptr = None;
for field in fields {
@@ -491,11 +491,11 @@ pub fn compute(
}
ty::Alias(..) => {
- let normalized = tcx.normalize_erasing_regions(param_env, ty);
+ let normalized = tcx.normalize_erasing_regions(typing_env, ty);
if ty == normalized {
Err(err)
} else {
- SizeSkeleton::compute(normalized, tcx, param_env)
+ SizeSkeleton::compute(normalized, tcx, typing_env)
}
}
@@ -521,8 +521,14 @@ pub trait HasTyCtxt<'tcx>: HasDataLayout {
fn tcx(&self) -> TyCtxt<'tcx>;
}
-pub trait HasParamEnv<'tcx> {
- fn param_env(&self) -> ty::ParamEnv<'tcx>;
+pub trait HasTypingEnv<'tcx> {
+ fn typing_env(&self) -> ty::TypingEnv<'tcx>;
+
+ /// FIXME(#132279): This method should not be used as in the future
+ /// everything should take a `TypingEnv` instead. Remove it as that point.
+ fn param_env(&self) -> ty::ParamEnv<'tcx> {
+ self.typing_env().param_env
+ }
}
impl<'tcx> HasDataLayout for TyCtxt<'tcx> {
@@ -577,9 +583,9 @@ fn tcx(&self) -> TyCtxt<'tcx> {
}
}
-impl<'tcx> HasParamEnv<'tcx> for LayoutCx<'tcx> {
- fn param_env(&self) -> ty::ParamEnv<'tcx> {
- self.param_env
+impl<'tcx> HasTypingEnv<'tcx> for LayoutCx<'tcx> {
+ fn typing_env(&self) -> ty::TypingEnv<'tcx> {
+ self.typing_env
}
}
@@ -646,7 +652,7 @@ fn to_result(self) -> Result<T, Self::Error> {
/// Trait for contexts that want to be able to compute layouts of types.
/// This automatically gives access to `LayoutOf`, through a blanket `impl`.
-pub trait LayoutOfHelpers<'tcx>: HasDataLayout + HasTyCtxt<'tcx> + HasParamEnv<'tcx> {
+pub trait LayoutOfHelpers<'tcx>: HasDataLayout + HasTyCtxt<'tcx> + HasTypingEnv<'tcx> {
/// The `TyAndLayout`-wrapping type (or `TyAndLayout` itself), which will be
/// returned from `layout_of` (see also `handle_layout_err`).
type LayoutOfResult: MaybeResult<TyAndLayout<'tcx>> = TyAndLayout<'tcx>;
@@ -692,7 +698,7 @@ fn spanned_layout_of(&self, ty: Ty<'tcx>, span: Span) -> Self::LayoutOfResult {
let tcx = self.tcx().at(span);
MaybeResult::from(
- tcx.layout_of(self.param_env().and(ty))
+ tcx.layout_of(self.typing_env().as_query_input(ty))
.map_err(|err| self.handle_layout_err(*err, span, ty)),
)
}
@@ -716,7 +722,7 @@ fn handle_layout_err(
impl<'tcx, C> TyAbiInterface<'tcx, C> for Ty<'tcx>
where
- C: HasTyCtxt<'tcx> + HasParamEnv<'tcx>,
+ C: HasTyCtxt<'tcx> + HasTypingEnv<'tcx>,
{
fn ty_and_layout_for_variant(
this: TyAndLayout<'tcx>,
@@ -736,10 +742,10 @@ fn ty_and_layout_for_variant(
Variants::Single { index } => {
let tcx = cx.tcx();
- let param_env = cx.param_env();
+ let typing_env = cx.typing_env();
// Deny calling for_variant more than once for non-Single enums.
- if let Ok(original_layout) = tcx.layout_of(param_env.and(this.ty)) {
+ if let Ok(original_layout) = tcx.layout_of(typing_env.as_query_input(this.ty)) {
assert_eq!(original_layout.variants, Variants::Single { index });
}
@@ -780,7 +786,7 @@ enum TyMaybeWithLayout<'tcx> {
fn field_ty_or_layout<'tcx>(
this: TyAndLayout<'tcx>,
- cx: &(impl HasTyCtxt<'tcx> + HasParamEnv<'tcx>),
+ cx: &(impl HasTyCtxt<'tcx> + HasTypingEnv<'tcx>),
i: usize,
) -> TyMaybeWithLayout<'tcx> {
let tcx = cx.tcx();
@@ -823,12 +829,13 @@ fn field_ty_or_layout<'tcx>(
Ty::new_mut_ref(tcx, tcx.lifetimes.re_static, nil)
};
- // NOTE(eddyb) using an empty `ParamEnv`, and `unwrap`-ing
- // the `Result` should always work because the type is
- // always either `*mut ()` or `&'static mut ()`.
+ // NOTE: using an fully monomorphized typing env and `unwrap`-ing
+ // the `Result` should always work because the type is always either
+ // `*mut ()` or `&'static mut ()`.
+ let typing_env = ty::TypingEnv::fully_monomorphized();
return TyMaybeWithLayout::TyAndLayout(TyAndLayout {
ty: this.ty,
- ..tcx.layout_of(ty::ParamEnv::reveal_all().and(unit_ptr_ty)).unwrap()
+ ..tcx.layout_of(typing_env.as_query_input(unit_ptr_ty)).unwrap()
});
}
@@ -848,7 +855,7 @@ fn field_ty_or_layout<'tcx>(
&& !pointee.references_error()
{
let metadata = tcx.normalize_erasing_regions(
- cx.param_env(),
+ cx.typing_env(),
Ty::new_projection(tcx, metadata_def_id, [pointee]),
);
@@ -865,7 +872,7 @@ fn field_ty_or_layout<'tcx>(
metadata
}
} else {
- match tcx.struct_tail_for_codegen(pointee, cx.param_env()).kind() {
+ match tcx.struct_tail_for_codegen(pointee, cx.typing_env()).kind() {
ty::Slice(_) | ty::Str => tcx.types.usize,
ty::Dynamic(data, _, ty::Dyn) => mk_dyn_vtable(data.principal()),
_ => bug!("TyAndLayout::field({:?}): not applicable", this),
@@ -953,7 +960,7 @@ fn field_ty_or_layout<'tcx>(
match field_ty_or_layout(this, cx, i) {
TyMaybeWithLayout::Ty(field_ty) => {
- cx.tcx().layout_of(cx.param_env().and(field_ty)).unwrap_or_else(|e| {
+ cx.tcx().layout_of(cx.typing_env().as_query_input(field_ty)).unwrap_or_else(|e| {
bug!(
"failed to get layout for `{field_ty}`: {e:?},\n\
despite it being a field (#{i}) of an existing layout: {this:#?}",
@@ -972,18 +979,18 @@ fn ty_and_layout_pointee_info_at(
offset: Size,
) -> Option<PointeeInfo> {
let tcx = cx.tcx();
- let param_env = cx.param_env();
+ let typing_env = cx.typing_env();
let pointee_info = match *this.ty.kind() {
ty::RawPtr(p_ty, _) if offset.bytes() == 0 => {
- tcx.layout_of(param_env.and(p_ty)).ok().map(|layout| PointeeInfo {
+ tcx.layout_of(typing_env.as_query_input(p_ty)).ok().map(|layout| PointeeInfo {
size: layout.size,
align: layout.align.abi,
safe: None,
})
}
ty::FnPtr(..) if offset.bytes() == 0 => {
- tcx.layout_of(param_env.and(this.ty)).ok().map(|layout| PointeeInfo {
+ tcx.layout_of(typing_env.as_query_input(this.ty)).ok().map(|layout| PointeeInfo {
size: layout.size,
align: layout.align.abi,
safe: None,
@@ -996,14 +1003,14 @@ fn ty_and_layout_pointee_info_at(
let optimize = tcx.sess.opts.optimize != OptLevel::No;
let kind = match mt {
hir::Mutability::Not => PointerKind::SharedRef {
- frozen: optimize && ty.is_freeze(tcx, cx.param_env()),
+ frozen: optimize && ty.is_freeze(tcx, typing_env.param_env),
},
hir::Mutability::Mut => PointerKind::MutableRef {
- unpin: optimize && ty.is_unpin(tcx, cx.param_env()),
+ unpin: optimize && ty.is_unpin(tcx, typing_env.param_env),
},
};
- tcx.layout_of(param_env.and(ty)).ok().map(|layout| PointeeInfo {
+ tcx.layout_of(typing_env.as_query_input(ty)).ok().map(|layout| PointeeInfo {
size: layout.size,
align: layout.align.abi,
safe: Some(kind),
@@ -1093,7 +1100,7 @@ fn ty_and_layout_pointee_info_at(
debug_assert!(pointee.safe.is_none());
let optimize = tcx.sess.opts.optimize != OptLevel::No;
pointee.safe = Some(PointerKind::Box {
- unpin: optimize && boxed_ty.is_unpin(tcx, cx.param_env()),
+ unpin: optimize && boxed_ty.is_unpin(tcx, typing_env.param_env),
global: this.ty.is_box_global(tcx),
});
}
@@ -1304,9 +1311,11 @@ fn fn_abi_of_fn_ptr(
let span = self.layout_tcx_at_span();
let tcx = self.tcx().at(span);
- MaybeResult::from(tcx.fn_abi_of_fn_ptr(self.param_env().and((sig, extra_args))).map_err(
- |err| self.handle_fn_abi_err(*err, span, FnAbiRequest::OfFnPtr { sig, extra_args }),
- ))
+ MaybeResult::from(
+ tcx.fn_abi_of_fn_ptr(self.typing_env().as_query_input((sig, extra_args))).map_err(
+ |err| self.handle_fn_abi_err(*err, span, FnAbiRequest::OfFnPtr { sig, extra_args }),
+ ),
+ )
}
/// Compute a `FnAbi` suitable for declaring/defining an `fn` instance, and for
@@ -1326,17 +1335,19 @@ fn fn_abi_of_instance(
let tcx = self.tcx().at(span);
MaybeResult::from(
- tcx.fn_abi_of_instance(self.param_env().and((instance, extra_args))).map_err(|err| {
- // HACK(eddyb) at least for definitions of/calls to `Instance`s,
- // we can get some kind of span even if one wasn't provided.
- // However, we don't do this early in order to avoid calling
- // `def_span` unconditionally (which may have a perf penalty).
- let span = if !span.is_dummy() { span } else { tcx.def_span(instance.def_id()) };
- self.handle_fn_abi_err(*err, span, FnAbiRequest::OfInstance {
- instance,
- extra_args,
- })
- }),
+ tcx.fn_abi_of_instance(self.typing_env().as_query_input((instance, extra_args)))
+ .map_err(|err| {
+ // HACK(eddyb) at least for definitions of/calls to `Instance`s,
+ // we can get some kind of span even if one wasn't provided.
+ // However, we don't do this early in order to avoid calling
+ // `def_span` unconditionally (which may have a perf penalty).
+ let span =
+ if !span.is_dummy() { span } else { tcx.def_span(instance.def_id()) };
+ self.handle_fn_abi_err(*err, span, FnAbiRequest::OfInstance {
+ instance,
+ extra_args,
+ })
+ }),
)
}
}
@@ -1346,14 +1357,14 @@ impl<'tcx, C: FnAbiOfHelpers<'tcx>> FnAbiOf<'tcx> for C {}
impl<'tcx> TyCtxt<'tcx> {
pub fn offset_of_subfield<I>(
self,
- param_env: ty::ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
mut layout: TyAndLayout<'tcx>,
indices: I,
) -> Size
where
I: Iterator<Item = (VariantIdx, FieldIdx)>,
{
- let cx = LayoutCx::new(self, param_env);
+ let cx = LayoutCx::new(self, typing_env);
let mut offset = Size::ZERO;
for (variant, field) in indices {
@@ -1363,7 +1374,7 @@ pub fn offset_of_subfield<I>(
layout = layout.field(&cx, index);
if !layout.is_sized() {
// If it is not sized, then the tail must still have at least a known static alignment.
- let tail = self.struct_tail_for_codegen(layout.ty, param_env);
+ let tail = self.struct_tail_for_codegen(layout.ty, typing_env);
if !matches!(tail.kind(), ty::Slice(..)) {
bug!(
"offset of not-statically-aligned field (type {:?}) cannot be computed statically",
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 7fda066..cddd611 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -103,7 +103,7 @@
use crate::metadata::ModChild;
use crate::middle::privacy::EffectiveVisibilities;
use crate::mir::{Body, CoroutineLayout};
-use crate::query::Providers;
+use crate::query::{IntoQueryParam, Providers};
use crate::traits::{self, Reveal};
use crate::ty;
pub use crate::ty::diagnostics::*;
@@ -1122,6 +1122,105 @@ pub fn into_parts(self) -> (ParamEnv<'tcx>, T) {
}
}
+/// The environment in which to do trait solving.
+///
+/// Most of the time you only need to care about the `ParamEnv`
+/// as the `TypingMode` is simply stored in the `InferCtxt`.
+///
+/// However, there are some places which rely on trait solving
+/// without using an `InferCtxt` themselves. For these to be
+/// able to use the trait system they have to be able to initialize
+/// such an `InferCtxt` with the right `typing_mode`, so they need
+/// to track both.
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
+#[derive(TypeVisitable, TypeFoldable)]
+pub struct TypingEnv<'tcx> {
+ pub typing_mode: TypingMode<'tcx>,
+ pub param_env: ParamEnv<'tcx>,
+}
+
+impl<'tcx> TypingEnv<'tcx> {
+ // FIXME(#132279): This method should be removed but simplifies the
+ // transition.
+ pub fn from_param_env(param_env: ParamEnv<'tcx>) -> TypingEnv<'tcx> {
+ TypingEnv { typing_mode: TypingMode::from_param_env(param_env), param_env }
+ }
+
+ /// Create a typing environment with no where-clauses in scope
+ /// where all opaque types and default associated items are revealed.
+ ///
+ /// This is only suitable for monomorphized, post-typeck environments.
+ /// Do not use this for MIR optimizations, as even though they also
+ /// use `TypingMode::PostAnalysis`, they may still have where-clauses
+ /// in scope.
+ pub fn fully_monomorphized() -> TypingEnv<'tcx> {
+ TypingEnv { typing_mode: TypingMode::PostAnalysis, param_env: ParamEnv::reveal_all() }
+ }
+
+ /// Create a typing environment for use during analysis outside of a body.
+ ///
+ /// Using a typing environment inside of bodies is not supported as the body
+ /// may define opaque types. In this case the used functions have to be
+ /// converted to use proper canonical inputs instead.
+ pub fn non_body_analysis(
+ tcx: TyCtxt<'tcx>,
+ def_id: impl IntoQueryParam<DefId>,
+ ) -> TypingEnv<'tcx> {
+ TypingEnv { typing_mode: TypingMode::non_body_analysis(), param_env: tcx.param_env(def_id) }
+ }
+
+ pub fn post_analysis(tcx: TyCtxt<'tcx>, def_id: impl IntoQueryParam<DefId>) -> TypingEnv<'tcx> {
+ TypingEnv {
+ typing_mode: TypingMode::PostAnalysis,
+ param_env: tcx.param_env_reveal_all_normalized(def_id),
+ }
+ }
+
+ /// Modify the `typing_mode` to `PostAnalysis` and eagerly reveal all
+ /// opaque types in the `param_env`.
+ pub fn with_reveal_all_normalized(self, tcx: TyCtxt<'tcx>) -> TypingEnv<'tcx> {
+ let TypingEnv { typing_mode: _, param_env } = self;
+ let param_env = param_env.with_reveal_all_normalized(tcx);
+ TypingEnv { typing_mode: TypingMode::PostAnalysis, param_env }
+ }
+
+ /// Combine this typing environment with the given `value` to be used by
+ /// not (yet) canonicalized queries. This only works if the value does not
+ /// contain anything local to some `InferCtxt`, i.e. inference variables or
+ /// placeholders.
+ pub fn as_query_input<T>(self, value: T) -> PseudoCanonicalInput<'tcx, T>
+ where
+ T: TypeVisitable<TyCtxt<'tcx>>,
+ {
+ debug_assert!(!value.has_infer());
+ // FIXME(#132279): We should assert that the value does not contain any placeholders
+ // as these placeholders are also local to the current inference context. However, we
+ // currently use pseudo-canonical queries in the trait solver which replaces params with
+ // placeholders. We should also simply not use pseudo-canonical queries in the trait
+ // solver, at which point we can readd this assert. As of writing this comment, this is
+ // only used by `fn layout_is_pointer_like` when calling `layout_of`.
+ //
+ // debug_assert!(!value.has_placeholders());
+ PseudoCanonicalInput { typing_env: self, value }
+ }
+}
+
+/// Similar to `CanonicalInput`, this carries the `typing_mode` and the environment
+/// necessary to do any kind of trait solving inside of nested queries.
+///
+/// Unlike proper canonicalization, this requires the `param_env` and the `value` to not
+/// contain anything local to the `infcx` of the caller, so we don't actually canonicalize
+/// anything.
+///
+/// This should be created by using `infcx.pseudo_canonicalize_query(param_env, value)`
+/// or by using `typing_env.as_query_input(value)`.
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+#[derive(HashStable)]
+pub struct PseudoCanonicalInput<'tcx, T> {
+ pub typing_env: TypingEnv<'tcx>,
+ pub value: T,
+}
+
#[derive(Copy, Clone, Debug, HashStable, Encodable, Decodable)]
pub struct Destructor {
/// The `DefId` of the destructor method
diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
index e51d220..f611b69 100644
--- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
+++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
@@ -35,16 +35,16 @@ impl<'tcx> TyCtxt<'tcx> {
///
/// This should only be used outside of type inference. For example,
/// it assumes that normalization will succeed.
- #[tracing::instrument(level = "debug", skip(self, param_env), ret)]
- pub fn normalize_erasing_regions<T>(self, param_env: ty::ParamEnv<'tcx>, value: T) -> T
+ #[tracing::instrument(level = "debug", skip(self, typing_env), ret)]
+ pub fn normalize_erasing_regions<T>(self, typing_env: ty::TypingEnv<'tcx>, value: T) -> T
where
T: TypeFoldable<TyCtxt<'tcx>>,
{
debug!(
- "normalize_erasing_regions::<{}>(value={:?}, param_env={:?})",
+ "normalize_erasing_regions::<{}>(value={:?}, typing_env={:?})",
std::any::type_name::<T>(),
value,
- param_env,
+ typing_env,
);
// Erase first before we do the real query -- this keeps the
@@ -55,7 +55,7 @@ pub fn normalize_erasing_regions<T>(self, param_env: ty::ParamEnv<'tcx>, value:
if !value.has_aliases() {
value
} else {
- value.fold_with(&mut NormalizeAfterErasingRegionsFolder { tcx: self, param_env })
+ value.fold_with(&mut NormalizeAfterErasingRegionsFolder { tcx: self, typing_env })
}
}
@@ -66,17 +66,17 @@ pub fn normalize_erasing_regions<T>(self, param_env: ty::ParamEnv<'tcx>, value:
/// succeeds.
pub fn try_normalize_erasing_regions<T>(
self,
- param_env: ty::ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
value: T,
) -> Result<T, NormalizationError<'tcx>>
where
T: TypeFoldable<TyCtxt<'tcx>>,
{
debug!(
- "try_normalize_erasing_regions::<{}>(value={:?}, param_env={:?})",
+ "try_normalize_erasing_regions::<{}>(value={:?}, typing_env={:?})",
std::any::type_name::<T>(),
value,
- param_env,
+ typing_env,
);
// Erase first before we do the real query -- this keeps the
@@ -87,7 +87,7 @@ pub fn try_normalize_erasing_regions<T>(
if !value.has_aliases() {
Ok(value)
} else {
- let mut folder = TryNormalizeAfterErasingRegionsFolder::new(self, param_env);
+ let mut folder = TryNormalizeAfterErasingRegionsFolder::new(self, typing_env);
value.try_fold_with(&mut folder)
}
}
@@ -103,17 +103,17 @@ pub fn try_normalize_erasing_regions<T>(
// FIXME(@lcnr): This method should not be necessary, we now normalize
// inside of binders. We should be able to only use
// `tcx.instantiate_bound_regions_with_erased`.
- #[tracing::instrument(level = "debug", skip(self, param_env))]
+ #[tracing::instrument(level = "debug", skip(self, typing_env))]
pub fn normalize_erasing_late_bound_regions<T>(
self,
- param_env: ty::ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
value: ty::Binder<'tcx, T>,
) -> T
where
T: TypeFoldable<TyCtxt<'tcx>>,
{
let value = self.instantiate_bound_regions_with_erased(value);
- self.normalize_erasing_regions(param_env, value)
+ self.normalize_erasing_regions(typing_env, value)
}
/// Monomorphizes a type from the AST by first applying the
@@ -125,14 +125,14 @@ pub fn normalize_erasing_late_bound_regions<T>(
pub fn instantiate_and_normalize_erasing_regions<T>(
self,
param_args: GenericArgsRef<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
value: EarlyBinder<'tcx, T>,
) -> T
where
T: TypeFoldable<TyCtxt<'tcx>>,
{
let instantiated = value.instantiate(self, param_args);
- self.normalize_erasing_regions(param_env, instantiated)
+ self.normalize_erasing_regions(typing_env, instantiated)
}
/// Monomorphizes a type from the AST by first applying the
@@ -143,20 +143,20 @@ pub fn instantiate_and_normalize_erasing_regions<T>(
pub fn try_instantiate_and_normalize_erasing_regions<T>(
self,
param_args: GenericArgsRef<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
value: EarlyBinder<'tcx, T>,
) -> Result<T, NormalizationError<'tcx>>
where
T: TypeFoldable<TyCtxt<'tcx>>,
{
let instantiated = value.instantiate(self, param_args);
- self.try_normalize_erasing_regions(param_env, instantiated)
+ self.try_normalize_erasing_regions(typing_env, instantiated)
}
}
struct NormalizeAfterErasingRegionsFolder<'tcx> {
tcx: TyCtxt<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
}
impl<'tcx> NormalizeAfterErasingRegionsFolder<'tcx> {
@@ -164,8 +164,7 @@ fn normalize_generic_arg_after_erasing_regions(
&self,
arg: ty::GenericArg<'tcx>,
) -> ty::GenericArg<'tcx> {
- let arg = self.param_env.and(arg);
-
+ let arg = self.typing_env.as_query_input(arg);
self.tcx.try_normalize_generic_arg_after_erasing_regions(arg).unwrap_or_else(|_| bug!(
"Failed to normalize {:?}, maybe try to call `try_normalize_erasing_regions` instead",
arg.value
@@ -189,12 +188,12 @@ fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> {
struct TryNormalizeAfterErasingRegionsFolder<'tcx> {
tcx: TyCtxt<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
}
impl<'tcx> TryNormalizeAfterErasingRegionsFolder<'tcx> {
- fn new(tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self {
- TryNormalizeAfterErasingRegionsFolder { tcx, param_env }
+ fn new(tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> Self {
+ TryNormalizeAfterErasingRegionsFolder { tcx, typing_env }
}
#[instrument(skip(self), level = "debug")]
@@ -202,10 +201,8 @@ fn try_normalize_generic_arg_after_erasing_regions(
&self,
arg: ty::GenericArg<'tcx>,
) -> Result<ty::GenericArg<'tcx>, NoSolution> {
- let arg = self.param_env.and(arg);
- debug!(?arg);
-
- self.tcx.try_normalize_generic_arg_after_erasing_regions(arg)
+ let input = self.typing_env.as_query_input(arg);
+ self.tcx.try_normalize_generic_arg_after_erasing_regions(input)
}
}
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 3c6e341..703a782 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -18,6 +18,7 @@
use smallvec::{SmallVec, smallvec};
use tracing::{debug, instrument};
+use super::TypingEnv;
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use crate::query::Providers;
use crate::ty::layout::{FloatExt, IntegerExt};
@@ -177,9 +178,13 @@ pub fn res_generics_def_id(self, res: Res) -> Option<DefId> {
/// Should only be called if `ty` has no inference variables and does not
/// need its lifetimes preserved (e.g. as part of codegen); otherwise
/// normalization attempt may cause compiler bugs.
- pub fn struct_tail_for_codegen(self, ty: Ty<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Ty<'tcx> {
+ pub fn struct_tail_for_codegen(
+ self,
+ ty: Ty<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
+ ) -> Ty<'tcx> {
let tcx = self;
- tcx.struct_tail_raw(ty, |ty| tcx.normalize_erasing_regions(param_env, ty), || {})
+ tcx.struct_tail_raw(ty, |ty| tcx.normalize_erasing_regions(typing_env, ty), || {})
}
/// Returns the deeply last field of nested structures, or the same type if
@@ -271,11 +276,11 @@ pub fn struct_lockstep_tails_for_codegen(
self,
source: Ty<'tcx>,
target: Ty<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
) -> (Ty<'tcx>, Ty<'tcx>) {
let tcx = self;
tcx.struct_lockstep_tails_raw(source, target, |ty| {
- tcx.normalize_erasing_regions(param_env, ty)
+ tcx.normalize_erasing_regions(typing_env, ty)
})
}
@@ -420,10 +425,10 @@ pub fn async_drop_glue_morphology(self, did: DefId) -> AsyncDropGlueMorphology {
// Async drop glue morphology is an internal detail, so reveal_all probably
// should be fine
- let param_env = ty::ParamEnv::reveal_all();
- if ty.needs_async_drop(self, param_env) {
+ let typing_env = ty::TypingEnv::fully_monomorphized();
+ if ty.needs_async_drop(self, typing_env) {
AsyncDropGlueMorphology::Custom
- } else if ty.needs_drop(self, param_env) {
+ } else if ty.needs_drop(self, typing_env) {
AsyncDropGlueMorphology::DeferredDropInPlace
} else {
AsyncDropGlueMorphology::Noop
@@ -683,12 +688,10 @@ pub fn thread_local_ptr_ty(self, def_id: DefId) -> Ty<'tcx> {
}
/// Get the type of the pointer to the static that we use in MIR.
- pub fn static_ptr_ty(self, def_id: DefId) -> Ty<'tcx> {
+ pub fn static_ptr_ty(self, def_id: DefId, typing_env: ty::TypingEnv<'tcx>) -> Ty<'tcx> {
// Make sure that any constants in the static's type are evaluated.
- let static_ty = self.normalize_erasing_regions(
- ty::ParamEnv::empty(),
- self.type_of(def_id).instantiate_identity(),
- );
+ let static_ty =
+ self.normalize_erasing_regions(typing_env, self.type_of(def_id).instantiate_identity());
// Make sure that accesses to unsafe statics end up using raw pointers.
// For thread-locals, this needs to be kept in sync with `Rvalue::ty`.
@@ -1157,15 +1160,17 @@ pub fn numeric_min_and_max_as_bits(self, tcx: TyCtxt<'tcx>) -> Option<(u128, u12
/// Returns the maximum value for the given numeric type (including `char`s)
/// or returns `None` if the type is not numeric.
pub fn numeric_max_val(self, tcx: TyCtxt<'tcx>) -> Option<ty::Const<'tcx>> {
+ let typing_env = TypingEnv::fully_monomorphized();
self.numeric_min_and_max_as_bits(tcx)
- .map(|(_, max)| ty::Const::from_bits(tcx, max, ty::ParamEnv::empty().and(self)))
+ .map(|(_, max)| ty::Const::from_bits(tcx, max, typing_env, self))
}
/// Returns the minimum value for the given numeric type (including `char`s)
/// or returns `None` if the type is not numeric.
pub fn numeric_min_val(self, tcx: TyCtxt<'tcx>) -> Option<ty::Const<'tcx>> {
+ let typing_env = TypingEnv::fully_monomorphized();
self.numeric_min_and_max_as_bits(tcx)
- .map(|(min, _)| ty::Const::from_bits(tcx, min, ty::ParamEnv::empty().and(self)))
+ .map(|(min, _)| ty::Const::from_bits(tcx, min, typing_env, self))
}
/// Checks whether values of this type `T` are *moved* or *copied*
@@ -1345,7 +1350,7 @@ pub fn async_drop_glue_morphology(self, tcx: TyCtxt<'tcx>) -> AsyncDropGlueMorph
///
/// Note that this method is used to check eligible types in unions.
#[inline]
- pub fn needs_drop(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool {
+ pub fn needs_drop(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> bool {
// Avoid querying in simple cases.
match needs_drop_components(tcx, self) {
Err(AlwaysRequiresDrop) => true,
@@ -1359,14 +1364,13 @@ pub fn needs_drop(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> boo
};
// This doesn't depend on regions, so try to minimize distinct
- // query keys used.
- // If normalization fails, we just use `query_ty`.
- debug_assert!(!param_env.has_infer());
+ // query keys used. If normalization fails, we just use `query_ty`.
+ debug_assert!(!typing_env.param_env.has_infer());
let query_ty = tcx
- .try_normalize_erasing_regions(param_env, query_ty)
+ .try_normalize_erasing_regions(typing_env, query_ty)
.unwrap_or_else(|_| tcx.erase_regions(query_ty));
- tcx.needs_drop_raw(param_env.and(query_ty))
+ tcx.needs_drop_raw(typing_env.as_query_input(query_ty))
}
}
}
@@ -1385,7 +1389,7 @@ pub fn needs_drop(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> boo
// FIXME(zetanumbers): Note that this method is used to check eligible types
// in unions.
#[inline]
- pub fn needs_async_drop(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool {
+ pub fn needs_async_drop(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> bool {
// Avoid querying in simple cases.
match needs_drop_components(tcx, self) {
Err(AlwaysRequiresDrop) => true,
@@ -1401,12 +1405,12 @@ pub fn needs_async_drop(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>)
// This doesn't depend on regions, so try to minimize distinct
// query keys used.
// If normalization fails, we just use `query_ty`.
- debug_assert!(!param_env.has_infer());
+ debug_assert!(!typing_env.has_infer());
let query_ty = tcx
- .try_normalize_erasing_regions(param_env, query_ty)
+ .try_normalize_erasing_regions(typing_env, query_ty)
.unwrap_or_else(|_| tcx.erase_regions(query_ty));
- tcx.needs_async_drop_raw(param_env.and(query_ty))
+ tcx.needs_async_drop_raw(typing_env.as_query_input(query_ty))
}
}
}
@@ -1420,7 +1424,7 @@ pub fn needs_async_drop(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>)
/// Note that this method is used to check for change in drop order for
/// 2229 drop reorder migration analysis.
#[inline]
- pub fn has_significant_drop(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool {
+ pub fn has_significant_drop(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> bool {
// Avoid querying in simple cases.
match needs_drop_components(tcx, self) {
Err(AlwaysRequiresDrop) => true,
@@ -1443,8 +1447,8 @@ pub fn has_significant_drop(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tc
// This doesn't depend on regions, so try to minimize distinct
// query keys used.
- let erased = tcx.normalize_erasing_regions(param_env, query_ty);
- tcx.has_significant_drop_raw(param_env.and(erased))
+ let erased = tcx.normalize_erasing_regions(typing_env, query_ty);
+ tcx.has_significant_drop_raw(typing_env.as_query_input(erased))
}
}
}
@@ -1793,7 +1797,7 @@ pub fn intrinsic_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::Intrinsi
Some(ty::IntrinsicDef {
name: tcx.item_name(def_id.into()),
must_be_overridden: tcx.has_attr(def_id, sym::rustc_intrinsic_must_be_overridden),
- const_stable: tcx.has_attr(def_id, sym::rustc_const_stable_intrinsic),
+ const_stable: tcx.has_attr(def_id, sym::rustc_intrinsic_const_stable_indirect),
})
} else {
None
diff --git a/compiler/rustc_middle/src/ty/vtable.rs b/compiler/rustc_middle/src/ty/vtable.rs
index 963fa12..e5eeb23 100644
--- a/compiler/rustc_middle/src/ty/vtable.rs
+++ b/compiler/rustc_middle/src/ty/vtable.rs
@@ -97,7 +97,7 @@ pub(super) fn vtable_allocation_provider<'tcx>(
assert!(vtable_entries.len() >= vtable_min_entries(tcx, poly_trait_ref));
let layout = tcx
- .layout_of(ty::ParamEnv::reveal_all().and(ty))
+ .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty))
.expect("failed to build vtable representation");
assert!(layout.is_sized(), "can't create a vtable for an unsized type");
let size = layout.size.bytes();
@@ -117,7 +117,7 @@ pub(super) fn vtable_allocation_provider<'tcx>(
let idx: u64 = u64::try_from(idx).unwrap();
let scalar = match entry {
VtblEntry::MetadataDropInPlace => {
- if ty.needs_drop(tcx, ty::ParamEnv::reveal_all()) {
+ if ty.needs_drop(tcx, ty::TypingEnv::fully_monomorphized()) {
let instance = ty::Instance::resolve_drop_in_place(tcx, ty);
let fn_alloc_id = tcx.reserve_and_set_fn_alloc(instance, CTFE_ALLOC_SALT);
let fn_ptr = Pointer::from(fn_alloc_id);
diff --git a/compiler/rustc_middle/src/util/call_kind.rs b/compiler/rustc_middle/src/util/call_kind.rs
index ed27a88..acfb78b 100644
--- a/compiler/rustc_middle/src/util/call_kind.rs
+++ b/compiler/rustc_middle/src/util/call_kind.rs
@@ -8,7 +8,7 @@
use rustc_span::{DesugaringKind, Span, sym};
use tracing::debug;
-use crate::ty::{AssocItemContainer, GenericArgsRef, Instance, ParamEnv, Ty, TyCtxt};
+use crate::ty::{AssocItemContainer, GenericArgsRef, Instance, Ty, TyCtxt, TypingEnv};
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum CallDesugaringKind {
@@ -62,7 +62,7 @@ pub enum CallKind<'tcx> {
pub fn call_kind<'tcx>(
tcx: TyCtxt<'tcx>,
- param_env: ParamEnv<'tcx>,
+ typing_env: TypingEnv<'tcx>,
method_did: DefId,
method_args: GenericArgsRef<'tcx>,
fn_call_span: Span,
@@ -98,10 +98,10 @@ pub fn call_kind<'tcx>(
Some(CallKind::Operator { self_arg, trait_id, self_ty: method_args.type_at(0) })
} else if is_deref {
let deref_target = tcx.get_diagnostic_item(sym::deref_target).and_then(|deref_target| {
- Instance::try_resolve(tcx, param_env, deref_target, method_args).transpose()
+ Instance::try_resolve(tcx, typing_env, deref_target, method_args).transpose()
});
if let Some(Ok(instance)) = deref_target {
- let deref_target_ty = instance.ty(tcx, param_env);
+ let deref_target_ty = instance.ty(tcx, typing_env);
Some(CallKind::DerefCoercion {
deref_target: tcx.def_span(instance.def_id()),
deref_target_ty,
diff --git a/compiler/rustc_mir_build/src/build/custom/mod.rs b/compiler/rustc_mir_build/src/build/custom/mod.rs
index 4815db4..e809c9a2 100644
--- a/compiler/rustc_mir_build/src/build/custom/mod.rs
+++ b/compiler/rustc_mir_build/src/build/custom/mod.rs
@@ -25,7 +25,7 @@
use rustc_middle::mir::*;
use rustc_middle::span_bug;
use rustc_middle::thir::*;
-use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::Span;
mod parse;
@@ -77,7 +77,7 @@ pub(super) fn build_custom_mir<'tcx>(
let mut pctxt = ParseCtxt {
tcx,
- param_env: tcx.param_env(did),
+ typing_env: body.typing_env(tcx),
thir,
source_scope: OUTERMOST_SOURCE_SCOPE,
body: &mut body,
@@ -136,7 +136,7 @@ fn parse_attribute(attr: &Attribute) -> MirPhase {
struct ParseCtxt<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
- param_env: ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
thir: &'a Thir<'tcx>,
source_scope: SourceScope,
body: &'a mut Body<'tcx>,
diff --git a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
index 07964e3..d08809e 100644
--- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
+++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
@@ -151,7 +151,7 @@ fn parse_match(&self, arms: &[ArmId], span: Span) -> PResult<SwitchTargets> {
expected: "constant pattern".to_string(),
});
};
- values.push(value.eval_bits(self.tcx, self.param_env));
+ values.push(value.eval_bits(self.tcx, self.typing_env));
targets.push(self.parse_block(arm.body)?);
}
@@ -385,7 +385,7 @@ fn parse_integer_literal(&self, expr_id: ExprId) -> PResult<u128> {
| ExprKind::NonHirLiteral { .. }
| ExprKind::ConstBlock { .. } => Ok({
let value = as_constant_inner(expr, |_| None, self.tcx);
- value.const_.eval_bits(self.tcx, self.param_env)
+ value.const_.eval_bits(self.tcx, self.typing_env)
}),
)
}
diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs
index 3f2e3b9..640408c 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs
@@ -114,8 +114,7 @@ fn lit_to_mir_constant<'tcx>(
) -> Result<Const<'tcx>, LitToConstError> {
let LitToConstInput { lit, ty, neg } = lit_input;
let trunc = |n| {
- let param_ty = ty::ParamEnv::reveal_all().and(ty);
- let width = match tcx.layout_of(param_ty) {
+ let width = match tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)) {
Ok(layout) => layout.size,
Err(_) => {
tcx.dcx().bug(format!("couldn't compute width of literal: {:?}", lit_input.lit))
diff --git a/compiler/rustc_mir_build/src/build/expr/as_operand.rs b/compiler/rustc_mir_build/src/build/expr/as_operand.rs
index 112eac3..aad7d54 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_operand.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_operand.rs
@@ -123,7 +123,7 @@ pub(crate) fn as_operand(
match category {
Category::Constant
if matches!(needs_temporary, NeedsTemporary::No)
- || !expr.ty.needs_drop(this.tcx, this.param_env) =>
+ || !expr.ty.needs_drop(this.tcx, this.typing_env()) =>
{
let constant = this.as_constant(expr);
block.and(Operand::Constant(Box::new(constant)))
diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
index 1985dd3..a3fee38 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
@@ -197,7 +197,8 @@ pub(crate) fn as_rvalue(
{
let discr_ty = adt_def.repr().discr_type().to_ty(this.tcx);
let temp = unpack!(block = this.as_temp(block, scope, source, Mutability::Not));
- let layout = this.tcx.layout_of(this.param_env.and(source_expr.ty));
+ let layout =
+ this.tcx.layout_of(this.typing_env().as_query_input(source_expr.ty));
let discr = this.temp(discr_ty, source_expr.span);
this.cfg.push_assign(
block,
@@ -226,10 +227,13 @@ pub(crate) fn as_rvalue(
if range.start <= range.end { BinOp::BitAnd } else { BinOp::BitOr };
let mut comparer = |range: u128, bin_op: BinOp| -> Place<'tcx> {
+ // We can use `ty::TypingEnv::fully_monomorphized()`` here
+ // as we only need it to compute the layout of a primitive.
let range_val = Const::from_bits(
this.tcx,
range,
- ty::ParamEnv::empty().and(unsigned_ty),
+ ty::TypingEnv::fully_monomorphized(),
+ unsigned_ty,
);
let lit_op = this.literal_operand(expr.span, range_val);
let is_bin_op = this.temp(bool_ty, expr_span);
@@ -812,9 +816,9 @@ fn limit_capture_mutability(
// Helper to get a `-1` value of the appropriate type
fn neg_1_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> {
- let param_ty = ty::ParamEnv::empty().and(ty);
- let size = self.tcx.layout_of(param_ty).unwrap().size;
- let literal = Const::from_bits(self.tcx, size.unsigned_int_max(), param_ty);
+ let typing_env = ty::TypingEnv::fully_monomorphized();
+ let size = self.tcx.layout_of(typing_env.as_query_input(ty)).unwrap().size;
+ let literal = Const::from_bits(self.tcx, size.unsigned_int_max(), typing_env, ty);
self.literal_operand(span, literal)
}
@@ -822,10 +826,10 @@ fn neg_1_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> {
// Helper to get the minimum value of the appropriate type
fn minval_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> {
assert!(ty.is_signed());
- let param_ty = ty::ParamEnv::empty().and(ty);
- let bits = self.tcx.layout_of(param_ty).unwrap().size.bits();
+ let typing_env = ty::TypingEnv::fully_monomorphized();
+ let bits = self.tcx.layout_of(typing_env.as_query_input(ty)).unwrap().size.bits();
let n = 1 << (bits - 1);
- let literal = Const::from_bits(self.tcx, n, param_ty);
+ let literal = Const::from_bits(self.tcx, n, typing_env, ty);
self.literal_operand(span, literal)
}
diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs
index dc317fe..0dec56d 100644
--- a/compiler/rustc_mir_build/src/build/expr/into.rs
+++ b/compiler/rustc_mir_build/src/build/expr/into.rs
@@ -266,7 +266,11 @@ pub(crate) fn expr_into_dest(
// that makes the call.
target: expr
.ty
- .is_inhabited_from(this.tcx, this.parent_module, this.param_env)
+ .is_inhabited_from(
+ this.tcx,
+ this.parent_module,
+ this.infcx.typing_env(this.param_env),
+ )
.then_some(success),
call_source: if from_hir_call {
CallSource::Normal
diff --git a/compiler/rustc_mir_build/src/build/expr/stmt.rs b/compiler/rustc_mir_build/src/build/expr/stmt.rs
index 76034c0..02ca120 100644
--- a/compiler/rustc_mir_build/src/build/expr/stmt.rs
+++ b/compiler/rustc_mir_build/src/build/expr/stmt.rs
@@ -42,7 +42,7 @@ pub(crate) fn stmt_expr(
// Generate better code for things that don't need to be
// dropped.
- if lhs_expr.ty.needs_drop(this.tcx, this.param_env) {
+ if lhs_expr.ty.needs_drop(this.tcx, this.typing_env()) {
let rhs = unpack!(block = this.as_local_rvalue(block, rhs));
let lhs = unpack!(block = this.as_place(block, lhs));
block =
diff --git a/compiler/rustc_mir_build/src/build/matches/match_pair.rs b/compiler/rustc_mir_build/src/build/matches/match_pair.rs
index 6df5005..fcbf84a 100644
--- a/compiler/rustc_mir_build/src/build/matches/match_pair.rs
+++ b/compiler/rustc_mir_build/src/build/matches/match_pair.rs
@@ -214,7 +214,7 @@ pub(in crate::build) fn for_pattern(
|| !v
.inhabited_predicate(cx.tcx, adt_def)
.instantiate(cx.tcx, args)
- .apply_ignore_module(cx.tcx, cx.param_env)
+ .apply_ignore_module(cx.tcx, cx.infcx.typing_env(cx.param_env))
}) && (adt_def.did().is_local()
|| !adt_def.is_variant_list_non_exhaustive());
if irrefutable {
diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs
index 37cedd8..4f7bbc4 100644
--- a/compiler/rustc_mir_build/src/build/matches/test.rs
+++ b/compiler/rustc_mir_build/src/build/matches/test.rs
@@ -567,7 +567,10 @@ pub(super) fn sort_candidate(
// not to add such values here.
let is_covering_range = |test_case: &TestCase<'_, 'tcx>| {
test_case.as_range().is_some_and(|range| {
- matches!(range.contains(value, self.tcx, self.param_env), None | Some(true))
+ matches!(
+ range.contains(value, self.tcx, self.typing_env()),
+ None | Some(true)
+ )
})
};
let is_conflicting_candidate = |candidate: &&mut Candidate<'_, 'tcx>| {
@@ -584,7 +587,7 @@ pub(super) fn sort_candidate(
None
} else {
fully_matched = true;
- let bits = value.eval_bits(self.tcx, self.param_env);
+ let bits = value.eval_bits(self.tcx, self.typing_env());
Some(TestBranch::Constant(value, bits))
}
}
@@ -596,7 +599,9 @@ pub(super) fn sort_candidate(
fully_matched = false;
let not_contained =
sorted_candidates.keys().filter_map(|br| br.as_constant()).copied().all(
- |val| matches!(range.contains(val, self.tcx, self.param_env), Some(false)),
+ |val| {
+ matches!(range.contains(val, self.tcx, self.typing_env()), Some(false))
+ },
);
not_contained.then(|| {
@@ -608,7 +613,7 @@ pub(super) fn sort_candidate(
(TestKind::If, TestCase::Constant { value }) => {
fully_matched = true;
- let value = value.try_eval_bool(self.tcx, self.param_env).unwrap_or_else(|| {
+ let value = value.try_eval_bool(self.tcx, self.typing_env()).unwrap_or_else(|| {
span_bug!(test.span, "expected boolean value but got {value:?}")
});
Some(if value { TestBranch::Success } else { TestBranch::Failure })
@@ -688,7 +693,7 @@ pub(super) fn sort_candidate(
fully_matched = false;
// If the testing range does not overlap with pattern range,
// the pattern can be matched only if this test fails.
- if !test.overlaps(pat, self.tcx, self.param_env)? {
+ if !test.overlaps(pat, self.tcx, self.typing_env())? {
Some(TestBranch::Failure)
} else {
None
@@ -697,7 +702,7 @@ pub(super) fn sort_candidate(
}
(TestKind::Range(range), &TestCase::Constant { value }) => {
fully_matched = false;
- if !range.contains(value, self.tcx, self.param_env)? {
+ if !range.contains(value, self.tcx, self.typing_env())? {
// `value` is not contained in the testing range,
// so `value` can be matched only if this test fails.
Some(TestBranch::Failure)
diff --git a/compiler/rustc_mir_build/src/build/misc.rs b/compiler/rustc_mir_build/src/build/misc.rs
index 53cb99d..a14dcad 100644
--- a/compiler/rustc_mir_build/src/build/misc.rs
+++ b/compiler/rustc_mir_build/src/build/misc.rs
@@ -32,7 +32,7 @@ pub(crate) fn literal_operand(&mut self, span: Span, const_: Const<'tcx>) -> Ope
/// Returns a zero literal operand for the appropriate type, works for
/// bool, char and integers.
pub(crate) fn zero_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> {
- let literal = Const::from_bits(self.tcx, 0, ty::ParamEnv::empty().and(ty));
+ let literal = Const::from_bits(self.tcx, 0, ty::TypingEnv::fully_monomorphized(), ty);
self.literal_operand(span, literal)
}
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index 46be2ae..cf8dc59 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -230,6 +230,10 @@ struct Capture<'tcx> {
}
impl<'a, 'tcx> Builder<'a, 'tcx> {
+ fn typing_env(&self) -> ty::TypingEnv<'tcx> {
+ self.infcx.typing_env(self.param_env)
+ }
+
fn is_bound_var_in_guard(&self, id: LocalVarId) -> bool {
self.guard_context.iter().any(|frame| frame.locals.iter().any(|local| local.id == id))
}
diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs
index a7e56b8..e63fbee 100644
--- a/compiler/rustc_mir_build/src/build/scope.rs
+++ b/compiler/rustc_mir_build/src/build/scope.rs
@@ -1010,7 +1010,7 @@ pub(crate) fn schedule_drop(
) {
let needs_drop = match drop_kind {
DropKind::Value => {
- if !self.local_decls[local].ty.needs_drop(self.tcx, self.param_env) {
+ if !self.local_decls[local].ty.needs_drop(self.tcx, self.typing_env()) {
return;
}
true
diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs
index 33e194f..da6b52c 100644
--- a/compiler/rustc_mir_build/src/check_unsafety.rs
+++ b/compiler/rustc_mir_build/src/check_unsafety.rs
@@ -566,7 +566,9 @@ fn visit_expr(&mut self, expr: &'a Expr<'tcx>) {
&& adt_def.is_union()
{
if let Some(assigned_ty) = self.assignment_info {
- if assigned_ty.needs_drop(self.tcx, self.param_env) {
+ if assigned_ty
+ .needs_drop(self.tcx, ty::TypingEnv::from_param_env(self.param_env))
+ {
// This would be unsafe, but should be outright impossible since we
// reject such unions.
assert!(
diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs
index 00f65e0..62c6d85 100644
--- a/compiler/rustc_mir_build/src/errors.rs
+++ b/compiler/rustc_mir_build/src/errors.rs
@@ -528,7 +528,7 @@ fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> {
}
if let ty::Ref(_, sub_ty, _) = self.ty.kind() {
- if !sub_ty.is_inhabited_from(self.cx.tcx, self.cx.module, self.cx.param_env) {
+ if !sub_ty.is_inhabited_from(self.cx.tcx, self.cx.module, self.cx.typing_env()) {
diag.note(fluent::mir_build_reference_note);
}
}
diff --git a/compiler/rustc_mir_build/src/lints.rs b/compiler/rustc_mir_build/src/lints.rs
index cb9a4e2..a1b75c2 100644
--- a/compiler/rustc_mir_build/src/lints.rs
+++ b/compiler/rustc_mir_build/src/lints.rs
@@ -136,12 +136,17 @@ fn is_recursive_terminator(
let func_ty = func.ty(body, tcx);
if let ty::FnDef(callee, args) = *func_ty.kind() {
- let Ok(normalized_args) = tcx.try_normalize_erasing_regions(param_env, args) else {
+ let Ok(normalized_args) =
+ tcx.try_normalize_erasing_regions(ty::TypingEnv::from_param_env(param_env), args)
+ else {
return false;
};
- let (callee, call_args) = if let Ok(Some(instance)) =
- Instance::try_resolve(tcx, param_env, callee, normalized_args)
- {
+ let (callee, call_args) = if let Ok(Some(instance)) = Instance::try_resolve(
+ tcx,
+ ty::TypingEnv::from_param_env(param_env),
+ callee,
+ normalized_args,
+ ) {
(instance.def_id(), instance.args)
} else {
(callee, normalized_args)
diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs
index b8877a6..3fa0e4d 100644
--- a/compiler/rustc_mir_build/src/thir/constant.rs
+++ b/compiler/rustc_mir_build/src/thir/constant.rs
@@ -2,7 +2,7 @@
use rustc_hir::LangItem;
use rustc_middle::bug;
use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput};
-use rustc_middle::ty::{self, ParamEnv, ScalarInt, TyCtxt};
+use rustc_middle::ty::{self, ScalarInt, TyCtxt};
use tracing::trace;
use crate::build::parse_float_into_scalar;
@@ -14,8 +14,7 @@ pub(crate) fn lit_to_const<'tcx>(
let LitToConstInput { lit, ty, neg } = lit_input;
let trunc = |n| {
- let param_ty = ParamEnv::reveal_all().and(ty);
- let width = match tcx.layout_of(param_ty) {
+ let width = match tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)) {
Ok(layout) => layout.size,
Err(_) => {
tcx.dcx().bug(format!("couldn't compute width of literal: {:?}", lit_input.lit))
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index 6445703..198fa4f 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -284,10 +284,9 @@ fn mirror_expr_cast(
let ty = adt_def.repr().discr_type();
let discr_ty = ty.to_ty(tcx);
- let param_env_ty = self.param_env.and(discr_ty);
let size = tcx
- .layout_of(param_env_ty)
- .unwrap_or_else(|e| panic!("could not compute layout for {param_env_ty:?}: {e:?}"))
+ .layout_of(self.typing_env().as_query_input(discr_ty))
+ .unwrap_or_else(|e| panic!("could not compute layout for {discr_ty:?}: {e:?}"))
.size;
let (lit, overflowing) = ScalarInt::truncate_from_uint(discr_offset as u128, size);
@@ -1025,7 +1024,7 @@ fn convert_path_expr(&mut self, expr: &'tcx hir::Expr<'tcx>, res: Res) -> ExprKi
// but distinguish between &STATIC and &THREAD_LOCAL as they have different semantics
Res::Def(DefKind::Static { .. }, id) => {
// this is &raw for extern static or static mut, and & for other statics
- let ty = self.tcx.static_ptr_ty(id);
+ let ty = self.tcx.static_ptr_ty(id, self.typing_env());
let temp_lifetime = self
.rvalue_scopes
.temporary_scope(self.region_scope_tree, expr.hir_id.local_id);
diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs
index 377931e..dfc180f 100644
--- a/compiler/rustc_mir_build/src/thir/cx/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs
@@ -12,6 +12,7 @@
use rustc_middle::bug;
use rustc_middle::middle::region;
use rustc_middle::thir::*;
+use rustc_middle::ty::solve::Reveal;
use rustc_middle::ty::{self, RvalueScopes, TyCtxt};
use tracing::instrument;
@@ -109,6 +110,17 @@ fn new(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Cx<'tcx> {
}
}
+ fn typing_mode(&self) -> ty::TypingMode<'tcx> {
+ debug_assert_eq!(self.param_env.reveal(), Reveal::UserFacing);
+ // FIXME(#132279): In case we're in a body, we should use a typing
+ // mode which reveals the opaque types defined by that body.
+ ty::TypingMode::non_body_analysis()
+ }
+
+ fn typing_env(&self) -> ty::TypingEnv<'tcx> {
+ ty::TypingEnv { typing_mode: self.typing_mode(), param_env: self.param_env }
+ }
+
#[instrument(level = "debug", skip(self))]
fn pattern_from_hir(&mut self, p: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tcx>> {
pat_from_hir(self.tcx, self.param_env, self.typeck_results(), p)
diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
index f222a86..73fcbea 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -721,8 +721,8 @@ fn check_binding_is_irrefutable(
.variant(*variant_index)
.inhabited_predicate(self.tcx, *adt)
.instantiate(self.tcx, args);
- variant_inhabited.apply(self.tcx, cx.param_env, cx.module)
- && !variant_inhabited.apply_ignore_module(self.tcx, cx.param_env)
+ variant_inhabited.apply(self.tcx, cx.typing_env(), cx.module)
+ && !variant_inhabited.apply_ignore_module(self.tcx, cx.typing_env())
} else {
false
};
@@ -1124,7 +1124,7 @@ fn report_non_exhaustive_match<'p, 'tcx>(
}
if let ty::Ref(_, sub_ty, _) = scrut_ty.kind() {
- if !sub_ty.is_inhabited_from(cx.tcx, cx.module, cx.param_env) {
+ if !sub_ty.is_inhabited_from(cx.tcx, cx.module, cx.typing_env()) {
err.note("references are always considered inhabited");
}
}
diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
index 8263235..6b46219 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
@@ -50,10 +50,10 @@ pub(super) fn const_to_pat(
struct ConstToPat<'tcx> {
span: Span,
- param_env: ty::ParamEnv<'tcx>,
// inference context used for checking `T: Structural` bounds.
infcx: InferCtxt<'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
treat_byte_string_as_slice: bool,
}
@@ -81,6 +81,10 @@ fn tcx(&self) -> TyCtxt<'tcx> {
self.infcx.tcx
}
+ fn typing_env(&self) -> ty::TypingEnv<'tcx> {
+ self.infcx.typing_env(self.param_env)
+ }
+
fn type_marked_structural(&self, ty: Ty<'tcx>) -> bool {
ty.is_structural_eq_shallow(self.infcx.tcx)
}
@@ -100,13 +104,14 @@ fn unevaluated_to_pat(
//
// FIXME: `const_eval_resolve_for_typeck` should probably just set the env to `Reveal::All`
// instead of having this logic here
- let param_env =
- self.tcx().erase_regions(self.param_env).with_reveal_all_normalized(self.tcx());
+ let typing_env =
+ self.tcx().erase_regions(self.typing_env()).with_reveal_all_normalized(self.tcx());
let uv = self.tcx().erase_regions(uv);
// try to resolve e.g. associated constants to their definition on an impl, and then
// evaluate the const.
- let valtree = match self.infcx.tcx.const_eval_resolve_for_typeck(param_env, uv, self.span) {
+ let valtree = match self.infcx.tcx.const_eval_resolve_for_typeck(typing_env, uv, self.span)
+ {
Ok(Ok(c)) => c,
Err(ErrorHandled::Reported(_, _)) => {
// Let's tell the use where this failing const occurs.
@@ -187,7 +192,7 @@ fn field_pats(
.map(|(idx, (val, ty))| {
let field = FieldIdx::new(idx);
// Patterns can only use monomorphic types.
- let ty = self.tcx().normalize_erasing_regions(self.param_env, ty);
+ let ty = self.tcx().normalize_erasing_regions(self.typing_env(), ty);
FieldPat { field, pattern: self.valtree_to_pat(val, ty) }
})
.collect()
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index ec852ad..d17bc85 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -242,7 +242,7 @@ fn lower_pattern_range(
let lo = lo.unwrap_or(PatRangeBoundary::NegInfinity);
let hi = hi.unwrap_or(PatRangeBoundary::PosInfinity);
- let cmp = lo.compare_with(hi, ty, self.tcx, self.param_env);
+ let cmp = lo.compare_with(hi, ty, self.tcx, ty::TypingEnv::from_param_env(self.param_env));
let mut kind = PatKind::Range(Box::new(PatRange { lo, hi, end, ty }));
match (end, cmp) {
// `x..y` where `x < y`.
diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
index 9a1f000..494b7d5 100644
--- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
@@ -6,7 +6,6 @@
use rustc_middle::mir::patch::MirPatch;
use rustc_middle::mir::*;
use rustc_middle::span_bug;
-use rustc_middle::traits::Reveal;
use rustc_middle::ty::util::IntTypeExt;
use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt};
use rustc_span::DUMMY_SP;
@@ -111,7 +110,7 @@ pub trait DropElaborator<'a, 'tcx>: fmt::Debug {
fn patch(&mut self) -> &mut MirPatch<'tcx>;
fn body(&self) -> &'a Body<'tcx>;
fn tcx(&self) -> TyCtxt<'tcx>;
- fn param_env(&self) -> ty::ParamEnv<'tcx>;
+ fn typing_env(&self) -> ty::TypingEnv<'tcx>;
// Drop logic
@@ -273,9 +272,9 @@ fn move_paths_for_fields(
let subpath = self.elaborator.field_subpath(variant_path, field);
let tcx = self.tcx();
- assert_eq!(self.elaborator.param_env().reveal(), Reveal::All);
+ assert_eq!(self.elaborator.typing_env().typing_mode, ty::TypingMode::PostAnalysis);
let field_ty =
- tcx.normalize_erasing_regions(self.elaborator.param_env(), f.ty(tcx, args));
+ tcx.normalize_erasing_regions(self.elaborator.typing_env(), f.ty(tcx, args));
(tcx.mk_place_field(base_place, field, field_ty), subpath)
})
@@ -372,7 +371,7 @@ fn drop_ladder(
let mut fields = fields;
fields.retain(|&(place, _)| {
- self.place_ty(place).needs_drop(self.tcx(), self.elaborator.param_env())
+ self.place_ty(place).needs_drop(self.tcx(), self.elaborator.typing_env())
});
debug!("drop_ladder - fields needing drop: {:?}", fields);
@@ -544,11 +543,11 @@ fn open_drop_for_multivariant(
} else {
have_otherwise = true;
- let param_env = self.elaborator.param_env();
+ let typing_env = self.elaborator.typing_env();
let have_field_with_drop_glue = variant
.fields
.iter()
- .any(|field| field.ty(tcx, args).needs_drop(tcx, param_env));
+ .any(|field| field.ty(tcx, args).needs_drop(tcx, typing_env));
if have_field_with_drop_glue {
have_otherwise_with_drop_glue = true;
}
diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs
index 3e01f05..9a5cf9d 100644
--- a/compiler/rustc_mir_dataflow/src/framework/direction.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs
@@ -4,8 +4,8 @@
self, BasicBlock, CallReturnPlaces, Location, SwitchTargets, TerminatorEdges,
};
-use super::visitor::{ResultsVisitable, ResultsVisitor};
-use super::{Analysis, Effect, EffectIndex, SwitchIntTarget};
+use super::visitor::ResultsVisitor;
+use super::{Analysis, Effect, EffectIndex, Results, SwitchIntTarget};
pub trait Direction {
const IS_FORWARD: bool;
@@ -33,14 +33,14 @@ fn apply_effects_in_block<'mir, 'tcx, A>(
where
A: Analysis<'tcx>;
- fn visit_results_in_block<'mir, 'tcx, D, R>(
- state: &mut D,
+ fn visit_results_in_block<'mir, 'tcx, A>(
+ state: &mut A::Domain,
block: BasicBlock,
block_data: &'mir mir::BasicBlockData<'tcx>,
- results: &mut R,
- vis: &mut impl ResultsVisitor<'mir, 'tcx, R, Domain = D>,
+ results: &mut Results<'tcx, A>,
+ vis: &mut impl ResultsVisitor<'mir, 'tcx, A>,
) where
- R: ResultsVisitable<'tcx, Domain = D>;
+ A: Analysis<'tcx>;
fn join_state_into_successors_of<'tcx, A>(
analysis: &mut A,
@@ -53,7 +53,7 @@ fn join_state_into_successors_of<'tcx, A>(
A: Analysis<'tcx>;
}
-/// Dataflow that runs from the exit of a block (the terminator), to its entry (the first statement).
+/// Dataflow that runs from the exit of a block (terminator), to its entry (the first statement).
pub struct Backward;
impl Direction for Backward {
@@ -157,32 +157,32 @@ fn apply_effects_in_range<'tcx, A>(
analysis.apply_statement_effect(state, statement, location);
}
- fn visit_results_in_block<'mir, 'tcx, D, R>(
- state: &mut D,
+ fn visit_results_in_block<'mir, 'tcx, A>(
+ state: &mut A::Domain,
block: BasicBlock,
block_data: &'mir mir::BasicBlockData<'tcx>,
- results: &mut R,
- vis: &mut impl ResultsVisitor<'mir, 'tcx, R, Domain = D>,
+ results: &mut Results<'tcx, A>,
+ vis: &mut impl ResultsVisitor<'mir, 'tcx, A>,
) where
- R: ResultsVisitable<'tcx, Domain = D>,
+ A: Analysis<'tcx>,
{
- results.reset_to_block_entry(state, block);
+ state.clone_from(results.entry_set_for_block(block));
vis.visit_block_end(state);
// Terminator
let loc = Location { block, statement_index: block_data.statements.len() };
let term = block_data.terminator();
- results.reconstruct_before_terminator_effect(state, term, loc);
+ results.analysis.apply_before_terminator_effect(state, term, loc);
vis.visit_terminator_before_primary_effect(results, state, term, loc);
- results.reconstruct_terminator_effect(state, term, loc);
+ results.analysis.apply_terminator_effect(state, term, loc);
vis.visit_terminator_after_primary_effect(results, state, term, loc);
for (statement_index, stmt) in block_data.statements.iter().enumerate().rev() {
let loc = Location { block, statement_index };
- results.reconstruct_before_statement_effect(state, stmt, loc);
+ results.analysis.apply_before_statement_effect(state, stmt, loc);
vis.visit_statement_before_primary_effect(results, state, stmt, loc);
- results.reconstruct_statement_effect(state, stmt, loc);
+ results.analysis.apply_statement_effect(state, stmt, loc);
vis.visit_statement_after_primary_effect(results, state, stmt, loc);
}
@@ -389,32 +389,32 @@ fn apply_effects_in_range<'tcx, A>(
}
}
- fn visit_results_in_block<'mir, 'tcx, F, R>(
- state: &mut F,
+ fn visit_results_in_block<'mir, 'tcx, A>(
+ state: &mut A::Domain,
block: BasicBlock,
block_data: &'mir mir::BasicBlockData<'tcx>,
- results: &mut R,
- vis: &mut impl ResultsVisitor<'mir, 'tcx, R, Domain = F>,
+ results: &mut Results<'tcx, A>,
+ vis: &mut impl ResultsVisitor<'mir, 'tcx, A>,
) where
- R: ResultsVisitable<'tcx, Domain = F>,
+ A: Analysis<'tcx>,
{
- results.reset_to_block_entry(state, block);
+ state.clone_from(results.entry_set_for_block(block));
vis.visit_block_start(state);
for (statement_index, stmt) in block_data.statements.iter().enumerate() {
let loc = Location { block, statement_index };
- results.reconstruct_before_statement_effect(state, stmt, loc);
+ results.analysis.apply_before_statement_effect(state, stmt, loc);
vis.visit_statement_before_primary_effect(results, state, stmt, loc);
- results.reconstruct_statement_effect(state, stmt, loc);
+ results.analysis.apply_statement_effect(state, stmt, loc);
vis.visit_statement_after_primary_effect(results, state, stmt, loc);
}
let loc = Location { block, statement_index: block_data.statements.len() };
let term = block_data.terminator();
- results.reconstruct_before_terminator_effect(state, term, loc);
+ results.analysis.apply_before_terminator_effect(state, term, loc);
vis.visit_terminator_before_primary_effect(results, state, term, loc);
- results.reconstruct_terminator_effect(state, term, loc);
+ results.analysis.apply_terminator_effect(state, term, loc);
vis.visit_terminator_after_primary_effect(results, state, term, loc);
vis.visit_block_end(state);
diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
index bac75b9..98a4f58 100644
--- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
@@ -544,20 +544,18 @@ fn run<'tcx, A>(
}
}
-impl<'tcx, A> ResultsVisitor<'_, 'tcx, Results<'tcx, A>> for StateDiffCollector<A::Domain>
+impl<'tcx, A> ResultsVisitor<'_, 'tcx, A> for StateDiffCollector<A::Domain>
where
A: Analysis<'tcx>,
A::Domain: DebugWithContext<A>,
{
- type Domain = A::Domain;
-
- fn visit_block_start(&mut self, state: &Self::Domain) {
+ fn visit_block_start(&mut self, state: &A::Domain) {
if A::Direction::IS_FORWARD {
self.prev_state.clone_from(state);
}
}
- fn visit_block_end(&mut self, state: &Self::Domain) {
+ fn visit_block_end(&mut self, state: &A::Domain) {
if A::Direction::IS_BACKWARD {
self.prev_state.clone_from(state);
}
@@ -566,7 +564,7 @@ fn visit_block_end(&mut self, state: &Self::Domain) {
fn visit_statement_before_primary_effect(
&mut self,
results: &mut Results<'tcx, A>,
- state: &Self::Domain,
+ state: &A::Domain,
_statement: &mir::Statement<'tcx>,
_location: Location,
) {
@@ -579,7 +577,7 @@ fn visit_statement_before_primary_effect(
fn visit_statement_after_primary_effect(
&mut self,
results: &mut Results<'tcx, A>,
- state: &Self::Domain,
+ state: &A::Domain,
_statement: &mir::Statement<'tcx>,
_location: Location,
) {
@@ -590,7 +588,7 @@ fn visit_statement_after_primary_effect(
fn visit_terminator_before_primary_effect(
&mut self,
results: &mut Results<'tcx, A>,
- state: &Self::Domain,
+ state: &A::Domain,
_terminator: &mir::Terminator<'tcx>,
_location: Location,
) {
@@ -603,7 +601,7 @@ fn visit_terminator_before_primary_effect(
fn visit_terminator_after_primary_effect(
&mut self,
results: &mut Results<'tcx, A>,
- state: &Self::Domain,
+ state: &A::Domain,
_terminator: &mir::Terminator<'tcx>,
_location: Location,
) {
diff --git a/compiler/rustc_mir_dataflow/src/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs
index 8f81da8..244dfe2 100644
--- a/compiler/rustc_mir_dataflow/src/framework/mod.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs
@@ -55,8 +55,8 @@
pub use self::cursor::ResultsCursor;
pub use self::direction::{Backward, Direction, Forward};
pub use self::lattice::{JoinSemiLattice, MaybeReachable};
-pub use self::results::Results;
-pub use self::visitor::{ResultsVisitable, ResultsVisitor, visit_results};
+pub use self::results::{EntrySets, Results};
+pub use self::visitor::{ResultsVisitor, visit_results};
/// Analysis domains are all bitsets of various kinds. This trait holds
/// operations needed by all of them.
diff --git a/compiler/rustc_mir_dataflow/src/framework/results.rs b/compiler/rustc_mir_dataflow/src/framework/results.rs
index 366fcbf..ff6cafb 100644
--- a/compiler/rustc_mir_dataflow/src/framework/results.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/results.rs
@@ -18,7 +18,7 @@
DuplicateValuesFor, PathMustEndInFilename, RequiresAnArgument, UnknownFormatter,
};
-type EntrySets<'tcx, A> = IndexVec<BasicBlock, <A as Analysis<'tcx>>::Domain>;
+pub type EntrySets<'tcx, A> = IndexVec<BasicBlock, <A as Analysis<'tcx>>::Domain>;
/// A dataflow analysis that has converged to fixpoint.
#[derive(Clone)]
@@ -27,7 +27,7 @@ pub struct Results<'tcx, A>
A: Analysis<'tcx>,
{
pub analysis: A,
- pub(super) entry_sets: EntrySets<'tcx, A>,
+ pub entry_sets: EntrySets<'tcx, A>,
}
impl<'tcx, A> Results<'tcx, A>
@@ -51,7 +51,7 @@ pub fn visit_with<'mir>(
&mut self,
body: &'mir mir::Body<'tcx>,
blocks: impl IntoIterator<Item = BasicBlock>,
- vis: &mut impl ResultsVisitor<'mir, 'tcx, Self, Domain = A::Domain>,
+ vis: &mut impl ResultsVisitor<'mir, 'tcx, A>,
) {
visit_results(body, blocks, self, vis)
}
@@ -59,7 +59,7 @@ pub fn visit_with<'mir>(
pub fn visit_reachable_with<'mir>(
&mut self,
body: &'mir mir::Body<'tcx>,
- vis: &mut impl ResultsVisitor<'mir, 'tcx, Self, Domain = A::Domain>,
+ vis: &mut impl ResultsVisitor<'mir, 'tcx, A>,
) {
let blocks = traversal::reachable(body);
visit_results(body, blocks.map(|(bb, _)| bb), self, vis)
diff --git a/compiler/rustc_mir_dataflow/src/framework/visitor.rs b/compiler/rustc_mir_dataflow/src/framework/visitor.rs
index 3d6b008..5c7539e 100644
--- a/compiler/rustc_mir_dataflow/src/framework/visitor.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/visitor.rs
@@ -4,15 +4,15 @@
/// Calls the corresponding method in `ResultsVisitor` for every location in a `mir::Body` with the
/// dataflow state at that location.
-pub fn visit_results<'mir, 'tcx, D, R>(
+pub fn visit_results<'mir, 'tcx, A>(
body: &'mir mir::Body<'tcx>,
blocks: impl IntoIterator<Item = BasicBlock>,
- results: &mut R,
- vis: &mut impl ResultsVisitor<'mir, 'tcx, R, Domain = D>,
+ results: &mut Results<'tcx, A>,
+ vis: &mut impl ResultsVisitor<'mir, 'tcx, A>,
) where
- R: ResultsVisitable<'tcx, Domain = D>,
+ A: Analysis<'tcx>,
{
- let mut state = results.bottom_value(body);
+ let mut state = results.analysis.bottom_value(body);
#[cfg(debug_assertions)]
let reachable_blocks = mir::traversal::reachable_as_bitset(body);
@@ -22,23 +22,23 @@ pub fn visit_results<'mir, 'tcx, D, R>(
assert!(reachable_blocks.contains(block));
let block_data = &body[block];
- R::Direction::visit_results_in_block(&mut state, block, block_data, results, vis);
+ A::Direction::visit_results_in_block(&mut state, block, block_data, results, vis);
}
}
-/// A visitor over the results of an `Analysis`. The type parameter `R` is the results type being
-/// visited.
-pub trait ResultsVisitor<'mir, 'tcx, R> {
- type Domain;
-
- fn visit_block_start(&mut self, _state: &Self::Domain) {}
+/// A visitor over the results of an `Analysis`.
+pub trait ResultsVisitor<'mir, 'tcx, A>
+where
+ A: Analysis<'tcx>,
+{
+ fn visit_block_start(&mut self, _state: &A::Domain) {}
/// Called with the `before_statement_effect` of the given statement applied to `state` but not
/// its `statement_effect`.
fn visit_statement_before_primary_effect(
&mut self,
- _results: &mut R,
- _state: &Self::Domain,
+ _results: &mut Results<'tcx, A>,
+ _state: &A::Domain,
_statement: &'mir mir::Statement<'tcx>,
_location: Location,
) {
@@ -48,19 +48,19 @@ fn visit_statement_before_primary_effect(
/// statement applied to `state`.
fn visit_statement_after_primary_effect(
&mut self,
- _results: &mut R,
- _state: &Self::Domain,
+ _results: &mut Results<'tcx, A>,
+ _state: &A::Domain,
_statement: &'mir mir::Statement<'tcx>,
_location: Location,
) {
}
- /// Called with the `before_terminator_effect` of the given terminator applied to `state` but not
- /// its `terminator_effect`.
+ /// Called with the `before_terminator_effect` of the given terminator applied to `state` but
+ /// not its `terminator_effect`.
fn visit_terminator_before_primary_effect(
&mut self,
- _results: &mut R,
- _state: &Self::Domain,
+ _results: &mut Results<'tcx, A>,
+ _state: &A::Domain,
_terminator: &'mir mir::Terminator<'tcx>,
_location: Location,
) {
@@ -72,109 +72,12 @@ fn visit_terminator_before_primary_effect(
/// The `call_return_effect` (if one exists) will *not* be applied to `state`.
fn visit_terminator_after_primary_effect(
&mut self,
- _results: &mut R,
- _state: &Self::Domain,
+ _results: &mut Results<'tcx, A>,
+ _state: &A::Domain,
_terminator: &'mir mir::Terminator<'tcx>,
_location: Location,
) {
}
- fn visit_block_end(&mut self, _state: &Self::Domain) {}
-}
-
-/// Things that can be visited by a `ResultsVisitor`.
-///
-/// This trait exists so that we can visit the results of one or more dataflow analyses
-/// simultaneously.
-pub trait ResultsVisitable<'tcx> {
- type Direction: Direction;
- type Domain;
-
- /// Creates an empty `Domain` to hold the transient state for these dataflow results.
- ///
- /// The value of the newly created `Domain` will be overwritten by `reset_to_block_entry`
- /// before it can be observed by a `ResultsVisitor`.
- fn bottom_value(&self, body: &mir::Body<'tcx>) -> Self::Domain;
-
- fn reset_to_block_entry(&self, state: &mut Self::Domain, block: BasicBlock);
-
- fn reconstruct_before_statement_effect(
- &mut self,
- state: &mut Self::Domain,
- statement: &mir::Statement<'tcx>,
- location: Location,
- );
-
- fn reconstruct_statement_effect(
- &mut self,
- state: &mut Self::Domain,
- statement: &mir::Statement<'tcx>,
- location: Location,
- );
-
- fn reconstruct_before_terminator_effect(
- &mut self,
- state: &mut Self::Domain,
- terminator: &mir::Terminator<'tcx>,
- location: Location,
- );
-
- fn reconstruct_terminator_effect(
- &mut self,
- state: &mut Self::Domain,
- terminator: &mir::Terminator<'tcx>,
- location: Location,
- );
-}
-
-impl<'tcx, A> ResultsVisitable<'tcx> for Results<'tcx, A>
-where
- A: Analysis<'tcx>,
-{
- type Domain = A::Domain;
- type Direction = A::Direction;
-
- fn bottom_value(&self, body: &mir::Body<'tcx>) -> Self::Domain {
- self.analysis.bottom_value(body)
- }
-
- fn reset_to_block_entry(&self, state: &mut Self::Domain, block: BasicBlock) {
- state.clone_from(self.entry_set_for_block(block));
- }
-
- fn reconstruct_before_statement_effect(
- &mut self,
- state: &mut Self::Domain,
- stmt: &mir::Statement<'tcx>,
- loc: Location,
- ) {
- self.analysis.apply_before_statement_effect(state, stmt, loc);
- }
-
- fn reconstruct_statement_effect(
- &mut self,
- state: &mut Self::Domain,
- stmt: &mir::Statement<'tcx>,
- loc: Location,
- ) {
- self.analysis.apply_statement_effect(state, stmt, loc);
- }
-
- fn reconstruct_before_terminator_effect(
- &mut self,
- state: &mut Self::Domain,
- term: &mir::Terminator<'tcx>,
- loc: Location,
- ) {
- self.analysis.apply_before_terminator_effect(state, term, loc);
- }
-
- fn reconstruct_terminator_effect(
- &mut self,
- state: &mut Self::Domain,
- term: &mir::Terminator<'tcx>,
- loc: Location,
- ) {
- self.analysis.apply_terminator_effect(state, term, loc);
- }
+ fn visit_block_end(&mut self, _state: &A::Domain) {}
}
diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs
index b404e3bf..ab1453f 100644
--- a/compiler/rustc_mir_dataflow/src/lib.rs
+++ b/compiler/rustc_mir_dataflow/src/lib.rs
@@ -18,8 +18,8 @@
move_path_children_matching, on_all_children_bits, on_lookup_result_bits,
};
pub use self::framework::{
- Analysis, Backward, Direction, Forward, GenKill, JoinSemiLattice, MaybeReachable, Results,
- ResultsCursor, ResultsVisitable, ResultsVisitor, SwitchIntEdgeEffects, fmt, graphviz, lattice,
+ Analysis, Backward, Direction, EntrySets, Forward, GenKill, JoinSemiLattice, MaybeReachable,
+ Results, ResultsCursor, ResultsVisitor, SwitchIntEdgeEffects, fmt, graphviz, lattice,
visit_results,
};
use self::move_paths::MoveData;
diff --git a/compiler/rustc_mir_dataflow/src/points.rs b/compiler/rustc_mir_dataflow/src/points.rs
index 73abb66..10f1e00 100644
--- a/compiler/rustc_mir_dataflow/src/points.rs
+++ b/compiler/rustc_mir_dataflow/src/points.rs
@@ -3,7 +3,7 @@
use rustc_index::{Idx, IndexVec};
use rustc_middle::mir::{self, BasicBlock, Body, Location};
-use crate::framework::{ResultsVisitable, ResultsVisitor, visit_results};
+use crate::framework::{Analysis, Results, ResultsVisitor, visit_results};
/// Maps between a `Location` and a `PointIndex` (and vice versa).
pub struct DenseLocationMap {
@@ -95,14 +95,14 @@ pub struct PointIndex {}
}
/// Add points depending on the result of the given dataflow analysis.
-pub fn save_as_intervals<'tcx, N, R>(
+pub fn save_as_intervals<'tcx, N, A>(
elements: &DenseLocationMap,
body: &mir::Body<'tcx>,
- mut results: R,
+ mut results: Results<'tcx, A>,
) -> SparseIntervalMatrix<N, PointIndex>
where
N: Idx,
- R: ResultsVisitable<'tcx, Domain = BitSet<N>>,
+ A: Analysis<'tcx, Domain = BitSet<N>>,
{
let values = SparseIntervalMatrix::new(elements.num_points());
let mut visitor = Visitor { elements, values };
@@ -120,16 +120,15 @@ struct Visitor<'a, N: Idx> {
values: SparseIntervalMatrix<N, PointIndex>,
}
-impl<'mir, 'tcx, R, N> ResultsVisitor<'mir, 'tcx, R> for Visitor<'_, N>
+impl<'mir, 'tcx, A, N> ResultsVisitor<'mir, 'tcx, A> for Visitor<'_, N>
where
+ A: Analysis<'tcx, Domain = BitSet<N>>,
N: Idx,
{
- type Domain = BitSet<N>;
-
fn visit_statement_after_primary_effect(
&mut self,
- _results: &mut R,
- state: &Self::Domain,
+ _results: &mut Results<'tcx, A>,
+ state: &A::Domain,
_statement: &'mir mir::Statement<'tcx>,
location: Location,
) {
@@ -142,8 +141,8 @@ fn visit_statement_after_primary_effect(
fn visit_terminator_after_primary_effect(
&mut self,
- _results: &mut R,
- state: &Self::Domain,
+ _results: &mut Results<'tcx, A>,
+ state: &A::Domain,
_terminator: &'mir mir::Terminator<'tcx>,
location: Location,
) {
diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs
index af2d514..ed8678d 100644
--- a/compiler/rustc_mir_dataflow/src/value_analysis.rs
+++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs
@@ -462,7 +462,7 @@ fn register(
drop(assignments);
// Create values for places whose type have scalar layout.
- let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
+ let typing_env = body.typing_env(tcx);
for place_info in self.places.iter_mut() {
// The user requires a bound on the number of created values.
if let Some(value_limit) = value_limit
@@ -471,13 +471,13 @@ fn register(
break;
}
- if let Ok(ty) = tcx.try_normalize_erasing_regions(param_env, place_info.ty) {
+ if let Ok(ty) = tcx.try_normalize_erasing_regions(typing_env, place_info.ty) {
place_info.ty = ty;
}
// Allocate a value slot if it doesn't have one, and the user requested one.
assert!(place_info.value_index.is_none());
- if let Ok(layout) = tcx.layout_of(param_env.and(place_info.ty))
+ if let Ok(layout) = tcx.layout_of(typing_env.as_query_input(place_info.ty))
&& layout.backend_repr.is_scalar()
{
place_info.value_index = Some(self.value_count.into());
@@ -874,7 +874,7 @@ fn try_from(value: ProjectionElem<V, T>) -> Result<Self, Self::Error> {
pub fn iter_fields<'tcx>(
ty: Ty<'tcx>,
tcx: TyCtxt<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
mut f: impl FnMut(Option<VariantIdx>, FieldIdx, Ty<'tcx>),
) {
match ty.kind() {
@@ -892,20 +892,20 @@ pub fn iter_fields<'tcx>(
for (f_index, f_def) in v_def.fields.iter().enumerate() {
let field_ty = f_def.ty(tcx, args);
let field_ty = tcx
- .try_normalize_erasing_regions(param_env, field_ty)
+ .try_normalize_erasing_regions(typing_env, field_ty)
.unwrap_or_else(|_| tcx.erase_regions(field_ty));
f(variant, f_index.into(), field_ty);
}
}
}
ty::Closure(_, args) => {
- iter_fields(args.as_closure().tupled_upvars_ty(), tcx, param_env, f);
+ iter_fields(args.as_closure().tupled_upvars_ty(), tcx, typing_env, f);
}
ty::Coroutine(_, args) => {
- iter_fields(args.as_coroutine().tupled_upvars_ty(), tcx, param_env, f);
+ iter_fields(args.as_coroutine().tupled_upvars_ty(), tcx, typing_env, f);
}
ty::CoroutineClosure(_, args) => {
- iter_fields(args.as_coroutine_closure().tupled_upvars_ty(), tcx, param_env, f);
+ iter_fields(args.as_coroutine_closure().tupled_upvars_ty(), tcx, typing_env, f);
}
_ => (),
}
diff --git a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs
index 559df22..12a2fe2 100644
--- a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs
+++ b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs
@@ -1,6 +1,6 @@
use rustc_middle::mir::patch::MirPatch;
use rustc_middle::mir::*;
-use rustc_middle::ty::TyCtxt;
+use rustc_middle::ty::{self, TyCtxt};
use tracing::debug;
use crate::util;
@@ -40,10 +40,10 @@
impl<'tcx> crate::MirPass<'tcx> for AddMovesForPackedDrops {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
debug!("add_moves_for_packed_drops({:?} @ {:?})", body.source, body.span);
-
- let def_id = body.source.def_id();
let mut patch = MirPatch::new(body);
- let param_env = tcx.param_env(def_id);
+ // FIXME(#132279): This is used during the phase transition from analysis
+ // to runtime, so we have to manually specify the correct typing mode.
+ let typing_env = ty::TypingEnv::post_analysis(tcx, body.source.def_id());
for (bb, data) in body.basic_blocks.iter_enumerated() {
let loc = Location { block: bb, statement_index: data.statements.len() };
@@ -51,7 +51,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
match terminator.kind {
TerminatorKind::Drop { place, .. }
- if util::is_disaligned(tcx, body, param_env, place) =>
+ if util::is_disaligned(tcx, body, typing_env, place) =>
{
add_move_for_packed_drop(
tcx,
diff --git a/compiler/rustc_mir_transform/src/check_packed_ref.rs b/compiler/rustc_mir_transform/src/check_packed_ref.rs
index 1922d4f..e9b85ba 100644
--- a/compiler/rustc_mir_transform/src/check_packed_ref.rs
+++ b/compiler/rustc_mir_transform/src/check_packed_ref.rs
@@ -9,9 +9,9 @@
impl<'tcx> crate::MirLint<'tcx> for CheckPackedRef {
fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
- let param_env = tcx.param_env(body.source.def_id());
+ let typing_env = body.typing_env(tcx);
let source_info = SourceInfo::outermost(body.span);
- let mut checker = PackedRefChecker { body, tcx, param_env, source_info };
+ let mut checker = PackedRefChecker { body, tcx, typing_env, source_info };
checker.visit_body(body);
}
}
@@ -19,7 +19,7 @@ fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
struct PackedRefChecker<'a, 'tcx> {
body: &'a Body<'tcx>,
tcx: TyCtxt<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
source_info: SourceInfo,
}
@@ -37,7 +37,8 @@ fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
}
fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) {
- if context.is_borrow() && util::is_disaligned(self.tcx, self.body, self.param_env, *place) {
+ if context.is_borrow() && util::is_disaligned(self.tcx, self.body, self.typing_env, *place)
+ {
let def_id = self.body.source.instance.def_id();
if let Some(impl_def_id) = self.tcx.impl_of_method(def_id)
&& self.tcx.is_builtin_derived(impl_def_id)
diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs
index 063f220..d38a1dd 100644
--- a/compiler/rustc_mir_transform/src/coroutine.rs
+++ b/compiler/rustc_mir_transform/src/coroutine.rs
@@ -68,11 +68,11 @@
self, CoroutineArgs, CoroutineArgsExt, GenericArgsRef, InstanceKind, Ty, TyCtxt, TypingMode,
};
use rustc_middle::{bug, span_bug};
-use rustc_mir_dataflow::Analysis;
use rustc_mir_dataflow::impls::{
MaybeBorrowedLocals, MaybeLiveLocals, MaybeRequiresStorage, MaybeStorageLive,
};
use rustc_mir_dataflow::storage::always_storage_live_locals;
+use rustc_mir_dataflow::{Analysis, Results, ResultsVisitor};
use rustc_span::Span;
use rustc_span::def_id::{DefId, LocalDefId};
use rustc_span::symbol::sym;
@@ -817,9 +817,9 @@ fn deref(&self) -> &Self::Target {
/// computation; see `CoroutineLayout` for more.
fn compute_storage_conflicts<'mir, 'tcx>(
body: &'mir Body<'tcx>,
- saved_locals: &CoroutineSavedLocals,
+ saved_locals: &'mir CoroutineSavedLocals,
always_live_locals: BitSet<Local>,
- mut requires_storage: rustc_mir_dataflow::Results<'tcx, MaybeRequiresStorage<'mir, 'tcx>>,
+ mut requires_storage: Results<'tcx, MaybeRequiresStorage<'mir, 'tcx>>,
) -> BitMatrix<CoroutineSavedLocal, CoroutineSavedLocal> {
assert_eq!(body.local_decls.len(), saved_locals.domain_size());
@@ -877,15 +877,13 @@ struct StorageConflictVisitor<'a, 'tcx> {
eligible_storage_live: BitSet<Local>,
}
-impl<'a, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'a, 'tcx, R>
+impl<'a, 'tcx> ResultsVisitor<'a, 'tcx, MaybeRequiresStorage<'a, 'tcx>>
for StorageConflictVisitor<'a, 'tcx>
{
- type Domain = BitSet<Local>;
-
fn visit_statement_before_primary_effect(
&mut self,
- _results: &mut R,
- state: &Self::Domain,
+ _results: &mut Results<'tcx, MaybeRequiresStorage<'a, 'tcx>>,
+ state: &BitSet<Local>,
_statement: &'a Statement<'tcx>,
loc: Location,
) {
@@ -894,8 +892,8 @@ fn visit_statement_before_primary_effect(
fn visit_terminator_before_primary_effect(
&mut self,
- _results: &mut R,
- state: &Self::Domain,
+ _results: &mut Results<'tcx, MaybeRequiresStorage<'a, 'tcx>>,
+ state: &BitSet<Local>,
_terminator: &'a Terminator<'tcx>,
loc: Location,
) {
@@ -1071,11 +1069,9 @@ fn elaborate_coroutine_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
// Note that `elaborate_drops` only drops the upvars of a coroutine, and
// this is ok because `open_drop` can only be reached within that own
// coroutine's resume function.
+ let typing_env = body.typing_env(tcx);
- let def_id = body.source.def_id();
- let param_env = tcx.param_env(def_id);
-
- let mut elaborator = DropShimElaborator { body, patch: MirPatch::new(body), tcx, param_env };
+ let mut elaborator = DropShimElaborator { body, patch: MirPatch::new(body), tcx, typing_env };
for (block, block_data) in body.basic_blocks.iter_enumerated() {
let (target, unwind, source_info) = match block_data.terminator() {
@@ -1206,9 +1202,9 @@ fn insert_panic_block<'tcx>(
insert_term_block(body, kind)
}
-fn can_return<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool {
+fn can_return<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> bool {
// Returning from a function with an uninhabited return type is undefined behavior.
- if body.return_ty().is_privately_uninhabited(tcx, param_env) {
+ if body.return_ty().is_privately_uninhabited(tcx, typing_env) {
return false;
}
@@ -1629,7 +1625,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
// `storage_liveness` tells us which locals have live storage at suspension points
let (remap, layout, storage_liveness) = compute_layout(liveness_info, body);
- let can_return = can_return(tcx, body, tcx.param_env(body.source.def_id()));
+ let can_return = can_return(tcx, body, body.typing_env(tcx));
// Run the transformation which converts Places from Local to coroutine struct
// accesses for locals in `remap`.
diff --git a/compiler/rustc_mir_transform/src/cost_checker.rs b/compiler/rustc_mir_transform/src/cost_checker.rs
index 59b4035..b23d8b9 100644
--- a/compiler/rustc_mir_transform/src/cost_checker.rs
+++ b/compiler/rustc_mir_transform/src/cost_checker.rs
@@ -1,7 +1,7 @@
use rustc_middle::bug;
use rustc_middle::mir::visit::*;
use rustc_middle::mir::*;
-use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt};
const INSTR_COST: usize = 5;
const CALL_PENALTY: usize = 25;
@@ -14,7 +14,7 @@
#[derive(Clone)]
pub(super) struct CostChecker<'b, 'tcx> {
tcx: TyCtxt<'tcx>,
- param_env: ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
penalty: usize,
bonus: usize,
callee_body: &'b Body<'tcx>,
@@ -24,11 +24,11 @@ pub(super) struct CostChecker<'b, 'tcx> {
impl<'b, 'tcx> CostChecker<'b, 'tcx> {
pub(super) fn new(
tcx: TyCtxt<'tcx>,
- param_env: ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
instance: Option<ty::Instance<'tcx>>,
callee_body: &'b Body<'tcx>,
) -> CostChecker<'b, 'tcx> {
- CostChecker { tcx, param_env, callee_body, instance, penalty: 0, bonus: 0 }
+ CostChecker { tcx, typing_env, callee_body, instance, penalty: 0, bonus: 0 }
}
/// Add function-level costs not well-represented by the block-level costs.
@@ -119,7 +119,7 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, _: Location) {
TerminatorKind::Drop { place, unwind, .. } => {
// If the place doesn't actually need dropping, treat it like a regular goto.
let ty = self.instantiate_ty(place.ty(self.callee_body, self.tcx).ty);
- if ty.needs_drop(self.tcx, self.param_env) {
+ if ty.needs_drop(self.tcx, self.typing_env) {
self.penalty += CALL_PENALTY;
if let UnwindAction::Cleanup(_) = unwind {
self.penalty += LANDINGPAD_PENALTY;
diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
index 7d073f1..500515b 100644
--- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
+++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
@@ -16,7 +16,7 @@
use rustc_middle::mir::interpret::{InterpResult, Scalar};
use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
use rustc_middle::mir::*;
-use rustc_middle::ty::layout::{HasParamEnv, LayoutOf};
+use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_mir_dataflow::fmt::DebugWithContext;
use rustc_mir_dataflow::lattice::{FlatSet, HasBottom};
@@ -82,7 +82,7 @@ struct ConstAnalysis<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
local_decls: &'a LocalDecls<'tcx>,
ecx: InterpCx<'tcx, DummyMachine>,
- param_env: ty::ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
}
impl<'tcx> Analysis<'tcx> for ConstAnalysis<'_, 'tcx> {
@@ -144,13 +144,13 @@ fn apply_call_return_effect(
impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, map: Map<'tcx>) -> Self {
- let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
+ let typing_env = body.typing_env(tcx);
Self {
map,
tcx,
local_decls: &body.local_decls,
- ecx: InterpCx::new(tcx, DUMMY_SP, param_env, DummyMachine),
- param_env,
+ ecx: InterpCx::new(tcx, DUMMY_SP, typing_env.param_env, DummyMachine),
+ typing_env,
}
}
@@ -389,7 +389,7 @@ fn handle_assign(
&& let Some(operand_ty) = operand_ty.builtin_deref(true)
&& let ty::Array(_, len) = operand_ty.kind()
&& let Some(len) = Const::Ty(self.tcx.types.usize, *len)
- .try_eval_scalar_int(self.tcx, self.param_env)
+ .try_eval_scalar_int(self.tcx, self.typing_env)
{
state.insert_value_idx(target_len, FlatSet::Elem(len.into()), &self.map);
}
@@ -411,7 +411,7 @@ fn handle_rvalue(
let place_ty = place.ty(self.local_decls, self.tcx);
if let ty::Array(_, len) = place_ty.ty.kind() {
Const::Ty(self.tcx.types.usize, *len)
- .try_eval_scalar(self.tcx, self.param_env)
+ .try_eval_scalar(self.tcx, self.typing_env)
.map_or(FlatSet::Top, FlatSet::Elem)
} else if let [ProjectionElem::Deref] = place.projection[..] {
state.get_len(place.local.into(), &self.map)
@@ -420,7 +420,7 @@ fn handle_rvalue(
}
}
Rvalue::Cast(CastKind::IntToInt | CastKind::IntToFloat, operand, ty) => {
- let Ok(layout) = self.tcx.layout_of(self.param_env.and(*ty)) else {
+ let Ok(layout) = self.tcx.layout_of(self.typing_env.as_query_input(*ty)) else {
return ValueOrPlace::Value(FlatSet::Top);
};
match self.eval_operand(operand, state) {
@@ -434,7 +434,7 @@ fn handle_rvalue(
}
}
Rvalue::Cast(CastKind::FloatToInt | CastKind::FloatToFloat, operand, ty) => {
- let Ok(layout) = self.tcx.layout_of(self.param_env.and(*ty)) else {
+ let Ok(layout) = self.tcx.layout_of(self.typing_env.as_query_input(*ty)) else {
return ValueOrPlace::Value(FlatSet::Top);
};
match self.eval_operand(operand, state) {
@@ -470,7 +470,7 @@ fn handle_rvalue(
FlatSet::Top => FlatSet::Top,
},
Rvalue::NullaryOp(null_op, ty) => {
- let Ok(layout) = self.tcx.layout_of(self.param_env.and(*ty)) else {
+ let Ok(layout) = self.tcx.layout_of(self.typing_env.as_query_input(*ty)) else {
return ValueOrPlace::Value(FlatSet::Top);
};
let val = match null_op {
@@ -479,7 +479,7 @@ fn handle_rvalue(
NullOp::OffsetOf(fields) => self
.ecx
.tcx
- .offset_of_subfield(self.ecx.param_env(), layout, fields.iter())
+ .offset_of_subfield(self.typing_env, layout, fields.iter())
.bytes(),
_ => return ValueOrPlace::Value(FlatSet::Top),
};
@@ -514,7 +514,7 @@ fn handle_constant(
) -> FlatSet<Scalar> {
constant
.const_
- .try_eval_scalar(self.tcx, self.param_env)
+ .try_eval_scalar(self.tcx, self.typing_env)
.map_or(FlatSet::Top, FlatSet::Elem)
}
@@ -554,7 +554,8 @@ fn assign_operand(
} else if rhs.projection.first() == Some(&PlaceElem::Deref)
&& let FlatSet::Elem(pointer) = state.get(rhs.local.into(), &self.map)
&& let rhs_ty = self.local_decls[rhs.local].ty
- && let Ok(rhs_layout) = self.tcx.layout_of(self.param_env.and(rhs_ty))
+ && let Ok(rhs_layout) =
+ self.tcx.layout_of(self.typing_env.as_query_input(rhs_ty))
{
let op = ImmTy::from_scalar(pointer, rhs_layout).into();
self.assign_constant(state, place, op, rhs.projection);
@@ -614,8 +615,10 @@ fn assign_constant(
TrackElem::DerefLen => {
let op: OpTy<'_> = self.ecx.deref_pointer(op).discard_err()?.into();
let len_usize = op.len(&self.ecx).discard_err()?;
- let layout =
- self.tcx.layout_of(self.param_env.and(self.tcx.types.usize)).unwrap();
+ let layout = self
+ .tcx
+ .layout_of(self.typing_env.as_query_input(self.tcx.types.usize))
+ .unwrap();
Some(ImmTy::from_uint(len_usize, layout).into())
}
},
@@ -702,9 +705,11 @@ fn eval_operand(
FlatSet::Top => FlatSet::Top,
FlatSet::Elem(scalar) => {
let ty = op.ty(self.local_decls, self.tcx);
- self.tcx.layout_of(self.param_env.and(ty)).map_or(FlatSet::Top, |layout| {
- FlatSet::Elem(ImmTy::from_scalar(scalar, layout))
- })
+ self.tcx
+ .layout_of(self.typing_env.as_query_input(ty))
+ .map_or(FlatSet::Top, |layout| {
+ FlatSet::Elem(ImmTy::from_scalar(scalar, layout))
+ })
}
FlatSet::Bottom => FlatSet::Bottom,
}
@@ -714,7 +719,7 @@ fn eval_discriminant(&self, enum_ty: Ty<'tcx>, variant_index: VariantIdx) -> Opt
if !enum_ty.is_enum() {
return None;
}
- let enum_ty_layout = self.tcx.layout_of(self.param_env.and(enum_ty)).ok()?;
+ let enum_ty_layout = self.tcx.layout_of(self.typing_env.as_query_input(enum_ty)).ok()?;
let discr_value =
self.ecx.discriminant_for_variant(enum_ty_layout.ty, variant_index).discard_err()?;
Some(discr_value.to_scalar())
@@ -941,16 +946,12 @@ fn try_write_constant<'tcx>(
interp_ok(())
}
-impl<'mir, 'tcx> ResultsVisitor<'mir, 'tcx, Results<'tcx, ConstAnalysis<'_, 'tcx>>>
- for Collector<'_, 'tcx>
-{
- type Domain = State<FlatSet<Scalar>>;
-
+impl<'mir, 'tcx> ResultsVisitor<'mir, 'tcx, ConstAnalysis<'_, 'tcx>> for Collector<'_, 'tcx> {
#[instrument(level = "trace", skip(self, results, statement))]
fn visit_statement_before_primary_effect(
&mut self,
results: &mut Results<'tcx, ConstAnalysis<'_, 'tcx>>,
- state: &Self::Domain,
+ state: &State<FlatSet<Scalar>>,
statement: &'mir Statement<'tcx>,
location: Location,
) {
@@ -972,7 +973,7 @@ fn visit_statement_before_primary_effect(
fn visit_statement_after_primary_effect(
&mut self,
results: &mut Results<'tcx, ConstAnalysis<'_, 'tcx>>,
- state: &Self::Domain,
+ state: &State<FlatSet<Scalar>>,
statement: &'mir Statement<'tcx>,
location: Location,
) {
@@ -997,7 +998,7 @@ fn visit_statement_after_primary_effect(
fn visit_terminator_before_primary_effect(
&mut self,
results: &mut Results<'tcx, ConstAnalysis<'_, 'tcx>>,
- state: &Self::Domain,
+ state: &State<FlatSet<Scalar>>,
terminator: &'mir Terminator<'tcx>,
location: Location,
) {
diff --git a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
index 753bae8..db72ec5 100644
--- a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
+++ b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
@@ -198,7 +198,7 @@ pub(super) fn deduced_param_attrs<'tcx>(
// see [1].
//
// [1]: https://github.com/rust-lang/rust/pull/103172#discussion_r999139997
- let param_env = tcx.param_env_reveal_all_normalized(def_id);
+ let typing_env = body.typing_env(tcx);
let mut deduced_param_attrs = tcx.arena.alloc_from_iter(
body.local_decls.iter().skip(1).take(body.arg_count).enumerate().map(
|(arg_index, local_decl)| DeducedParamAttrs {
@@ -207,8 +207,8 @@ pub(super) fn deduced_param_attrs<'tcx>(
// their generic parameters, otherwise we'll see exponential
// blow-up in compile times: #113372
&& tcx
- .normalize_erasing_regions(param_env, local_decl.ty)
- .is_freeze(tcx, param_env),
+ .normalize_erasing_regions(typing_env, local_decl.ty)
+ .is_freeze(tcx, typing_env.param_env),
},
),
);
diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs
index 7457210..b0f041d 100644
--- a/compiler/rustc_mir_transform/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs
@@ -3,6 +3,7 @@
use rustc_abi::{FieldIdx, VariantIdx};
use rustc_index::IndexVec;
use rustc_index::bit_set::BitSet;
+use rustc_infer::traits::Reveal;
use rustc_middle::mir::patch::MirPatch;
use rustc_middle::mir::*;
use rustc_middle::ty::{self, TyCtxt};
@@ -53,14 +54,14 @@ impl<'tcx> crate::MirPass<'tcx> for ElaborateDrops {
#[instrument(level = "trace", skip(self, tcx, body))]
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
debug!("elaborate_drops({:?} @ {:?})", body.source, body.span);
-
- let def_id = body.source.def_id();
- let param_env = tcx.param_env_reveal_all_normalized(def_id);
+ // FIXME(#132279): This is used during the phase transition from analysis
+ // to runtime, so we have to manually specify the correct typing mode.
+ let typing_env = ty::TypingEnv::post_analysis(tcx, body.source.def_id());
// For types that do not need dropping, the behaviour is trivial. So we only need to track
// init/uninit for types that do need dropping.
- let move_data = MoveData::gather_moves(body, tcx, |ty| ty.needs_drop(tcx, param_env));
+ let move_data = MoveData::gather_moves(body, tcx, |ty| ty.needs_drop(tcx, typing_env));
let elaborate_patch = {
- let env = MoveDataParamEnv { move_data, param_env };
+ let env = MoveDataParamEnv { move_data, param_env: typing_env.param_env };
let mut inits = MaybeInitializedPlaces::new(tcx, body, &env.move_data)
.skipping_unreachable_unwind()
@@ -147,8 +148,8 @@ fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}
- fn param_env(&self) -> ty::ParamEnv<'tcx> {
- self.param_env()
+ fn typing_env(&self) -> ty::TypingEnv<'tcx> {
+ self.typing_env()
}
#[instrument(level = "debug", skip(self), ret)]
@@ -250,6 +251,11 @@ fn param_env(&self) -> ty::ParamEnv<'tcx> {
self.env.param_env
}
+ fn typing_env(&self) -> ty::TypingEnv<'tcx> {
+ debug_assert_eq!(self.param_env().reveal(), Reveal::All);
+ ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env: self.param_env() }
+ }
+
fn create_drop_flag(&mut self, index: MovePathIndex, span: Span) {
let patch = &mut self.patch;
debug!("create_drop_flag({:?})", self.body.span);
@@ -335,7 +341,7 @@ fn elaborate_drops(&mut self) {
if !place
.ty(&self.body.local_decls, self.tcx)
.ty
- .needs_drop(self.tcx, self.env.param_env)
+ .needs_drop(self.tcx, self.typing_env())
{
self.patch.patch_terminator(bb, TerminatorKind::Goto { target });
continue;
diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs
index 274eea9..27fe0ad 100644
--- a/compiler/rustc_mir_transform/src/gvn.rs
+++ b/compiler/rustc_mir_transform/src/gvn.rs
@@ -100,7 +100,7 @@
use rustc_middle::mir::interpret::GlobalAlloc;
use rustc_middle::mir::visit::*;
use rustc_middle::mir::*;
-use rustc_middle::ty::layout::{HasParamEnv, LayoutOf};
+use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::DUMMY_SP;
use rustc_span::def_id::DefId;
@@ -295,6 +295,10 @@ fn new(
}
}
+ fn typing_env(&self) -> ty::TypingEnv<'tcx> {
+ ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env: self.param_env }
+ }
+
#[instrument(level = "trace", skip(self), ret)]
fn insert(&mut self, value: Value<'tcx>) -> VnIndex {
let (index, new) = self.values.insert_full(value);
@@ -531,7 +535,7 @@ fn eval_to_const(&mut self, value: VnIndex) -> Option<OpTy<'tcx>> {
NullOp::OffsetOf(fields) => self
.ecx
.tcx
- .offset_of_subfield(self.ecx.param_env(), layout, fields.iter())
+ .offset_of_subfield(self.typing_env(), layout, fields.iter())
.bytes(),
NullOp::UbChecks => return None,
};
@@ -1476,8 +1480,9 @@ fn pointers_have_same_metadata(&self, left_ptr_ty: Ty<'tcx>, right_ptr_ty: Ty<'t
if left_meta_ty == right_meta_ty {
true
} else if let Ok(left) =
- self.tcx.try_normalize_erasing_regions(self.param_env, left_meta_ty)
- && let Ok(right) = self.tcx.try_normalize_erasing_regions(self.param_env, right_meta_ty)
+ self.tcx.try_normalize_erasing_regions(self.typing_env(), left_meta_ty)
+ && let Ok(right) =
+ self.tcx.try_normalize_erasing_regions(self.typing_env(), right_meta_ty)
{
left == right
} else {
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index e95ab4f..fcb51fb 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -13,9 +13,7 @@
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
use rustc_middle::mir::visit::*;
use rustc_middle::mir::*;
-use rustc_middle::ty::{
- self, Instance, InstanceKind, ParamEnv, Ty, TyCtxt, TypeFlags, TypeVisitableExt,
-};
+use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TyCtxt, TypeFlags, TypeVisitableExt};
use rustc_session::config::{DebugInfo, OptLevel};
use rustc_span::source_map::Spanned;
use rustc_span::sym;
@@ -94,12 +92,12 @@ fn inline<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool {
return false;
}
- let param_env = tcx.param_env_reveal_all_normalized(def_id);
+ let typing_env = body.typing_env(tcx);
let codegen_fn_attrs = tcx.codegen_fn_attrs(def_id);
let mut this = Inliner {
tcx,
- param_env,
+ typing_env,
codegen_fn_attrs,
history: Vec::new(),
changed: false,
@@ -115,7 +113,7 @@ fn inline<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool {
struct Inliner<'tcx> {
tcx: TyCtxt<'tcx>,
- param_env: ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
/// Caller codegen attributes.
codegen_fn_attrs: &'tcx CodegenFnAttrs,
/// Stack of inlined instances.
@@ -201,7 +199,11 @@ fn try_inlining(
let TerminatorKind::Call { args, destination, .. } = &terminator.kind else { bug!() };
let destination_ty = destination.ty(&caller_body.local_decls, self.tcx).ty;
for arg in args {
- if !arg.node.ty(&caller_body.local_decls, self.tcx).is_sized(self.tcx, self.param_env) {
+ if !arg
+ .node
+ .ty(&caller_body.local_decls, self.tcx)
+ .is_sized(self.tcx, self.typing_env.param_env)
+ {
// We do not allow inlining functions with unsized params. Inlining these functions
// could create unsized locals, which are unsound and being phased out.
return Err("Call has unsized argument");
@@ -219,7 +221,7 @@ fn try_inlining(
let Ok(callee_body) = callsite.callee.try_instantiate_mir_and_normalize_erasing_regions(
self.tcx,
- self.param_env,
+ self.typing_env,
ty::EarlyBinder::bind(callee_body.clone()),
) else {
return Err("failed to normalize callee body");
@@ -230,7 +232,7 @@ fn try_inlining(
if !validate_types(
self.tcx,
MirPhase::Runtime(RuntimePhase::Optimized),
- self.param_env,
+ self.typing_env,
&callee_body,
&caller_body,
)
@@ -243,13 +245,7 @@ fn try_inlining(
// Normally, this shouldn't be required, but trait normalization failure can create a
// validation ICE.
let output_type = callee_body.return_ty();
- if !util::sub_types(
- self.tcx,
- caller_body.typing_mode(self.tcx),
- self.param_env,
- output_type,
- destination_ty,
- ) {
+ if !util::sub_types(self.tcx, self.typing_env, output_type, destination_ty) {
trace!(?output_type, ?destination_ty);
return Err("failed to normalize return type");
}
@@ -279,13 +275,7 @@ fn try_inlining(
self_arg_ty.into_iter().chain(arg_tuple_tys).zip(callee_body.args_iter())
{
let input_type = callee_body.local_decls[input].ty;
- if !util::sub_types(
- self.tcx,
- caller_body.typing_mode(self.tcx),
- self.param_env,
- input_type,
- arg_ty,
- ) {
+ if !util::sub_types(self.tcx, self.typing_env, input_type, arg_ty) {
trace!(?arg_ty, ?input_type);
return Err("failed to normalize tuple argument type");
}
@@ -294,13 +284,7 @@ fn try_inlining(
for (arg, input) in args.iter().zip(callee_body.args_iter()) {
let input_type = callee_body.local_decls[input].ty;
let arg_ty = arg.node.ty(&caller_body.local_decls, self.tcx);
- if !util::sub_types(
- self.tcx,
- caller_body.typing_mode(self.tcx),
- self.param_env,
- input_type,
- arg_ty,
- ) {
+ if !util::sub_types(self.tcx, self.typing_env, input_type, arg_ty) {
trace!(?arg_ty, ?input_type);
return Err("failed to normalize argument type");
}
@@ -402,9 +386,10 @@ fn resolve_callsite(
let func_ty = func.ty(caller_body, self.tcx);
if let ty::FnDef(def_id, args) = *func_ty.kind() {
// To resolve an instance its args have to be fully normalized.
- let args = self.tcx.try_normalize_erasing_regions(self.param_env, args).ok()?;
- let callee =
- Instance::try_resolve(self.tcx, self.param_env, def_id, args).ok().flatten()?;
+ let args = self.tcx.try_normalize_erasing_regions(self.typing_env, args).ok()?;
+ let callee = Instance::try_resolve(self.tcx, self.typing_env, def_id, args)
+ .ok()
+ .flatten()?;
if let InstanceKind::Virtual(..) | InstanceKind::Intrinsic(_) = callee.def {
return None;
@@ -528,7 +513,7 @@ fn check_mir_body(
// FIXME: Give a bonus to functions with only a single caller
let mut checker =
- CostChecker::new(self.tcx, self.param_env, Some(callsite.callee), callee_body);
+ CostChecker::new(self.tcx, self.typing_env, Some(callsite.callee), callee_body);
checker.add_function_level_costs();
@@ -552,7 +537,7 @@ fn check_mir_body(
self.tcx,
ty::EarlyBinder::bind(&place.ty(callee_body, tcx).ty),
);
- if ty.needs_drop(tcx, self.param_env)
+ if ty.needs_drop(tcx, self.typing_env)
&& let UnwindAction::Cleanup(unwind) = unwind
{
work_list.push(unwind);
diff --git a/compiler/rustc_mir_transform/src/inline/cycle.rs b/compiler/rustc_mir_transform/src/inline/cycle.rs
index 9828e90..a407683 100644
--- a/compiler/rustc_mir_transform/src/inline/cycle.rs
+++ b/compiler/rustc_mir_transform/src/inline/cycle.rs
@@ -15,7 +15,6 @@ pub(crate) fn mir_callgraph_reachable<'tcx>(
(root, target): (ty::Instance<'tcx>, LocalDefId),
) -> bool {
trace!(%root, target = %tcx.def_path_str(target));
- let param_env = tcx.param_env_reveal_all_normalized(target);
assert_ne!(
root.def_id().expect_local(),
target,
@@ -31,11 +30,11 @@ pub(crate) fn mir_callgraph_reachable<'tcx>(
);
#[instrument(
level = "debug",
- skip(tcx, param_env, target, stack, seen, recursion_limiter, caller, recursion_limit)
+ skip(tcx, typing_env, target, stack, seen, recursion_limiter, caller, recursion_limit)
)]
fn process<'tcx>(
tcx: TyCtxt<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
caller: ty::Instance<'tcx>,
target: LocalDefId,
stack: &mut Vec<ty::Instance<'tcx>>,
@@ -47,13 +46,13 @@ fn process<'tcx>(
for &(callee, args) in tcx.mir_inliner_callees(caller.def) {
let Ok(args) = caller.try_instantiate_mir_and_normalize_erasing_regions(
tcx,
- param_env,
+ typing_env,
ty::EarlyBinder::bind(args),
) else {
- trace!(?caller, ?param_env, ?args, "cannot normalize, skipping");
+ trace!(?caller, ?typing_env, ?args, "cannot normalize, skipping");
continue;
};
- let Ok(Some(callee)) = ty::Instance::try_resolve(tcx, param_env, callee, args) else {
+ let Ok(Some(callee)) = ty::Instance::try_resolve(tcx, typing_env, callee, args) else {
trace!(?callee, "cannot resolve, skipping");
continue;
};
@@ -115,7 +114,7 @@ fn process<'tcx>(
let found_recursion = ensure_sufficient_stack(|| {
process(
tcx,
- param_env,
+ typing_env,
callee,
target,
stack,
@@ -146,7 +145,7 @@ fn process<'tcx>(
let recursion_limit = tcx.recursion_limit() / 2;
process(
tcx,
- param_env,
+ ty::TypingEnv::post_analysis(tcx, target),
root,
target,
&mut Vec::new(),
diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs
index 9471c1b..b80abcc 100644
--- a/compiler/rustc_mir_transform/src/instsimplify.rs
+++ b/compiler/rustc_mir_transform/src/instsimplify.rs
@@ -70,6 +70,12 @@ struct InstSimplifyContext<'a, 'tcx> {
}
impl<'tcx> InstSimplifyContext<'_, 'tcx> {
+ fn typing_env(&self) -> ty::TypingEnv<'tcx> {
+ ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env: self.param_env }
+ }
+}
+
+impl<'tcx> InstSimplifyContext<'_, 'tcx> {
fn should_simplify(&self, source_info: &SourceInfo, rvalue: &Rvalue<'tcx>) -> bool {
self.should_simplify_custom(source_info, "Rvalue", rvalue)
}
@@ -348,7 +354,7 @@ fn simplify_intrinsic_assert(&self, terminator: &mut Terminator<'tcx>) {
}
let known_is_valid =
- intrinsic_assert_panics(self.tcx, self.param_env, args[0], intrinsic_name);
+ intrinsic_assert_panics(self.tcx, self.typing_env(), args[0], intrinsic_name);
match known_is_valid {
// We don't know the layout or it's not validity assertion at all, don't touch it
None => {}
@@ -366,13 +372,13 @@ fn simplify_intrinsic_assert(&self, terminator: &mut Terminator<'tcx>) {
fn intrinsic_assert_panics<'tcx>(
tcx: TyCtxt<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
arg: ty::GenericArg<'tcx>,
intrinsic_name: Symbol,
) -> Option<bool> {
let requirement = ValidityRequirement::from_intrinsic(intrinsic_name)?;
let ty = arg.expect_ty();
- Some(!tcx.check_validity_requirement((requirement, param_env.and(ty))).ok()?)
+ Some(!tcx.check_validity_requirement((requirement, typing_env.as_query_input(ty))).ok()?)
}
fn resolve_rust_intrinsic<'tcx>(
diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs
index 3772589..71a843a 100644
--- a/compiler/rustc_mir_transform/src/jump_threading.rs
+++ b/compiler/rustc_mir_transform/src/jump_threading.rs
@@ -77,13 +77,12 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
return;
}
- let param_env = tcx.param_env_reveal_all_normalized(def_id);
-
+ let typing_env = body.typing_env(tcx);
let arena = &DroplessArena::default();
let mut finder = TOFinder {
tcx,
- param_env,
- ecx: InterpCx::new(tcx, DUMMY_SP, param_env, DummyMachine),
+ typing_env,
+ ecx: InterpCx::new(tcx, DUMMY_SP, typing_env.param_env, DummyMachine),
body,
arena,
map: Map::new(tcx, body, Some(MAX_PLACES)),
@@ -119,7 +118,7 @@ struct ThreadingOpportunity {
struct TOFinder<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
ecx: InterpCx<'tcx, DummyMachine>,
body: &'a Body<'tcx>,
map: Map<'tcx>,
@@ -207,7 +206,7 @@ fn start_from_switch(&mut self, bb: BasicBlock) {
let Some(discr) = self.map.find(discr.as_ref()) else { return };
debug!(?discr);
- let cost = CostChecker::new(self.tcx, self.param_env, None, self.body);
+ let cost = CostChecker::new(self.tcx, self.typing_env, None, self.body);
let mut state = State::new_reachable();
let conds = if let Some((value, then, else_)) = targets.as_static_if() {
@@ -528,7 +527,8 @@ fn process_assign(
// Avoid handling them, though this could be extended in the future.
return;
}
- let Some(value) = value.const_.try_eval_scalar_int(self.tcx, self.param_env) else {
+ let Some(value) = value.const_.try_eval_scalar_int(self.tcx, self.typing_env)
+ else {
return;
};
let conds = conditions.map(self.arena, |c| Condition {
diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs
index 0604665..3911b0a 100644
--- a/compiler/rustc_mir_transform/src/known_panics_lint.rs
+++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs
@@ -18,7 +18,7 @@
use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::*;
use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout};
-use rustc_middle::ty::{self, ConstInt, ParamEnv, ScalarInt, Ty, TyCtxt, TypeVisitableExt};
+use rustc_middle::ty::{self, ConstInt, ScalarInt, Ty, TyCtxt, TypeVisitableExt};
use rustc_span::Span;
use tracing::{debug, instrument, trace};
@@ -65,7 +65,7 @@ fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
struct ConstPropagator<'mir, 'tcx> {
ecx: InterpCx<'tcx, DummyMachine>,
tcx: TyCtxt<'tcx>,
- param_env: ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
worklist: Vec<BasicBlock>,
visited_blocks: BitSet<BasicBlock>,
locals: IndexVec<Local, Value<'tcx>>,
@@ -169,25 +169,26 @@ fn tcx(&self) -> TyCtxt<'tcx> {
}
}
-impl<'tcx> ty::layout::HasParamEnv<'tcx> for ConstPropagator<'_, 'tcx> {
+impl<'tcx> ty::layout::HasTypingEnv<'tcx> for ConstPropagator<'_, 'tcx> {
#[inline]
- fn param_env(&self) -> ty::ParamEnv<'tcx> {
- self.param_env
+ fn typing_env(&self) -> ty::TypingEnv<'tcx> {
+ self.typing_env
}
}
impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
fn new(body: &'mir Body<'tcx>, tcx: TyCtxt<'tcx>) -> ConstPropagator<'mir, 'tcx> {
let def_id = body.source.def_id();
- let param_env = tcx.param_env_reveal_all_normalized(def_id);
-
- let can_const_prop = CanConstProp::check(tcx, param_env, body);
- let ecx = InterpCx::new(tcx, tcx.def_span(def_id), param_env, DummyMachine);
+ // FIXME(#132279): This is used during the phase transition from analysis
+ // to runtime, so we have to manually specify the correct typing mode.
+ let typing_env = ty::TypingEnv::post_analysis(tcx, body.source.def_id());
+ let can_const_prop = CanConstProp::check(tcx, typing_env, body);
+ let ecx = InterpCx::new(tcx, tcx.def_span(def_id), typing_env.param_env, DummyMachine);
ConstPropagator {
ecx,
tcx,
- param_env,
+ typing_env,
worklist: vec![START_BLOCK],
visited_blocks: BitSet::new_empty(body.basic_blocks.len()),
locals: IndexVec::from_elem_n(Value::Uninit, body.local_decls.len()),
@@ -260,7 +261,7 @@ fn eval_constant(&mut self, c: &ConstOperand<'tcx>) -> Option<ImmTy<'tcx>> {
// that the `RevealAll` pass has happened and that the body's consts
// are normalized, so any call to resolve before that needs to be
// manually normalized.
- let val = self.tcx.try_normalize_erasing_regions(self.param_env, c.const_).ok()?;
+ let val = self.tcx.try_normalize_erasing_regions(self.typing_env, c.const_).ok()?;
self.use_ecx(|this| this.ecx.eval_mir_constant(&val, c.span, None))?
.as_mplace_or_imm()
@@ -450,7 +451,7 @@ fn check_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) -> Option<
if rvalue.has_param() {
return None;
}
- if !rvalue.ty(self.local_decls(), self.tcx).is_sized(self.tcx, self.param_env) {
+ if !rvalue.ty(self.local_decls(), self.tcx).is_sized(self.tcx, self.typing_env.param_env) {
// the interpreter doesn't support unsized locals (only unsized arguments),
// but rustc does (in a kinda broken way), so we have to skip them here
return None;
@@ -622,7 +623,7 @@ fn eval_rvalue(&mut self, rvalue: &Rvalue<'tcx>, dest: &Place<'tcx>) -> Option<(
NullOp::AlignOf => op_layout.align.abi.bytes(),
NullOp::OffsetOf(fields) => self
.tcx
- .offset_of_subfield(self.param_env, op_layout, fields.iter())
+ .offset_of_subfield(self.typing_env, op_layout, fields.iter())
.bytes(),
NullOp::UbChecks => return None,
};
@@ -873,7 +874,7 @@ impl CanConstProp {
/// Returns true if `local` can be propagated
fn check<'tcx>(
tcx: TyCtxt<'tcx>,
- param_env: ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
body: &Body<'tcx>,
) -> IndexVec<Local, ConstPropMode> {
let mut cpv = CanConstProp {
@@ -888,7 +889,7 @@ fn check<'tcx>(
// variant of a union
*val = ConstPropMode::NoPropagation;
} else {
- match tcx.layout_of(param_env.and(ty)) {
+ match tcx.layout_of(typing_env.as_query_input(ty)) {
Ok(layout) if layout.size < Size::from_bytes(MAX_ALLOC_LIMIT) => {}
// Either the layout fails to compute, then we can't use this local anyway
// or the local is too large, then we don't want to.
diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs
index fa659a5..8be5a63 100644
--- a/compiler/rustc_mir_transform/src/large_enums.rs
+++ b/compiler/rustc_mir_transform/src/large_enums.rs
@@ -3,7 +3,7 @@
use rustc_middle::mir::interpret::AllocId;
use rustc_middle::mir::*;
use rustc_middle::ty::util::IntTypeExt;
-use rustc_middle::ty::{self, AdtDef, ParamEnv, Ty, TyCtxt};
+use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt};
use rustc_session::Session;
/// A pass that seeks to optimize unnecessary moves of large enum types, if there is a large
@@ -39,8 +39,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
// platform, but it will still be valid.
let mut alloc_cache = FxHashMap::default();
- let body_did = body.source.def_id();
- let param_env = tcx.param_env_reveal_all_normalized(body_did);
+ let typing_env = body.typing_env(tcx);
let blocks = body.basic_blocks.as_mut();
let local_decls = &mut body.local_decls;
@@ -58,7 +57,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let ty = lhs.ty(local_decls, tcx).ty;
let (adt_def, num_variants, alloc_id) =
- self.candidate(tcx, param_env, ty, &mut alloc_cache)?;
+ self.candidate(tcx, typing_env, ty, &mut alloc_cache)?;
let source_info = st.source_info;
let span = source_info.span;
@@ -207,7 +206,7 @@ impl EnumSizeOpt {
fn candidate<'tcx>(
&self,
tcx: TyCtxt<'tcx>,
- param_env: ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
ty: Ty<'tcx>,
alloc_cache: &mut FxHashMap<Ty<'tcx>, AllocId>,
) -> Option<(AdtDef<'tcx>, usize, AllocId)> {
@@ -215,7 +214,7 @@ fn candidate<'tcx>(
ty::Adt(adt_def, _args) if adt_def.is_enum() => adt_def,
_ => return None,
};
- let layout = tcx.layout_of(param_env.and(ty)).ok()?;
+ let layout = tcx.layout_of(typing_env.as_query_input(ty)).ok()?;
let variants = match &layout.variants {
Variants::Single { .. } => return None,
Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, .. } => return None,
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index d2d5fac..5651bf4 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -333,10 +333,14 @@ fn mir_keys(tcx: TyCtxt<'_>, (): ()) -> FxIndexSet<LocalDefId> {
}
fn mir_const_qualif(tcx: TyCtxt<'_>, def: LocalDefId) -> ConstQualifs {
- let const_kind = tcx.hir().body_const_context(def);
-
+ // N.B., this `borrow()` is guaranteed to be valid (i.e., the value
+ // cannot yet be stolen), because `mir_promoted()`, which steals
+ // from `mir_built()`, forces this query to execute before
+ // performing the steal.
+ let body = &tcx.mir_built(def).borrow();
+ let ccx = check_consts::ConstCx::new(tcx, body);
// No need to const-check a non-const `fn`.
- match const_kind {
+ match ccx.const_kind {
Some(ConstContext::Const { .. } | ConstContext::Static(_) | ConstContext::ConstFn) => {}
None => span_bug!(
tcx.def_span(def),
@@ -344,20 +348,12 @@ fn mir_const_qualif(tcx: TyCtxt<'_>, def: LocalDefId) -> ConstQualifs {
),
}
- // N.B., this `borrow()` is guaranteed to be valid (i.e., the value
- // cannot yet be stolen), because `mir_promoted()`, which steals
- // from `mir_built()`, forces this query to execute before
- // performing the steal.
- let body = &tcx.mir_built(def).borrow();
-
if body.return_ty().references_error() {
// It's possible to reach here without an error being emitted (#121103).
tcx.dcx().span_delayed_bug(body.span, "mir_const_qualif: MIR had errors");
return Default::default();
}
- let ccx = check_consts::ConstCx { body, tcx, const_kind, param_env: tcx.param_env(def) };
-
let mut validator = check_consts::check::Checker::new(&ccx);
validator.check_body();
diff --git a/compiler/rustc_mir_transform/src/match_branches.rs b/compiler/rustc_mir_transform/src/match_branches.rs
index 237227f..ff02768 100644
--- a/compiler/rustc_mir_transform/src/match_branches.rs
+++ b/compiler/rustc_mir_transform/src/match_branches.rs
@@ -5,7 +5,7 @@
use rustc_middle::mir::patch::MirPatch;
use rustc_middle::mir::*;
use rustc_middle::ty::layout::{IntegerExt, TyAndLayout};
-use rustc_middle::ty::{ParamEnv, ScalarInt, Ty, TyCtxt};
+use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt};
use rustc_type_ir::TyKind::*;
use super::simplify::simplify_cfg;
@@ -19,8 +19,7 @@ fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let def_id = body.source.def_id();
- let param_env = tcx.param_env_reveal_all_normalized(def_id);
-
+ let typing_env = body.typing_env(tcx);
let mut should_cleanup = false;
for i in 0..body.basic_blocks.len() {
let bbs = &*body.basic_blocks;
@@ -40,11 +39,11 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
_ => continue,
};
- if SimplifyToIf.simplify(tcx, body, bb_idx, param_env).is_some() {
+ if SimplifyToIf.simplify(tcx, body, bb_idx, typing_env).is_some() {
should_cleanup = true;
continue;
}
- if SimplifyToExp::default().simplify(tcx, body, bb_idx, param_env).is_some() {
+ if SimplifyToExp::default().simplify(tcx, body, bb_idx, typing_env).is_some() {
should_cleanup = true;
continue;
}
@@ -65,7 +64,7 @@ fn simplify(
tcx: TyCtxt<'tcx>,
body: &mut Body<'tcx>,
switch_bb_idx: BasicBlock,
- param_env: ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
) -> Option<()> {
let bbs = &body.basic_blocks;
let (discr, targets) = match bbs[switch_bb_idx].terminator().kind {
@@ -74,7 +73,7 @@ fn simplify(
};
let discr_ty = discr.ty(body.local_decls(), tcx);
- self.can_simplify(tcx, targets, param_env, bbs, discr_ty)?;
+ self.can_simplify(tcx, targets, typing_env, bbs, discr_ty)?;
let mut patch = MirPatch::new(body);
@@ -90,7 +89,16 @@ fn simplify(
let parent_end = Location { block: switch_bb_idx, statement_index };
patch.add_statement(parent_end, StatementKind::StorageLive(discr_local));
patch.add_assign(parent_end, Place::from(discr_local), Rvalue::Use(discr));
- self.new_stmts(tcx, targets, param_env, &mut patch, parent_end, bbs, discr_local, discr_ty);
+ self.new_stmts(
+ tcx,
+ targets,
+ typing_env,
+ &mut patch,
+ parent_end,
+ bbs,
+ discr_local,
+ discr_ty,
+ );
patch.add_statement(parent_end, StatementKind::StorageDead(discr_local));
patch.patch_terminator(switch_bb_idx, bbs[first].terminator().kind.clone());
patch.apply(body);
@@ -104,7 +112,7 @@ fn can_simplify(
&mut self,
tcx: TyCtxt<'tcx>,
targets: &SwitchTargets,
- param_env: ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
bbs: &IndexSlice<BasicBlock, BasicBlockData<'tcx>>,
discr_ty: Ty<'tcx>,
) -> Option<()>;
@@ -113,7 +121,7 @@ fn new_stmts(
&self,
tcx: TyCtxt<'tcx>,
targets: &SwitchTargets,
- param_env: ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
patch: &mut MirPatch<'tcx>,
parent_end: Location,
bbs: &IndexSlice<BasicBlock, BasicBlockData<'tcx>>,
@@ -160,7 +168,7 @@ fn can_simplify(
&mut self,
tcx: TyCtxt<'tcx>,
targets: &SwitchTargets,
- param_env: ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
bbs: &IndexSlice<BasicBlock, BasicBlockData<'tcx>>,
_discr_ty: Ty<'tcx>,
) -> Option<()> {
@@ -197,8 +205,8 @@ fn can_simplify(
) if lhs_f == lhs_s
&& f_c.const_.ty().is_bool()
&& s_c.const_.ty().is_bool()
- && f_c.const_.try_eval_bool(tcx, param_env).is_some()
- && s_c.const_.try_eval_bool(tcx, param_env).is_some() => {}
+ && f_c.const_.try_eval_bool(tcx, typing_env).is_some()
+ && s_c.const_.try_eval_bool(tcx, typing_env).is_some() => {}
// Otherwise we cannot optimize. Try another block.
_ => return None,
@@ -211,7 +219,7 @@ fn new_stmts(
&self,
tcx: TyCtxt<'tcx>,
targets: &SwitchTargets,
- param_env: ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
patch: &mut MirPatch<'tcx>,
parent_end: Location,
bbs: &IndexSlice<BasicBlock, BasicBlockData<'tcx>>,
@@ -235,15 +243,15 @@ fn new_stmts(
StatementKind::Assign(box (_, Rvalue::Use(Operand::Constant(s_c)))),
) => {
// From earlier loop we know that we are dealing with bool constants only:
- let f_b = f_c.const_.try_eval_bool(tcx, param_env).unwrap();
- let s_b = s_c.const_.try_eval_bool(tcx, param_env).unwrap();
+ let f_b = f_c.const_.try_eval_bool(tcx, typing_env).unwrap();
+ let s_b = s_c.const_.try_eval_bool(tcx, typing_env).unwrap();
if f_b == s_b {
// Same value in both blocks. Use statement as is.
patch.add_statement(parent_end, f.kind.clone());
} else {
// Different value between blocks. Make value conditional on switch
// condition.
- let size = tcx.layout_of(param_env.and(discr_ty)).unwrap().size;
+ let size = tcx.layout_of(typing_env.as_query_input(discr_ty)).unwrap().size;
let const_cmp = Operand::const_from_scalar(
tcx,
discr_ty,
@@ -363,7 +371,7 @@ fn can_simplify(
&mut self,
tcx: TyCtxt<'tcx>,
targets: &SwitchTargets,
- param_env: ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
bbs: &IndexSlice<BasicBlock, BasicBlockData<'tcx>>,
discr_ty: Ty<'tcx>,
) -> Option<()> {
@@ -388,7 +396,7 @@ fn can_simplify(
return None;
}
- let discr_layout = tcx.layout_of(param_env.and(discr_ty)).unwrap();
+ let discr_layout = tcx.layout_of(typing_env.as_query_input(discr_ty)).unwrap();
let first_stmts = &bbs[first_target].statements;
let (second_case_val, second_target) = target_iter.next().unwrap();
let second_stmts = &bbs[second_target].statements;
@@ -414,8 +422,8 @@ fn can_simplify(
&& f_c.const_.ty().is_integral() =>
{
match (
- f_c.const_.try_eval_scalar_int(tcx, param_env),
- s_c.const_.try_eval_scalar_int(tcx, param_env),
+ f_c.const_.try_eval_scalar_int(tcx, typing_env),
+ s_c.const_.try_eval_scalar_int(tcx, typing_env),
) {
(Some(f), Some(s)) if f == s => ExpectedTransformKind::SameByEq {
place: lhs_f,
@@ -467,11 +475,11 @@ fn can_simplify(
StatementKind::Assign(box (lhs_s, Rvalue::Use(Operand::Constant(s_c)))),
) if lhs_f == lhs_s
&& s_c.const_.ty() == f_ty
- && s_c.const_.try_eval_scalar_int(tcx, param_env) == Some(scalar) => {}
+ && s_c.const_.try_eval_scalar_int(tcx, typing_env) == Some(scalar) => {}
(
ExpectedTransformKind::Cast { place: lhs_f, ty: f_ty },
StatementKind::Assign(box (lhs_s, Rvalue::Use(Operand::Constant(s_c)))),
- ) if let Some(f) = s_c.const_.try_eval_scalar_int(tcx, param_env)
+ ) if let Some(f) = s_c.const_.try_eval_scalar_int(tcx, typing_env)
&& lhs_f == lhs_s
&& s_c.const_.ty() == f_ty
&& can_cast(tcx, other_val, discr_layout, f_ty, f) => {}
@@ -487,7 +495,7 @@ fn new_stmts(
&self,
_tcx: TyCtxt<'tcx>,
targets: &SwitchTargets,
- _param_env: ParamEnv<'tcx>,
+ _typing_env: ty::TypingEnv<'tcx>,
patch: &mut MirPatch<'tcx>,
parent_end: Location,
bbs: &IndexSlice<BasicBlock, BasicBlockData<'tcx>>,
diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs
index fa9a6bf..6be95b1 100644
--- a/compiler/rustc_mir_transform/src/promote_consts.rs
+++ b/compiler/rustc_mir_transform/src/promote_consts.rs
@@ -325,7 +325,7 @@ fn validate_place(&mut self, place: PlaceRef<'tcx>) -> Result<(), Unpromotable>
if let TempState::Defined { location: loc, .. } = self.temps[local]
&& let Left(statement) = self.body.stmt_at(loc)
&& let Some((_, Rvalue::Use(Operand::Constant(c)))) = statement.kind.as_assign()
- && let Some(idx) = c.const_.try_eval_target_usize(self.tcx, self.param_env)
+ && let Some(idx) = c.const_.try_eval_target_usize(self.tcx, self.typing_env)
// Determine the type of the thing we are indexing.
&& let ty::Array(_, len) = place_base.ty(self.body, self.tcx).ty.kind()
// It's an array; determine its length.
@@ -490,7 +490,7 @@ fn validate_rvalue(&mut self, rvalue: &Rvalue<'tcx>) -> Result<(), Unpromotable>
// Integer division: the RHS must be a non-zero const.
let rhs_val = match rhs {
Operand::Constant(c) => {
- c.const_.try_eval_scalar_int(self.tcx, self.param_env)
+ c.const_.try_eval_scalar_int(self.tcx, self.typing_env)
}
_ => None,
};
@@ -509,7 +509,7 @@ fn validate_rvalue(&mut self, rvalue: &Rvalue<'tcx>) -> Result<(), Unpromotable>
let lhs_val = match lhs {
Operand::Constant(c) => c
.const_
- .try_eval_scalar_int(self.tcx, self.param_env),
+ .try_eval_scalar_int(self.tcx, self.typing_env),
_ => None,
};
let lhs_min = sz.signed_int_min();
diff --git a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs
index 20c34a7..f786c67 100644
--- a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs
+++ b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs
@@ -1,7 +1,7 @@
use rustc_abi::FieldIdx;
use rustc_index::bit_set::ChunkedBitSet;
use rustc_middle::mir::{Body, TerminatorKind};
-use rustc_middle::ty::{self, GenericArgsRef, ParamEnv, Ty, TyCtxt, VariantDef};
+use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, VariantDef};
use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
use rustc_mir_dataflow::move_paths::{LookupResult, MoveData, MovePathIndex};
use rustc_mir_dataflow::{Analysis, MaybeReachable, move_path_children_matching};
@@ -18,8 +18,8 @@
impl<'tcx> crate::MirPass<'tcx> for RemoveUninitDrops {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
- let param_env = tcx.param_env(body.source.def_id());
- let move_data = MoveData::gather_moves(body, tcx, |ty| ty.needs_drop(tcx, param_env));
+ let typing_env = body.typing_env(tcx);
+ let move_data = MoveData::gather_moves(body, tcx, |ty| ty.needs_drop(tcx, typing_env));
let mut maybe_inits = MaybeInitializedPlaces::new(tcx, body, &move_data)
.iterate_to_fixpoint(tcx, body, Some("remove_uninit_drops"))
@@ -40,7 +40,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let should_keep = is_needs_drop_and_init(
tcx,
- param_env,
+ typing_env,
maybe_inits,
&move_data,
place.ty(body, tcx).ty,
@@ -66,24 +66,24 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
fn is_needs_drop_and_init<'tcx>(
tcx: TyCtxt<'tcx>,
- param_env: ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
maybe_inits: &ChunkedBitSet<MovePathIndex>,
move_data: &MoveData<'tcx>,
ty: Ty<'tcx>,
mpi: MovePathIndex,
) -> bool {
// No need to look deeper if the root is definitely uninit or if it has no `Drop` impl.
- if !maybe_inits.contains(mpi) || !ty.needs_drop(tcx, param_env) {
+ if !maybe_inits.contains(mpi) || !ty.needs_drop(tcx, typing_env) {
return false;
}
let field_needs_drop_and_init = |(f, f_ty, mpi)| {
let child = move_path_children_matching(move_data, mpi, |x| x.is_field_to(f));
let Some(mpi) = child else {
- return Ty::needs_drop(f_ty, tcx, param_env);
+ return Ty::needs_drop(f_ty, tcx, typing_env);
};
- is_needs_drop_and_init(tcx, param_env, maybe_inits, move_data, f_ty, mpi)
+ is_needs_drop_and_init(tcx, typing_env, maybe_inits, move_data, f_ty, mpi)
};
// This pass is only needed for const-checking, so it doesn't handle as many cases as
@@ -110,7 +110,7 @@ fn is_needs_drop_and_init<'tcx>(
let downcast =
move_path_children_matching(move_data, mpi, |x| x.is_downcast_to(vid));
let Some(dc_mpi) = downcast else {
- return variant_needs_drop(tcx, param_env, args, variant);
+ return variant_needs_drop(tcx, typing_env, args, variant);
};
dc_mpi
@@ -139,12 +139,12 @@ fn is_needs_drop_and_init<'tcx>(
fn variant_needs_drop<'tcx>(
tcx: TyCtxt<'tcx>,
- param_env: ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
args: GenericArgsRef<'tcx>,
variant: &VariantDef,
) -> bool {
variant.fields.iter().any(|field| {
let f_ty = field.ty(tcx, args);
- f_ty.needs_drop(tcx, param_env)
+ f_ty.needs_drop(tcx, typing_env)
})
}
diff --git a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs
index 28925ba..ad62b47 100644
--- a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs
+++ b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs
@@ -16,18 +16,18 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveUnneededDrops {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
trace!("Running RemoveUnneededDrops on {:?}", body.source);
- let did = body.source.def_id();
- let param_env = tcx.param_env_reveal_all_normalized(did);
+ let typing_env = body.typing_env(tcx);
let mut should_simplify = false;
-
for block in body.basic_blocks.as_mut() {
let terminator = block.terminator_mut();
if let TerminatorKind::Drop { place, target, .. } = terminator.kind {
let ty = place.ty(&body.local_decls, tcx);
- if ty.ty.needs_drop(tcx, param_env) {
+ if ty.ty.needs_drop(tcx, typing_env) {
continue;
}
- if !tcx.consider_optimizing(|| format!("RemoveUnneededDrops {did:?} ")) {
+ if !tcx.consider_optimizing(|| {
+ format!("RemoveUnneededDrops {:?}", body.source.def_id())
+ }) {
continue;
}
debug!("SUCCESS: replacing `drop` with goto({:?})", target);
diff --git a/compiler/rustc_mir_transform/src/remove_zsts.rs b/compiler/rustc_mir_transform/src/remove_zsts.rs
index f13bb1c..2f723bc 100644
--- a/compiler/rustc_mir_transform/src/remove_zsts.rs
+++ b/compiler/rustc_mir_transform/src/remove_zsts.rs
@@ -21,9 +21,9 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
return;
}
- let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
+ let typing_env = body.typing_env(tcx);
let local_decls = &body.local_decls;
- let mut replacer = Replacer { tcx, param_env, local_decls };
+ let mut replacer = Replacer { tcx, typing_env, local_decls };
for var_debug_info in &mut body.var_debug_info {
replacer.visit_var_debug_info(var_debug_info);
}
@@ -35,7 +35,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
struct Replacer<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
local_decls: &'a LocalDecls<'tcx>,
}
@@ -61,7 +61,7 @@ fn known_to_be_zst(&self, ty: Ty<'tcx>) -> bool {
if !maybe_zst(ty) {
return false;
}
- let Ok(layout) = self.tcx.layout_of(self.param_env.and(ty)) else {
+ let Ok(layout) = self.tcx.layout_of(self.typing_env.as_query_input(ty)) else {
return false;
};
layout.is_zst()
diff --git a/compiler/rustc_mir_transform/src/reveal_all.rs b/compiler/rustc_mir_transform/src/reveal_all.rs
index f3b2f78..587032e 100644
--- a/compiler/rustc_mir_transform/src/reveal_all.rs
+++ b/compiler/rustc_mir_transform/src/reveal_all.rs
@@ -8,14 +8,16 @@
impl<'tcx> crate::MirPass<'tcx> for RevealAll {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
- let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
- RevealAllVisitor { tcx, param_env }.visit_body_preserves_cfg(body);
+ // FIXME(#132279): This is used during the phase transition from analysis
+ // to runtime, so we have to manually specify the correct typing mode.
+ let typing_env = ty::TypingEnv::post_analysis(tcx, body.source.def_id());
+ RevealAllVisitor { tcx, typing_env }.visit_body_preserves_cfg(body);
}
}
struct RevealAllVisitor<'tcx> {
tcx: TyCtxt<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
}
impl<'tcx> MutVisitor<'tcx> for RevealAllVisitor<'tcx> {
@@ -53,7 +55,7 @@ fn visit_const_operand(&mut self, constant: &mut ConstOperand<'tcx>, location: L
// We have to use `try_normalize_erasing_regions` here, since it's
// possible that we visit impossible-to-satisfy where clauses here,
// see #91745
- if let Ok(c) = self.tcx.try_normalize_erasing_regions(self.param_env, constant.const_) {
+ if let Ok(c) = self.tcx.try_normalize_erasing_regions(self.typing_env, constant.const_) {
constant.const_ = c;
}
self.super_const_operand(constant, location);
@@ -64,7 +66,7 @@ fn visit_ty(&mut self, ty: &mut Ty<'tcx>, _: TyContext) {
// We have to use `try_normalize_erasing_regions` here, since it's
// possible that we visit impossible-to-satisfy where clauses here,
// see #91745
- if let Ok(t) = self.tcx.try_normalize_erasing_regions(self.param_env, *ty) {
+ if let Ok(t) = self.tcx.try_normalize_erasing_regions(self.typing_env, *ty) {
*ty = t;
}
}
diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs
index ffa11f5..f16cde7 100644
--- a/compiler/rustc_mir_transform/src/shim.rs
+++ b/compiler/rustc_mir_transform/src/shim.rs
@@ -274,9 +274,9 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option<Ty<'tcx>>)
if ty.is_some() {
let patch = {
- let param_env = tcx.param_env_reveal_all_normalized(def_id);
+ let typing_env = ty::TypingEnv::post_analysis(tcx, def_id);
let mut elaborator =
- DropShimElaborator { body: &body, patch: MirPatch::new(&body), tcx, param_env };
+ DropShimElaborator { body: &body, patch: MirPatch::new(&body), tcx, typing_env };
let dropee = tcx.mk_place_deref(dropee_ptr);
let resume_block = elaborator.patch.resume_block();
elaborate_drops::elaborate_drop(
@@ -334,7 +334,7 @@ pub(super) struct DropShimElaborator<'a, 'tcx> {
pub body: &'a Body<'tcx>,
pub patch: MirPatch<'tcx>,
pub tcx: TyCtxt<'tcx>,
- pub param_env: ty::ParamEnv<'tcx>,
+ pub typing_env: ty::TypingEnv<'tcx>,
}
impl fmt::Debug for DropShimElaborator<'_, '_> {
@@ -355,8 +355,8 @@ fn body(&self) -> &'a Body<'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}
- fn param_env(&self) -> ty::ParamEnv<'tcx> {
- self.param_env
+ fn typing_env(&self) -> ty::TypingEnv<'tcx> {
+ self.typing_env
}
fn drop_style(&self, _path: Self::Path, mode: DropFlagMode) -> DropStyle {
@@ -914,7 +914,7 @@ fn build_call_shim<'tcx>(
pub(super) fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> {
debug_assert!(tcx.is_constructor(ctor_id));
- let param_env = tcx.param_env_reveal_all_normalized(ctor_id);
+ let typing_env = ty::TypingEnv::post_analysis(tcx, ctor_id);
// Normalize the sig.
let sig = tcx
@@ -922,7 +922,7 @@ pub(super) fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> {
.instantiate_identity()
.no_bound_vars()
.expect("LBR in ADT constructor signature");
- let sig = tcx.normalize_erasing_regions(param_env, sig);
+ let sig = tcx.normalize_erasing_regions(typing_env, sig);
let ty::Adt(adt_def, args) = sig.output().kind() else {
bug!("unexpected type for ADT ctor {:?}", sig.output());
diff --git a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs
index f167227..139b25b 100644
--- a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs
+++ b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs
@@ -48,7 +48,7 @@ struct AsyncDestructorCtorShimBuilder<'tcx> {
self_ty: Option<Ty<'tcx>>,
span: Span,
source_info: SourceInfo,
- param_env: ty::ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
stack: Vec<Operand<'tcx>>,
last_bb: BasicBlock,
@@ -86,14 +86,14 @@ fn new(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Option<Ty<'tcx>>) -> Self {
// Usual case: noop() + unwind resume + return
let mut bbs = IndexVec::with_capacity(3);
- let param_env = tcx.param_env_reveal_all_normalized(def_id);
+ let typing_env = ty::TypingEnv::post_analysis(tcx, def_id);
AsyncDestructorCtorShimBuilder {
tcx,
def_id,
self_ty,
span,
source_info,
- param_env,
+ typing_env,
stack: Vec::with_capacity(Self::MAX_STACK_LEN),
last_bb: bbs.push(BasicBlockData::new(None)),
@@ -422,7 +422,7 @@ fn put_operand(&mut self, operand: Operand<'tcx>) {
statements: Vec::new(),
terminator: Some(Terminator {
source_info,
- kind: if self.locals[local].ty.needs_drop(self.tcx, self.param_env) {
+ kind: if self.locals[local].ty.needs_drop(self.tcx, self.typing_env) {
TerminatorKind::Drop {
place: local.into(),
target: *top_cleanup_bb,
diff --git a/compiler/rustc_mir_transform/src/simplify_branches.rs b/compiler/rustc_mir_transform/src/simplify_branches.rs
index e83b472..bea3d0d 100644
--- a/compiler/rustc_mir_transform/src/simplify_branches.rs
+++ b/compiler/rustc_mir_transform/src/simplify_branches.rs
@@ -18,14 +18,14 @@ fn name(&self) -> &'static str {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
trace!("Running SimplifyConstCondition on {:?}", body.source);
- let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
+ let typing_env = body.typing_env(tcx);
'blocks: for block in body.basic_blocks_mut() {
for stmt in block.statements.iter_mut() {
// Simplify `assume` of a known value: either a NOP or unreachable.
if let StatementKind::Intrinsic(box ref intrinsic) = stmt.kind
&& let NonDivergingIntrinsic::Assume(discr) = intrinsic
&& let Operand::Constant(ref c) = discr
- && let Some(constant) = c.const_.try_eval_bool(tcx, param_env)
+ && let Some(constant) = c.const_.try_eval_bool(tcx, typing_env)
{
if constant {
stmt.make_nop();
@@ -42,7 +42,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
TerminatorKind::SwitchInt {
discr: Operand::Constant(ref c), ref targets, ..
} => {
- let constant = c.const_.try_eval_bits(tcx, param_env);
+ let constant = c.const_.try_eval_bits(tcx, typing_env);
if let Some(constant) = constant {
let target = targets.target_for_value(constant);
TerminatorKind::Goto { target }
@@ -52,7 +52,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
}
TerminatorKind::Assert {
target, cond: Operand::Constant(ref c), expected, ..
- } => match c.const_.try_eval_bool(tcx, param_env) {
+ } => match c.const_.try_eval_bool(tcx, typing_env) {
Some(v) if v == expected => TerminatorKind::Goto { target },
_ => continue,
},
diff --git a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs
index 26496b7..b6d8017 100644
--- a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs
+++ b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs
@@ -37,7 +37,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let opts = helper.find_optimizations();
let mut storage_deads_to_insert = vec![];
let mut storage_deads_to_remove: Vec<(usize, BasicBlock)> = vec![];
- let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
+ let typing_env = body.typing_env(tcx);
for opt in opts {
trace!("SUCCESS: Applying {:?}", opt);
// replace terminator with a switchInt that switches on the integer directly
@@ -46,7 +46,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let new_value = match opt.branch_value_scalar {
Scalar::Int(int) => {
let layout = tcx
- .layout_of(param_env.and(opt.branch_value_ty))
+ .layout_of(typing_env.as_query_input(opt.branch_value_ty))
.expect("if we have an evaluated constant we must know the layout");
int.to_bits(layout.size)
}
diff --git a/compiler/rustc_mir_transform/src/sroa.rs b/compiler/rustc_mir_transform/src/sroa.rs
index 53bbb12..52b9ec1 100644
--- a/compiler/rustc_mir_transform/src/sroa.rs
+++ b/compiler/rustc_mir_transform/src/sroa.rs
@@ -28,12 +28,12 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
}
let mut excluded = excluded_locals(body);
- let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
+ let typing_env = body.typing_env(tcx);
loop {
debug!(?excluded);
- let escaping = escaping_locals(tcx, param_env, &excluded, body);
+ let escaping = escaping_locals(tcx, typing_env, &excluded, body);
debug!(?escaping);
- let replacements = compute_flattening(tcx, param_env, body, escaping);
+ let replacements = compute_flattening(tcx, typing_env, body, escaping);
debug!(?replacements);
let all_dead_locals = replace_flattened_locals(tcx, body, replacements);
if !all_dead_locals.is_empty() {
@@ -59,7 +59,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
/// client code.
fn escaping_locals<'tcx>(
tcx: TyCtxt<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
excluded: &BitSet<Local>,
body: &Body<'tcx>,
) -> BitSet<Local> {
@@ -84,7 +84,7 @@ fn escaping_locals<'tcx>(
// niche, so we do not want to automatically exclude it.
return false;
}
- let Ok(layout) = tcx.layout_of(param_env.and(ty)) else {
+ let Ok(layout) = tcx.layout_of(typing_env.as_query_input(ty)) else {
// We can't get the layout
return true;
};
@@ -196,7 +196,7 @@ fn place_fragments(
/// The replacement will be done later in `ReplacementVisitor`.
fn compute_flattening<'tcx>(
tcx: TyCtxt<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
body: &mut Body<'tcx>,
escaping: BitSet<Local>,
) -> ReplacementMap<'tcx> {
@@ -208,7 +208,7 @@ fn compute_flattening<'tcx>(
}
let decl = body.local_decls[local].clone();
let ty = decl.ty;
- iter_fields(ty, tcx, param_env, |variant, field, field_ty| {
+ iter_fields(ty, tcx, typing_env, |variant, field, field_ty| {
if variant.is_some() {
// Downcasts are currently not supported.
return;
diff --git a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs
index 3011af4..57e255b 100644
--- a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs
+++ b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs
@@ -92,9 +92,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let Some(discriminant_ty) = get_switched_on_type(bb_data, tcx, body) else { continue };
- let layout = tcx.layout_of(
- tcx.param_env_reveal_all_normalized(body.source.def_id()).and(discriminant_ty),
- );
+ let layout = tcx.layout_of(body.typing_env(tcx).as_query_input(discriminant_ty));
let mut allowed_variants = if let Ok(layout) = layout {
// Find allowed variants based on uninhabited.
diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs
index ae4e6ea..ae0e6f5 100644
--- a/compiler/rustc_mir_transform/src/validate.rs
+++ b/compiler/rustc_mir_transform/src/validate.rs
@@ -12,8 +12,7 @@
use rustc_middle::mir::*;
use rustc_middle::ty::adjustment::PointerCoercion;
use rustc_middle::ty::{
- self, CoroutineArgsExt, InstanceKind, ParamEnv, ScalarInt, Ty, TyCtxt, TypeVisitableExt,
- Variance,
+ self, CoroutineArgsExt, InstanceKind, ScalarInt, Ty, TyCtxt, TypeVisitableExt, Variance,
};
use rustc_middle::{bug, span_bug};
use rustc_trait_selection::traits::ObligationCtxt;
@@ -47,9 +46,10 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
if matches!(body.source.instance, InstanceKind::Intrinsic(..) | InstanceKind::Virtual(..)) {
return;
}
+ debug_assert_eq!(self.mir_phase, body.phase);
let def_id = body.source.def_id();
- let mir_phase = self.mir_phase;
- let param_env = mir_phase.param_env(tcx, def_id);
+ let mir_phase = body.phase;
+ let typing_env = body.typing_env(tcx);
let can_unwind = if mir_phase <= MirPhase::Runtime(RuntimePhase::Initial) {
// In this case `AbortUnwindingCalls` haven't yet been executed.
true
@@ -86,7 +86,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
cfg_checker.check_cleanup_control_flow();
// Also run the TypeChecker.
- for (location, msg) in validate_types(tcx, self.mir_phase, param_env, body, body) {
+ for (location, msg) in validate_types(tcx, self.mir_phase, typing_env, body, body) {
cfg_checker.fail(location, msg);
}
@@ -532,12 +532,12 @@ fn visit_source_scope(&mut self, scope: SourceScope) {
pub(super) fn validate_types<'tcx>(
tcx: TyCtxt<'tcx>,
mir_phase: MirPhase,
- param_env: ty::ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
body: &Body<'tcx>,
caller_body: &Body<'tcx>,
) -> Vec<(Location, String)> {
let mut type_checker =
- TypeChecker { body, caller_body, tcx, param_env, mir_phase, failures: Vec::new() };
+ TypeChecker { body, caller_body, tcx, typing_env, mir_phase, failures: Vec::new() };
type_checker.visit_body(body);
type_checker.failures
}
@@ -546,7 +546,7 @@ struct TypeChecker<'a, 'tcx> {
body: &'a Body<'tcx>,
caller_body: &'a Body<'tcx>,
tcx: TyCtxt<'tcx>,
- param_env: ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
mir_phase: MirPhase,
failures: Vec<(Location, String)>,
}
@@ -582,14 +582,7 @@ fn mir_assign_valid_types(&self, src: Ty<'tcx>, dest: Ty<'tcx>) -> bool {
Variance::Covariant
};
- crate::util::relate_types(
- self.tcx,
- self.body.typing_mode(self.tcx),
- self.param_env,
- variance,
- src,
- dest,
- )
+ crate::util::relate_types(self.tcx, self.typing_env, variance, src, dest)
}
/// Check that the given predicate definitely holds in the param-env of this MIR body.
@@ -608,12 +601,12 @@ fn predicate_must_hold_modulo_regions(
return true;
}
- let infcx = self.tcx.infer_ctxt().build(self.body.typing_mode(self.tcx));
+ let (infcx, param_env) = self.tcx.infer_ctxt().build_with_typing_env(self.typing_env);
let ocx = ObligationCtxt::new(&infcx);
ocx.register_obligation(Obligation::new(
self.tcx,
ObligationCause::dummy(),
- self.param_env,
+ param_env,
pred,
));
ocx.select_all_or_error().is_empty()
@@ -630,7 +623,7 @@ fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
if let Operand::Copy(place) = operand {
let ty = place.ty(&self.body.local_decls, self.tcx).ty;
- if !ty.is_copy_modulo_regions(self.tcx, self.param_env) {
+ if !ty.is_copy_modulo_regions(self.tcx, self.typing_env.param_env) {
self.fail(location, format!("`Operand::Copy` with non-`Copy` type {ty}"));
}
}
@@ -802,8 +795,7 @@ fn visit_projection_elem(
ProjectionElem::Subtype(ty) => {
if !util::sub_types(
self.tcx,
- self.body.typing_mode(self.tcx),
- self.param_env,
+ self.typing_env,
ty,
place_ref.ty(&self.body.local_decls, self.tcx).ty,
) {
@@ -916,7 +908,7 @@ macro_rules! check_kinds {
assert!(adt_def.is_union());
assert_eq!(idx, FIRST_VARIANT);
let dest_ty = self.tcx.normalize_erasing_regions(
- self.param_env,
+ self.typing_env,
adt_def.non_enum_variant().fields[field].ty(self.tcx, args),
);
if let [field] = fields.raw.as_slice() {
@@ -938,7 +930,7 @@ macro_rules! check_kinds {
for (src, dest) in std::iter::zip(fields, &variant.fields) {
let dest_ty = self
.tcx
- .normalize_erasing_regions(self.param_env, dest.ty(self.tcx, args));
+ .normalize_erasing_regions(self.typing_env, dest.ty(self.tcx, args));
if !self.mir_assign_valid_types(src.ty(self.body, self.tcx), dest_ty) {
self.fail(location, "adt field has the wrong type");
}
@@ -997,7 +989,7 @@ macro_rules! check_kinds {
}
// FIXME: check `Thin` instead of `Sized`
- if !in_pointee.is_sized(self.tcx, self.param_env) {
+ if !in_pointee.is_sized(self.tcx, self.typing_env.param_env) {
self.fail(location, "input pointer must be thin");
}
} else {
@@ -1012,7 +1004,7 @@ macro_rules! check_kinds {
if !self.mir_assign_valid_types(metadata_ty, self.tcx.types.usize) {
self.fail(location, "slice metadata must be usize");
}
- } else if pointee_ty.is_sized(self.tcx, self.param_env) {
+ } else if pointee_ty.is_sized(self.tcx, self.typing_env.param_env) {
if metadata_ty != self.tcx.types.unit {
self.fail(location, "metadata for pointer-to-thin must be unit");
}
@@ -1301,8 +1293,8 @@ macro_rules! check_kinds {
if !self
.tcx
- .normalize_erasing_regions(self.param_env, op_ty)
- .is_sized(self.tcx, self.param_env)
+ .normalize_erasing_regions(self.typing_env, op_ty)
+ .is_sized(self.tcx, self.typing_env.param_env)
{
self.fail(
location,
@@ -1311,8 +1303,8 @@ macro_rules! check_kinds {
}
if !self
.tcx
- .normalize_erasing_regions(self.param_env, *target_type)
- .is_sized(self.tcx, self.param_env)
+ .normalize_erasing_regions(self.typing_env, *target_type)
+ .is_sized(self.tcx, self.typing_env.param_env)
{
self.fail(
location,
@@ -1353,7 +1345,7 @@ macro_rules! check_kinds {
return;
};
- current_ty = self.tcx.normalize_erasing_regions(self.param_env, f_ty);
+ current_ty = self.tcx.normalize_erasing_regions(self.typing_env, f_ty);
}
ty::Adt(adt_def, args) => {
let Some(field) = adt_def.variant(variant).fields.get(field) else {
@@ -1362,7 +1354,7 @@ macro_rules! check_kinds {
};
let f_ty = field.ty(self.tcx, args);
- current_ty = self.tcx.normalize_erasing_regions(self.param_env, f_ty);
+ current_ty = self.tcx.normalize_erasing_regions(self.typing_env, f_ty);
}
_ => {
self.fail(
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 429e31b..1b94c62 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -207,6 +207,7 @@
use std::path::PathBuf;
+use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::sync::{LRef, MTLock, par_for_each_in};
use rustc_data_structures::unord::{UnordMap, UnordSet};
use rustc_hir as hir;
@@ -215,7 +216,7 @@
use rustc_hir::lang_items::LangItem;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::mir::interpret::{AllocId, ErrorHandled, GlobalAlloc, Scalar};
-use rustc_middle::mir::mono::{InstantiationMode, MonoItem};
+use rustc_middle::mir::mono::{CollectionMode, InstantiationMode, MonoItem};
use rustc_middle::mir::visit::Visitor as MirVisitor;
use rustc_middle::mir::{self, Location, MentionedItem, traversal};
use rustc_middle::query::TyCtxtAt;
@@ -243,16 +244,6 @@ pub(crate) enum MonoItemCollectionStrategy {
Lazy,
}
-pub(crate) struct UsageMap<'tcx> {
- // Maps every mono item to the mono items used by it.
- used_map: UnordMap<MonoItem<'tcx>, Vec<MonoItem<'tcx>>>,
-
- // Maps every mono item to the mono items that use it.
- user_map: UnordMap<MonoItem<'tcx>, Vec<MonoItem<'tcx>>>,
-}
-
-type MonoItems<'tcx> = Vec<Spanned<MonoItem<'tcx>>>;
-
/// The state that is shared across the concurrent threads that are doing collection.
struct SharedState<'tcx> {
/// Items that have been or are currently being recursively collected.
@@ -264,22 +255,12 @@ struct SharedState<'tcx> {
usage_map: MTLock<UsageMap<'tcx>>,
}
-/// See module-level docs on some contect for "mentioned" items.
-#[derive(Copy, Clone, Debug, PartialEq)]
-enum CollectionMode {
- /// Collect items that are used, i.e., actually needed for codegen.
- ///
- /// Which items are used can depend on optimization levels, as MIR optimizations can remove
- /// uses.
- UsedItems,
- /// Collect items that are mentioned. The goal of this mode is that it is independent of
- /// optimizations: the set of "mentioned" items is computed before optimizations are run.
- ///
- /// The exact contents of this set are *not* a stable guarantee. (For instance, it is currently
- /// computed after drop-elaboration. If we ever do some optimizations even in debug builds, we
- /// might decide to run them before computing mentioned items.) The key property of this set is
- /// that it is optimization-independent.
- MentionedItems,
+pub(crate) struct UsageMap<'tcx> {
+ // Maps every mono item to the mono items used by it.
+ used_map: UnordMap<MonoItem<'tcx>, Vec<MonoItem<'tcx>>>,
+
+ // Maps every mono item to the mono items that use it.
+ user_map: UnordMap<MonoItem<'tcx>, Vec<MonoItem<'tcx>>>,
}
impl<'tcx> UsageMap<'tcx> {
@@ -287,19 +268,15 @@ fn new() -> UsageMap<'tcx> {
UsageMap { used_map: Default::default(), user_map: Default::default() }
}
- fn record_used<'a>(
- &mut self,
- user_item: MonoItem<'tcx>,
- used_items: &'a [Spanned<MonoItem<'tcx>>],
- ) where
+ fn record_used<'a>(&mut self, user_item: MonoItem<'tcx>, used_items: &'a MonoItems<'tcx>)
+ where
'tcx: 'a,
{
- let used_items: Vec<_> = used_items.iter().map(|item| item.node).collect();
- for &used_item in used_items.iter() {
+ for used_item in used_items.items() {
self.user_map.entry(used_item).or_default().push(user_item);
}
- assert!(self.used_map.insert(user_item, used_items).is_none());
+ assert!(self.used_map.insert(user_item, used_items.items().collect()).is_none());
}
pub(crate) fn get_user_items(&self, item: MonoItem<'tcx>) -> &[MonoItem<'tcx>] {
@@ -325,6 +302,52 @@ pub(crate) fn for_each_inlined_used_item<F>(
}
}
+struct MonoItems<'tcx> {
+ // We want a set of MonoItem + Span where trying to re-insert a MonoItem with a different Span
+ // is ignored. Map does that, but it looks odd.
+ items: FxIndexMap<MonoItem<'tcx>, Span>,
+}
+
+impl<'tcx> MonoItems<'tcx> {
+ fn new() -> Self {
+ Self { items: FxIndexMap::default() }
+ }
+
+ fn is_empty(&self) -> bool {
+ self.items.is_empty()
+ }
+
+ fn push(&mut self, item: Spanned<MonoItem<'tcx>>) {
+ // Insert only if the entry does not exist. A normal insert would stomp the first span that
+ // got inserted.
+ self.items.entry(item.node).or_insert(item.span);
+ }
+
+ fn items(&self) -> impl Iterator<Item = MonoItem<'tcx>> + '_ {
+ self.items.keys().cloned()
+ }
+}
+
+impl<'tcx> IntoIterator for MonoItems<'tcx> {
+ type Item = Spanned<MonoItem<'tcx>>;
+ type IntoIter = impl Iterator<Item = Spanned<MonoItem<'tcx>>>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ self.items.into_iter().map(|(item, span)| respan(span, item))
+ }
+}
+
+impl<'tcx> Extend<Spanned<MonoItem<'tcx>>> for MonoItems<'tcx> {
+ fn extend<I>(&mut self, iter: I)
+ where
+ I: IntoIterator<Item = Spanned<MonoItem<'tcx>>>,
+ {
+ for item in iter {
+ self.push(item)
+ }
+ }
+}
+
/// Collect all monomorphized items reachable from `starting_point`, and emit a note diagnostic if a
/// post-monomorphization error is encountered during a collection step.
///
@@ -404,7 +427,7 @@ fn collect_items_rec<'tcx>(
let DefKind::Static { nested, .. } = tcx.def_kind(def_id) else { bug!() };
// Nested statics have no type.
if !nested {
- let ty = instance.ty(tcx, ty::ParamEnv::reveal_all());
+ let ty = instance.ty(tcx, ty::TypingEnv::fully_monomorphized());
visit_drop_use(tcx, ty, true, starting_item.span, &mut used_items);
}
@@ -443,13 +466,9 @@ fn collect_items_rec<'tcx>(
));
rustc_data_structures::stack::ensure_sufficient_stack(|| {
- collect_items_of_instance(
- tcx,
- instance,
- &mut used_items,
- &mut mentioned_items,
- mode,
- )
+ let (used, mentioned) = tcx.items_of_instance((instance, mode));
+ used_items.extend(used.into_iter().copied());
+ mentioned_items.extend(mentioned.into_iter().copied());
});
}
MonoItem::GlobalAsm(item_id) => {
@@ -617,7 +636,7 @@ fn monomorphize<T>(&self, value: T) -> T
trace!("monomorphize: self.instance={:?}", self.instance);
self.instance.instantiate_mir_and_normalize_erasing_regions(
self.tcx,
- ty::ParamEnv::reveal_all(),
+ ty::TypingEnv::fully_monomorphized(),
ty::EarlyBinder::bind(value),
)
}
@@ -628,12 +647,11 @@ fn eval_constant(
constant: &mir::ConstOperand<'tcx>,
) -> Option<mir::ConstValue<'tcx>> {
let const_ = self.monomorphize(constant.const_);
- let param_env = ty::ParamEnv::reveal_all();
// Evaluate the constant. This makes const eval failure a collection-time error (rather than
// a codegen-time error). rustc stops after collection if there was an error, so this
// ensures codegen never has to worry about failing consts.
// (codegen relies on this and ICEs will happen if this is violated.)
- match const_.eval(self.tcx, param_env, constant.span) {
+ match const_.eval(self.tcx, ty::TypingEnv::fully_monomorphized(), constant.span) {
Ok(v) => Some(v),
Err(ErrorHandled::TooGeneric(..)) => span_bug!(
constant.span,
@@ -844,9 +862,20 @@ fn visit_fn_use<'tcx>(
) {
if let ty::FnDef(def_id, args) = *ty.kind() {
let instance = if is_direct_call {
- ty::Instance::expect_resolve(tcx, ty::ParamEnv::reveal_all(), def_id, args, source)
+ ty::Instance::expect_resolve(
+ tcx,
+ ty::TypingEnv::fully_monomorphized(),
+ def_id,
+ args,
+ source,
+ )
} else {
- match ty::Instance::resolve_for_fn_ptr(tcx, ty::ParamEnv::reveal_all(), def_id, args) {
+ match ty::Instance::resolve_for_fn_ptr(
+ tcx,
+ ty::TypingEnv::fully_monomorphized(),
+ def_id,
+ args,
+ ) {
Some(instance) => instance,
_ => bug!("failed to resolve instance for {ty}"),
}
@@ -1005,12 +1034,12 @@ fn find_vtable_types_for_unsizing<'tcx>(
target_ty: Ty<'tcx>,
) -> (Ty<'tcx>, Ty<'tcx>) {
let ptr_vtable = |inner_source: Ty<'tcx>, inner_target: Ty<'tcx>| {
- let param_env = ty::ParamEnv::reveal_all();
+ let typing_env = ty::TypingEnv::fully_monomorphized();
let type_has_metadata = |ty: Ty<'tcx>| -> bool {
- if ty.is_sized(tcx.tcx, param_env) {
+ if ty.is_sized(tcx.tcx, typing_env.param_env) {
return false;
}
- let tail = tcx.struct_tail_for_codegen(ty, param_env);
+ let tail = tcx.struct_tail_for_codegen(ty, typing_env);
match tail.kind() {
ty::Foreign(..) => false,
ty::Str | ty::Slice(..) | ty::Dynamic(..) => true,
@@ -1020,7 +1049,7 @@ fn find_vtable_types_for_unsizing<'tcx>(
if type_has_metadata(inner_source) {
(inner_source, inner_target)
} else {
- tcx.struct_lockstep_tails_for_codegen(inner_source, inner_target, param_env)
+ tcx.struct_lockstep_tails_for_codegen(inner_source, inner_target, typing_env)
}
};
@@ -1171,14 +1200,12 @@ fn collect_alloc<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut MonoIt
/// Scans the MIR in order to find function calls, closures, and drop-glue.
///
/// Anything that's found is added to `output`. Furthermore the "mentioned items" of the MIR are returned.
-#[instrument(skip(tcx, used_items, mentioned_items), level = "debug")]
+#[instrument(skip(tcx), level = "debug")]
fn collect_items_of_instance<'tcx>(
tcx: TyCtxt<'tcx>,
instance: Instance<'tcx>,
- used_items: &mut MonoItems<'tcx>,
- mentioned_items: &mut MonoItems<'tcx>,
mode: CollectionMode,
-) {
+) -> (MonoItems<'tcx>, MonoItems<'tcx>) {
// This item is getting monomorphized, do mono-time checks.
tcx.ensure().check_mono_item(instance);
@@ -1193,11 +1220,13 @@ fn collect_items_of_instance<'tcx>(
// mentioned item. So instead we collect all pre-monomorphized `MentionedItem` that were already
// added to `used_items` in a hash set, which can efficiently query in the
// `body.mentioned_items` loop below without even having to monomorphize the item.
+ let mut used_items = MonoItems::new();
+ let mut mentioned_items = MonoItems::new();
let mut used_mentioned_items = Default::default();
let mut collector = MirUsedCollector {
tcx,
body,
- used_items,
+ used_items: &mut used_items,
used_mentioned_items: &mut used_mentioned_items,
instance,
};
@@ -1212,7 +1241,7 @@ fn collect_items_of_instance<'tcx>(
// them errors.
for const_op in body.required_consts() {
if let Some(val) = collector.eval_constant(const_op) {
- collect_const_value(tcx, val, mentioned_items);
+ collect_const_value(tcx, val, &mut mentioned_items);
}
}
@@ -1221,9 +1250,23 @@ fn collect_items_of_instance<'tcx>(
for item in body.mentioned_items() {
if !collector.used_mentioned_items.contains(&item.node) {
let item_mono = collector.monomorphize(item.node);
- visit_mentioned_item(tcx, &item_mono, item.span, mentioned_items);
+ visit_mentioned_item(tcx, &item_mono, item.span, &mut mentioned_items);
}
}
+
+ (used_items, mentioned_items)
+}
+
+fn items_of_instance<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ (instance, mode): (Instance<'tcx>, CollectionMode),
+) -> (&'tcx [Spanned<MonoItem<'tcx>>], &'tcx [Spanned<MonoItem<'tcx>>]) {
+ let (used_items, mentioned_items) = collect_items_of_instance(tcx, instance, mode);
+
+ let used_items = tcx.arena.alloc_from_iter(used_items);
+ let mentioned_items = tcx.arena.alloc_from_iter(mentioned_items);
+
+ (used_items, mentioned_items)
}
/// `item` must be already monomorphized.
@@ -1237,8 +1280,13 @@ fn visit_mentioned_item<'tcx>(
match *item {
MentionedItem::Fn(ty) => {
if let ty::FnDef(def_id, args) = *ty.kind() {
- let instance =
- Instance::expect_resolve(tcx, ty::ParamEnv::reveal_all(), def_id, args, span);
+ let instance = Instance::expect_resolve(
+ tcx,
+ ty::TypingEnv::fully_monomorphized(),
+ def_id,
+ args,
+ span,
+ );
// `visit_instance_use` was written for "used" item collection but works just as well
// for "mentioned" item collection.
// We can set `is_direct_call`; that just means we'll skip a bunch of shims that anyway
@@ -1304,7 +1352,7 @@ fn collect_const_value<'tcx>(
#[instrument(skip(tcx, mode), level = "debug")]
fn collect_roots(tcx: TyCtxt<'_>, mode: MonoItemCollectionStrategy) -> Vec<MonoItem<'_>> {
debug!("collecting roots");
- let mut roots = Vec::new();
+ let mut roots = MonoItems::new();
{
let entry_fn = tcx.entry_fn(());
@@ -1454,13 +1502,13 @@ fn push_extra_entry_roots(&mut self) {
// regions must appear in the argument
// listing.
let main_ret_ty = self.tcx.normalize_erasing_regions(
- ty::ParamEnv::reveal_all(),
+ ty::TypingEnv::fully_monomorphized(),
main_ret_ty.no_bound_vars().unwrap(),
);
let start_instance = Instance::expect_resolve(
self.tcx,
- ty::ParamEnv::reveal_all(),
+ ty::TypingEnv::fully_monomorphized(),
start_def_id,
self.tcx.mk_args(&[main_ret_ty.into()]),
DUMMY_SP,
@@ -1518,8 +1566,8 @@ fn create_mono_items_for_default_impls<'tcx>(
return;
}
- let param_env = ty::ParamEnv::reveal_all();
- let trait_ref = tcx.normalize_erasing_regions(param_env, trait_ref);
+ let typing_env = ty::TypingEnv::fully_monomorphized();
+ let trait_ref = tcx.normalize_erasing_regions(typing_env, trait_ref);
let overridden_methods = tcx.impl_item_implementor_ids(item.owner_id);
for method in tcx.provided_trait_methods(trait_ref.def_id) {
if overridden_methods.contains_key(&method.def_id) {
@@ -1534,7 +1582,7 @@ fn create_mono_items_for_default_impls<'tcx>(
// only has lifetime generic parameters. This is validated by calling
// `own_requires_monomorphization` on both the impl and method.
let args = trait_ref.args.extend_to(tcx, method.def_id, only_region_params);
- let instance = ty::Instance::expect_resolve(tcx, param_env, method.def_id, args, DUMMY_SP);
+ let instance = ty::Instance::expect_resolve(tcx, typing_env, method.def_id, args, DUMMY_SP);
let mono_item = create_fn_mono_item(tcx, instance, DUMMY_SP);
if mono_item.node.is_instantiable(tcx) && tcx.should_codegen_locally(instance) {
@@ -1596,4 +1644,5 @@ pub(crate) fn collect_crate_mono_items<'tcx>(
pub(crate) fn provide(providers: &mut Providers) {
providers.hooks.should_codegen_locally = should_codegen_locally;
+ providers.items_of_instance = items_of_instance;
}
diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs
index 0cfc437..0f08930 100644
--- a/compiler/rustc_monomorphize/src/lib.rs
+++ b/compiler/rustc_monomorphize/src/lib.rs
@@ -2,6 +2,7 @@
#![feature(array_windows)]
#![feature(file_buffered)]
#![feature(if_let_guard)]
+#![feature(impl_trait_in_assoc_type)]
#![feature(let_chains)]
#![warn(unreachable_pub)]
// tidy-alphabetical-end
@@ -34,7 +35,9 @@ fn custom_coerce_unsize_info<'tcx>(
[source_ty, target_ty],
);
- match tcx.codegen_select_candidate((ty::ParamEnv::reveal_all(), trait_ref)) {
+ match tcx
+ .codegen_select_candidate(ty::TypingEnv::fully_monomorphized().as_query_input(trait_ref))
+ {
Ok(traits::ImplSource::UserDefined(traits::ImplSourceUserDefinedData {
impl_def_id,
..
diff --git a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
index d535959..30e634d 100644
--- a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
+++ b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
@@ -3,7 +3,7 @@
use rustc_hir::CRATE_HIR_ID;
use rustc_middle::mir::{self, traversal};
use rustc_middle::ty::inherent::*;
-use rustc_middle::ty::{self, Instance, InstanceKind, ParamEnv, Ty, TyCtxt};
+use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TyCtxt};
use rustc_session::lint::builtin::ABI_UNSUPPORTED_VECTOR_TYPES;
use rustc_span::def_id::DefId;
use rustc_span::{DUMMY_SP, Span, Symbol};
@@ -36,9 +36,7 @@ fn do_check_abi<'tcx>(
target_feature_def: DefId,
mut emit_err: impl FnMut(Option<&'static str>),
) {
- let Some(feature_def) = tcx.sess.target.features_for_correct_vector_abi() else {
- return;
- };
+ let feature_def = tcx.sess.target.features_for_correct_vector_abi();
let codegen_attrs = tcx.codegen_fn_attrs(target_feature_def);
for arg_abi in abi.args.iter().chain(std::iter::once(&abi.ret)) {
let size = arg_abi.layout.size;
@@ -64,8 +62,9 @@ fn do_check_abi<'tcx>(
/// Checks that the ABI of a given instance of a function does not contain vector-passed arguments
/// or return values for which the corresponding target feature is not enabled.
fn check_instance_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
- let param_env = ParamEnv::reveal_all();
- let Ok(abi) = tcx.fn_abi_of_instance(param_env.and((instance, ty::List::empty()))) else {
+ let typing_env = ty::TypingEnv::fully_monomorphized();
+ let Ok(abi) = tcx.fn_abi_of_instance(typing_env.as_query_input((instance, ty::List::empty())))
+ else {
// An error will be reported during codegen if we cannot determine the ABI of this
// function.
return;
@@ -102,18 +101,18 @@ fn check_call_site_abi<'tcx>(
// "Rust" ABI never passes arguments in vector registers.
return;
}
- let param_env = ParamEnv::reveal_all();
+ let typing_env = ty::TypingEnv::fully_monomorphized();
let callee_abi = match *callee.kind() {
ty::FnPtr(..) => {
- tcx.fn_abi_of_fn_ptr(param_env.and((callee.fn_sig(tcx), ty::List::empty())))
+ tcx.fn_abi_of_fn_ptr(typing_env.as_query_input((callee.fn_sig(tcx), ty::List::empty())))
}
ty::FnDef(def_id, args) => {
// Intrinsics are handled separately by the compiler.
if tcx.intrinsic(def_id).is_some() {
return;
}
- let instance = ty::Instance::expect_resolve(tcx, param_env, def_id, args, DUMMY_SP);
- tcx.fn_abi_of_instance(param_env.and((instance, ty::List::empty())))
+ let instance = ty::Instance::expect_resolve(tcx, typing_env, def_id, args, DUMMY_SP);
+ tcx.fn_abi_of_instance(typing_env.as_query_input((instance, ty::List::empty())))
}
_ => {
panic!("Invalid function call");
@@ -153,7 +152,7 @@ fn check_callees_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, body: &m
let callee_ty = func.ty(body, tcx);
let callee_ty = instance.instantiate_mir_and_normalize_erasing_regions(
tcx,
- ty::ParamEnv::reveal_all(),
+ ty::TypingEnv::fully_monomorphized(),
ty::EarlyBinder::bind(callee_ty),
);
check_call_site_abi(tcx, callee_ty, *fn_span, body.source.instance);
diff --git a/compiler/rustc_monomorphize/src/mono_checks/move_check.rs b/compiler/rustc_monomorphize/src/mono_checks/move_check.rs
index 7f04bdf..438d49f 100644
--- a/compiler/rustc_monomorphize/src/mono_checks/move_check.rs
+++ b/compiler/rustc_monomorphize/src/mono_checks/move_check.rs
@@ -61,7 +61,7 @@ fn monomorphize<T>(&self, value: T) -> T
trace!("monomorphize: self.instance={:?}", self.instance);
self.instance.instantiate_mir_and_normalize_erasing_regions(
self.tcx,
- ty::ParamEnv::reveal_all(),
+ ty::TypingEnv::fully_monomorphized(),
ty::EarlyBinder::bind(value),
)
}
@@ -128,7 +128,9 @@ fn operand_size_if_too_large(
) -> Option<Size> {
let ty = operand.ty(self.body, self.tcx);
let ty = self.monomorphize(ty);
- let Ok(layout) = self.tcx.layout_of(ty::ParamEnv::reveal_all().and(ty)) else {
+ let Ok(layout) =
+ self.tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty))
+ else {
return None;
};
if layout.size.bytes_usize() > limit.0 {
diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs
index e2a6d39..7240cfc 100644
--- a/compiler/rustc_monomorphize/src/partitioning.rs
+++ b/compiler/rustc_monomorphize/src/partitioning.rs
@@ -666,7 +666,7 @@ fn characteristic_def_id_of_mono_item<'tcx>(
// This is a method within an impl, find out what the self-type is:
let impl_self_ty = tcx.instantiate_and_normalize_erasing_regions(
instance.args,
- ty::ParamEnv::reveal_all(),
+ ty::TypingEnv::fully_monomorphized(),
tcx.type_of(impl_def_id),
);
if let Some(def_id) = characteristic_def_id_of_type(impl_self_ty) {
@@ -1319,5 +1319,20 @@ pub(crate) fn provide(providers: &mut Providers) {
.unwrap_or_else(|| panic!("failed to find cgu with name {name:?}"))
};
+ providers.size_estimate = |tcx, instance| {
+ match instance.def {
+ // "Normal" functions size estimate: the number of
+ // statements, plus one for the terminator.
+ InstanceKind::Item(..)
+ | InstanceKind::DropGlue(..)
+ | InstanceKind::AsyncDropGlueCtorShim(..) => {
+ let mir = tcx.instance_mir(instance.def);
+ mir.basic_blocks.iter().map(|bb| bb.statements.len() + 1).sum()
+ }
+ // Other compiler-generated shims size estimate: 1
+ _ => 1,
+ }
+ };
+
collector::provide(providers);
}
diff --git a/compiler/rustc_monomorphize/src/util.rs b/compiler/rustc_monomorphize/src/util.rs
index 093a697..deb4ab4 100644
--- a/compiler/rustc_monomorphize/src/util.rs
+++ b/compiler/rustc_monomorphize/src/util.rs
@@ -22,29 +22,29 @@ pub(crate) fn dump_closure_profile<'tcx>(tcx: TyCtxt<'tcx>, closure_instance: In
let typeck_results = tcx.typeck(closure_def_id);
if typeck_results.closure_size_eval.contains_key(&closure_def_id) {
- let param_env = ty::ParamEnv::reveal_all();
+ let typing_env = ty::TypingEnv::fully_monomorphized();
let ClosureSizeProfileData { before_feature_tys, after_feature_tys } =
typeck_results.closure_size_eval[&closure_def_id];
let before_feature_tys = tcx.instantiate_and_normalize_erasing_regions(
closure_instance.args,
- param_env,
+ typing_env,
ty::EarlyBinder::bind(before_feature_tys),
);
let after_feature_tys = tcx.instantiate_and_normalize_erasing_regions(
closure_instance.args,
- param_env,
+ typing_env,
ty::EarlyBinder::bind(after_feature_tys),
);
let new_size = tcx
- .layout_of(param_env.and(after_feature_tys))
+ .layout_of(typing_env.as_query_input(after_feature_tys))
.map(|l| format!("{:?}", l.size.bytes()))
.unwrap_or_else(|e| format!("Failed {e:?}"));
let old_size = tcx
- .layout_of(param_env.and(before_feature_tys))
+ .layout_of(typing_env.as_query_input(before_feature_tys))
.map(|l| format!("{:?}", l.size.bytes()))
.unwrap_or_else(|e| format!("Failed {e:?}"));
diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
index df4f0ff..5f74059 100644
--- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
@@ -262,7 +262,11 @@ fn consider_builtin_pointer_like_candidate(
return ecx.forced_ambiguity(MaybeCause::Ambiguity);
}
- if cx.layout_is_pointer_like(goal.param_env, goal.predicate.self_ty()) {
+ if cx.layout_is_pointer_like(
+ ecx.typing_mode(goal.param_env),
+ goal.param_env,
+ goal.predicate.self_ty(),
+ ) {
ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
.enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
} else {
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index 7ec4ad6..37eb463 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -650,8 +650,9 @@ pub(crate) struct LeftArrowOperator {
#[diag(parse_remove_let)]
pub(crate) struct RemoveLet {
#[primary_span]
- #[suggestion(applicability = "machine-applicable", code = "", style = "verbose")]
pub span: Span,
+ #[suggestion(applicability = "machine-applicable", code = "", style = "verbose")]
+ pub suggestion: Span,
}
#[derive(Diagnostic)]
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 0ac6133..0012db4 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -2683,6 +2683,13 @@ fn parse_expr_else(&mut self) -> PResult<'a, P<Expr>> {
// ^^
// }
//
+ // We account for macro calls that were meant as conditions as well.
+ //
+ // if ... {
+ // } else if macro! { foo bar } {
+ // ^^
+ // }
+ //
// If $cond is "statement-like" such as ExprKind::While then we
// want to suggest wrapping in braces.
//
@@ -2693,7 +2700,9 @@ fn parse_expr_else(&mut self) -> PResult<'a, P<Expr>> {
// }
// ^
if self.check(&TokenKind::OpenDelim(Delimiter::Brace))
- && classify::expr_requires_semi_to_be_stmt(&cond) =>
+ && (classify::expr_requires_semi_to_be_stmt(&cond)
+ || matches!(cond.kind, ExprKind::MacCall(..)))
+ =>
{
self.dcx().emit_err(errors::ExpectedElseBlock {
first_tok_span,
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 6b4e2d0..fddbf58 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -77,18 +77,35 @@ pub fn parse_mod(
if !self.eat(term) {
let token_str = super::token_descr(&self.token);
if !self.maybe_consume_incorrect_semicolon(items.last().map(|x| &**x)) {
+ let is_let = self.token.is_keyword(kw::Let);
+ let is_let_mut = is_let && self.look_ahead(1, |t| t.is_keyword(kw::Mut));
+ let let_has_ident = is_let && !is_let_mut && self.is_kw_followed_by_ident(kw::Let);
+
let msg = format!("expected item, found {token_str}");
let mut err = self.dcx().struct_span_err(self.token.span, msg);
- let span = self.token.span;
- if self.is_kw_followed_by_ident(kw::Let) {
- err.span_label(
- span,
- "consider using `const` or `static` instead of `let` for global variables",
- );
+
+ let label = if is_let {
+ "`let` cannot be used for global variables"
} else {
- err.span_label(span, "expected item")
- .note("for a full list of items that can appear in modules, see <https://doc.rust-lang.org/reference/items.html>");
+ "expected item"
};
+ err.span_label(self.token.span, label);
+
+ if is_let {
+ if is_let_mut {
+ err.help("consider using `static` and a `Mutex` instead of `let mut`");
+ } else if let_has_ident {
+ err.span_suggestion_short(
+ self.token.span,
+ "consider using `static` or `const` instead of `let`",
+ "static",
+ Applicability::MaybeIncorrect,
+ );
+ } else {
+ err.help("consider using `static` or `const` instead of `let`");
+ }
+ }
+ err.note("for a full list of items that can appear in modules, see <https://doc.rust-lang.org/reference/items.html>");
return Err(err);
}
}
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index 3546e5b..c432642 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -685,7 +685,7 @@ fn parse_pat_with_range_pat(
self.bump();
// Trim extra space after the `let`
let span = lo.with_hi(self.token.span.lo());
- self.dcx().emit_err(RemoveLet { span });
+ self.dcx().emit_err(RemoveLet { span: lo, suggestion: span });
lo = self.token.span;
}
diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs
index b7cdae3..190cd9e 100644
--- a/compiler/rustc_parse/src/parser/stmt.rs
+++ b/compiler/rustc_parse/src/parser/stmt.rs
@@ -475,6 +475,7 @@ pub fn parse_block(&mut self) -> PResult<'a, P<Block>> {
}
fn error_block_no_opening_brace_msg(&mut self, msg: Cow<'static, str>) -> Diag<'a> {
+ let prev = self.prev_token.span;
let sp = self.token.span;
let mut e = self.dcx().struct_span_err(sp, msg);
let do_not_suggest_help = self.token.is_keyword(kw::In) || self.token == token::Colon;
@@ -514,14 +515,11 @@ fn error_block_no_opening_brace_msg(&mut self, msg: Cow<'static, str>) -> Diag<'
} else {
stmt.span
};
- e.multipart_suggestion(
- "try placing this code inside a block",
- vec![
- (stmt_span.shrink_to_lo(), "{ ".to_string()),
- (stmt_span.shrink_to_hi(), " }".to_string()),
- ],
- // Speculative; has been misleading in the past (#46836).
- Applicability::MaybeIncorrect,
+ self.suggest_fixes_misparsed_for_loop_head(
+ &mut e,
+ prev.between(sp),
+ stmt_span,
+ &stmt.kind,
);
}
Err(e) => {
@@ -534,6 +532,103 @@ fn error_block_no_opening_brace_msg(&mut self, msg: Cow<'static, str>) -> Diag<'
e
}
+ fn suggest_fixes_misparsed_for_loop_head(
+ &self,
+ e: &mut Diag<'_>,
+ between: Span,
+ stmt_span: Span,
+ stmt_kind: &StmtKind,
+ ) {
+ match (&self.token.kind, &stmt_kind) {
+ (token::OpenDelim(Delimiter::Brace), StmtKind::Expr(expr))
+ if let ExprKind::Call(..) = expr.kind =>
+ {
+ // for _ in x y() {}
+ e.span_suggestion_verbose(
+ between,
+ "you might have meant to write a method call",
+ ".".to_string(),
+ Applicability::MaybeIncorrect,
+ );
+ }
+ (token::OpenDelim(Delimiter::Brace), StmtKind::Expr(expr))
+ if let ExprKind::Field(..) = expr.kind =>
+ {
+ // for _ in x y.z {}
+ e.span_suggestion_verbose(
+ between,
+ "you might have meant to write a field access",
+ ".".to_string(),
+ Applicability::MaybeIncorrect,
+ );
+ }
+ (token::CloseDelim(Delimiter::Brace), StmtKind::Expr(expr))
+ if let ExprKind::Struct(expr) = &expr.kind
+ && let None = expr.qself
+ && expr.path.segments.len() == 1 =>
+ {
+ // This is specific to "mistyped `if` condition followed by empty body"
+ //
+ // for _ in x y {}
+ e.span_suggestion_verbose(
+ between,
+ "you might have meant to write a field access",
+ ".".to_string(),
+ Applicability::MaybeIncorrect,
+ );
+ }
+ (token::OpenDelim(Delimiter::Brace), StmtKind::Expr(expr))
+ if let ExprKind::Lit(lit) = expr.kind
+ && let None = lit.suffix
+ && let token::LitKind::Integer | token::LitKind::Float = lit.kind =>
+ {
+ // for _ in x 0 {}
+ // for _ in x 0.0 {}
+ e.span_suggestion_verbose(
+ between,
+ format!("you might have meant to write a field access"),
+ ".".to_string(),
+ Applicability::MaybeIncorrect,
+ );
+ }
+ (token::OpenDelim(Delimiter::Brace), StmtKind::Expr(expr))
+ if let ExprKind::Loop(..)
+ | ExprKind::If(..)
+ | ExprKind::While(..)
+ | ExprKind::Match(..)
+ | ExprKind::ForLoop { .. }
+ | ExprKind::TryBlock(..)
+ | ExprKind::Ret(..)
+ | ExprKind::Closure(..)
+ | ExprKind::Struct(..)
+ | ExprKind::Try(..) = expr.kind =>
+ {
+ // These are more likely to have been meant as a block body.
+ e.multipart_suggestion(
+ "you might have meant to write this as part of a block",
+ vec![
+ (stmt_span.shrink_to_lo(), "{ ".to_string()),
+ (stmt_span.shrink_to_hi(), " }".to_string()),
+ ],
+ // Speculative; has been misleading in the past (#46836).
+ Applicability::MaybeIncorrect,
+ );
+ }
+ (token::OpenDelim(Delimiter::Brace), _) => {}
+ (_, _) => {
+ e.multipart_suggestion(
+ "you might have meant to write this as part of a block",
+ vec![
+ (stmt_span.shrink_to_lo(), "{ ".to_string()),
+ (stmt_span.shrink_to_hi(), " }".to_string()),
+ ],
+ // Speculative; has been misleading in the past (#46836).
+ Applicability::MaybeIncorrect,
+ );
+ }
+ }
+ }
+
fn error_block_no_opening_brace<T>(&mut self) -> PResult<'a, T> {
let tok = super::token_descr(&self.token);
let msg = format!("expected `{{`, found {tok}");
diff --git a/compiler/rustc_passes/src/abi_test.rs b/compiler/rustc_passes/src/abi_test.rs
index b126756..4db8584 100644
--- a/compiler/rustc_passes/src/abi_test.rs
+++ b/compiler/rustc_passes/src/abi_test.rs
@@ -59,9 +59,9 @@ fn unwrap_fn_abi<'tcx>(
}
fn dump_abi_of_fn_item(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) {
- let param_env = tcx.param_env(item_def_id);
+ let typing_env = ty::TypingEnv::post_analysis(tcx, item_def_id);
let args = GenericArgs::identity_for_item(tcx, item_def_id);
- let instance = match Instance::try_resolve(tcx, param_env, item_def_id.into(), args) {
+ let instance = match Instance::try_resolve(tcx, typing_env, item_def_id.into(), args) {
Ok(Some(instance)) => instance,
Ok(None) => {
// Not sure what to do here, but `LayoutError::Unknown` seems reasonable?
@@ -75,7 +75,9 @@ fn dump_abi_of_fn_item(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut
Err(_guaranteed) => return,
};
let abi = unwrap_fn_abi(
- tcx.fn_abi_of_instance(param_env.and((instance, /* extra_args */ ty::List::empty()))),
+ tcx.fn_abi_of_instance(
+ typing_env.as_query_input((instance, /* extra_args */ ty::List::empty())),
+ ),
tcx,
item_def_id,
);
@@ -117,10 +119,10 @@ fn test_abi_eq<'tcx>(abi1: &'tcx FnAbi<'tcx, Ty<'tcx>>, abi2: &'tcx FnAbi<'tcx,
}
fn dump_abi_of_fn_type(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) {
- let param_env = tcx.param_env(item_def_id);
+ let typing_env = ty::TypingEnv::post_analysis(tcx, item_def_id);
let ty = tcx.type_of(item_def_id).instantiate_identity();
let span = tcx.def_span(item_def_id);
- if !ensure_wf(tcx, param_env, ty, item_def_id, span) {
+ if !ensure_wf(tcx, typing_env, ty, item_def_id, span) {
return;
}
let meta_items = attr.meta_item_list().unwrap_or_default();
@@ -134,10 +136,10 @@ fn dump_abi_of_fn_type(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut
);
};
let abi = unwrap_fn_abi(
- tcx.fn_abi_of_fn_ptr(
- param_env
- .and((sig_tys.with(*hdr), /* extra_args */ ty::List::empty())),
- ),
+ tcx.fn_abi_of_fn_ptr(typing_env.as_query_input((
+ sig_tys.with(*hdr),
+ /* extra_args */ ty::List::empty(),
+ ))),
tcx,
item_def_id,
);
@@ -165,10 +167,10 @@ fn dump_abi_of_fn_type(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut
);
};
let abi1 = unwrap_fn_abi(
- tcx.fn_abi_of_fn_ptr(
- param_env
- .and((sig_tys1.with(*hdr1), /* extra_args */ ty::List::empty())),
- ),
+ tcx.fn_abi_of_fn_ptr(typing_env.as_query_input((
+ sig_tys1.with(*hdr1),
+ /* extra_args */ ty::List::empty(),
+ ))),
tcx,
item_def_id,
);
@@ -179,10 +181,10 @@ fn dump_abi_of_fn_type(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut
);
};
let abi2 = unwrap_fn_abi(
- tcx.fn_abi_of_fn_ptr(
- param_env
- .and((sig_tys2.with(*hdr2), /* extra_args */ ty::List::empty())),
- ),
+ tcx.fn_abi_of_fn_ptr(typing_env.as_query_input((
+ sig_tys2.with(*hdr2),
+ /* extra_args */ ty::List::empty(),
+ ))),
tcx,
item_def_id,
);
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index b1db66f..ecf8d34 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -273,7 +273,7 @@ fn handle_offset_of(&mut self, expr: &'tcx hir::Expr<'tcx>) {
data.get(expr.hir_id).expect("no offset_of_data for offset_of");
let body_did = self.typeck_results().hir_owner.to_def_id();
- let param_env = self.tcx.param_env(body_did);
+ let typing_env = ty::TypingEnv::non_body_analysis(self.tcx, body_did);
let mut current_ty = container;
@@ -285,13 +285,13 @@ fn handle_offset_of(&mut self, expr: &'tcx hir::Expr<'tcx>) {
self.insert_def_id(field.did);
let field_ty = field.ty(self.tcx, args);
- current_ty = self.tcx.normalize_erasing_regions(param_env, field_ty);
+ current_ty = self.tcx.normalize_erasing_regions(typing_env, field_ty);
}
// we don't need to mark tuple fields as live,
// but we may need to mark subfields
ty::Tuple(tys) => {
current_ty =
- self.tcx.normalize_erasing_regions(param_env, tys[field.as_usize()]);
+ self.tcx.normalize_erasing_regions(typing_env, tys[field.as_usize()]);
}
_ => span_bug!(expr.span, "named field access on non-ADT"),
}
@@ -944,7 +944,10 @@ fn should_warn_about_field(&mut self, field: &ty::FieldDef) -> ShouldWarnAboutFi
if is_positional
&& self
.tcx
- .layout_of(self.tcx.param_env(field.did).and(field_type))
+ .layout_of(
+ ty::TypingEnv::non_body_analysis(self.tcx, field.did)
+ .as_query_input(field_type),
+ )
.map_or(true, |layout| layout.is_zst())
{
return ShouldWarnAboutField::No;
diff --git a/compiler/rustc_passes/src/layout_test.rs b/compiler/rustc_passes/src/layout_test.rs
index 986dce5..bb90b5a 100644
--- a/compiler/rustc_passes/src/layout_test.rs
+++ b/compiler/rustc_passes/src/layout_test.rs
@@ -2,10 +2,9 @@
use rustc_ast::Attribute;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::LocalDefId;
-use rustc_middle::infer::canonical::ir::TypingMode;
use rustc_middle::span_bug;
-use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt, LayoutError, LayoutOfHelpers};
-use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt};
+use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutError, LayoutOfHelpers};
+use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::Span;
use rustc_span::source_map::Spanned;
use rustc_span::symbol::sym;
@@ -39,11 +38,13 @@ pub fn test_layout(tcx: TyCtxt<'_>) {
pub fn ensure_wf<'tcx>(
tcx: TyCtxt<'tcx>,
- param_env: ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
ty: Ty<'tcx>,
def_id: LocalDefId,
span: Span,
) -> bool {
+ let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env);
+ let ocx = traits::ObligationCtxt::new_with_diagnostics(&infcx);
let pred = ty::ClauseKind::WellFormed(ty.into());
let obligation = traits::Obligation::new(
tcx,
@@ -55,8 +56,6 @@ pub fn ensure_wf<'tcx>(
param_env,
pred,
);
- let infcx = tcx.infer_ctxt().build(TypingMode::from_param_env(param_env));
- let ocx = traits::ObligationCtxt::new_with_diagnostics(&infcx);
ocx.register_obligation(obligation);
let errors = ocx.select_all_or_error();
if !errors.is_empty() {
@@ -69,13 +68,13 @@ pub fn ensure_wf<'tcx>(
}
fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) {
- let param_env = tcx.param_env(item_def_id);
+ let typing_env = ty::TypingEnv::post_analysis(tcx, item_def_id);
let ty = tcx.type_of(item_def_id).instantiate_identity();
let span = tcx.def_span(item_def_id.to_def_id());
- if !ensure_wf(tcx, param_env, ty, item_def_id, span) {
+ if !ensure_wf(tcx, typing_env, ty, item_def_id, span) {
return;
}
- match tcx.layout_of(param_env.and(ty)) {
+ match tcx.layout_of(typing_env.as_query_input(ty)) {
Ok(ty_layout) => {
// Check out the `#[rustc_layout(..)]` attribute to tell what to dump.
// The `..` are the names of fields to dump.
@@ -107,19 +106,15 @@ fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) {
span,
homogeneous_aggregate: format!(
"{:?}",
- ty_layout.homogeneous_aggregate(&UnwrapLayoutCx { tcx, param_env })
+ ty_layout
+ .homogeneous_aggregate(&UnwrapLayoutCx { tcx, typing_env })
),
});
}
sym::debug => {
- let normalized_ty = format!(
- "{}",
- tcx.normalize_erasing_regions(
- param_env.with_reveal_all_normalized(tcx),
- ty,
- )
- );
+ let normalized_ty =
+ format!("{}", tcx.normalize_erasing_regions(typing_env, ty));
// FIXME: using the `Debug` impl here isn't ideal.
let ty_layout = format!("{:#?}", *ty_layout);
tcx.dcx().emit_err(LayoutOf { span, normalized_ty, ty_layout });
@@ -140,7 +135,7 @@ fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) {
struct UnwrapLayoutCx<'tcx> {
tcx: TyCtxt<'tcx>,
- param_env: ParamEnv<'tcx>,
+ typing_env: ty::TypingEnv<'tcx>,
}
impl<'tcx> LayoutOfHelpers<'tcx> for UnwrapLayoutCx<'tcx> {
@@ -155,9 +150,9 @@ fn tcx(&self) -> TyCtxt<'tcx> {
}
}
-impl<'tcx> HasParamEnv<'tcx> for UnwrapLayoutCx<'tcx> {
- fn param_env(&self) -> ParamEnv<'tcx> {
- self.param_env
+impl<'tcx> HasTypingEnv<'tcx> for UnwrapLayoutCx<'tcx> {
+ fn typing_env(&self) -> ty::TypingEnv<'tcx> {
+ self.typing_env
}
}
diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs
index 366f7dd..c6c9985 100644
--- a/compiler/rustc_passes/src/liveness.rs
+++ b/compiler/rustc_passes/src/liveness.rs
@@ -1297,7 +1297,7 @@ fn propagate_through_loop(
fn check_is_ty_uninhabited(&mut self, expr: &Expr<'_>, succ: LiveNode) -> LiveNode {
let ty = self.typeck_results.expr_ty(expr);
let m = self.ir.tcx.parent_module(expr.hir_id).to_def_id();
- if ty.is_inhabited_from(self.ir.tcx, m, self.param_env) {
+ if ty.is_inhabited_from(self.ir.tcx, m, ty::TypingEnv::from_param_env(self.param_env)) {
return succ;
}
match self.ir.lnks[succ] {
diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs
index 9ea5023..936e523 100644
--- a/compiler/rustc_pattern_analysis/src/rustc.rs
+++ b/compiler/rustc_pattern_analysis/src/rustc.rs
@@ -9,6 +9,7 @@
use rustc_middle::middle::stability::EvalResult;
use rustc_middle::mir::{self, Const};
use rustc_middle::thir::{self, Pat, PatKind, PatRange, PatRangeBoundary};
+use rustc_middle::traits::Reveal;
use rustc_middle::ty::layout::IntegerExt;
use rustc_middle::ty::{
self, FieldDef, OpaqueTypeKey, ScalarInt, Ty, TyCtxt, TypeVisitableExt, VariantDef,
@@ -108,6 +109,17 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
+ pub fn typing_mode(&self) -> ty::TypingMode<'tcx> {
+ debug_assert_eq!(self.param_env.reveal(), Reveal::UserFacing);
+ // FIXME(#132279): This is inside of a body. If we need to use the `param_env`
+ // and `typing_mode` we should reveal opaques defined by that body.
+ ty::TypingMode::non_body_analysis()
+ }
+
+ pub fn typing_env(&self) -> ty::TypingEnv<'tcx> {
+ ty::TypingEnv { typing_mode: self.typing_mode(), param_env: self.param_env }
+ }
+
/// Type inference occasionally gives us opaque types in places where corresponding patterns
/// have more specific types. To avoid inconsistencies as well as detect opaque uninhabited
/// types, we use the corresponding concrete type if possible.
@@ -139,7 +151,7 @@ fn reveal_opaque_key(&self, key: OpaqueTypeKey<'tcx>) -> Option<Ty<'tcx>> {
pub fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool {
!ty.inhabited_predicate(self.tcx).apply_revealing_opaque(
self.tcx,
- self.param_env,
+ self.typing_env(),
self.module,
&|key| self.reveal_opaque_key(key),
)
@@ -179,7 +191,7 @@ pub(crate) fn variant_sub_tys(
variant.fields.iter().map(move |field| {
let ty = field.ty(self.tcx, args);
// `field.ty()` doesn't normalize after instantiating.
- let ty = self.tcx.normalize_erasing_regions(self.param_env, ty);
+ let ty = self.tcx.normalize_erasing_regions(self.typing_env(), ty);
let ty = self.reveal_opaque_ty(ty);
(field, ty)
})
@@ -369,7 +381,7 @@ pub fn ctors_for_ty(
let is_inhabited = v
.inhabited_predicate(cx.tcx, *def)
.instantiate(cx.tcx, args)
- .apply_revealing_opaque(cx.tcx, cx.param_env, cx.module, &|key| {
+ .apply_revealing_opaque(cx.tcx, cx.typing_env(), cx.module, &|key| {
cx.reveal_opaque_key(key)
});
// Variants that depend on a disabled unstable feature.
@@ -430,7 +442,7 @@ pub(crate) fn lower_pat_range_bdy(
match bdy {
PatRangeBoundary::NegInfinity => MaybeInfiniteInt::NegInfinity,
PatRangeBoundary::Finite(value) => {
- let bits = value.eval_bits(self.tcx, self.param_env);
+ let bits = value.eval_bits(self.tcx, self.typing_env());
match *ty.kind() {
ty::Int(ity) => {
let size = Integer::from_int_ty(&self.tcx, ity).size().bits();
@@ -539,7 +551,7 @@ pub fn lower_pat(&self, pat: &'p Pat<'tcx>) -> DeconstructedPat<'p, 'tcx> {
PatKind::Constant { value } => {
match ty.kind() {
ty::Bool => {
- ctor = match value.try_eval_bool(cx.tcx, cx.param_env) {
+ ctor = match value.try_eval_bool(cx.tcx, cx.typing_env()) {
Some(b) => Bool(b),
None => Opaque(OpaqueId::new()),
};
@@ -547,7 +559,7 @@ pub fn lower_pat(&self, pat: &'p Pat<'tcx>) -> DeconstructedPat<'p, 'tcx> {
arity = 0;
}
ty::Char | ty::Int(_) | ty::Uint(_) => {
- ctor = match value.try_eval_bits(cx.tcx, cx.param_env) {
+ ctor = match value.try_eval_bits(cx.tcx, cx.typing_env()) {
Some(bits) => {
let x = match *ty.kind() {
ty::Int(ity) => {
@@ -564,7 +576,7 @@ pub fn lower_pat(&self, pat: &'p Pat<'tcx>) -> DeconstructedPat<'p, 'tcx> {
arity = 0;
}
ty::Float(ty::FloatTy::F16) => {
- ctor = match value.try_eval_bits(cx.tcx, cx.param_env) {
+ ctor = match value.try_eval_bits(cx.tcx, cx.typing_env()) {
Some(bits) => {
use rustc_apfloat::Float;
let value = rustc_apfloat::ieee::Half::from_bits(bits);
@@ -576,7 +588,7 @@ pub fn lower_pat(&self, pat: &'p Pat<'tcx>) -> DeconstructedPat<'p, 'tcx> {
arity = 0;
}
ty::Float(ty::FloatTy::F32) => {
- ctor = match value.try_eval_bits(cx.tcx, cx.param_env) {
+ ctor = match value.try_eval_bits(cx.tcx, cx.typing_env()) {
Some(bits) => {
use rustc_apfloat::Float;
let value = rustc_apfloat::ieee::Single::from_bits(bits);
@@ -588,7 +600,7 @@ pub fn lower_pat(&self, pat: &'p Pat<'tcx>) -> DeconstructedPat<'p, 'tcx> {
arity = 0;
}
ty::Float(ty::FloatTy::F64) => {
- ctor = match value.try_eval_bits(cx.tcx, cx.param_env) {
+ ctor = match value.try_eval_bits(cx.tcx, cx.typing_env()) {
Some(bits) => {
use rustc_apfloat::Float;
let value = rustc_apfloat::ieee::Double::from_bits(bits);
@@ -600,7 +612,7 @@ pub fn lower_pat(&self, pat: &'p Pat<'tcx>) -> DeconstructedPat<'p, 'tcx> {
arity = 0;
}
ty::Float(ty::FloatTy::F128) => {
- ctor = match value.try_eval_bits(cx.tcx, cx.param_env) {
+ ctor = match value.try_eval_bits(cx.tcx, cx.typing_env()) {
Some(bits) => {
use rustc_apfloat::Float;
let value = rustc_apfloat::ieee::Quad::from_bits(bits);
@@ -649,8 +661,8 @@ pub fn lower_pat(&self, pat: &'p Pat<'tcx>) -> DeconstructedPat<'p, 'tcx> {
}
ty::Float(fty) => {
use rustc_apfloat::Float;
- let lo = lo.as_finite().map(|c| c.eval_bits(cx.tcx, cx.param_env));
- let hi = hi.as_finite().map(|c| c.eval_bits(cx.tcx, cx.param_env));
+ let lo = lo.as_finite().map(|c| c.eval_bits(cx.tcx, cx.typing_env()));
+ let hi = hi.as_finite().map(|c| c.eval_bits(cx.tcx, cx.typing_env()));
match fty {
ty::FloatTy::F16 => {
use rustc_apfloat::ieee::Half;
diff --git a/compiler/rustc_query_system/src/lib.rs b/compiler/rustc_query_system/src/lib.rs
index ba7a631..a85e8a5 100644
--- a/compiler/rustc_query_system/src/lib.rs
+++ b/compiler/rustc_query_system/src/lib.rs
@@ -2,6 +2,7 @@
#![allow(rustc::potential_query_instability, internal_features)]
#![feature(assert_matches)]
#![feature(core_intrinsics)]
+#![feature(dropck_eyepatch)]
#![feature(hash_raw_entry)]
#![feature(let_chains)]
#![feature(min_specialization)]
diff --git a/compiler/rustc_query_system/src/query/caches.rs b/compiler/rustc_query_system/src/query/caches.rs
index a4ced3d..e6f3d97 100644
--- a/compiler/rustc_query_system/src/query/caches.rs
+++ b/compiler/rustc_query_system/src/query/caches.rs
@@ -3,9 +3,10 @@
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sharded::{self, Sharded};
-use rustc_data_structures::sync::{Lock, OnceLock};
+use rustc_data_structures::sync::OnceLock;
+pub use rustc_data_structures::vec_cache::VecCache;
use rustc_hir::def_id::LOCAL_CRATE;
-use rustc_index::{Idx, IndexVec};
+use rustc_index::Idx;
use rustc_span::def_id::{DefId, DefIndex};
use crate::dep_graph::DepNodeIndex;
@@ -100,52 +101,10 @@ fn iter(&self, f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex)) {
}
}
-pub struct VecCache<K: Idx, V> {
- cache: Lock<IndexVec<K, Option<(V, DepNodeIndex)>>>,
-}
-
-impl<K: Idx, V> Default for VecCache<K, V> {
- fn default() -> Self {
- VecCache { cache: Default::default() }
- }
-}
-
-impl<K, V> QueryCache for VecCache<K, V>
-where
- K: Eq + Idx + Copy + Debug,
- V: Copy,
-{
- type Key = K;
- type Value = V;
-
- #[inline(always)]
- fn lookup(&self, key: &K) -> Option<(V, DepNodeIndex)> {
- let lock = self.cache.lock();
- if let Some(Some(value)) = lock.get(*key) { Some(*value) } else { None }
- }
-
- #[inline]
- fn complete(&self, key: K, value: V, index: DepNodeIndex) {
- let mut lock = self.cache.lock();
- lock.insert(key, (value, index));
- }
-
- fn iter(&self, f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex)) {
- for (k, v) in self.cache.lock().iter_enumerated() {
- if let Some(v) = v {
- f(&k, &v.0, v.1);
- }
- }
- }
-}
-
pub struct DefIdCache<V> {
/// Stores the local DefIds in a dense map. Local queries are much more often dense, so this is
/// a win over hashing query keys at marginal memory cost (~5% at most) compared to FxHashMap.
- ///
- /// The second element of the tuple is the set of keys actually present in the IndexVec, used
- /// for faster iteration in `iter()`.
- local: Lock<(IndexVec<DefIndex, Option<(V, DepNodeIndex)>>, Vec<DefIndex>)>,
+ local: VecCache<DefIndex, V, DepNodeIndex>,
foreign: DefaultCache<DefId, V>,
}
@@ -165,8 +124,7 @@ impl<V> QueryCache for DefIdCache<V>
#[inline(always)]
fn lookup(&self, key: &DefId) -> Option<(V, DepNodeIndex)> {
if key.krate == LOCAL_CRATE {
- let cache = self.local.lock();
- cache.0.get(key.index).and_then(|v| *v)
+ self.local.lookup(&key.index)
} else {
self.foreign.lookup(key)
}
@@ -175,27 +133,39 @@ fn lookup(&self, key: &DefId) -> Option<(V, DepNodeIndex)> {
#[inline]
fn complete(&self, key: DefId, value: V, index: DepNodeIndex) {
if key.krate == LOCAL_CRATE {
- let mut cache = self.local.lock();
- let (cache, present) = &mut *cache;
- let slot = cache.ensure_contains_elem(key.index, Default::default);
- if slot.is_none() {
- // FIXME: Only store the present set when running in incremental mode. `iter` is not
- // used outside of saving caches to disk and self-profile.
- present.push(key.index);
- }
- *slot = Some((value, index));
+ self.local.complete(key.index, value, index)
} else {
self.foreign.complete(key, value, index)
}
}
fn iter(&self, f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex)) {
- let guard = self.local.lock();
- let (cache, present) = &*guard;
- for &idx in present.iter() {
- let value = cache[idx].unwrap();
- f(&DefId { krate: LOCAL_CRATE, index: idx }, &value.0, value.1);
- }
+ self.local.iter(&mut |key, value, index| {
+ f(&DefId { krate: LOCAL_CRATE, index: *key }, value, index);
+ });
self.foreign.iter(f);
}
}
+
+impl<K, V> QueryCache for VecCache<K, V, DepNodeIndex>
+where
+ K: Idx + Eq + Hash + Copy + Debug,
+ V: Copy,
+{
+ type Key = K;
+ type Value = V;
+
+ #[inline(always)]
+ fn lookup(&self, key: &K) -> Option<(V, DepNodeIndex)> {
+ self.lookup(key)
+ }
+
+ #[inline]
+ fn complete(&self, key: K, value: V, index: DepNodeIndex) {
+ self.complete(key, value, index)
+ }
+
+ fn iter(&self, f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex)) {
+ self.iter(f)
+ }
+}
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index bdf940a..293cee5 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -1324,7 +1324,7 @@ fn visit_item(&mut self, item: &'a Item) {
// This way they can use `macro_rules` defined later.
self.visit_vis(&item.vis);
self.visit_ident(&item.ident);
- item.kind.walk(item, AssocCtxt::Trait, self);
+ item.kind.walk(item.span, item.id, &item.ident, &item.vis, (), self);
visit::walk_list!(self, visit_attribute, &item.attrs);
}
_ => visit::walk_item(self, item),
diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs
index 0e6f905..2f4387e 100644
--- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs
+++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs
@@ -133,7 +133,7 @@ fn encode_const<'tcx>(
match ct_ty.kind() {
ty::Int(ity) => {
let bits = c
- .try_to_bits(tcx, ty::ParamEnv::reveal_all())
+ .try_to_bits(tcx, ty::TypingEnv::fully_monomorphized())
.expect("expected monomorphic const in cfi");
let val = Integer::from_int_ty(&tcx, *ity).size().sign_extend(bits) as i128;
if val < 0 {
@@ -143,7 +143,7 @@ fn encode_const<'tcx>(
}
ty::Uint(_) => {
let val = c
- .try_to_bits(tcx, ty::ParamEnv::reveal_all())
+ .try_to_bits(tcx, ty::TypingEnv::fully_monomorphized())
.expect("expected monomorphic const in cfi");
let _ = write!(s, "{val}");
}
diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/mod.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/mod.rs
index 01568a0..562e288 100644
--- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/mod.rs
+++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/mod.rs
@@ -117,7 +117,9 @@ pub fn typeid_for_instance<'tcx>(
.unwrap_or_else(|| bug!("typeid_for_instance: invalid option(s) `{:?}`", options.bits()));
let instance = transform_instance(tcx, instance, transform_ty_options);
let fn_abi = tcx
- .fn_abi_of_instance(ty::ParamEnv::reveal_all().and((instance, ty::List::empty())))
+ .fn_abi_of_instance(
+ ty::TypingEnv::fully_monomorphized().as_query_input((instance, ty::List::empty())),
+ )
.unwrap_or_else(|error| {
bug!("typeid_for_instance: couldn't get fn_abi of instance {instance:?}: {error:?}")
});
diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs
index cba79a0..9c01bd0 100644
--- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs
+++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs
@@ -136,18 +136,18 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
return t;
}
let variant = adt_def.non_enum_variant();
- let param_env = self.tcx.param_env(variant.def_id);
+ let typing_env = ty::TypingEnv::post_analysis(self.tcx, variant.def_id);
let field = variant.fields.iter().find(|field| {
let ty = self.tcx.type_of(field.did).instantiate_identity();
let is_zst = self
.tcx
- .layout_of(param_env.and(ty))
+ .layout_of(typing_env.as_query_input(ty))
.is_ok_and(|layout| layout.is_zst());
!is_zst
});
if let Some(field) = field {
let ty0 = self.tcx.normalize_erasing_regions(
- ty::ParamEnv::reveal_all(),
+ ty::TypingEnv::fully_monomorphized(),
field.ty(self.tcx, args),
);
// Generalize any repr(transparent) user-defined type that is either a
@@ -209,9 +209,9 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
}
}
- ty::Alias(..) => {
- self.fold_ty(self.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), t))
- }
+ ty::Alias(..) => self.fold_ty(
+ self.tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), t),
+ ),
ty::Bound(..) | ty::Error(..) | ty::Infer(..) | ty::Param(..) | ty::Placeholder(..) => {
bug!("fold_ty: unexpected `{:?}`", t.kind());
@@ -241,7 +241,7 @@ fn trait_object_ty<'tcx>(tcx: TyCtxt<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tc
let alias_ty =
ty::AliasTy::new_from_args(tcx, assoc_ty.def_id, super_trait_ref.args);
let resolved = tcx.normalize_erasing_regions(
- ty::ParamEnv::reveal_all(),
+ ty::TypingEnv::fully_monomorphized(),
alias_ty.to_ty(tcx),
);
debug!("Resolved {:?} -> {resolved}", alias_ty.to_ty(tcx));
@@ -376,7 +376,7 @@ pub(crate) fn transform_instance<'tcx>(
// implementation will not. We need to walk back to the more general trait method
let trait_ref = tcx.instantiate_and_normalize_erasing_regions(
instance.args,
- ty::ParamEnv::reveal_all(),
+ ty::TypingEnv::fully_monomorphized(),
trait_ref,
);
let invoke_ty = trait_object_ty(tcx, ty::Binder::dummy(trait_ref));
@@ -397,7 +397,7 @@ pub(crate) fn transform_instance<'tcx>(
} else if tcx.is_closure_like(instance.def_id()) {
// We're either a closure or a coroutine. Our goal is to find the trait we're defined on,
// instantiate it, and take the type of its only method as our own.
- let closure_ty = instance.ty(tcx, ty::ParamEnv::reveal_all());
+ let closure_ty = instance.ty(tcx, ty::TypingEnv::fully_monomorphized());
let (trait_id, inputs) = match closure_ty.kind() {
ty::Closure(..) => {
let closure_args = instance.args.as_closure();
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 44721bd..f6e6fd3 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -30,17 +30,18 @@
};
use tracing::debug;
+pub use crate::config::cfg::{Cfg, CheckCfg, ExpectedValues};
+use crate::config::native_libs::parse_native_libs;
use crate::errors::FileWriteFail;
pub use crate::options::*;
use crate::search_paths::SearchPath;
-use crate::utils::{CanonicalizedPath, NativeLib, NativeLibKind};
+use crate::utils::CanonicalizedPath;
use crate::{EarlyDiagCtxt, HashStableContext, Session, filesearch, lint};
mod cfg;
+mod native_libs;
pub mod sigpipe;
-pub use cfg::{Cfg, CheckCfg, ExpectedValues};
-
/// The different settings that the `-C strip` flag can have.
#[derive(Clone, Copy, PartialEq, Hash, Debug)]
pub enum Strip {
@@ -2134,143 +2135,6 @@ fn parse_assert_incr_state(
}
}
-fn parse_native_lib_kind(
- early_dcx: &EarlyDiagCtxt,
- matches: &getopts::Matches,
- kind: &str,
-) -> (NativeLibKind, Option<bool>) {
- let (kind, modifiers) = match kind.split_once(':') {
- None => (kind, None),
- Some((kind, modifiers)) => (kind, Some(modifiers)),
- };
-
- let kind = match kind {
- "static" => NativeLibKind::Static { bundle: None, whole_archive: None },
- "dylib" => NativeLibKind::Dylib { as_needed: None },
- "framework" => NativeLibKind::Framework { as_needed: None },
- "link-arg" => {
- if !nightly_options::is_unstable_enabled(matches) {
- let why = if nightly_options::match_is_nightly_build(matches) {
- " and only accepted on the nightly compiler"
- } else {
- ", the `-Z unstable-options` flag must also be passed to use it"
- };
- early_dcx.early_fatal(format!("library kind `link-arg` is unstable{why}"))
- }
- NativeLibKind::LinkArg
- }
- _ => early_dcx.early_fatal(format!(
- "unknown library kind `{kind}`, expected one of: static, dylib, framework, link-arg"
- )),
- };
- match modifiers {
- None => (kind, None),
- Some(modifiers) => parse_native_lib_modifiers(early_dcx, kind, modifiers, matches),
- }
-}
-
-fn parse_native_lib_modifiers(
- early_dcx: &EarlyDiagCtxt,
- mut kind: NativeLibKind,
- modifiers: &str,
- matches: &getopts::Matches,
-) -> (NativeLibKind, Option<bool>) {
- let mut verbatim = None;
- for modifier in modifiers.split(',') {
- let (modifier, value) = match modifier.strip_prefix(['+', '-']) {
- Some(m) => (m, modifier.starts_with('+')),
- None => early_dcx.early_fatal(
- "invalid linking modifier syntax, expected '+' or '-' prefix \
- before one of: bundle, verbatim, whole-archive, as-needed",
- ),
- };
-
- let report_unstable_modifier = || {
- if !nightly_options::is_unstable_enabled(matches) {
- let why = if nightly_options::match_is_nightly_build(matches) {
- " and only accepted on the nightly compiler"
- } else {
- ", the `-Z unstable-options` flag must also be passed to use it"
- };
- early_dcx.early_fatal(format!("linking modifier `{modifier}` is unstable{why}"))
- }
- };
- let assign_modifier = |dst: &mut Option<bool>| {
- if dst.is_some() {
- let msg = format!("multiple `{modifier}` modifiers in a single `-l` option");
- early_dcx.early_fatal(msg)
- } else {
- *dst = Some(value);
- }
- };
- match (modifier, &mut kind) {
- ("bundle", NativeLibKind::Static { bundle, .. }) => assign_modifier(bundle),
- ("bundle", _) => early_dcx.early_fatal(
- "linking modifier `bundle` is only compatible with `static` linking kind",
- ),
-
- ("verbatim", _) => assign_modifier(&mut verbatim),
-
- ("whole-archive", NativeLibKind::Static { whole_archive, .. }) => {
- assign_modifier(whole_archive)
- }
- ("whole-archive", _) => early_dcx.early_fatal(
- "linking modifier `whole-archive` is only compatible with `static` linking kind",
- ),
-
- ("as-needed", NativeLibKind::Dylib { as_needed })
- | ("as-needed", NativeLibKind::Framework { as_needed }) => {
- report_unstable_modifier();
- assign_modifier(as_needed)
- }
- ("as-needed", _) => early_dcx.early_fatal(
- "linking modifier `as-needed` is only compatible with \
- `dylib` and `framework` linking kinds",
- ),
-
- // Note: this error also excludes the case with empty modifier
- // string, like `modifiers = ""`.
- _ => early_dcx.early_fatal(format!(
- "unknown linking modifier `{modifier}`, expected one \
- of: bundle, verbatim, whole-archive, as-needed"
- )),
- }
- }
-
- (kind, verbatim)
-}
-
-fn parse_libs(early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches) -> Vec<NativeLib> {
- matches
- .opt_strs("l")
- .into_iter()
- .map(|s| {
- // Parse string of the form "[KIND[:MODIFIERS]=]lib[:new_name]",
- // where KIND is one of "dylib", "framework", "static", "link-arg" and
- // where MODIFIERS are a comma separated list of supported modifiers
- // (bundle, verbatim, whole-archive, as-needed). Each modifier is prefixed
- // with either + or - to indicate whether it is enabled or disabled.
- // The last value specified for a given modifier wins.
- let (name, kind, verbatim) = match s.split_once('=') {
- None => (s, NativeLibKind::Unspecified, None),
- Some((kind, name)) => {
- let (kind, verbatim) = parse_native_lib_kind(early_dcx, matches, kind);
- (name.to_string(), kind, verbatim)
- }
- };
-
- let (name, new_name) = match name.split_once(':') {
- None => (name, None),
- Some((name, new_name)) => (name.to_string(), Some(new_name.to_owned())),
- };
- if name.is_empty() {
- early_dcx.early_fatal("library name must not be empty");
- }
- NativeLib { name, new_name, kind, verbatim }
- })
- .collect()
-}
-
pub fn parse_externs(
early_dcx: &EarlyDiagCtxt,
matches: &getopts::Matches,
@@ -2644,7 +2508,10 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
let debuginfo = select_debuginfo(matches, &cg);
let debuginfo_compression = unstable_opts.debuginfo_compression;
- let libs = parse_libs(early_dcx, matches);
+ let crate_name = matches.opt_str("crate-name");
+ let unstable_features = UnstableFeatures::from_environment(crate_name.as_deref());
+ // Parse any `-l` flags, which link to native libraries.
+ let libs = parse_native_libs(early_dcx, &unstable_opts, unstable_features, matches);
let test = matches.opt_present("test");
@@ -2659,8 +2526,6 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
let externs = parse_externs(early_dcx, matches, &unstable_opts);
- let crate_name = matches.opt_str("crate-name");
-
let remap_path_prefix = parse_remap_path_prefix(early_dcx, matches, &unstable_opts);
let pretty = parse_pretty(early_dcx, &unstable_opts);
@@ -2734,7 +2599,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
error_format,
diagnostic_width,
externs,
- unstable_features: UnstableFeatures::from_environment(crate_name.as_deref()),
+ unstable_features,
crate_name,
libs,
debug_assertions,
diff --git a/compiler/rustc_session/src/config/native_libs.rs b/compiler/rustc_session/src/config/native_libs.rs
new file mode 100644
index 0000000..f1f0aeb
--- /dev/null
+++ b/compiler/rustc_session/src/config/native_libs.rs
@@ -0,0 +1,192 @@
+//! Parser for the `-l` command-line option, which links the generated crate to
+//! a native library.
+//!
+//! (There is also a similar but separate syntax for `#[link]` attributes,
+//! which have their own parser in `rustc_metadata`.)
+
+use rustc_feature::UnstableFeatures;
+
+use crate::EarlyDiagCtxt;
+use crate::config::UnstableOptions;
+use crate::utils::{NativeLib, NativeLibKind};
+
+#[cfg(test)]
+mod tests;
+
+/// Parses all `-l` options.
+pub(crate) fn parse_native_libs(
+ early_dcx: &EarlyDiagCtxt,
+ unstable_opts: &UnstableOptions,
+ unstable_features: UnstableFeatures,
+ matches: &getopts::Matches,
+) -> Vec<NativeLib> {
+ let cx = ParseNativeLibCx {
+ early_dcx,
+ unstable_options_enabled: unstable_opts.unstable_options,
+ is_nightly: unstable_features.is_nightly_build(),
+ };
+ matches.opt_strs("l").into_iter().map(|value| parse_native_lib(&cx, &value)).collect()
+}
+
+struct ParseNativeLibCx<'a> {
+ early_dcx: &'a EarlyDiagCtxt,
+ unstable_options_enabled: bool,
+ is_nightly: bool,
+}
+
+impl ParseNativeLibCx<'_> {
+ /// If unstable values are not permitted, exits with a fatal error made by
+ /// combining the given strings.
+ fn on_unstable_value(&self, message: &str, if_nightly: &str, if_stable: &str) {
+ if self.unstable_options_enabled {
+ return;
+ }
+
+ let suffix = if self.is_nightly { if_nightly } else { if_stable };
+ self.early_dcx.early_fatal(format!("{message}{suffix}"));
+ }
+}
+
+/// Parses the value of a single `-l` option.
+fn parse_native_lib(cx: &ParseNativeLibCx<'_>, value: &str) -> NativeLib {
+ let NativeLibParts { kind, modifiers, name, new_name } = split_native_lib_value(value);
+
+ let kind = kind.map_or(NativeLibKind::Unspecified, |kind| match kind {
+ "static" => NativeLibKind::Static { bundle: None, whole_archive: None },
+ "dylib" => NativeLibKind::Dylib { as_needed: None },
+ "framework" => NativeLibKind::Framework { as_needed: None },
+ "link-arg" => {
+ cx.on_unstable_value(
+ "library kind `link-arg` is unstable",
+ ", the `-Z unstable-options` flag must also be passed to use it",
+ " and only accepted on the nightly compiler",
+ );
+ NativeLibKind::LinkArg
+ }
+ _ => cx.early_dcx.early_fatal(format!(
+ "unknown library kind `{kind}`, expected one of: static, dylib, framework, link-arg"
+ )),
+ });
+
+ // Provisionally create the result, so that modifiers can modify it.
+ let mut native_lib = NativeLib {
+ name: name.to_owned(),
+ new_name: new_name.map(str::to_owned),
+ kind,
+ verbatim: None,