Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Rollup of 10 pull requests #133770

Merged
merged 28 commits into from
Dec 3, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
41c3b5c
show forbidden_lint_groups in future-compat reports
RalfJung Nov 27, 2024
20630c5
add "profiler" option coverage for ci-rustc
onur-ozkan Dec 1, 2024
a17294d
fix ICE when promoted has layout size overflow
RalfJung Dec 1, 2024
85e4765
Add specific test for check-cfg "and X more" diagnostic
Urgau Nov 29, 2024
1c4657d
compiletest: un-escape new-line in normalize replacement string
Urgau Dec 1, 2024
d37ed10
Fix crash with `-Zdump-mir-dataflow`
nnethercote Nov 28, 2024
9f2f690
Add test for `-Zdump-mir-dataflow`.
nnethercote Dec 1, 2024
cecef13
Simplify `ResultsHandle`.
nnethercote Dec 1, 2024
99e726b
add "optimized-compiler-builtins" option coverage for ci-rustc
onur-ozkan Dec 2, 2024
778321d
Change `AttrArgs::Eq` into a struct variant
oli-obk Dec 2, 2024
c0b5322
Add a helper method for extracting spans from AttrArgsEq
oli-obk Dec 2, 2024
da182b6
Deduplicate some matches that always panic in one arm
oli-obk Dec 2, 2024
43bed16
Reduce conflicts for check-cfg `target_feature` cfg values
Urgau Dec 1, 2024
72297d4
Fix `f16::midpoint` const feature gate
Urgau Dec 2, 2024
eadea77
Use c"lit" for CStrings without unwrap
kornelski Nov 30, 2024
c5fedc2
Stabilize `const_maybe_uninit_write`
tgross35 Oct 14, 2024
277e049
Move `Const::{from_anon_const,try_from_lit}` to hir_ty_lowering
camelid Nov 29, 2024
dcf332b
Fix broken intra-doc link
camelid Nov 29, 2024
e56e685
Rollup merge of #131713 - tgross35:stabilize-const_maybe_uninit_write…
GuillaumeGomez Dec 2, 2024
f79e09c
Rollup merge of #133535 - RalfJung:forbidden_lint_groups-future-compa…
GuillaumeGomez Dec 2, 2024
6f0d15a
Rollup merge of #133610 - camelid:move-from_anon_const, r=BoxyUwU
GuillaumeGomez Dec 2, 2024
65b0dad
Rollup merge of #133701 - kornelski:c-str, r=workingjubilee
GuillaumeGomez Dec 2, 2024
b1a643e
Rollup merge of #133704 - RalfJung:promoted-size-overflow-ice, r=comp…
GuillaumeGomez Dec 2, 2024
7d67af9
Rollup merge of #133705 - onur-ozkan:profiler-check, r=jieyouxu
GuillaumeGomez Dec 2, 2024
8a26a8b
Rollup merge of #133710 - Urgau:target_feature-merge-conflitcs, r=jie…
GuillaumeGomez Dec 2, 2024
3586e4a
Rollup merge of #133732 - nnethercote:fix-Z-dump-mir-dataflow, r=comp…
GuillaumeGomez Dec 2, 2024
6f9f17f
Rollup merge of #133746 - oli-obk:push-xwyrylxmrtvq, r=jieyouxu
GuillaumeGomez Dec 2, 2024
73f225a
Rollup merge of #133763 - Urgau:f16-midpoint-const-feat, r=Amanieu
GuillaumeGomez Dec 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 8 additions & 13 deletions compiler/rustc_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use rustc_hir::lang_items::LangItem;
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
use rustc_macros::LintDiagnostic;
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::query::Providers;
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::trait_def::TraitSpecializationKind;
Expand Down Expand Up @@ -1170,19 +1171,13 @@ fn check_type_defn<'tcx>(

