Skip to content

Commit 69500f9

Browse files
committed
Do not try to reveal hidden types when trying to prove Freeze in the defining scope
1 parent e55d738 commit 69500f9

File tree

10 files changed

+52
-111
lines changed

10 files changed

+52
-111
lines changed

Diff for: compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs

+27-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,33 @@ impl Qualif for HasMutInterior {
9898
}
9999

100100
fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool {
101-
!ty.is_freeze(cx.tcx, cx.param_env)
101+
// Avoid selecting for simple cases, such as builtin types.
102+
if ty.is_trivially_freeze() {
103+
return false;
104+
}
105+
106+
// We do not use `ty.is_freeze` here, because that requires revealing opaque types, which
107+
// requires borrowck, which in turn will invoke mir_const_qualifs again, causing a cycle error.
108+
// Instead we invoke an obligation context manually, and provide the opaque type inference settings
109+
// that allow the trait solver to just error out instead of cycling.
110+
let freeze_def_id = cx.tcx.require_lang_item(LangItem::Freeze, Some(cx.body.span));
111+
112+
let obligation = Obligation::new(
113+
cx.tcx,
114+
ObligationCause::dummy_with_span(cx.body.span),
115+
cx.param_env,
116+
ty::TraitRef::new(cx.tcx, freeze_def_id, [ty::GenericArg::from(ty)]),
117+
);
118+
119+
let infcx = cx
120+
.tcx
121+
.infer_ctxt()
122+
.with_opaque_type_inference(cx.body.source.def_id().expect_local())
123+
.build();
124+
let ocx = ObligationCtxt::new(&infcx);
125+
ocx.register_obligation(obligation);
126+
let errors = ocx.select_all_or_error();
127+
!errors.is_empty()
102128
}
103129

104130
fn in_adt_inherently<'tcx>(

Diff for: compiler/rustc_errors/src/lib.rs

+1-7
Original file line numberDiff line numberDiff line change
@@ -768,13 +768,7 @@ impl DiagCtxt {
768768
format!("invalid level in `stash_diagnostic`: {:?}", diag.level),
769769
);
770770
}
771-
Error => {
772-
// This `unchecked_error_guaranteed` is valid. It is where the
773-
// `ErrorGuaranteed` for stashed errors originates. See
774-
// `DiagCtxtInner::drop`.
775-
#[allow(deprecated)]
776-
Some(ErrorGuaranteed::unchecked_error_guaranteed())
777-
}
771+
Error => Some(self.span_delayed_bug(span, "stashing {key:?}")),
778772
DelayedBug => return self.inner.borrow_mut().emit_diagnostic(diag),
779773
ForceWarning(_) | Warning | Note | OnceNote | Help | OnceHelp | FailureNote | Allow
780774
| Expect(_) => None,

