Skip to content

Commit 136dfc1

Browse files
committed
Auto merge of #80417 - Mark-Simulacrum:beta-next, r=Mark-Simulacrum
[beta] backports This backports the following to 1.49: * Revert change to trait evaluation order #80132 * Don't allow `const` to begin a nonterminal #80135 * Prevent caching normalization results with a cycle #80246 r? `@Mark-Simulacrum`
2 parents b0dc3c6 + 2f925da commit 136dfc1

16 files changed

+220
-27
lines changed

compiler/rustc_infer/src/traits/project.rs

+15-1
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ impl ProjectionCacheKey<'tcx> {
9090
pub enum ProjectionCacheEntry<'tcx> {
9191
InProgress,
9292
Ambiguous,
93+
Recur,
9394
Error,
9495
NormalizedTy(NormalizedTy<'tcx>),
9596
}
@@ -143,7 +144,12 @@ impl<'tcx> ProjectionCache<'_, 'tcx> {
143144
"ProjectionCacheEntry::insert_ty: adding cache entry: key={:?}, value={:?}",
144145
key, value
145146
);
146-
let fresh_key = self.map().insert(key, ProjectionCacheEntry::NormalizedTy(value));
147+
let mut map = self.map();
148+
if let Some(ProjectionCacheEntry::Recur) = map.get(&key) {
149+
debug!("Not overwriting Recur");
150+
return;
151+
}
152+
let fresh_key = map.insert(key, ProjectionCacheEntry::NormalizedTy(value));
147153
assert!(!fresh_key, "never started projecting `{:?}`", key);
148154
}
149155

@@ -197,6 +203,14 @@ impl<'tcx> ProjectionCache<'_, 'tcx> {
197203
assert!(!fresh, "never started projecting `{:?}`", key);
198204
}
199205

