Skip to content

Commit 62ceb9a

Browse files
committed
Account for for<'a> types when checking for non-structural type in constant as pattern
When we encounter a constant in a pattern, we check if it is non-structural. If so, we check if the type implements `PartialEq`, but for types with escaping bound vars the check would be incorrect as is, so we break early. This is ok because these types would be filtered anyways. Fix rust-lang#134764.
1 parent ad211ce commit 62ceb9a

File tree

3 files changed

+40
-3
lines changed

3 files changed

+40
-3
lines changed

compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ use rustc_infer::infer::TyCtxtInferExt;
88
use rustc_infer::traits::Obligation;
99
use rustc_middle::mir::interpret::ErrorHandled;
1010
use rustc_middle::thir::{FieldPat, Pat, PatKind};
11-
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, TypeVisitor, ValTree};
11+
use rustc_middle::ty::{
12+
self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitableExt, TypeVisitor, ValTree,
13+
};
1214
use rustc_middle::{mir, span_bug};
1315
use rustc_span::def_id::DefId;
1416
use rustc_span::{Span, sym};
@@ -387,7 +389,9 @@ fn extend_type_not_partial_eq<'tcx>(
387389

388390
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for UsedParamsNeedInstantiationVisitor<'tcx> {
389391
fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
390-
if let ty::Adt(def, _args) = ty.kind() {
392+
if let ty::Adt(def, _args) = ty.kind()
393+
&& !ty.has_escaping_bound_vars()
394+
{
391395
let ty_def_id = def.did();
392396
let ty_def_span = self.tcx.def_span(ty_def_id);
393397
let (impls_partial_eq, derived, structural, impl_def_id) =
@@ -412,7 +416,6 @@ fn extend_type_not_partial_eq<'tcx>(
412416
_ => {}
413417
};
414418
}
415-
use rustc_middle::ty::TypeSuperVisitable;
416419
ty.super_visit_with(self)
417420
}
418421
}
@@ -468,6 +471,10 @@ fn type_has_partial_eq_impl<'tcx>(
468471
let partial_eq_trait_id = tcx.require_lang_item(hir::LangItem::PartialEq, None);
469472
let structural_partial_eq_trait_id = tcx.require_lang_item(hir::LangItem::StructuralPeq, None);
470473

474+
if ty.has_escaping_bound_vars() {
475+
return (false, false, false, None);
476+
}
477+
471478
let partial_eq_obligation = Obligation::new(
472479
tcx,
473480
ObligationCause::dummy(),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#![feature(structural_match)]
2+
impl<T: ?Sized> std::marker::StructuralPartialEq for O<T> { }
3+
4+
enum O<T: ?Sized> {
5+
Some(*const T),
6+
None,
7+
}
8+
9+
const C: O<dyn for<'a> Fn(Box<dyn Fn(&'a u8)>)> = O::None;
10+
11+
fn main() {
12+
match O::None {
13+
C => (), //~ ERROR constant of non-structural type
14+
}
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error: constant of non-structural type `O<dyn for<'a> Fn(Box<dyn Fn(&'a u8)>)>` in a pattern
2+
--> $DIR/non_structural_with_escaping_bounds.rs:13:9
3+
|
4+
LL | const C: O<dyn for<'a> Fn(Box<dyn Fn(&'a u8)>)> = O::None;
5+
| ----------------------------------------------- constant defined here
6+
...
7+
LL | C => (),
8+
| ^ constant of non-structural type
9+
|
10+
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
11+
= note: `std::alloc::Global` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
12+
= note: `std::alloc::Global` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
13+
14+
error: aborting due to 1 previous error
15+

0 commit comments

Comments
 (0)