// Explicit `enum` discriminant values must const-evaluate successfully.
if let ty::VariantDiscr::Explicit(discr_def_id) = variant.discr {
let cause = traits::ObligationCause::new(
tcx.def_span(discr_def_id),
wfcx.body_def_id,
ObligationCauseCode::Misc,
);
wfcx.register_obligation(Obligation::new(
tcx,
cause,
wfcx.param_env,
ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(
ty::Const::from_anon_const(tcx, discr_def_id.expect_local()),
))),
));
match tcx.const_eval_poly(discr_def_id) {
Ok(_) => {}
Err(ErrorHandled::Reported(..)) => {}
Err(ErrorHandled::TooGeneric(sp)) => {
span_bug!(sp, "enum variant discr was too generic to eval")
}
}
}
}

Expand Down
11 changes: 6 additions & 5 deletions compiler/rustc_hir_analysis/src/collect/dump.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId};
use rustc_hir::intravisit;
use rustc_middle::hir::nested_filter::OnlyBodies;
use rustc_middle::hir::nested_filter;
use rustc_middle::ty::TyCtxt;
use rustc_span::sym;

Expand Down Expand Up @@ -42,15 +42,16 @@ pub(crate) fn predicates_and_item_bounds(tcx: TyCtxt<'_>) {
}