206+
/// Indicates that while trying to normalize `key`, `key` was required to
207+
/// be normalized again. Selection or evaluation should eventually report
208+
/// an error here.
209+
pub fn recur(&mut self, key: ProjectionCacheKey<'tcx>) {
210+
let fresh = self.map().insert(key, ProjectionCacheEntry::Recur);
211+
assert!(!fresh, "never started projecting `{:?}`", key);
212+
}
213+
200214
/// Indicates that trying to normalize `key` resulted in
201215
/// error.
202216
pub fn error(&mut self, key: ProjectionCacheKey<'tcx>) {

compiler/rustc_parse/src/parser/nonterminal.rs

+2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ impl<'a> Parser<'a> {
2727
token.can_begin_expr()
2828
// This exception is here for backwards compatibility.
2929
&& !token.is_keyword(kw::Let)
30+
// This exception is here for backwards compatibility.
31+
&& !token.is_keyword(kw::Const)
3032
}
3133
NonterminalKind::Ty => token.can_begin_type(),
3234
NonterminalKind::Ident => get_macro_ident(token).is_some(),

compiler/rustc_trait_selection/src/traits/project.rs

+16-7
Original file line numberDiff line numberDiff line change
@@ -496,12 +496,6 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
496496
return Ok(None);
497497
}
498498
Err(ProjectionCacheEntry::InProgress) => {
499-
// If while normalized A::B, we are asked to normalize
500-
// A::B, just return A::B itself. This is a conservative
501-
// answer, in the sense that A::B *is* clearly equivalent
502-
// to A::B, though there may be a better value we can
503-
// find.
504-
505499
// Under lazy normalization, this can arise when
506500
// bootstrapping. That is, imagine an environment with a
507501
// where-clause like `A::B == u32`. Now, if we are asked
@@ -512,6 +506,14 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
512506

513507
debug!("found cache entry: in-progress");
514508

509+
// Cache that normalizing this projection resulted in a cycle. This
510+
// should ensure that, unless this happens within a snapshot that's
511+
// rolled back, fulfillment or evaluation will notice the cycle.
512+
513+
infcx.inner.borrow_mut().projection_cache().recur(cache_key);
514+
return Err(InProgress);
515+
}
516+
Err(ProjectionCacheEntry::Recur) => {
515517
return Err(InProgress);
516518
}
517519
Err(ProjectionCacheEntry::NormalizedTy(ty)) => {
@@ -734,7 +736,14 @@ fn project_type<'cx, 'tcx>(
734736

735737
if !selcx.tcx().sess.recursion_limit().value_within_limit(obligation.recursion_depth) {
736738
debug!("project: overflow!");
737-
return Err(ProjectionTyError::TraitSelectionError(SelectionError::Overflow));
739+
match selcx.query_mode() {
740+
super::TraitQueryMode::Standard => {
741+
selcx.infcx().report_overflow_error(&obligation, true);
742+
}
743+
super::TraitQueryMode::Canonical => {
744+
return Err(ProjectionTyError::TraitSelectionError(SelectionError::Overflow));
745+
}
746+
}
738747
}
739748

740749
let obligation_trait_ref = &obligation.predicate.trait_ref(selcx.tcx());

compiler/rustc_trait_selection/src/traits/select/confirmation.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
335335
fn vtable_impl(
336336
&mut self,
337337
impl_def_id: DefId,
338-
mut substs: Normalized<'tcx, SubstsRef<'tcx>>,
338+
substs: Normalized<'tcx, SubstsRef<'tcx>>,
339339
cause: ObligationCause<'tcx>,
340340
recursion_depth: usize,
341341
param_env: ty::ParamEnv<'tcx>,
@@ -357,9 +357,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
357357
// relying on projections in the impl-trait-ref.
358358
//
359359
// e.g., `impl<U: Tr, V: Iterator<Item=U>> Foo<<U as Tr>::T> for V`
360-
substs.obligations.append(&mut impl_obligations);
360+
impl_obligations.extend(substs.obligations);
361361

362-
ImplSourceUserDefinedData { impl_def_id, substs: substs.value, nested: substs.obligations }
362+
ImplSourceUserDefinedData { impl_def_id, substs: substs.value, nested: impl_obligations }
363363
}
364364

365365
fn confirm_object_candidate(

compiler/rustc_trait_selection/src/traits/select/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
290290
self.infcx.tcx
291291
}
292292

293+
pub(super) fn query_mode(&self) -> TraitQueryMode {
294+
self.query_mode
295+
}
296+
293297
///////////////////////////////////////////////////////////////////////////
294298
// Selection
295299
//

src/test/ui/associated-types/defaults-cyclic-fail-1.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,13 @@ impl Tr for u32 {
2424
// ...but not in an impl that redefines one of the types.
2525
impl Tr for bool {
2626
type A = Box<Self::B>;
27-
//~^ ERROR type mismatch resolving `<bool as Tr>::B == _`
27+
//~^ ERROR overflow evaluating the requirement `<bool as Tr>::B == _`
2828
}
2929
// (the error is shown twice for some reason)
3030

3131
impl Tr for usize {
3232
type B = &'static Self::A;
33-
//~^ ERROR type mismatch resolving `<usize as Tr>::A == _`
33+
//~^ ERROR overflow evaluating the requirement `<usize as Tr>::A == _`
3434
}
3535

3636
fn main() {
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
error[E0271]: type mismatch resolving `<bool as Tr>::B == _`
1+
error[E0275]: overflow evaluating the requirement `<bool as Tr>::B == _`
22
--> $DIR/defaults-cyclic-fail-1.rs:26:5
33
|
44
LL | type A = Box<Self::B>;
5-
| ^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size
5+
| ^^^^^^^^^^^^^^^^^^^^^^
66

7-
error[E0271]: type mismatch resolving `<usize as Tr>::A == _`
7+
error[E0275]: overflow evaluating the requirement `<usize as Tr>::A == _`
88
--> $DIR/defaults-cyclic-fail-1.rs:32:5
99
|
1010
LL | type B = &'static Self::A;
11-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
1212

1313
error: aborting due to 2 previous errors
1414

15-
For more information about this error, try `rustc --explain E0271`.
15+
For more information about this error, try `rustc --explain E0275`.

src/test/ui/associated-types/defaults-cyclic-fail-2.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,13 @@ impl Tr for u32 {
2525

2626
impl Tr for bool {
2727
type A = Box<Self::B>;
28-
//~^ ERROR type mismatch resolving `<bool as Tr>::B == _`
28+
//~^ ERROR overflow evaluating the requirement `<bool as Tr>::B == _`
2929
}
3030
// (the error is shown twice for some reason)
3131

3232
impl Tr for usize {
3333
type B = &'static Self::A;
34-
//~^ ERROR type mismatch resolving `<usize as Tr>::A == _`
34+
//~^ ERROR overflow evaluating the requirement `<usize as Tr>::A == _`
3535
}
3636

3737
fn main() {
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
error[E0271]: type mismatch resolving `<bool as Tr>::B == _`
1+
error[E0275]: overflow evaluating the requirement `<bool as Tr>::B == _`
22
--> $DIR/defaults-cyclic-fail-2.rs:27:5
33
|
44
LL | type A = Box<Self::B>;
5-
| ^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size
5+
| ^^^^^^^^^^^^^^^^^^^^^^
66

7-
error[E0271]: type mismatch resolving `<usize as Tr>::A == _`
7+
error[E0275]: overflow evaluating the requirement `<usize as Tr>::A == _`
88
--> $DIR/defaults-cyclic-fail-2.rs:33:5
99
|
1010
LL | type B = &'static Self::A;
11-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
1212

1313
error: aborting due to 2 previous errors
1414

15-
For more information about this error, try `rustc --explain E0271`.
15+
For more information about this error, try `rustc --explain E0275`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Regression test for #79714
2+
3+
trait Baz {}
4+
impl Baz for () {}
5+
impl<T> Baz for (T,) {}
6+
7+
trait Fiz {}
8+
impl Fiz for bool {}
9+
10+
trait Grault {
11+
type A;
12+
type B;
13+
}
14+
15+
impl<T: Grault> Grault for (T,)
16+
where
17+
Self::A: Baz,
18+
Self::B: Fiz,
19+
{
20+
type A = ();
21+
//~^ ERROR overflow evaluating the requirement `<(T,) as Grault>::A == _`
22+
type B = bool;
23+
//~^ ERROR overflow evaluating the requirement `<(T,) as Grault>::A == _`
24+
}
25+
//~^^^^^^^^^^ ERROR overflow evaluating the requirement `<(T,) as Grault>::A == _`
26+
27+
fn main() {
28+
let x: <(_,) as Grault>::A = ();
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _`
2+
--> $DIR/impl-wf-cycle-1.rs:15:1
3+
|
4+
LL | / impl<T: Grault> Grault for (T,)
5+
LL | | where
6+
LL | | Self::A: Baz,
7+
LL | | Self::B: Fiz,
8+
... |
9+
LL | |
10+
LL | | }
11+
| |_^
12+
|
13+
= note: required because of the requirements on the impl of `Grault` for `(T,)`
14+
= note: required because of the requirements on the impl of `Grault` for `(T,)`
15+
16+
error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _`
17+
--> $DIR/impl-wf-cycle-1.rs:20:5
18+
|
19+
LL | type A = ();
20+
| ^^^^^^^^^^^^
21+
|
22+
= note: required because of the requirements on the impl of `Grault` for `(T,)`
23+
= note: required because of the requirements on the impl of `Grault` for `(T,)`
24+
25+
error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _`
26+
--> $DIR/impl-wf-cycle-1.rs:22:5
27+
|
28+
LL | type B = bool;
29+
| ^^^^^^^^^^^^^^
30+
|
31+
= note: required because of the requirements on the impl of `Grault` for `(T,)`
32+
= note: required because of the requirements on the impl of `Grault` for `(T,)`
33+
34+
error: aborting due to 3 previous errors
35+
36+
For more information about this error, try `rustc --explain E0275`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Regression test for #79714
2+
3+
trait Grault {
4+
type A;
5+
}
6+
7+
impl<T: Grault> Grault for (T,)
8+
where
9+
Self::A: Copy,
10+
{
11+
type A = ();
12+
//~^ ERROR overflow evaluating the requirement `<(T,) as Grault>::A == _`
13+
}
14+
//~^^^^^^^ ERROR overflow evaluating the requirement `<(T,) as Grault>::A == _`
15+
16+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _`
2+
--> $DIR/impl-wf-cycle-2.rs:7:1
3+
|
4+
LL | / impl<T: Grault> Grault for (T,)
5+
LL | | where
6+
LL | | Self::A: Copy,
7+
LL | | {
8+
LL | | type A = ();
9+
LL | |
10+
LL | | }
11+
| |_^
12+
|
13+
= note: required because of the requirements on the impl of `Grault` for `(T,)`
14+
15+
error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _`
16+
--> $DIR/impl-wf-cycle-2.rs:11:5
17+
|
18+
LL | type A = ();
19+
| ^^^^^^^^^^^^
20+
|
21+
= note: required because of the requirements on the impl of `Grault` for `(T,)`
22+
23+
error: aborting due to 2 previous errors
24+
25+
For more information about this error, try `rustc --explain E0275`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// check-pass
2+
3+
macro_rules! exp {
4+
(const $n:expr) => {
5+
$n
6+
};
7+
}
8+
9+
macro_rules! stmt {
10+
(exp $e:expr) => {
11+
$e
12+
};
13+
(exp $($t:tt)+) => {
14+
exp!($($t)+)
15+
};
16+
}
17+
18+
fn main() {
19+
stmt!(exp const 1);
20+
}

src/test/ui/issues/issue-23122-2.stderr

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
error[E0275]: overflow evaluating the requirement `<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next: Sized`
1+
error[E0275]: overflow evaluating the requirement `<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next`
22
--> $DIR/issue-23122-2.rs:9:5
33
|
44
LL | type Next = <GetNext<T::Next> as Next>::Next;
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66
|
77
= help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_23122_2`)
8-
= note: required because of the requirements on the impl of `Next` for `GetNext<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>`
98

109
error: aborting due to previous error
1110

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Regression test for #79902
2+
3+
// Check that evaluation (which is used to determine whether to copy a type in
4+
// MIR building) evaluates bounds from normalizing an impl after evaluating
5+
// any bounds on the impl.
6+
7+
// check-pass
8+
9+
trait A {
10+
type B;
11+
}
12+
trait M {}
13+
14+
struct G<T, U>(*const T, *const U);
15+
16+
impl<T, U> Clone for G<T, U> {
17+
fn clone(&self) -> Self {
18+
G { ..*self }
19+
}
20+
}
21+
22+
impl<T, U> Copy for G<T, U::B>
23+
where
24+
T: A<B = U>,
25+
U: A,
26+
{
27+
}
28+
29+
impl A for () {
30+
type B = ();
31+
}
32+
33+
fn is_m<T: M>(_: T) {}
34+
35+
fn main() {
36+
let x = G(&(), &());
37+
drop(x);
38+
drop(x);
39+
}

0 commit comments

Comments
 (0)