Diff for: compiler/rustc_middle/src/ty/util.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1191,7 +1191,7 @@ impl<'tcx> Ty<'tcx> {
11911191
///
11921192
/// Returning true means the type is known to be `Freeze`. Returning
11931193
/// `false` means nothing -- could be `Freeze`, might not be.
1194-
fn is_trivially_freeze(self) -> bool {
1194+
pub fn is_trivially_freeze(self) -> bool {
11951195
match self.kind() {
11961196
ty::Int(_)
11971197
| ty::Uint(_)

Diff for: compiler/rustc_trait_selection/src/traits/select/mod.rs

+14-7
Original file line numberDiff line numberDiff line change
@@ -2337,13 +2337,20 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
23372337
}
23382338

23392339
ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
2340-
// We can resolve the `impl Trait` to its concrete type,
2341-
// which enforces a DAG between the functions requiring
2342-
// the auto trait bounds in question.
2343-
match self.tcx().type_of_opaque(def_id) {
2344-
Ok(ty) => t.rebind(vec![ty.instantiate(self.tcx(), args)]),
2345-
Err(_) => {
2346-
return Err(SelectionError::OpaqueTypeAutoTraitLeakageUnknown(def_id));
2340+
if let Some(local) = def_id.as_local()
2341+
&& self.infcx.opaque_type_origin(local).is_some()
2342+
{
2343+
// We cannot possibly resolve this opaque type, because we are currently computing its hidden type.
2344+
return Err(SelectionError::OpaqueTypeAutoTraitLeakageUnknown(def_id));
2345+
} else {
2346+
// We can resolve the `impl Trait` to its concrete type,
2347+
// which enforces a DAG between the functions requiring
2348+
// the auto trait bounds in question.
2349+
match self.tcx().type_of_opaque(def_id) {
2350+
Ok(ty) => t.rebind(vec![ty.instantiate(self.tcx(), args)]),
2351+
Err(_) => {
2352+
return Err(SelectionError::OpaqueTypeAutoTraitLeakageUnknown(def_id));
2353+
}
23472354
}
23482355
}
23492356
}

Diff for: tests/ui/impl-trait/rpit/const_check_false_cycle.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
//! This test causes a cycle error when checking whether the
1+
//! This test caused a cycle error when checking whether the
22
//! return type is `Freeze` during const checking, even though
33
//! the information is readily available.
44
5+
//@ check-pass
6+
57
const fn f() -> impl Eq {
6-
//~^ ERROR cycle detected
78
g()
89
}
910
const fn g() {}

Diff for: tests/ui/impl-trait/rpit/const_check_false_cycle.stderr

-34
This file was deleted.

Diff for: tests/ui/rfcs/rfc-2632-const-trait-impl/effects/ice-112822-expected-type-for-param.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
#![feature(const_trait_impl, effects)]
22

33
const fn test() -> impl ~const Fn() { //~ ERROR `~const` can only be applied to `#[const_trait]` traits
4-
//~^ ERROR cycle detected
54
const move || { //~ ERROR const closures are experimental
65
let sl: &[u8] = b"foo";
76

Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0658]: const closures are experimental
2-
--> $DIR/ice-112822-expected-type-for-param.rs:5:5
2+
--> $DIR/ice-112822-expected-type-for-param.rs:4:5
33
|
44
LL | const move || {
55
| ^^^^^
@@ -15,46 +15,15 @@ LL | const fn test() -> impl ~const Fn() {
1515
| ^^^^
1616

1717
error[E0277]: can't compare `&u8` with `&u8`
18-
--> $DIR/ice-112822-expected-type-for-param.rs:10:17
18+
--> $DIR/ice-112822-expected-type-for-param.rs:9:17
1919
|
2020
LL | assert_eq!(first, &b'f');
2121
| ^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `&u8 == &u8`
2222
|
2323
= help: the trait `~const PartialEq<&u8>` is not implemented for `&u8`
2424
= note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
2525

26-
error[E0391]: cycle detected when computing type of opaque `test::{opaque#0}`
27-
--> $DIR/ice-112822-expected-type-for-param.rs:3:20
28-
|
29-
LL | const fn test() -> impl ~const Fn() {
30-
| ^^^^^^^^^^^^^^^^
31-
|
32-
note: ...which requires borrow-checking `test`...
33-
--> $DIR/ice-112822-expected-type-for-param.rs:3:1
34-
|
35-
LL | const fn test() -> impl ~const Fn() {
36-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
37-
note: ...which requires promoting constants in MIR for `test`...
38-
--> $DIR/ice-112822-expected-type-for-param.rs:3:1
39-
|
40-
LL | const fn test() -> impl ~const Fn() {
41-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
42-
note: ...which requires const checking `test`...
43-
--> $DIR/ice-112822-expected-type-for-param.rs:3:1
44-
|
45-
LL | const fn test() -> impl ~const Fn() {
46-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
47-
= note: ...which requires computing whether `test::{opaque#0}` is freeze...
48-
= note: ...which requires evaluating trait selection obligation `test::{opaque#0}: core::marker::Freeze`...
49-
= note: ...which again requires computing type of opaque `test::{opaque#0}`, completing the cycle
50-
note: cycle used when computing type of `test::{opaque#0}`
51-
--> $DIR/ice-112822-expected-type-for-param.rs:3:20
52-
|
53-
LL | const fn test() -> impl ~const Fn() {
54-
| ^^^^^^^^^^^^^^^^
55-
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
56-
57-
error: aborting due to 4 previous errors
26+
error: aborting due to 3 previous errors
5827

59-
Some errors have detailed explanations: E0277, E0391, E0658.
28+
Some errors have detailed explanations: E0277, E0658.
6029
For more information about an error, try `rustc --explain E0277`.

Diff for: tests/ui/type-alias-impl-trait/in-where-clause.rs

-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
#![feature(type_alias_impl_trait)]
55
type Bar = impl Sized;
66
//~^ ERROR: cycle
7-
//~| ERROR: cycle
87

98
fn foo() -> Bar
109
where

Diff for: tests/ui/type-alias-impl-trait/in-where-clause.stderr

+2-22
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ note: ...which requires computing type of opaque `Bar::{opaque#0}`...
1010
LL | type Bar = impl Sized;
1111
| ^^^^^^^^^^
1212
note: ...which requires type-checking `foo`...
13-
--> $DIR/in-where-clause.rs:9:1
13+
--> $DIR/in-where-clause.rs:8:1
1414
|
1515
LL | / fn foo() -> Bar
1616
LL | | where
@@ -25,26 +25,6 @@ LL | type Bar = impl Sized;
2525
| ^^^^^^^^^^
2626
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
2727

28-
error[E0391]: cycle detected when computing type of opaque `Bar::{opaque#0}`
29-
--> $DIR/in-where-clause.rs:5:12
30-
|
31-
LL | type Bar = impl Sized;
32-
| ^^^^^^^^^^
33-
|
34-
note: ...which requires type-checking `foo`...
35-
--> $DIR/in-where-clause.rs:13:9
36-
|
37-
LL | [0; 1 + 2]
38-
| ^^^^^
39-
= note: ...which requires evaluating trait selection obligation `Bar: core::marker::Send`...
40-
= note: ...which again requires computing type of opaque `Bar::{opaque#0}`, completing the cycle
41-
note: cycle used when computing type of `Bar::{opaque#0}`
42-
--> $DIR/in-where-clause.rs:5:12
43-
|
44-
LL | type Bar = impl Sized;
45-
| ^^^^^^^^^^
46-
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
47-
48-
error: aborting due to 2 previous errors
28+
error: aborting due to 1 previous error
4929

5030
For more information about this error, try `rustc --explain E0391`.

0 commit comments

Comments
 (0)