Skip to content

Support const args in type dependent paths #71154

New issue

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

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

Already on GitHub? # to your account

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))
}
}

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