Skip to content

Commit ee8efc5

Browse files
committed
Coalesce branches
Move a bunch of branches together into one if block, for easier reading. Resolve comments Attempt to make some branches unreachable [tmp] Revert unreachable branches
1 parent edae6ed commit ee8efc5

File tree

2 files changed

+133
-137
lines changed

2 files changed

+133
-137
lines changed

compiler/rustc_trait_selection/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#![feature(label_break_value)]
2222
#![feature(let_chains)]
2323
#![feature(let_else)]
24+
#![feature(if_let_guard)]
2425
#![feature(never_type)]
2526
#![recursion_limit = "512"] // For rustdoc
2627

compiler/rustc_trait_selection/src/traits/const_evaluatable.rs

+132-137
Original file line numberDiff line numberDiff line change
@@ -39,153 +39,148 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
3939
let tcx = infcx.tcx;
4040

4141
if tcx.features().generic_const_exprs {
42-
match AbstractConst::new(tcx, uv)? {
43-
// We are looking at a generic abstract constant.
44-
Some(ct) => {
45-
if satisfied_from_param_env(tcx, ct, param_env)? {
46-
return Ok(());
47-
}
48-
49-
// We were unable to unify the abstract constant with
50-
// a constant found in the caller bounds, there are
51-
// now three possible cases here.
52-
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
53-
enum FailureKind {
54-
/// The abstract const still references an inference
55-
/// variable, in this case we return `TooGeneric`.
56-
MentionsInfer,
57-
/// The abstract const references a generic parameter,
58-
/// this means that we emit an error here.
59-
MentionsParam,
60-
/// The substs are concrete enough that we can simply
61-
/// try and evaluate the given constant.
62-
Concrete,
63-
}
64-
let mut failure_kind = FailureKind::Concrete;
65-
walk_abstract_const::<!, _>(tcx, ct, |node| match node.root(tcx) {
66-
Node::Leaf(leaf) => {
67-
if leaf.has_infer_types_or_consts() {
68-
failure_kind = FailureKind::MentionsInfer;
69-
} else if leaf.has_param_types_or_consts() {
70-
failure_kind = cmp::min(failure_kind, FailureKind::MentionsParam);
71-
}
72-
73-
ControlFlow::CONTINUE
42+
if let Some(ct) = AbstractConst::new(tcx, uv)? {
43+
if satisfied_from_param_env(tcx, ct, param_env)? {
44+
return Ok(());
45+
}
46+
47+
// We were unable to unify the abstract constant with
48+
// a constant found in the caller bounds, there are
49+
// now three possible cases here.
50+
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
51+
enum FailureKind {
52+
/// The abstract const still references an inference
53+
/// variable, in this case we return `TooGeneric`.
54+
MentionsInfer,
55+
/// The abstract const references a generic parameter,
56+
/// this means that we emit an error here.
57+
MentionsParam,
58+
/// The substs are concrete enough that we can simply
59+
/// try and evaluate the given constant.
60+
Concrete,
61+
}
62+
let mut failure_kind = FailureKind::Concrete;
63+
walk_abstract_const::<!, _>(tcx, ct, |node| match node.root(tcx) {
64+
Node::Leaf(leaf) => {
65+
if leaf.has_infer_types_or_consts() {
66+
failure_kind = FailureKind::MentionsInfer;
67+
} else if leaf.has_param_types_or_consts() {
68+
failure_kind = cmp::min(failure_kind, FailureKind::MentionsParam);
7469
}
75-
Node::Cast(_, _, ty) => {
76-
if ty.has_infer_types_or_consts() {
77-
failure_kind = FailureKind::MentionsInfer;
78-
} else if ty.has_param_types_or_consts() {
79-
failure_kind = cmp::min(failure_kind, FailureKind::MentionsParam);
80-
}
8170

82-
ControlFlow::CONTINUE
83-
}
84-
Node::Binop(_, _, _) | Node::UnaryOp(_, _) | Node::FunctionCall(_, _) => {
85-
ControlFlow::CONTINUE
71+
ControlFlow::CONTINUE
72+
}
73+
Node::Cast(_, _, ty) => {
74+
if ty.has_infer_types_or_consts() {
75+
failure_kind = FailureKind::MentionsInfer;
76+
} else if ty.has_param_types_or_consts() {
77+
failure_kind = cmp::min(failure_kind, FailureKind::MentionsParam);
8678
}
87-
});
8879

89-
match failure_kind {
90-
FailureKind::MentionsInfer => {
91-
return Err(NotConstEvaluatable::MentionsInfer);
92-
}
93-
FailureKind::MentionsParam => {
94-
return Err(NotConstEvaluatable::MentionsParam);
95-
}
96-
FailureKind::Concrete => {
97-
// Dealt with below by the same code which handles this
98-
// without the feature gate.
99-
}
80+
ControlFlow::CONTINUE
10081
}
101-
}
102-
None => {
103-
// If we are dealing with a concrete constant, we can
104-
// reuse the old code path and try to evaluate
105-
// the constant.
106-
}
107-
}
108-
}
82+
Node::Binop(_, _, _) | Node::UnaryOp(_, _) | Node::FunctionCall(_, _) => {
83+
ControlFlow::CONTINUE
84+
}
85+
});
10986

110-
let future_compat_lint = || {
111-
if tcx.features().generic_const_exprs {
112-
return;
113-
}
114-
if let Some(local_def_id) = uv.def.did.as_local() {
115-
infcx.tcx.struct_span_lint_hir(
116-
lint::builtin::CONST_EVALUATABLE_UNCHECKED,
117-
infcx.tcx.hir().local_def_id_to_hir_id(local_def_id),
118-
span,
119-
|err| {
120-
err.build("cannot use constants which depend on generic parameters in types")
121-
.emit();
122-
},
123-
);
124-
}
125-
};
126-
127-
// FIXME: We should only try to evaluate a given constant here if it is fully concrete
128-
// as we don't want to allow things like `[u8; std::mem::size_of::<*mut T>()]`.
129-
//
130-
// We previously did not check this, so we only emit a future compat warning if
131-
// const evaluation succeeds and the given constant is still polymorphic for now
132-
// and hopefully soon change this to an error.
133-
//
134-
// See #74595 for more details about this.
135-
let concrete = infcx.const_eval_resolve(param_env, uv.expand(), Some(span));
136-
137-
if concrete.is_ok() && uv.substs.has_param_types_or_consts() {
138-
match infcx.tcx.def_kind(uv.def.did) {
139-
DefKind::AnonConst | DefKind::InlineConst => {
140-
let mir_body = infcx.tcx.mir_for_ctfe_opt_const_arg(uv.def);
141-
142-
if mir_body.is_polymorphic {
143-
future_compat_lint();
87+
match failure_kind {
88+
FailureKind::MentionsInfer => {
89+
return Err(NotConstEvaluatable::MentionsInfer);
90+
}
91+
FailureKind::MentionsParam => {
92+
return Err(NotConstEvaluatable::MentionsParam);
14493
}
94+
// returned below
95+
FailureKind::Concrete => {}
14596
}
146-
_ => future_compat_lint(),
14797
}
148-
}
149-
150-
// If we're evaluating a foreign constant, under a nightly compiler without generic
151-
// const exprs, AND it would've passed if that expression had been evaluated with
152-
// generic const exprs, then suggest using generic const exprs.
153-
if concrete.is_err()
154-
&& tcx.sess.is_nightly_build()
155-
&& !uv.def.did.is_local()
156-
&& !tcx.features().generic_const_exprs
157-
&& let Ok(Some(ct)) = AbstractConst::new(tcx, uv)
158-
&& satisfied_from_param_env(tcx, ct, param_env) == Ok(true)
159-
{
160-
tcx.sess
161-
.struct_span_fatal(
162-
// Slightly better span than just using `span` alone
163-
if span == rustc_span::DUMMY_SP { tcx.def_span(uv.def.did) } else { span },
164-
"failed to evaluate generic const expression",
165-
)
166-
.note("the crate this constant originates from uses `#![feature(generic_const_exprs)]`")
167-
.span_suggestion_verbose(
168-
rustc_span::DUMMY_SP,
169-
"consider enabling this feature",
170-
"#![feature(generic_const_exprs)]\n".to_string(),
171-
rustc_errors::Applicability::MaybeIncorrect,
172-
)
173-
.emit()
174-
}
175-
176-
debug!(?concrete, "is_const_evaluatable");
177-
match concrete {
178-
Err(ErrorHandled::TooGeneric) => Err(match uv.has_infer_types_or_consts() {
179-
true => NotConstEvaluatable::MentionsInfer,
180-
false => NotConstEvaluatable::MentionsParam,
181-
}),
182-
Err(ErrorHandled::Linted) => {
183-
let reported =
184-
infcx.tcx.sess.delay_span_bug(span, "constant in type had error reported as lint");
185-
Err(NotConstEvaluatable::Error(reported))
98+
let concrete = infcx.const_eval_resolve(param_env, uv.expand(), Some(span));
99+
match concrete {
100+
Err(ErrorHandled::TooGeneric) => Err(if !uv.has_infer_types_or_consts() {
101+
infcx
102+
.tcx
103+
.sess
104+
.delay_span_bug(span, &format!("unexpected `TooGeneric` for {:?}", uv));
105+
NotConstEvaluatable::MentionsParam
106+
} else {
107+
NotConstEvaluatable::MentionsInfer
108+
}),
109+
Err(ErrorHandled::Linted) => {
110+
let reported = infcx
111+
.tcx
112+
.sess
113+
.delay_span_bug(span, "constant in type had error reported as lint");
114+
Err(NotConstEvaluatable::Error(reported))
115+
}
116+
Err(ErrorHandled::Reported(e)) => Err(NotConstEvaluatable::Error(e)),
117+
Ok(_) => Ok(()),
118+
}
119+
} else {
120+
// FIXME: We should only try to evaluate a given constant here if it is fully concrete
121+
// as we don't want to allow things like `[u8; std::mem::size_of::<*mut T>()]`.
122+
//
123+
// We previously did not check this, so we only emit a future compat warning if
124+
// const evaluation succeeds and the given constant is still polymorphic for now
125+
// and hopefully soon change this to an error.
126+
//
127+
// See #74595 for more details about this.
128+
let concrete = infcx.const_eval_resolve(param_env, uv.expand(), Some(span));
129+
130+
match concrete {
131+
// If we're evaluating a foreign constant, under a nightly compiler without generic
132+
// const exprs, AND it would've passed if that expression had been evaluated with
133+
// generic const exprs, then suggest using generic const exprs.
134+
Err(_) if tcx.sess.is_nightly_build()
135+
&& let Ok(Some(ct)) = AbstractConst::new(tcx, uv)
136+
&& satisfied_from_param_env(tcx, ct, param_env) == Ok(true) => {
137+
tcx.sess
138+
.struct_span_fatal(
139+
// Slightly better span than just using `span` alone
140+
if span == rustc_span::DUMMY_SP { tcx.def_span(uv.def.did) } else { span },
141+
"failed to evaluate generic const expression",
142+
)
143+
.note("the crate this constant originates from uses `#![feature(generic_const_exprs)]`")
144+
.span_suggestion_verbose(
145+
rustc_span::DUMMY_SP,
146+
"consider enabling this feature",
147+
"#![feature(generic_const_exprs)]\n".to_string(),
148+
rustc_errors::Applicability::MaybeIncorrect,
149+
)
150+
.emit()
151+
}
152+
153+
Err(ErrorHandled::TooGeneric) => Err(if uv.has_infer_types_or_consts() {
154+
NotConstEvaluatable::MentionsInfer
155+
} else {
156+
NotConstEvaluatable::MentionsParam
157+
}),
158+
Err(ErrorHandled::Linted) => {
159+
let reported =
160+
infcx.tcx.sess.delay_span_bug(span, "constant in type had error reported as lint");
161+
Err(NotConstEvaluatable::Error(reported))
162+
}
163+
Err(ErrorHandled::Reported(e)) => Err(NotConstEvaluatable::Error(e)),
164+
Ok(_) => {
165+
if uv.substs.has_param_types_or_consts() {
166+
assert!(matches!(infcx.tcx.def_kind(uv.def.did), DefKind::AnonConst));
167+
let mir_body = infcx.tcx.mir_for_ctfe_opt_const_arg(uv.def);
168+
169+
if mir_body.is_polymorphic {
170+
let Some(local_def_id) = uv.def.did.as_local() else { return Ok(()) };
171+
tcx.struct_span_lint_hir(
172+
lint::builtin::CONST_EVALUATABLE_UNCHECKED,
173+
tcx.hir().local_def_id_to_hir_id(local_def_id),
174+
span,
175+
|err| {
176+
err.build("cannot use constants which depend on generic parameters in types").emit();
177+
})
178+
}
179+
}
180+
181+
Ok(())
182+
},
186183
}
187-
Err(ErrorHandled::Reported(e)) => Err(NotConstEvaluatable::Error(e)),
188-
Ok(_) => Ok(()),
189184
}
190185
}
191186

0 commit comments

Comments
 (0)