Skip to content

Commit 39a0377

Browse files
committed
correctly deal with user type ascriptions in pat
1 parent 4a86c79 commit 39a0377

File tree

12 files changed

+208
-103
lines changed

12 files changed

+208
-103
lines changed

compiler/rustc_middle/src/thir.rs

Lines changed: 9 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,11 @@ use rustc_index::vec::IndexVec;
1818
use rustc_middle::infer::canonical::Canonical;
1919
use rustc_middle::middle::region;
2020
use rustc_middle::mir::interpret::AllocId;
21-
use rustc_middle::mir::{
22-
self, BinOp, BorrowKind, FakeReadCause, Field, Mutability, UnOp, UserTypeProjection,
23-
};
21+
use rustc_middle::mir::{self, BinOp, BorrowKind, FakeReadCause, Field, Mutability, UnOp};
2422
use rustc_middle::ty::adjustment::PointerCast;
2523
use rustc_middle::ty::subst::SubstsRef;
24+
use rustc_middle::ty::CanonicalUserTypeAnnotation;
2625
use rustc_middle::ty::{self, AdtDef, Ty, UpvarSubsts, UserType};
27-
use rustc_middle::ty::{
28-
CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
29-
};
3026
use rustc_span::{Span, Symbol, DUMMY_SP};
3127
use rustc_target::abi::VariantIdx;
3228
use rustc_target::asm::InlineAsmRegOrRegClass;
@@ -540,13 +536,13 @@ pub enum BindingMode {
540536
ByRef(BorrowKind),
541537
}
542538

543-
#[derive(Clone, Debug, PartialEq, HashStable)]
539+
#[derive(Clone, Debug, HashStable)]
544540
pub struct FieldPat<'tcx> {
545541
pub field: Field,
546542
pub pattern: Pat<'tcx>,
547543
}
548544

549-
#[derive(Clone, Debug, PartialEq, HashStable)]
545+
#[derive(Clone, Debug, HashStable)]
550546
pub struct Pat<'tcx> {
551547
pub ty: Ty<'tcx>,
552548
pub span: Span,
@@ -559,37 +555,10 @@ impl<'tcx> Pat<'tcx> {
559555
}
560556
}
561557

562-
#[derive(Copy, Clone, Debug, PartialEq, HashStable)]
563-
pub struct PatTyProj<'tcx> {
564-
pub user_ty: CanonicalUserType<'tcx>,
565-
}
566-
567-
impl<'tcx> PatTyProj<'tcx> {
568-
pub fn from_user_type(user_annotation: CanonicalUserType<'tcx>) -> Self {
569-
Self { user_ty: user_annotation }
570-
}
571-
572-
pub fn user_ty(
573-
self,
574-
annotations: &mut CanonicalUserTypeAnnotations<'tcx>,
575-
inferred_ty: Ty<'tcx>,
576-
span: Span,
577-
) -> UserTypeProjection {
578-
UserTypeProjection {
579-
base: annotations.push(CanonicalUserTypeAnnotation {
580-
span,
581-
user_ty: self.user_ty,
582-
inferred_ty,
583-
}),
584-
projs: Vec::new(),
585-
}
586-
}
587-
}
588-
589-
#[derive(Copy, Clone, Debug, PartialEq, HashStable)]
558+
#[derive(Clone, Debug, HashStable)]
590559
pub struct Ascription<'tcx> {
591-
pub user_ty: PatTyProj<'tcx>,
592-
/// Variance to use when relating the type `user_ty` to the **type of the value being
560+
pub annotation: CanonicalUserTypeAnnotation<'tcx>,
561+
/// Variance to use when relating the `user_ty` to the **type of the value being
593562
/// matched**. Typically, this is `Variance::Covariant`, since the value being matched must
594563
/// have a type that is some subtype of the ascribed type.
595564
///
@@ -608,12 +577,11 @@ pub struct Ascription<'tcx> {
608577
/// probably be checking for a `PartialEq` impl instead, but this preserves the behavior
609578
/// of the old type-check for now. See #57280 for details.
610579
pub variance: ty::Variance,
611-
pub user_ty_span: Span,
612580
}
613581

614-
#[derive(Clone, Debug, PartialEq, HashStable)]
582+
#[derive(Clone, Debug, HashStable)]
615583
pub enum PatKind<'tcx> {
616-
/// A wildward pattern: `_`.
584+
/// A wildcard pattern: `_`.
617585
Wild,
618586

