Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Support const args in type dependent paths #71154

Closed
wants to merge 14 commits into from
2 changes: 1 addition & 1 deletion src/librustc_codegen_llvm/debuginfo/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1295,7 +1295,7 @@ fn generator_layout_and_saved_local_names(
tcx: TyCtxt<'tcx>,
def_id: DefId,
) -> (&'tcx GeneratorLayout<'tcx>, IndexVec<mir::GeneratorSavedLocal, Option<Symbol>>) {
let body = tcx.optimized_mir(def_id);
let body = tcx.optimized_mir(tcx.with_opt_param(def_id));
let generator_layout = body.generator_layout.as_ref().unwrap();
let mut generator_saved_local_names = IndexVec::from_elem(None, &generator_layout.field_tys);

Expand Down
4 changes: 2 additions & 2 deletions src/librustc_codegen_ssa/back/symbol_export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,9 +249,9 @@ fn exported_symbols_provider_local(
}

match *mono_item {
MonoItem::Fn(Instance { def: InstanceDef::Item(def_id), substs }) => {
MonoItem::Fn(Instance { def: InstanceDef::Item(def), substs }) => {
if substs.non_erasable_generics().next().is_some() {
let symbol = ExportedSymbol::Generic(def_id, substs);
let symbol = ExportedSymbol::Generic(def.did, substs);
symbols.push((symbol, SymbolExportLevel::Rust));
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_codegen_ssa/mir/constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
constant: &mir::Constant<'tcx>,
) -> Result<ConstValue<'tcx>, ErrorHandled> {
match self.monomorphize(&constant.literal).val {
ty::ConstKind::Unevaluated(def_id, substs, promoted) => self
ty::ConstKind::Unevaluated(def, substs, promoted) => self
.cx
.tcx()
.const_eval_resolve(ty::ParamEnv::reveal_all(), def_id, substs, promoted, None)
.const_eval_resolve(ty::ParamEnv::reveal_all(), def, substs, promoted, None)
.map_err(|err| {
if promoted.is_none() {
self.cx
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_infer/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1538,7 +1538,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
pub fn const_eval_resolve(
&self,
param_env: ty::ParamEnv<'tcx>,
def_id: DefId,
def: ty::WithOptParam<DefId>,
substs: SubstsRef<'tcx>,
promoted: Option<mir::Promoted>,
span: Option<Span>,
Expand All @@ -1549,7 +1549,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
let (param_env, substs) = canonical.value;
// The return value is the evaluated value which doesn't contain any reference to inference
// variables, thus we don't need to substitute back the original values.
self.tcx.const_eval_resolve(param_env, def_id, substs, promoted, span)
self.tcx.const_eval_resolve(param_env, def, substs, promoted, span)
}

/// If `typ` is a type variable of some kind, resolve it one level
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_infer/traits/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ pub fn anonymize_predicate<'tcx>(
ty::PredicateKind::Subtype(tcx.anonymize_late_bound_regions(data))
}

&ty::PredicateKind::ConstEvaluatable(def_id, substs) => {
ty::PredicateKind::ConstEvaluatable(def_id, substs)
&ty::PredicateKind::ConstEvaluatable(def, substs) => {
ty::PredicateKind::ConstEvaluatable(def, substs)
}

ty::PredicateKind::ConstEquate(c1, c2) => ty::PredicateKind::ConstEquate(c1, c2),
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_interface/passes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -848,15 +848,15 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> {
});

sess.time("MIR_borrow_checking", || {
tcx.par_body_owners(|def_id| tcx.ensure().mir_borrowck(def_id));
tcx.par_body_owners(|def_id| tcx.ensure().mir_borrowck(tcx.with_opt_param(def_id)));
});

sess.time("MIR_effect_checking", || {
for def_id in tcx.body_owners() {
mir::transform::check_unsafety::check_unsafety(tcx, def_id);

if tcx.hir().body_const_context(def_id).is_some() {
tcx.ensure().mir_drops_elaborated_and_const_checked(def_id);
tcx.ensure().mir_drops_elaborated_and_const_checked(tcx.with_opt_param(def_id));
}
}
});
Expand Down
6 changes: 6 additions & 0 deletions src/librustc_metadata/rmeta/decoder/cstore_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,12 @@ impl IntoArgs for DefId {
}
}

impl IntoArgs for ty::WithOptParam<DefId> {
fn into_args(self) -> (DefId, DefId) {
(self.did, self.param_did.unwrap_or(self.did))
}
}

impl IntoArgs for CrateNum {
fn into_args(self) -> (DefId, DefId) {
(self.as_def_id(), self.as_def_id())
Expand Down
23 changes: 15 additions & 8 deletions src/librustc_metadata/rmeta/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -939,7 +939,8 @@ impl EncodeContext<'tcx> {
record!(self.tables.kind[def_id] <- match impl_item.kind {
ty::AssocKind::Const => {
if let hir::ImplItemKind::Const(_, body_id) = ast_item.kind {
let qualifs = self.tcx.at(ast_item.span).mir_const_qualif(def_id);
let tcx = self.tcx.at(ast_item.span);
let qualifs = tcx.mir_const_qualif(tcx.with_opt_param(def_id));

EntryKind::AssocConst(
container,
Expand Down Expand Up @@ -1021,14 +1022,18 @@ impl EncodeContext<'tcx> {
fn encode_optimized_mir(&mut self, def_id: LocalDefId) {
debug!("EntryBuilder::encode_mir({:?})", def_id);
if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id) {
record!(self.tables.mir[def_id.to_def_id()] <- self.tcx.optimized_mir(def_id));
record!(self.tables.mir[def_id.to_def_id()] <- self.tcx.optimized_mir(
self.tcx.with_opt_param(def_id.to_def_id())
));
}
}

fn encode_promoted_mir(&mut self, def_id: LocalDefId) {
debug!("EncodeContext::encode_promoted_mir({:?})", def_id);
if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id) {
record!(self.tables.promoted_mir[def_id.to_def_id()] <- self.tcx.promoted_mir(def_id));
record!(self.tables.promoted_mir[def_id.to_def_id()] <- self.tcx.promoted_mir(
self.tcx.with_opt_param(def_id.to_def_id())
));
}
}

Expand Down Expand Up @@ -1086,7 +1091,8 @@ impl EncodeContext<'tcx> {
hir::ItemKind::Static(_, hir::Mutability::Mut, _) => EntryKind::MutStatic,
hir::ItemKind::Static(_, hir::Mutability::Not, _) => EntryKind::ImmStatic,
hir::ItemKind::Const(_, body_id) => {
let qualifs = self.tcx.at(item.span).mir_const_qualif(def_id);
let tcx = self.tcx.at(item.span);
let qualifs = tcx.mir_const_qualif(tcx.with_opt_param(def_id));
EntryKind::Const(
qualifs,
self.encode_rendered_const_for_body(body_id)
Expand Down Expand Up @@ -1328,7 +1334,7 @@ impl EncodeContext<'tcx> {
// NOTE(eddyb) `tcx.type_of(def_id)` isn't used because it's fully generic,
// including on the signature, which is inferred in `typeck_tables_of.
let hir_id = self.tcx.hir().as_local_hir_id(def_id);
let ty = self.tcx.typeck_tables_of(def_id).node_type(hir_id);
let ty = self.tcx.typeck_tables_of(self.tcx.with_opt_param(def_id)).node_type(hir_id);

record!(self.tables.kind[def_id.to_def_id()] <- match ty.kind {
ty::Generator(..) => {
Expand Down Expand Up @@ -1357,7 +1363,7 @@ impl EncodeContext<'tcx> {
let id = self.tcx.hir().as_local_hir_id(def_id);
let body_id = self.tcx.hir().body_owned_by(id);
let const_data = self.encode_rendered_const_for_body(body_id);
let qualifs = self.tcx.mir_const_qualif(def_id);
let qualifs = self.tcx.mir_const_qualif(self.tcx.with_opt_param(def_id.to_def_id()));

record!(self.tables.kind[def_id.to_def_id()] <- EntryKind::AnonConst(qualifs, const_data));
record!(self.tables.visibility[def_id.to_def_id()] <- ty::Visibility::Public);
Expand Down Expand Up @@ -1744,8 +1750,9 @@ struct PrefetchVisitor<'tcx> {
impl<'tcx> PrefetchVisitor<'tcx> {
fn prefetch_mir(&self, def_id: LocalDefId) {
if self.mir_keys.contains(&def_id) {
self.tcx.ensure().optimized_mir(def_id);
self.tcx.ensure().promoted_mir(def_id);
let def = self.tcx.with_opt_param(def_id).to_global();
self.tcx.ensure().optimized_mir(def);
self.tcx.ensure().promoted_mir(def);
}
}
}
Expand Down
38 changes: 38 additions & 0 deletions src/librustc_middle/dep_graph/dep_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,44 @@ impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for CrateNum {
}
}

impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for ty::WithOptParam<DefId> {
#[inline]
fn can_reconstruct_query_key() -> bool {
true
}

fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
tcx.def_path_hash(self.did).0
}

fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
tcx.def_path_str(self.did)
}

fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
dep_node.extract_def_id(tcx).map(|def_id| tcx.with_opt_param(def_id))
}
}
lcnr marked this conversation as resolved.
Show resolved Hide resolved

impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for ty::WithOptParam<LocalDefId> {
#[inline]
fn can_reconstruct_query_key() -> bool {
true
}

fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
tcx.def_path_hash(self.did.to_def_id()).0
}

fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
tcx.def_path_str(self.did.to_def_id())
}

fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
dep_node.extract_def_id(tcx).map(|def_id| tcx.with_opt_param(def_id.expect_local()))
}
}

impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for (DefId, DefId) {
#[inline]
fn can_reconstruct_query_key() -> bool {
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_middle/mir/interpret/queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn const_eval_resolve(
self,
param_env: ty::ParamEnv<'tcx>,
def_id: DefId,
def: ty::WithOptParam<DefId>,
substs: SubstsRef<'tcx>,
promoted: Option<mir::Promoted>,
span: Option<Span>,
) -> ConstEvalResult<'tcx> {
match ty::Instance::resolve(self, param_env, def_id, substs) {
match ty::Instance::resolve_const_arg(self, param_env, def, substs) {
Ok(Some(instance)) => {
let cid = GlobalId { instance, promoted };
self.const_eval_global_id(param_env, cid, span)
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_middle/mir/mono.rs
Original file line number Diff line number Diff line change
Expand Up @@ -346,8 +346,8 @@ impl<'tcx> CodegenUnit<'tcx> {
// instances into account. The others don't matter for
// the codegen tests and can even make item order
// unstable.
InstanceDef::Item(def_id) => {
def_id.as_local().map(|def_id| tcx.hir().as_local_hir_id(def_id))
InstanceDef::Item(def) => {
def.did.as_local().map(|def_id| tcx.hir().as_local_hir_id(def_id))
}
InstanceDef::VtableShim(..)
| InstanceDef::ReifyShim(..)
Expand Down
71 changes: 45 additions & 26 deletions src/librustc_middle/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,25 @@ rustc_queries! {
desc { |tcx| "HIR owner items in `{}`", tcx.def_path_str(key.to_def_id()) }
}

/// Computes the `DefId` of the corresponding const parameter in case the `key` is a
/// const argument and returns `None` otherwise.
///
/// ```rust
/// let a = foo::<7>();
Copy link
Member

Choose a reason for hiding this comment

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

This is a clear example :)

/// // ^ Calling `const_param_of` for this argument,
///
/// fn foo<const N: usize>()
/// // ^ returns this `DefId`.
///
/// fn bar() {
/// // ^ While calling `const_param_of` for other bodies returns `None`.
/// }
/// ```
query const_param_of(key: DefId) -> Option<DefId> {
cache_on_disk_if { key.is_local() }
desc { |tcx| "computing the const parameter of `{}`", tcx.def_path_str(key) }
}

/// Records the type of every item.
query type_of(key: DefId) -> Ty<'tcx> {
desc { |tcx| "computing type of `{}`", tcx.def_path_str(key) }
Expand Down Expand Up @@ -185,50 +204,50 @@ rustc_queries! {
/// Maps DefId's that have an associated `mir::Body` to the result
/// of the MIR const-checking pass. This is the set of qualifs in
/// the final value of a `const`.
query mir_const_qualif(key: DefId) -> mir::ConstQualifs {
desc { |tcx| "const checking `{}`", tcx.def_path_str(key) }
cache_on_disk_if { key.is_local() }
query mir_const_qualif(key: ty::WithOptParam<DefId>) -> mir::ConstQualifs {
desc { |tcx| "const checking `{}`", tcx.def_path_str(key.did) }
cache_on_disk_if { key.did.is_local() }
}

/// Fetch the MIR for a given `DefId` right after it's built - this includes
/// unreachable code.
query mir_built(key: LocalDefId) -> Steal<mir::Body<'tcx>> {
query mir_built(key: ty::WithOptParam<LocalDefId>) -> Steal<mir::Body<'tcx>> {
storage(ArenaCacheSelector<'tcx>)
desc { |tcx| "building MIR for `{}`", tcx.def_path_str(key.to_def_id()) }
desc { |tcx| "building MIR for `{}`", tcx.def_path_str(key.did.to_def_id()) }
}

/// Fetch the MIR for a given `DefId` up till the point where it is
/// ready for const qualification.
///
/// See the README for the `mir` module for details.
query mir_const(key: DefId) -> Steal<mir::Body<'tcx>> {
desc { |tcx| "processing MIR for `{}`", tcx.def_path_str(key) }
query mir_const(key: ty::WithOptParam<DefId>) -> Steal<mir::Body<'tcx>> {
desc { |tcx| "processing MIR for `{}`", tcx.def_path_str(key.did) }
storage(ArenaCacheSelector<'tcx>)
no_hash
}

query mir_drops_elaborated_and_const_checked(key: LocalDefId) -> Steal<mir::Body<'tcx>> {
query mir_drops_elaborated_and_const_checked(key: ty::WithOptParam<LocalDefId>) -> Steal<mir::Body<'tcx>> {
storage(ArenaCacheSelector<'tcx>)
no_hash
desc { |tcx| "elaborating drops for `{}`", tcx.def_path_str(key.to_def_id()) }
desc { |tcx| "elaborating drops for `{}`", tcx.def_path_str(key.did.to_def_id()) }
}

query mir_validated(key: LocalDefId) ->
query mir_validated(key: ty::WithOptParam<LocalDefId>) ->
(
Steal<mir::Body<'tcx>>,
Steal<IndexVec<mir::Promoted, mir::Body<'tcx>>>
) {
storage(ArenaCacheSelector<'tcx>)
no_hash
desc { |tcx| "processing `{}`", tcx.def_path_str(key.to_def_id()) }
desc { |tcx| "processing `{}`", tcx.def_path_str(key.did.to_def_id()) }
}

/// MIR after our optimization passes have run. This is MIR that is ready
/// for codegen. This is also the only query that can fetch non-local MIR, at present.
query optimized_mir(key: DefId) -> mir::Body<'tcx> {
desc { |tcx| "optimizing MIR for `{}`", tcx.def_path_str(key) }
query optimized_mir(key: ty::WithOptParam<DefId>) -> mir::Body<'tcx> {
desc { |tcx| "optimizing MIR for `{}`", tcx.def_path_str(key.did) }
storage(ArenaCacheSelector<'tcx>)
cache_on_disk_if { key.is_local() }
cache_on_disk_if { key.did.is_local() }
}

query coverage_data(key: DefId) -> mir::CoverageData {
Expand All @@ -237,10 +256,10 @@ rustc_queries! {
cache_on_disk_if { key.is_local() }
}

query promoted_mir(key: DefId) -> IndexVec<mir::Promoted, mir::Body<'tcx>> {
desc { |tcx| "optimizing promoted MIR for `{}`", tcx.def_path_str(key) }
query promoted_mir(key: ty::WithOptParam<DefId>) -> IndexVec<mir::Promoted, mir::Body<'tcx>> {
desc { |tcx| "optimizing promoted MIR for `{}`", tcx.def_path_str(key.did) }
storage(ArenaCacheSelector<'tcx>)
cache_on_disk_if { key.is_local() }
cache_on_disk_if { key.did.is_local() }
}
}

Expand Down Expand Up @@ -450,8 +469,8 @@ rustc_queries! {

TypeChecking {
/// The result of unsafety-checking this `DefId`.
query unsafety_check_result(key: LocalDefId) -> mir::UnsafetyCheckResult {
desc { |tcx| "unsafety-checking `{}`", tcx.def_path_str(key.to_def_id()) }
query unsafety_check_result(key: ty::WithOptParam<LocalDefId>) -> mir::UnsafetyCheckResult {
desc { |tcx| "unsafety-checking `{}`", tcx.def_path_str(key.did.to_def_id()) }
cache_on_disk_if { true }
storage(ArenaCacheSelector<'tcx>)
}
Expand Down Expand Up @@ -531,8 +550,8 @@ rustc_queries! {
desc { "type-checking all item bodies" }
}

query typeck_tables_of(key: LocalDefId) -> &'tcx ty::TypeckTables<'tcx> {
desc { |tcx| "type-checking `{}`", tcx.def_path_str(key.to_def_id()) }
query typeck_tables_of(key: ty::WithOptParam<LocalDefId>) -> &'tcx ty::TypeckTables<'tcx> {
desc { |tcx| "type-checking `{}`", tcx.def_path_str(key.did.to_def_id()) }
cache_on_disk_if { true }
}
query diagnostic_only_typeck_tables_of(key: LocalDefId) -> &'tcx ty::TypeckTables<'tcx> {
Expand Down Expand Up @@ -568,11 +587,11 @@ rustc_queries! {
BorrowChecking {
/// Borrow-checks the function body. If this is a closure, returns
/// additional requirements that the closure's creator must verify.
query mir_borrowck(key: LocalDefId) -> mir::BorrowCheckResult<'tcx> {
query mir_borrowck(key: ty::WithOptParam<LocalDefId>) -> mir::BorrowCheckResult<'tcx> {
storage(ArenaCacheSelector<'tcx>)
desc { |tcx| "borrow-checking `{}`", tcx.def_path_str(key.to_def_id()) }
desc { |tcx| "borrow-checking `{}`", tcx.def_path_str(key.did.to_def_id()) }
cache_on_disk_if(tcx, opt_result) {
tcx.is_closure(key.to_def_id())
tcx.is_closure(key.did.to_def_id())
|| opt_result.map_or(false, |r| !r.concrete_opaque_types.is_empty())
}
}
Expand Down Expand Up @@ -1434,9 +1453,9 @@ rustc_queries! {
/// from `Ok(None)` to avoid misleading diagnostics when an error
/// has already been/will be emitted, for the original cause
query resolve_instance(
key: ty::ParamEnvAnd<'tcx, (DefId, SubstsRef<'tcx>)>
key: ty::ParamEnvAnd<'tcx, (ty::WithOptParam<DefId>, SubstsRef<'tcx>)>
) -> Result<Option<ty::Instance<'tcx>>, ErrorReported> {
desc { "resolving instance `{}`", ty::Instance::new(key.value.0, key.value.1) }
desc { "resolving instance `{}`", ty::Instance::new(key.value.0.did, key.value.1) }
}
}
}
Loading