pub(crate) fn def_parents(tcx: TyCtxt<'_>) {
for did in tcx.hir().body_owners() {
for iid in tcx.hir().items() {
let did = iid.owner_id.def_id;
if tcx.has_attr(did, sym::rustc_dump_def_parents) {
struct AnonConstFinder<'tcx> {
tcx: TyCtxt<'tcx>,
anon_consts: Vec<LocalDefId>,
}

impl<'tcx> intravisit::Visitor<'tcx> for AnonConstFinder<'tcx> {
type NestedFilter = OnlyBodies;
type NestedFilter = nested_filter::All;

fn nested_visit_map(&mut self) -> Self::Map {
self.tcx.hir()
Expand All @@ -62,11 +63,11 @@ pub(crate) fn def_parents(tcx: TyCtxt<'_>) {
}
}

// Look for any anon consts inside of this body owner as there is no way to apply
// Look for any anon consts inside of this item as there is no way to apply
// the `rustc_dump_def_parents` attribute to the anon const so it would not be possible
// to see what its def parent is.
let mut anon_ct_finder = AnonConstFinder { tcx, anon_consts: vec![] };
intravisit::walk_expr(&mut anon_ct_finder, tcx.hir().body_owned_by(did).value);
intravisit::walk_item(&mut anon_ct_finder, tcx.hir().item(iid));

for did in [did].into_iter().chain(anon_ct_finder.anon_consts) {
let span = tcx.def_span(did);
Expand Down
96 changes: 58 additions & 38 deletions compiler/rustc_hir_analysis/src/collect/predicates_of.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
use std::assert_matches::assert_matches;

use hir::{HirId, Node};
use hir::Node;
use rustc_data_structures::fx::FxIndexSet;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::{self, Visitor};
use rustc_middle::ty::{self, GenericPredicates, ImplTraitInTraitData, Ty, TyCtxt, Upcast};
use rustc_middle::ty::{
self, GenericPredicates, ImplTraitInTraitData, Ty, TyCtxt, TypeVisitable, TypeVisitor, Upcast,
};
use rustc_middle::{bug, span_bug};
use rustc_span::symbol::Ident;
use rustc_span::{DUMMY_SP, Span};
Expand Down Expand Up @@ -305,7 +306,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
}

if tcx.features().generic_const_exprs() {
predicates.extend(const_evaluatable_predicates_of(tcx, def_id));
predicates.extend(const_evaluatable_predicates_of(tcx, def_id, &predicates));
}

let mut predicates: Vec<_> = predicates.into_iter().collect();
Expand Down Expand Up @@ -369,61 +370,80 @@ fn compute_bidirectional_outlives_predicates<'tcx>(
}
}

fn const_evaluatable_predicates_of(
tcx: TyCtxt<'_>,
#[instrument(level = "debug", skip(tcx, predicates), ret)]
fn const_evaluatable_predicates_of<'tcx>(
tcx: TyCtxt<'tcx>,
def_id: LocalDefId,
) -> FxIndexSet<(ty::Clause<'_>, Span)> {
predicates: &FxIndexSet<(ty::Clause<'tcx>, Span)>,
) -> FxIndexSet<(ty::Clause<'tcx>, Span)> {
struct ConstCollector<'tcx> {
tcx: TyCtxt<'tcx>,
preds: FxIndexSet<(ty::Clause<'tcx>, Span)>,
}

impl<'tcx> intravisit::Visitor<'tcx> for ConstCollector<'tcx> {
fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) {
let ct = ty::Const::from_anon_const(self.tcx, c.def_id);
if let ty::ConstKind::Unevaluated(_) = ct.kind() {
let span = self.tcx.def_span(c.def_id);
self.preds.insert((ty::ClauseKind::ConstEvaluatable(ct).upcast(self.tcx), span));
}
}
fn is_const_param_default(tcx: TyCtxt<'_>, def: LocalDefId) -> bool {
let hir_id = tcx.local_def_id_to_hir_id(def);
let (_, parent_node) = tcx
.hir()
.parent_iter(hir_id)
.skip_while(|(_, n)| matches!(n, Node::ConstArg(..)))
.next()
.unwrap();
matches!(
parent_node,
Node::GenericParam(hir::GenericParam { kind: hir::GenericParamKind::Const { .. }, .. })
)
}

fn visit_const_param_default(&mut self, _param: HirId, _ct: &'tcx hir::ConstArg<'tcx>) {
// Do not look into const param defaults,
// these get checked when they are actually instantiated.
//
// We do not want the following to error:
//
// struct Foo<const N: usize, const M: usize = { N + 1 }>;
// struct Bar<const N: usize>(Foo<N, 3>);
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ConstCollector<'tcx> {
fn visit_const(&mut self, c: ty::Const<'tcx>) {
if let ty::ConstKind::Unevaluated(uv) = c.kind() {
if is_const_param_default(self.tcx, uv.def.expect_local()) {
// Do not look into const param defaults,
// these get checked when they are actually instantiated.
//
// We do not want the following to error:
//
// struct Foo<const N: usize, const M: usize = { N + 1 }>;
// struct Bar<const N: usize>(Foo<N, 3>);
return;
}

let span = self.tcx.def_span(uv.def);
self.preds.insert((ty::ClauseKind::ConstEvaluatable(c).upcast(self.tcx), span));
}
}
}

let hir_id = tcx.local_def_id_to_hir_id(def_id);
let node = tcx.hir_node(hir_id);

let mut collector = ConstCollector { tcx, preds: FxIndexSet::default() };

for (clause, _sp) in predicates {
clause.visit_with(&mut collector);
}

if let hir::Node::Item(item) = node
&& let hir::ItemKind::Impl(impl_) = item.kind
&& let hir::ItemKind::Impl(_) = item.kind
{
if let Some(of_trait) = &impl_.of_trait {
debug!("const_evaluatable_predicates_of({:?}): visit impl trait_ref", def_id);
collector.visit_trait_ref(of_trait);
if let Some(of_trait) = tcx.impl_trait_ref(def_id) {
debug!("visit impl trait_ref");
of_trait.instantiate_identity().visit_with(&mut collector);
}

debug!("const_evaluatable_predicates_of({:?}): visit_self_ty", def_id);
collector.visit_ty(impl_.self_ty);
}

if let Some(generics) = node.generics() {
debug!("const_evaluatable_predicates_of({:?}): visit_generics", def_id);
collector.visit_generics(generics);
debug!("visit self_ty");
let self_ty = tcx.type_of(def_id);
self_ty.instantiate_identity().visit_with(&mut collector);
}

if let Some(fn_sig) = tcx.hir().fn_sig_by_hir_id(hir_id) {
debug!("const_evaluatable_predicates_of({:?}): visit_fn_decl", def_id);
collector.visit_fn_decl(fn_sig.decl);
if let Some(_) = tcx.hir().fn_sig_by_hir_id(hir_id) {
debug!("visit fn sig");
let fn_sig = tcx.fn_sig(def_id);
let fn_sig = fn_sig.instantiate_identity();
debug!(?fn_sig);
fn_sig.visit_with(&mut collector);
}
debug!("const_evaluatable_predicates_of({:?}) = {:?}", def_id, collector.preds);

collector.preds
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -703,7 +703,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
///
/// It might actually be possible that we can already support early-bound generic params
/// in such types if we just lifted some more checks in other places, too, for example
/// inside [`ty::Const::from_anon_const`]. However, even if that were the case, we should
/// inside `HirTyLowerer::lower_anon_const`. However, even if that were the case, we should
/// probably gate this behind another feature flag.
///
/// [^1]: <https://github.com/rust-lang/project-const-generics/issues/28>.
Expand Down
88 changes: 87 additions & 1 deletion compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2089,7 +2089,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
qpath.span(),
format!("Const::lower_const_arg: invalid qpath {qpath:?}"),
),
hir::ConstArgKind::Anon(anon) => Const::from_anon_const(tcx, anon.def_id),
hir::ConstArgKind::Anon(anon) => self.lower_anon_const(anon.def_id),
hir::ConstArgKind::Infer(span) => self.ct_infer(None, span),
}
}
Expand Down Expand Up @@ -2177,6 +2177,92 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
}
}