619587
AscribeUserType {

compiler/rustc_mir_build/src/build/matches/mod.rs

Lines changed: 22 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -523,8 +523,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
523523
},
524524
..
525525
},
526-
ascription:
527-
thir::Ascription { user_ty: pat_ascription_ty, variance: _, user_ty_span },
526+
ascription: thir::Ascription { annotation, variance: _ },
528527
} => {
529528
let place =
530529
self.storage_live_binding(block, var, irrefutable_pat.span, OutsideGuard, true);
@@ -535,18 +534,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
535534
let cause_let = FakeReadCause::ForLet(None);
536535
self.cfg.push_fake_read(block, pattern_source_info, cause_let, place);
537536

538-
let ty_source_info = self.source_info(user_ty_span);
539-
let user_ty = pat_ascription_ty.user_ty(
540-
&mut self.canonical_user_type_annotations,
541-
place.ty(&self.local_decls, self.tcx).ty,
542-
ty_source_info.span,
543-
);
537+
let ty_source_info = self.source_info(annotation.span);
538+
539+
let base = self.canonical_user_type_annotations.push(annotation);
544540
self.cfg.push(
545541
block,
546542
Statement {
547543
source_info: ty_source_info,
548544
kind: StatementKind::AscribeUserType(
549-
Box::new((place, user_ty)),
545+
Box::new((place, UserTypeProjection { base, projs: Vec::new() })),
550546
// We always use invariant as the variance here. This is because the
551547
// variance field from the ascription refers to the variance to use
552548
// when applying the type to the value being matched, but this
@@ -784,7 +780,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
784780

785781
PatKind::AscribeUserType {
786782
ref subpattern,
787-
ascription: thir::Ascription { ref user_ty, user_ty_span, variance: _ },
783+
ascription: thir::Ascription { ref annotation, variance: _ },
788784
} => {
789785
// This corresponds to something like
790786
//
@@ -794,16 +790,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
794790
//
795791
// Note that the variance doesn't apply here, as we are tracking the effect
796792
// of `user_ty` on any bindings contained with subpattern.
797-
let annotation = CanonicalUserTypeAnnotation {
798-
span: user_ty_span,
799-
user_ty: user_ty.user_ty,
800-
inferred_ty: subpattern.ty,
801-
};
793+
802794
let projection = UserTypeProjection {
803-
base: self.canonical_user_type_annotations.push(annotation),
795+
base: self.canonical_user_type_annotations.push(annotation.clone()),
804796
projs: Vec::new(),
805797
};
806-
let subpattern_user_ty = pattern_user_ty.push_projection(&projection, user_ty_span);
798+
let subpattern_user_ty =
799+
pattern_user_ty.push_projection(&projection, annotation.span);
807800
self.visit_primary_bindings(subpattern, subpattern_user_ty, f)
808801
}
809802

@@ -927,9 +920,8 @@ struct Binding<'tcx> {
927920
/// influence region inference.
928921
#[derive(Clone, Debug)]
929922
struct Ascription<'tcx> {
930-
span: Span,
931923
source: Place<'tcx>,
932-
user_ty: PatTyProj<'tcx>,
924+
annotation: CanonicalUserTypeAnnotation<'tcx>,
933925
variance: ty::Variance,
934926
}
935927

@@ -1858,7 +1850,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
18581850
parent_bindings
18591851
.iter()
18601852
.flat_map(|(_, ascriptions)| ascriptions)
1861-
.chain(&candidate.ascriptions),
1853+
.cloned()
1854+
.chain(candidate.ascriptions),
18621855
);
18631856

18641857
// rust-lang/rust#27282: The `autoref` business deserves some
@@ -2062,32 +2055,24 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
20622055

20632056
/// Append `AscribeUserType` statements onto the end of `block`
20642057
/// for each ascription
2065-
fn ascribe_types<'b>(
2058+
fn ascribe_types(
20662059
&mut self,
20672060
block: BasicBlock,
2068-
ascriptions: impl IntoIterator<Item = &'b Ascription<'tcx>>,
2069-
) where
2070-
'tcx: 'b,
2071-
{
2061+
ascriptions: impl IntoIterator<Item = Ascription<'tcx>>,
2062+
) {
20722063
for ascription in ascriptions {
2073-
let source_info = self.source_info(ascription.span);
2064+
let source_info = self.source_info(ascription.annotation.span);
20742065

2075-
debug!(
2076-
"adding user ascription at span {:?} of place {:?} and {:?}",
2077-
source_info.span, ascription.source, ascription.user_ty,
2078-
);
2079-
2080-
let user_ty = ascription.user_ty.user_ty(
2081-
&mut self.canonical_user_type_annotations,
2082-
ascription.source.ty(&self.local_decls, self.tcx).ty,
2083-
source_info.span,
2084-
);
2066+
let base = self.canonical_user_type_annotations.push(ascription.annotation);
20852067
self.cfg.push(
20862068
block,
20872069
Statement {
20882070
source_info,
20892071
kind: StatementKind::AscribeUserType(
2090-
Box::new((ascription.source, user_ty)),
2072+
Box::new((
2073+
ascription.source,
2074+
UserTypeProjection { base, projs: Vec::new() },
2075+
)),
20912076
ascription.variance,
20922077
),
20932078
},

compiler/rustc_mir_build/src/build/matches/simplify.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,15 +152,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
152152
match *match_pair.pattern.kind {
153153
PatKind::AscribeUserType {
154154
ref subpattern,
155-
ascription: thir::Ascription { variance, user_ty, user_ty_span },
155+
ascription: thir::Ascription { ref annotation, variance },
156156
} => {
157157
// Apply the type ascription to the value at `match_pair.place`, which is the
158158
if let Ok(place_resolved) =
159159
match_pair.place.clone().try_upvars_resolved(self.tcx, self.typeck_results)
160160
{
161161
candidate.ascriptions.push(Ascription {
162-
span: user_ty_span,
163-
user_ty,
162+
annotation: annotation.clone(),
164163
source: place_resolved.into_place(self.tcx, self.typeck_results),
165164
variance,
166165
});

compiler/rustc_mir_build/src/thir/cx/block.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use rustc_middle::thir::*;
66
use rustc_middle::ty;
77

88
use rustc_index::vec::Idx;
9+
use rustc_middle::ty::CanonicalUserTypeAnnotation;
910

1011
impl<'tcx> Cx<'tcx> {
1112
crate fn mirror_block(&mut self, block: &'tcx hir::Block<'tcx>) -> Block {
@@ -80,13 +81,17 @@ impl<'tcx> Cx<'tcx> {
8081
self.typeck_results.user_provided_types().get(ty.hir_id)
8182
{
8283
debug!("mirror_stmts: user_ty={:?}", user_ty);
84+
let annotation = CanonicalUserTypeAnnotation {
85+
user_ty,
86+
span: ty.span,
87+
inferred_ty: self.typeck_results.node_type(ty.hir_id),
88+
};
8389
pattern = Pat {
8490
ty: pattern.ty,
8591
span: pattern.span,
8692
kind: Box::new(PatKind::AscribeUserType {
8793
ascription: Ascription {
88-
user_ty: PatTyProj::from_user_type(user_ty),
89-
user_ty_span: ty.span,
94+
annotation,
9095
variance: ty::Variance::Covariant,
9196
},
9297
subpattern: pattern,

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

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@ use rustc_middle::mir::interpret::{get_slice_bytes, ConstValue};
1919
use rustc_middle::mir::interpret::{ErrorHandled, LitToConstError, LitToConstInput};
2020
use rustc_middle::mir::{self, UserTypeProjection};
2121
use rustc_middle::mir::{BorrowKind, Field, Mutability};
22-
use rustc_middle::thir::{Ascription, BindingMode, FieldPat, Pat, PatKind, PatRange, PatTyProj};
22+
use rustc_middle::thir::{Ascription, BindingMode, FieldPat, Pat, PatKind, PatRange};
2323
use rustc_middle::ty::subst::{GenericArg, SubstsRef};
24+
use rustc_middle::ty::CanonicalUserTypeAnnotation;
2425
use rustc_middle::ty::{self, AdtDef, ConstKind, DefIdTree, Region, Ty, TyCtxt, UserType};
2526
use rustc_span::{Span, Symbol};
2627

@@ -227,7 +228,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
227228
for end in &[lo, hi] {
228229
if let Some((_, Some(ascription))) = end {
229230
let subpattern = Pat { span: pat.span, ty, kind: Box::new(kind) };
230-
kind = PatKind::AscribeUserType { ascription: *ascription, subpattern };
231+
kind =
232+
PatKind::AscribeUserType { ascription: ascription.clone(), subpattern };
231233
}
232234
}
233235

@@ -432,13 +434,14 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
432434

433435
if let Some(user_ty) = self.user_substs_applied_to_ty_of_hir_id(hir_id) {
434436
debug!("lower_variant_or_leaf: kind={:?} user_ty={:?} span={:?}", kind, user_ty, span);
437+
let annotation = CanonicalUserTypeAnnotation {
438+
user_ty,
439+
span,
440+
inferred_ty: self.typeck_results.node_type(hir_id),
441+
};
435442
kind = PatKind::AscribeUserType {
436443
subpattern: Pat { span, ty, kind: Box::new(kind) },
437-
ascription: Ascription {
438-
user_ty: PatTyProj::from_user_type(user_ty),
439-
user_ty_span: span,
440-
variance: ty::Variance::Covariant,
441-
},
444+
ascription: Ascription { annotation, variance: ty::Variance::Covariant },
442445
};
443446
}
444447

@@ -499,18 +502,21 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
499502
}
500503

501504
let user_provided_types = self.typeck_results().user_provided_types();
502-
if let Some(u_ty) = user_provided_types.get(id) {
503-
let user_ty = PatTyProj::from_user_type(*u_ty);
505+
if let Some(&user_ty) = user_provided_types.get(id) {
506+
let annotation = CanonicalUserTypeAnnotation {
507+
user_ty,
508+
span,
509+
inferred_ty: self.typeck_results().node_type(id),
510+
};
504511
Pat {
505512
span,
506513
kind: Box::new(PatKind::AscribeUserType {
507514
subpattern: pattern,
508515
ascription: Ascription {
516+
annotation,
509517
/// Note that use `Contravariant` here. See the
510518
/// `variance` field documentation for details.
511519
variance: ty::Variance::Contravariant,
512-
user_ty,
513-
user_ty_span: span,
514520
},
515521
}),
516522
ty: const_.ty(),
@@ -645,7 +651,7 @@ impl<'tcx, T: PatternFoldable<'tcx>> PatternFoldable<'tcx> for Option<T> {
645651
}
646652
}
647653

648-
macro_rules! CloneImpls {
654+
macro_rules! ClonePatternFoldableImpls {
649655
(<$lt_tcx:tt> $($ty:ty),+) => {
650656
$(
651657
impl<$lt_tcx> PatternFoldable<$lt_tcx> for $ty {
@@ -657,11 +663,11 @@ macro_rules! CloneImpls {
657663
}
658664
}
659665

660-
CloneImpls! { <'tcx>
666+
ClonePatternFoldableImpls! { <'tcx>
661667
Span, Field, Mutability, Symbol, hir::HirId, usize, ty::Const<'tcx>,
662668
Region<'tcx>, Ty<'tcx>, BindingMode, AdtDef<'tcx>,
663669
SubstsRef<'tcx>, &'tcx GenericArg<'tcx>, UserType<'tcx>,
664-
UserTypeProjection, PatTyProj<'tcx>
670+
UserTypeProjection, CanonicalUserTypeAnnotation<'tcx>
665671
}
666672

667673
impl<'tcx> PatternFoldable<'tcx> for FieldPat<'tcx> {
@@ -694,14 +700,10 @@ impl<'tcx> PatternFoldable<'tcx> for PatKind<'tcx> {
694700
PatKind::Wild => PatKind::Wild,
695701
PatKind::AscribeUserType {
696702
ref subpattern,
697-
ascription: Ascription { variance, ref user_ty, user_ty_span },
703+
ascription: Ascription { ref annotation, variance },
698704
} => PatKind::AscribeUserType {
699705
subpattern: subpattern.fold_with(folder),
700-
ascription: Ascription {
701-
user_ty: user_ty.fold_with(folder),
702-
variance,
703-
user_ty_span,
704-
},
706+
ascription: Ascription { annotation: annotation.fold_with(folder), variance },
705707
},
706708
PatKind::Binding { mutability, name, mode, var, ty, ref subpattern, is_primary } => {
707709
PatKind::Binding {
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Check that incorrect higher ranked subtyping
2+
// causes an error.
3+
struct Inv<'a>(fn(&'a ()) -> &'a ());
4+
fn hr_subtype<'c>(f: for<'a, 'b> fn(Inv<'a>, Inv<'a>)) {
5+
// ok
6+
let _: for<'a> fn(Inv<'a>, Inv<'a>) = f;
7+
let sub: for<'a> fn(Inv<'a>, Inv<'a>) = f;
8+
// no
9+
let _: for<'a, 'b> fn(Inv<'a>, Inv<'b>) = sub;
10+
//~^ ERROR mismatched types
11+
}
12+
13+
fn simple1<'c>(x: (&'c i32,)) {
14+
let _x: (&'static i32,) = x;
15+
//~^ ERROR mismatched types
16+
}
17+
18+
fn simple2<'c>(x: (&'c i32,)) {
19+
let _: (&'static i32,) = x;
20+
//~^ ERROR mismatched types
21+
}
22+
23+
fn main() {
24+
hr_subtype(|_, _| {});
25+
simple1((&3,));
26+
simple2((&3,));
27+
}

0 commit comments

Comments
 (0)