Skip to content

Commit a4ef47d

Browse files
authored
Rollup merge of #105897 - oli-obk:tait_patterns, r=TaKO8Ki
Fix an opaque type ICE fixes #104551 The issue is that if you have ```rust type T = impl Sized; let (_a, _b): T = .. ``` we have only the type annotation `T`, but want to use that ascription for `_a` and `_b`, so what we generate is a type ascription plus a field projection saying `_a`'s type is `T::0`. Of course `T` has no fields. Of course we could also not generate type annotations for projections into opaque types at all, but that's more fragile, as we now have to make sure that https://github.com/rust-lang/rust/blob/12bbdbdb440119a0b86d2ee742ec1460cdb2c5b9/compiler/rustc_mir_build/src/build/matches/mod.rs#L709 doesn't have any arm that introduces a user type annotation except for `PatKind::Binding`.
2 parents 4726e51 + c9588d5 commit a4ef47d

File tree

7 files changed

+69
-35
lines changed

7 files changed

+69
-35
lines changed

compiler/rustc_borrowck/src/diagnostics/region_errors.rs

+21-3
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ use rustc_infer::infer::{
1818
use rustc_middle::hir::place::PlaceBase;
1919
use rustc_middle::mir::{ConstraintCategory, ReturnConstraint};
2020
use rustc_middle::ty::subst::InternalSubsts;
21-
use rustc_middle::ty::Region;
2221
use rustc_middle::ty::TypeVisitor;
2322
use rustc_middle::ty::{self, RegionVid, Ty};
23+
use rustc_middle::ty::{Region, TyCtxt};
2424
use rustc_span::symbol::{kw, Ident};
25-
use rustc_span::Span;
25+
use rustc_span::{Span, DUMMY_SP};
2626

2727
use crate::borrowck_errors;
2828
use crate::session_diagnostics::{
@@ -70,7 +70,25 @@ impl<'tcx> ConstraintDescription for ConstraintCategory<'tcx> {
7070
///
7171
/// Usually we expect this to either be empty or contain a small number of items, so we can avoid
7272
/// allocation most of the time.
73-
pub(crate) type RegionErrors<'tcx> = Vec<RegionErrorKind<'tcx>>;
73+
pub(crate) struct RegionErrors<'tcx>(Vec<RegionErrorKind<'tcx>>, TyCtxt<'tcx>);
74+
75+
impl<'tcx> RegionErrors<'tcx> {
76+
pub fn new(tcx: TyCtxt<'tcx>) -> Self {
77+
Self(vec![], tcx)
78+
}
79+
#[track_caller]
80+
pub fn push(&mut self, val: impl Into<RegionErrorKind<'tcx>>) {
81+
let val = val.into();
82+
self.1.sess.delay_span_bug(DUMMY_SP, "{val:?}");
83+
self.0.push(val);
84+
}
85+
pub fn is_empty(&self) -> bool {
86+
self.0.is_empty()
87+
}
88+
pub fn into_iter(self) -> impl Iterator<Item = RegionErrorKind<'tcx>> {
89+
self.0.into_iter()
90+
}
91+
}
7492

7593
#[derive(Clone, Debug)]
7694
pub(crate) enum RegionErrorKind<'tcx> {

compiler/rustc_borrowck/src/region_infer/mod.rs

+23-20
Original file line numberDiff line numberDiff line change
@@ -562,7 +562,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
562562
let mir_def_id = body.source.def_id();
563563
self.propagate_constraints(body);
564564

565-
let mut errors_buffer = RegionErrors::new();
565+
let mut errors_buffer = RegionErrors::new(infcx.tcx);
566566

567567
// If this is a closure, we can propagate unsatisfied
568568
// `outlives_requirements` to our creator, so create a vector
@@ -1647,26 +1647,29 @@ impl<'tcx> RegionInferenceContext<'tcx> {
16471647
let longer_fr_scc = self.constraint_sccs.scc(longer_fr);
16481648
debug!("check_bound_universal_region: longer_fr_scc={:?}", longer_fr_scc,);
16491649

1650-
// If we have some bound universal region `'a`, then the only
1651-
// elements it can contain is itself -- we don't know anything
1652-
// else about it!
1653-
let Some(error_element) = ({
1654-
self.scc_values.elements_contained_in(longer_fr_scc).find(|element| match element {
1655-
RegionElement::Location(_) => true,
1656-
RegionElement::RootUniversalRegion(_) => true,
1657-
RegionElement::PlaceholderRegion(placeholder1) => placeholder != *placeholder1,
1658-
})
1659-
}) else {
1660-
return;
1661-
};
1662-
debug!("check_bound_universal_region: error_element = {:?}", error_element);
1650+
for error_element in self.scc_values.elements_contained_in(longer_fr_scc) {
1651+
match error_element {
1652+
RegionElement::Location(_) | RegionElement::RootUniversalRegion(_) => {}
1653+
// If we have some bound universal region `'a`, then the only
1654+
// elements it can contain is itself -- we don't know anything
1655+
// else about it!
1656+
RegionElement::PlaceholderRegion(placeholder1) => {
1657+
if placeholder == placeholder1 {
1658+
continue;
1659+
}
1660+
}
1661+
}
16631662

1664-
// Find the region that introduced this `error_element`.
1665-
errors_buffer.push(RegionErrorKind::BoundUniversalRegionError {
1666-
longer_fr,
1667-
error_element,
1668-
placeholder,
1669-
});
1663+
errors_buffer.push(RegionErrorKind::BoundUniversalRegionError {
1664+
longer_fr,
1665+
error_element,
1666+
placeholder,
1667+
});
1668+
1669+
// Stop after the first error, it gets too noisy otherwise, and does not provide more information.
1670+
break;
1671+
}
1672+
debug!("check_bound_universal_region: all bounds satisfied");
16701673
}
16711674

16721675
#[instrument(level = "debug", skip(self, infcx, errors_buffer))]

compiler/rustc_borrowck/src/type_check/mod.rs

+9-5
Original file line numberDiff line numberDiff line change
@@ -1153,27 +1153,31 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
11531153
category: ConstraintCategory<'tcx>,
11541154
) -> Fallible<()> {
11551155
let annotated_type = self.user_type_annotations[user_ty.base].inferred_ty;
1156+
trace!(?annotated_type);
11561157
let mut curr_projected_ty = PlaceTy::from_ty(annotated_type);
11571158

11581159
let tcx = self.infcx.tcx;
11591160

11601161
for proj in &user_ty.projs {
1162+
if let ty::Alias(ty::Opaque, ..) = curr_projected_ty.ty.kind() {
1163+
// There is nothing that we can compare here if we go through an opaque type.
1164+
// We're always in its defining scope as we can otherwise not project through
1165+
// it, so we're constraining it anyways.
1166+
return Ok(());
1167+
}
11611168
let projected_ty = curr_projected_ty.projection_ty_core(
11621169
tcx,
11631170
self.param_env,
11641171
proj,
1165-
|this, field, _| {
1172+
|this, field, ()| {
11661173
let ty = this.field_ty(tcx, field);
11671174
self.normalize(ty, locations)
11681175
},
11691176
|_, _| unreachable!(),
11701177
);
11711178
curr_projected_ty = projected_ty;
11721179
}
1173-
debug!(
1174-
"user_ty base: {:?} freshened: {:?} projs: {:?} yields: {:?}",
1175-
user_ty.base, annotated_type, user_ty.projs, curr_projected_ty
1176-
);
1180+
trace!(?curr_projected_ty);
11771181

11781182
let ty = curr_projected_ty.ty;
11791183
self.relate_types(ty, v.xform(ty::Variance::Contravariant), a, locations, category)?;

compiler/rustc_middle/src/mir/tcx.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,9 @@ impl<'tcx> PlaceTy<'tcx> {
3232
/// not carry a `Ty` for `T`.)
3333
///
3434
/// Note that the resulting type has not been normalized.
35+
#[instrument(level = "debug", skip(tcx), ret)]
3536
pub fn field_ty(self, tcx: TyCtxt<'tcx>, f: Field) -> Ty<'tcx> {
36-
let answer = match self.ty.kind() {
37+
match self.ty.kind() {
3738
ty::Adt(adt_def, substs) => {
3839
let variant_def = match self.variant_index {
3940
None => adt_def.non_enum_variant(),
@@ -47,9 +48,7 @@ impl<'tcx> PlaceTy<'tcx> {
4748
}
4849
ty::Tuple(tys) => tys[f.index()],
4950
_ => bug!("extracting field of non-tuple non-adt: {:?}", self),
50-
};
51-
debug!("field_ty self: {:?} f: {:?} yields: {:?}", self, f, answer);
52-
answer
51+
}
5352
}
5453

5554
/// Convenience wrapper around `projection_ty_core` for

compiler/rustc_mir_build/src/build/expr/as_constant.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,14 @@ pub fn as_constant_inner<'tcx>(
6666

6767
let literal = ConstantKind::Val(ConstValue::Scalar(Scalar::Int(lit)), ty);
6868

69-
Constant { span, user_ty: user_ty, literal }
69+
Constant { span, user_ty, literal }
7070
}
7171
ExprKind::ZstLiteral { ref user_ty } => {
7272
let user_ty = user_ty.as_ref().map(push_cuta).flatten();
7373

7474
let literal = ConstantKind::Val(ConstValue::ZeroSized, ty);
7575

76-
Constant { span, user_ty: user_ty, literal }
76+
Constant { span, user_ty, literal }
7777
}
7878
ExprKind::NamedConst { def_id, substs, ref user_ty } => {
7979
let user_ty = user_ty.as_ref().map(push_cuta).flatten();

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -2210,7 +2210,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
22102210
BindingMode::ByValue => ty::BindingMode::BindByValue(mutability),
22112211
BindingMode::ByRef(_) => ty::BindingMode::BindByReference(mutability),
22122212
};
2213-
let local = LocalDecl::<'tcx> {
2213+
let local = LocalDecl {
22142214
mutability,
22152215
ty: var_ty,
22162216
user_ty: if user_ty.is_empty() { None } else { Some(Box::new(user_ty)) },
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#![feature(type_alias_impl_trait)]
2+
3+
// check-pass
4+
5+
// issue: https://github.com/rust-lang/rust/issues/104551
6+
7+
fn main() {
8+
type T = impl Sized;
9+
let (_a, _b): T = (1u32, 2u32);
10+
}

0 commit comments

Comments
 (0)