/// Literals and const generic parameters are eagerly converted to a constant, everything else
/// becomes `Unevaluated`.
#[instrument(skip(self), level = "debug")]
fn lower_anon_const(&self, def: LocalDefId) -> Const<'tcx> {
let tcx = self.tcx();

let body_id = match tcx.hir_node_by_def_id(def) {
hir::Node::AnonConst(ac) => ac.body,
node => span_bug!(
tcx.def_span(def.to_def_id()),
"from_anon_const can only process anonymous constants, not {node:?}"
),
};

let expr = &tcx.hir().body(body_id).value;
debug!(?expr);

let ty = tcx.type_of(def).no_bound_vars().expect("const parameter types cannot be generic");

match self.try_lower_anon_const_lit(ty, expr) {
Some(v) => v,
None => ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst {
def: def.to_def_id(),
args: ty::GenericArgs::identity_for_item(tcx, def.to_def_id()),
}),
}
}

#[instrument(skip(self), level = "debug")]
fn try_lower_anon_const_lit(
&self,
ty: Ty<'tcx>,
expr: &'tcx hir::Expr<'tcx>,
) -> Option<Const<'tcx>> {
let tcx = self.tcx();

// Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments
// currently have to be wrapped in curly brackets, so it's necessary to special-case.
let expr = match &expr.kind {
hir::ExprKind::Block(block, _) if block.stmts.is_empty() && block.expr.is_some() => {
block.expr.as_ref().unwrap()
}
_ => expr,
};

if let hir::ExprKind::Path(hir::QPath::Resolved(
_,
&hir::Path { res: Res::Def(DefKind::ConstParam, _), .. },
)) = expr.kind
{
span_bug!(
expr.span,
"try_lower_anon_const_lit: received const param which shouldn't be possible"
);
};

let lit_input = match expr.kind {
hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }),
hir::ExprKind::Unary(hir::UnOp::Neg, expr) => match expr.kind {
hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: true }),
_ => None,
},
_ => None,
};

if let Some(lit_input) = lit_input {
// If an error occurred, ignore that it's a literal and leave reporting the error up to
// mir.
match tcx.at(expr.span).lit_to_const(lit_input) {
Ok(c) => return Some(c),
Err(_) if lit_input.ty.has_aliases() => {
// allow the `ty` to be an alias type, though we cannot handle it here
return None;
}
Err(e) => {
tcx.dcx().span_delayed_bug(
expr.span,
format!("try_lower_anon_const_lit: couldn't lit_to_const {e:?}"),
);
}
}
}

None
}

fn lower_delegation_ty(&self, idx: hir::InferDelegationKind) -> Ty<'tcx> {
let delegation_sig = self.tcx().inherit_sig_for_delegation_item(self.item_def_id());
match idx {
Expand Down
Loading