Skip to content

Commit 34ccd04

Browse files
committedAug 4, 2023
Auto merge of #114451 - matthiaskrgr:rollup-37qmv19, r=matthiaskrgr
Rollup of 5 pull requests Successful merges: - #114022 (Perform OpaqueCast field projection on HIR, too.) - #114253 (Compute variances for lazy type aliases) - #114355 (resolve before canonicalization in new solver, ICE if unresolved) - #114427 (Handle non-utf8 rpaths (fix FIXME)) - #114440 (bootstrap: config: fix version comparison bug) r? `@ghost` `@rustbot` modify labels: rollup
·
1.88.01.73.0
2 parents 73dc6f0 + 50f47d9 commit 34ccd04

File tree

40 files changed

+492
-286
lines changed

40 files changed

+492
-286
lines changed
 

‎compiler/rustc_borrowck/src/type_check/mod.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -498,14 +498,13 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
498498

499499
/// Checks that the types internal to the `place` match up with
500500
/// what would be expected.
501+
#[instrument(level = "debug", skip(self, location), ret)]
501502
fn sanitize_place(
502503
&mut self,
503504
place: &Place<'tcx>,
504505
location: Location,
505506
context: PlaceContext,
506507
) -> PlaceTy<'tcx> {
507-
debug!("sanitize_place: {:?}", place);
508-
509508
let mut place_ty = PlaceTy::from_ty(self.body().local_decls[place.local].ty);
510509

511510
for elem in place.projection.iter() {
@@ -608,7 +607,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
608607
}
609608
}
610609

611-
#[instrument(skip(self), level = "debug")]
610+
#[instrument(skip(self, location), ret, level = "debug")]
612611
fn sanitize_projection(
613612
&mut self,
614613
base: PlaceTy<'tcx>,
@@ -617,7 +616,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
617616
location: Location,
618617
context: PlaceContext,
619618
) -> PlaceTy<'tcx> {
620-
debug!("sanitize_projection: {:?} {:?} {:?}", base, pi, place);
621619
let tcx = self.tcx();
622620
let base_ty = base.ty;
623621
match pi {

‎compiler/rustc_codegen_ssa/src/back/rpath.rs

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use pathdiff::diff_paths;
22
use rustc_data_structures::fx::FxHashSet;
33
use std::env;
4+
use std::ffi::OsString;
45
use std::fs;
56
use std::path::{Path, PathBuf};
67

@@ -12,7 +13,7 @@ pub struct RPathConfig<'a> {
1213
pub linker_is_gnu: bool,
1314
}
1415

15-
pub fn get_rpath_flags(config: &mut RPathConfig<'_>) -> Vec<String> {
16+
pub fn get_rpath_flags(config: &mut RPathConfig<'_>) -> Vec<OsString> {
1617
// No rpath on windows
1718
if !config.has_rpath {
1819
return Vec::new();
@@ -21,36 +22,38 @@ pub fn get_rpath_flags(config: &mut RPathConfig<'_>) -> Vec<String> {
2122
debug!("preparing the RPATH!");
2223

2324
let rpaths = get_rpaths(config);
24-
let mut flags = rpaths_to_flags(&rpaths);
25+
let mut flags = rpaths_to_flags(rpaths);
2526

2627
if config.linker_is_gnu {
2728
// Use DT_RUNPATH instead of DT_RPATH if available
28-
flags.push("-Wl,--enable-new-dtags".to_owned());
29+
flags.push("-Wl,--enable-new-dtags".into());
2930

3031
// Set DF_ORIGIN for substitute $ORIGIN
31-
flags.push("-Wl,-z,origin".to_owned());
32+
flags.push("-Wl,-z,origin".into());
3233
}
3334

3435
flags
3536
}
3637

37-
fn rpaths_to_flags(rpaths: &[String]) -> Vec<String> {
38+
fn rpaths_to_flags(rpaths: Vec<OsString>) -> Vec<OsString> {
3839
let mut ret = Vec::with_capacity(rpaths.len()); // the minimum needed capacity
3940

4041
for rpath in rpaths {
41-
if rpath.contains(',') {
42+
if rpath.to_string_lossy().contains(',') {
4243
ret.push("-Wl,-rpath".into());
4344
ret.push("-Xlinker".into());
44-
ret.push(rpath.clone());
45+
ret.push(rpath);
4546
} else {
46-
ret.push(format!("-Wl,-rpath,{}", &(*rpath)));
47+
let mut single_arg = OsString::from("-Wl,-rpath,");
48+
single_arg.push(rpath);
49+
ret.push(single_arg);
4750
}
4851
}
4952

5053
ret
5154
}
5255

53-
fn get_rpaths(config: &mut RPathConfig<'_>) -> Vec<String> {
56+
fn get_rpaths(config: &mut RPathConfig<'_>) -> Vec<OsString> {
5457
debug!("output: {:?}", config.out_filename.display());
5558
debug!("libs:");
5659
for libpath in config.libs {
@@ -64,18 +67,18 @@ fn get_rpaths(config: &mut RPathConfig<'_>) -> Vec<String> {
6467

6568
debug!("rpaths:");
6669
for rpath in &rpaths {
67-
debug!(" {}", rpath);
70+
debug!(" {:?}", rpath);
6871
}
6972

7073
// Remove duplicates
7174
minimize_rpaths(&rpaths)
7275
}
7376

74-
fn get_rpaths_relative_to_output(config: &mut RPathConfig<'_>) -> Vec<String> {
77+
fn get_rpaths_relative_to_output(config: &mut RPathConfig<'_>) -> Vec<OsString> {
7578
config.libs.iter().map(|a| get_rpath_relative_to_output(config, a)).collect()
7679
}
7780

78-
fn get_rpath_relative_to_output(config: &mut RPathConfig<'_>, lib: &Path) -> String {
81+
fn get_rpath_relative_to_output(config: &mut RPathConfig<'_>, lib: &Path) -> OsString {
7982
// Mac doesn't appear to support $ORIGIN
8083
let prefix = if config.is_like_osx { "@loader_path" } else { "$ORIGIN" };
8184

@@ -87,8 +90,11 @@ fn get_rpath_relative_to_output(config: &mut RPathConfig<'_>, lib: &Path) -> Str
8790
let output = fs::canonicalize(&output).unwrap_or(output);
8891
let relative = path_relative_from(&lib, &output)
8992
.unwrap_or_else(|| panic!("couldn't create relative path from {output:?} to {lib:?}"));
90-
// FIXME (#9639): This needs to handle non-utf8 paths
91-
format!("{}/{}", prefix, relative.to_str().expect("non-utf8 component in path"))
93+
94+
let mut rpath = OsString::from(prefix);
95+
rpath.push("/");
96+
rpath.push(relative);
97+
rpath
9298
}
9399

94100
// This routine is adapted from the *old* Path's `path_relative_from`
@@ -99,7 +105,7 @@ fn path_relative_from(path: &Path, base: &Path) -> Option<PathBuf> {
99105
diff_paths(path, base)
100106
}
101107

102-
fn minimize_rpaths(rpaths: &[String]) -> Vec<String> {
108+
fn minimize_rpaths(rpaths: &[OsString]) -> Vec<OsString> {
103109
let mut set = FxHashSet::default();
104110
let mut minimized = Vec::new();
105111
for rpath in rpaths {

‎compiler/rustc_codegen_ssa/src/back/rpath/tests.rs

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,33 @@
11
use super::RPathConfig;
22
use super::{get_rpath_relative_to_output, minimize_rpaths, rpaths_to_flags};
3+
use std::ffi::OsString;
34
use std::path::{Path, PathBuf};
45

56
#[test]
67
fn test_rpaths_to_flags() {
7-
let flags = rpaths_to_flags(&["path1".to_string(), "path2".to_string()]);
8+
let flags = rpaths_to_flags(vec!["path1".into(), "path2".into()]);
89
assert_eq!(flags, ["-Wl,-rpath,path1", "-Wl,-rpath,path2"]);
910
}
1011

1112
#[test]
1213
fn test_minimize1() {
13-
let res = minimize_rpaths(&["rpath1".to_string(), "rpath2".to_string(), "rpath1".to_string()]);
14+
let res = minimize_rpaths(&["rpath1".into(), "rpath2".into(), "rpath1".into()]);
1415
assert!(res == ["rpath1", "rpath2",]);
1516
}
1617

1718
#[test]
1819
fn test_minimize2() {
1920
let res = minimize_rpaths(&[
20-
"1a".to_string(),
21-
"2".to_string(),
22-
"2".to_string(),
23-
"1a".to_string(),
24-
"4a".to_string(),
25-
"1a".to_string(),
26-
"2".to_string(),
27-
"3".to_string(),
28-
"4a".to_string(),
29-
"3".to_string(),
21+
"1a".into(),
22+
"2".into(),
23+
"2".into(),
24+
"1a".into(),
25+
"4a".into(),
26+
"1a".into(),
27+
"2".into(),
28+
"3".into(),
29+
"4a".into(),
30+
"3".into(),
3031
]);
3132
assert!(res == ["1a", "2", "4a", "3",]);
3233
}
@@ -58,15 +59,15 @@ fn test_rpath_relative() {
5859

5960
#[test]
6061
fn test_xlinker() {
61-
let args = rpaths_to_flags(&["a/normal/path".to_string(), "a,comma,path".to_string()]);
62+
let args = rpaths_to_flags(vec!["a/normal/path".into(), "a,comma,path".into()]);
6263

6364
assert_eq!(
6465
args,
6566
vec![
66-
"-Wl,-rpath,a/normal/path".to_string(),
67-
"-Wl,-rpath".to_string(),
68-
"-Xlinker".to_string(),
69-
"a,comma,path".to_string()
67+
OsString::from("-Wl,-rpath,a/normal/path"),
68+
OsString::from("-Wl,-rpath"),
69+
OsString::from("-Xlinker"),
70+
OsString::from("a,comma,path")
7071
]
7172
);
7273
}

‎compiler/rustc_hir_analysis/src/check/wfcheck.rs

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -245,13 +245,14 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) {
245245
}
246246
// `ForeignItem`s are handled separately.
247247
hir::ItemKind::ForeignMod { .. } => {}
248-
hir::ItemKind::TyAlias(hir_ty, ..) => {
248+
hir::ItemKind::TyAlias(hir_ty, ast_generics) => {
249249
if tcx.features().lazy_type_alias
250250
|| tcx.type_of(item.owner_id).skip_binder().has_opaque_types()
251251
{
252252
// Bounds of lazy type aliases and of eager ones that contain opaque types are respected.
253253
// E.g: `type X = impl Trait;`, `type X = (impl Trait, Y);`.
254254
check_item_type(tcx, def_id, hir_ty.span, UnsizedHandling::Allow);
255+
check_variances_for_type_defn(tcx, item, ast_generics);
255256
}
256257
}
257258
_ => {}
@@ -1700,10 +1701,27 @@ fn check_variances_for_type_defn<'tcx>(
17001701
hir_generics: &hir::Generics<'_>,
17011702
) {
17021703
let identity_args = ty::GenericArgs::identity_for_item(tcx, item.owner_id);
1703-
for field in tcx.adt_def(item.owner_id).all_fields() {
1704-
if field.ty(tcx, identity_args).references_error() {
1705-
return;
1704+
1705+
match item.kind {
1706+
ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) => {
1707+
for field in tcx.adt_def(item.owner_id).all_fields() {
1708+
if field.ty(tcx, identity_args).references_error() {
1709+
return;
1710+
}
1711+
}
1712+
}
1713+
ItemKind::TyAlias(..) => {
1714+
let ty = tcx.type_of(item.owner_id).instantiate_identity();
1715+
1716+
if tcx.features().lazy_type_alias || ty.has_opaque_types() {
1717+
if ty.references_error() {
1718+
return;
1719+
}
1720+
} else {
1721+
bug!();
1722+
}
17061723
}
1724+
_ => bug!(),
17071725
}
17081726

17091727
let ty_predicates = tcx.predicates_of(item.owner_id);

‎compiler/rustc_hir_analysis/src/variance/constraints.rs

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
use hir::def_id::{DefId, LocalDefId};
77
use rustc_hir as hir;
88
use rustc_hir::def::DefKind;
9-
use rustc_middle::ty::{self, Ty, TyCtxt};
9+
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
1010
use rustc_middle::ty::{GenericArgKind, GenericArgsRef};
1111

1212
use super::terms::VarianceTerm::*;
@@ -78,6 +78,12 @@ pub fn add_constraints_from_crate<'a, 'tcx>(
7878
}
7979
}
8080
DefKind::Fn | DefKind::AssocFn => constraint_cx.build_constraints_for_item(def_id),
81+
DefKind::TyAlias
82+
if tcx.features().lazy_type_alias
83+
|| tcx.type_of(def_id).instantiate_identity().has_opaque_types() =>
84+
{
85+
constraint_cx.build_constraints_for_item(def_id)
86+
}
8187
_ => {}
8288
}
8389
}
@@ -101,7 +107,18 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
101107

102108
let inferred_start = self.terms_cx.inferred_starts[&def_id];
103109
let current_item = &CurrentItem { inferred_start };
104-
match tcx.type_of(def_id).instantiate_identity().kind() {
110+
let ty = tcx.type_of(def_id).instantiate_identity();
111+
112+
// The type as returned by `type_of` is the underlying type and generally not a weak projection.
113+
// Therefore we need to check the `DefKind` first.
114+
if let DefKind::TyAlias = tcx.def_kind(def_id)
115+
&& (tcx.features().lazy_type_alias || ty.has_opaque_types())
116+
{
117+
self.add_constraints_from_ty(current_item, ty, self.covariant);
118+
return;
119+
}
120+
121+
match ty.kind() {
105122
ty::Adt(def, _) => {
106123
// Not entirely obvious: constraints on structs/enums do not
107124
// affect the variance of their type parameters. See discussion
@@ -127,6 +144,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
127144
}
128145

129146
ty::Error(_) => {}
147+
130148
_ => {
131149
span_bug!(
132150
tcx.def_span(def_id),
@@ -252,10 +270,14 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
252270
self.add_constraints_from_args(current, def.did(), args, variance);
253271
}
254272

255-
ty::Alias(_, ref data) => {
273+
ty::Alias(ty::Projection | ty::Inherent | ty::Opaque, ref data) => {
256274
self.add_constraints_from_invariant_args(current, data.args, variance);
257275
}
258276

277+
ty::Alias(ty::Weak, ref data) => {
278+
self.add_constraints_from_args(current, data.def_id, data.args, variance);
279+
}
280+
259281
ty::Dynamic(data, r, _) => {
260282
// The type `dyn Trait<T> +'a` is covariant w/r/t `'a`:
261283
self.add_constraints_from_region(current, r, variance);

‎compiler/rustc_hir_analysis/src/variance/mod.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use rustc_hir::def::DefKind;
88
use rustc_hir::def_id::{DefId, LocalDefId};
99
use rustc_middle::query::Providers;
1010
use rustc_middle::ty::{self, CrateVariancesMap, GenericArgsRef, Ty, TyCtxt};
11-
use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable};
11+
use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt};
1212
use std::ops::ControlFlow;
1313

1414
/// Defines the `TermsContext` basically houses an arena where we can
@@ -56,6 +56,14 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] {
5656
let crate_map = tcx.crate_variances(());
5757
return crate_map.variances.get(&item_def_id.to_def_id()).copied().unwrap_or(&[]);
5858
}
59+
DefKind::TyAlias
60+
if tcx.features().lazy_type_alias
61+
|| tcx.type_of(item_def_id).instantiate_identity().has_opaque_types() =>
62+
{
63+
// These are inferred.
64+
let crate_map = tcx.crate_variances(());
65+
return crate_map.variances.get(&item_def_id.to_def_id()).copied().unwrap_or(&[]);
66+
}
5967
DefKind::OpaqueTy => {
6068
return variance_of_opaque(tcx, item_def_id);
6169
}

‎compiler/rustc_hir_analysis/src/variance/terms.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
use rustc_arena::DroplessArena;
1313
use rustc_hir::def::DefKind;
1414
use rustc_hir::def_id::{LocalDefId, LocalDefIdMap};
15-
use rustc_middle::ty::{self, TyCtxt};
15+
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
1616
use std::fmt;
1717

1818
use self::VarianceTerm::*;
@@ -97,6 +97,12 @@ pub fn determine_parameters_to_be_inferred<'a, 'tcx>(
9797
}
9898
}
9999
DefKind::Fn | DefKind::AssocFn => terms_cx.add_inferreds_for_item(def_id),
100+
DefKind::TyAlias
101+
if tcx.features().lazy_type_alias
102+
|| tcx.type_of(def_id).instantiate_identity().has_opaque_types() =>
103+
{
104+
terms_cx.add_inferreds_for_item(def_id)
105+
}
100106
_ => {}
101107
}
102108
}

‎compiler/rustc_hir_typeck/src/mem_categorization.rs

Lines changed: 40 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -198,13 +198,14 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
198198
}
199199

200200
/// Like `pat_ty`, but ignores implicit `&` patterns.
201+
#[instrument(level = "debug", skip(self), ret)]
201202
fn pat_ty_unadjusted(&self, pat: &hir::Pat<'_>) -> McResult<Ty<'tcx>> {
202203
let base_ty = self.node_ty(pat.hir_id)?;
203-
debug!("pat_ty(pat={:?}) base_ty={:?}", pat, base_ty);
204+
trace!(?base_ty);
204205

205206
// This code detects whether we are looking at a `ref x`,
206207
// and if so, figures out what the type *being borrowed* is.
207-
let ret_ty = match pat.kind {
208+
match pat.kind {
208209
PatKind::Binding(..) => {
209210
let bm = *self
210211
.typeck_results
@@ -217,21 +218,18 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
217218
// but what we want here is the type of the underlying value being borrowed.
218219
// So peel off one-level, turning the &T into T.
219220
match base_ty.builtin_deref(false) {
220-
Some(t) => t.ty,
221+
Some(t) => Ok(t.ty),
221222
None => {
222-
debug!("By-ref binding of non-derefable type {:?}", base_ty);
223-
return Err(());
223+
debug!("By-ref binding of non-derefable type");
224+
Err(())
224225
}
225226
}
226227
} else {
227-
base_ty
228+
Ok(base_ty)
228229
}
229230
}
230-
_ => base_ty,
231-
};
232-
debug!("pat_ty(pat={:?}) ret_ty={:?}", pat, ret_ty);
233-
234-
Ok(ret_ty)
231+
_ => Ok(base_ty),
232+
}
235233
}
236234

237235
pub(crate) fn cat_expr(&self, expr: &hir::Expr<'_>) -> McResult<PlaceWithHirId<'tcx>> {
@@ -299,13 +297,11 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
299297
}
300298
}
301299

302-
#[instrument(level = "debug", skip(self))]
300+
#[instrument(level = "debug", skip(self), ret)]
303301
pub(crate) fn cat_expr_unadjusted(
304302
&self,
305303
expr: &hir::Expr<'_>,
306304
) -> McResult<PlaceWithHirId<'tcx>> {
307-
debug!("cat_expr: id={} expr={:?}", expr.hir_id, expr);
308-
309305
let expr_ty = self.expr_ty(expr)?;
310306
match expr.kind {
311307
hir::ExprKind::Unary(hir::UnOp::Deref, ref e_base) => {
@@ -319,7 +315,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
319315

320316
hir::ExprKind::Field(ref base, _) => {
321317
let base = self.cat_expr(base)?;
322-
debug!("cat_expr(cat_field): id={} expr={:?} base={:?}", expr.hir_id, expr, base);
318+
debug!(?base);
323319

324320
let field_idx = self
325321
.typeck_results
@@ -389,7 +385,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
389385
}
390386
}
391387

392-
#[instrument(level = "debug", skip(self, span))]
388+
#[instrument(level = "debug", skip(self, span), ret)]
393389
pub(crate) fn cat_res(
394390
&self,
395391
hir_id: hir::HirId,
@@ -430,6 +426,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
430426
/// Note: the actual upvar access contains invisible derefs of closure
431427
/// environment and upvar reference as appropriate. Only regionck cares
432428
/// about these dereferences, so we let it compute them as needed.
429+
#[instrument(level = "debug", skip(self), ret)]
433430
fn cat_upvar(&self, hir_id: hir::HirId, var_id: hir::HirId) -> McResult<PlaceWithHirId<'tcx>> {
434431
let closure_expr_def_id = self.body_owner;
435432

@@ -439,41 +436,44 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
439436
};
440437
let var_ty = self.node_ty(var_id)?;
441438

442-
let ret = PlaceWithHirId::new(hir_id, var_ty, PlaceBase::Upvar(upvar_id), Vec::new());
443-
444-
debug!("cat_upvar ret={:?}", ret);
445-
Ok(ret)
439+
Ok(PlaceWithHirId::new(hir_id, var_ty, PlaceBase::Upvar(upvar_id), Vec::new()))
446440
}
447441

442+
#[instrument(level = "debug", skip(self), ret)]
448443
pub(crate) fn cat_rvalue(
449444
&self,
450445
hir_id: hir::HirId,
451446
span: Span,
452447
expr_ty: Ty<'tcx>,
453448
) -> PlaceWithHirId<'tcx> {
454-
debug!("cat_rvalue hir_id={:?}, expr_ty={:?}, span={:?}", hir_id, expr_ty, span);
455-
let ret = PlaceWithHirId::new(hir_id, expr_ty, PlaceBase::Rvalue, Vec::new());
456-
debug!("cat_rvalue ret={:?}", ret);
457-
ret
449+
PlaceWithHirId::new(hir_id, expr_ty, PlaceBase::Rvalue, Vec::new())
458450
}
459451

452+
#[instrument(level = "debug", skip(self, node), ret)]
460453
pub(crate) fn cat_projection<N: HirNode>(
461454
&self,
462455
node: &N,
463456
base_place: PlaceWithHirId<'tcx>,
464457
ty: Ty<'tcx>,
465458
kind: ProjectionKind,
466459
) -> PlaceWithHirId<'tcx> {
460+
let place_ty = base_place.place.ty();
467461
let mut projections = base_place.place.projections;
462+
463+
let node_ty = self.typeck_results.node_type(node.hir_id());
464+
// Opaque types can't have field projections, but we can instead convert
465+
// the current place in-place (heh) to the hidden type, and then apply all
466+
// follow up projections on that.
467+
if node_ty != place_ty && place_ty.has_opaque_types() {
468+
projections.push(Projection { kind: ProjectionKind::OpaqueCast, ty: node_ty });
469+
}
468470
projections.push(Projection { kind, ty });
469-
let ret = PlaceWithHirId::new(
471+
PlaceWithHirId::new(
470472
node.hir_id(),
471473
base_place.place.base_ty,
472474
base_place.place.base,
473475
projections,
474-
);
475-
debug!("cat_field ret {:?}", ret);
476-
ret
476+
)
477477
}
478478

479479
#[instrument(level = "debug", skip(self))]
@@ -497,7 +497,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
497497
self.cat_deref(expr, base)
498498
}
499499

500-
#[instrument(level = "debug", skip(self, node))]
500+
#[instrument(level = "debug", skip(self, node), ret)]
501501
fn cat_deref(
502502
&self,
503503
node: &impl HirNode,
@@ -514,14 +514,12 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
514514
let mut projections = base_place.place.projections;
515515
projections.push(Projection { kind: ProjectionKind::Deref, ty: deref_ty });
516516

517-
let ret = PlaceWithHirId::new(
517+
Ok(PlaceWithHirId::new(
518518
node.hir_id(),
519519
base_place.place.base_ty,
520520
base_place.place.base,
521521
projections,
522-
);
523-
debug!("cat_deref ret {:?}", ret);
524-
Ok(ret)
522+
))
525523
}
526524

527525
pub(crate) fn cat_pattern<F>(
@@ -603,6 +601,13 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
603601
}
604602
}
605603

604+
/// Here, `place` is the `PlaceWithHirId` being matched and pat is the pattern it
605+
/// is being matched against.
606+
///
607+
/// In general, the way that this works is that we walk down the pattern,
608+
/// constructing a `PlaceWithHirId` that represents the path that will be taken
609+
/// to reach the value being matched.
610+
#[instrument(skip(self, op), ret, level = "debug")]
606611
fn cat_pattern_<F>(
607612
&self,
608613
mut place_with_id: PlaceWithHirId<'tcx>,
@@ -612,15 +617,6 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
612617
where
613618
F: FnMut(&PlaceWithHirId<'tcx>, &hir::Pat<'_>),
614619
{
615-
// Here, `place` is the `PlaceWithHirId` being matched and pat is the pattern it
616-
// is being matched against.
617-
//
618-
// In general, the way that this works is that we walk down the pattern,
619-
// constructing a `PlaceWithHirId` that represents the path that will be taken
620-
// to reach the value being matched.
621-
622-
debug!("cat_pattern(pat={:?}, place_with_id={:?})", pat, place_with_id);
623-
624620
// If (pattern) adjustments are active for this pattern, adjust the `PlaceWithHirId` correspondingly.
625621
// `PlaceWithHirId`s are constructed differently from patterns. For example, in
626622
//
@@ -654,11 +650,11 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
654650
// `deref { deref { place_foo }}` instead of `place_foo` since the pattern is now `Some(x,)`
655651
// and not `&&Some(x,)`, even though its assigned type is that of `&&Some(x,)`.
656652
for _ in 0..self.typeck_results.pat_adjustments().get(pat.hir_id).map_or(0, |v| v.len()) {
657-
debug!("cat_pattern: applying adjustment to place_with_id={:?}", place_with_id);
653+
debug!("applying adjustment to place_with_id={:?}", place_with_id);
658654
place_with_id = self.cat_deref(pat, place_with_id)?;
659655
}
660656
let place_with_id = place_with_id; // lose mutability
661-
debug!("cat_pattern: applied adjustment derefs to get place_with_id={:?}", place_with_id);
657+
debug!("applied adjustment derefs to get place_with_id={:?}", place_with_id);
662658

663659
// Invoke the callback, but only now, after the `place_with_id` has adjusted.
664660
//

‎compiler/rustc_hir_typeck/src/upvar.rs

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -264,12 +264,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
264264
self.demand_eqtype(span, closure_kind.to_ty(self.tcx), closure_kind_ty);
265265

266266
// If we have an origin, store it.
267-
if let Some(origin) = origin {
268-
let origin = if enable_precise_capture(span) {
269-
(origin.0, origin.1)
270-
} else {
271-
(origin.0, Place { projections: vec![], ..origin.1 })
272-
};
267+
if let Some(mut origin) = origin {
268+
if !enable_precise_capture(span) {
269+
// Without precise captures, we just capture the base and ignore
270+
// the projections.
271+
origin.1.projections.clear()
272+
}
273273

274274
self.typeck_results
275275
.borrow_mut()
@@ -294,10 +294,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
294294

295295
// Equate the type variables for the upvars with the actual types.
296296
let final_upvar_tys = self.final_upvar_tys(closure_def_id);
297-
debug!(
298-
"analyze_closure: id={:?} args={:?} final_upvar_tys={:?}",
299-
closure_hir_id, args, final_upvar_tys
300-
);
297+
debug!(?closure_hir_id, ?args, ?final_upvar_tys);
301298

302299
// Build a tuple (U0..Un) of the final upvar types U0..Un
303300
// and unify the upvar tuple type in the closure with it:
@@ -338,10 +335,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
338335
let upvar_ty = captured_place.place.ty();
339336
let capture = captured_place.info.capture_kind;
340337

341-
debug!(
342-
"final_upvar_tys: place={:?} upvar_ty={:?} capture={:?}, mutability={:?}",
343-
captured_place.place, upvar_ty, capture, captured_place.mutability,
344-
);
338+
debug!(?captured_place.place, ?upvar_ty, ?capture, ?captured_place.mutability);
345339

346340
apply_capture_kind_on_capture_ty(self.tcx, upvar_ty, capture, captured_place.region)
347341
})
@@ -679,6 +673,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
679673
match (p1.kind, p2.kind) {
680674
// Paths are the same, continue to next loop.
681675
(ProjectionKind::Deref, ProjectionKind::Deref) => {}
676+
(ProjectionKind::OpaqueCast, ProjectionKind::OpaqueCast) => {}
682677
(ProjectionKind::Field(i1, _), ProjectionKind::Field(i2, _))
683678
if i1 == i2 => {}
684679

@@ -701,10 +696,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
701696
l @ (ProjectionKind::Index
702697
| ProjectionKind::Subslice
703698
| ProjectionKind::Deref
699+
| ProjectionKind::OpaqueCast
704700
| ProjectionKind::Field(..)),
705701
r @ (ProjectionKind::Index
706702
| ProjectionKind::Subslice
707703
| ProjectionKind::Deref
704+
| ProjectionKind::OpaqueCast
708705
| ProjectionKind::Field(..)),
709706
) => bug!(
710707
"ProjectionKinds Index or Subslice were unexpected: ({:?}, {:?})",
@@ -1890,6 +1887,7 @@ fn restrict_capture_precision(
18901887
return (place, curr_mode);
18911888
}
18921889
ProjectionKind::Deref => {}
1890+
ProjectionKind::OpaqueCast => {}
18931891
ProjectionKind::Field(..) => {} // ignore
18941892
}
18951893
}
@@ -1946,6 +1944,7 @@ fn construct_place_string<'tcx>(tcx: TyCtxt<'_>, place: &Place<'tcx>) -> String
19461944
ProjectionKind::Deref => String::from("Deref"),
19471945
ProjectionKind::Index => String::from("Index"),
19481946
ProjectionKind::Subslice => String::from("Subslice"),
1947+
ProjectionKind::OpaqueCast => String::from("OpaqueCast"),
19491948
};
19501949
if i != 0 {
19511950
projections_str.push(',');

‎compiler/rustc_infer/src/infer/canonical/canonicalizer.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -562,15 +562,9 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
562562
V: TypeFoldable<TyCtxt<'tcx>>,
563563
{
564564
let needs_canonical_flags = if canonicalize_region_mode.any() {
565-
TypeFlags::HAS_INFER |
566-
TypeFlags::HAS_FREE_REGIONS | // `HAS_RE_PLACEHOLDER` implies `HAS_FREE_REGIONS`
567-
TypeFlags::HAS_TY_PLACEHOLDER |
568-
TypeFlags::HAS_CT_PLACEHOLDER
565+
TypeFlags::HAS_INFER | TypeFlags::HAS_PLACEHOLDER | TypeFlags::HAS_FREE_REGIONS
569566
} else {
570-
TypeFlags::HAS_INFER
571-
| TypeFlags::HAS_RE_PLACEHOLDER
572-
| TypeFlags::HAS_TY_PLACEHOLDER
573-
| TypeFlags::HAS_CT_PLACEHOLDER
567+
TypeFlags::HAS_INFER | TypeFlags::HAS_PLACEHOLDER
574568
};
575569

576570
// Fast path: nothing that needs to be canonicalized.

‎compiler/rustc_metadata/src/rmeta/encoder.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ use rustc_middle::query::Providers;
3030
use rustc_middle::traits::specialization_graph;
3131
use rustc_middle::ty::codec::TyEncoder;
3232
use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams};
33+
use rustc_middle::ty::TypeVisitableExt;
3334
use rustc_middle::ty::{self, AssocItemContainer, SymbolName, Ty, TyCtxt};
3435
use rustc_middle::util::common::to_readable_str;
3536
use rustc_serialize::{opaque, Decodable, Decoder, Encodable, Encoder};
@@ -1034,7 +1035,7 @@ fn should_encode_mir(tcx: TyCtxt<'_>, def_id: LocalDefId) -> (bool, bool) {
10341035
}
10351036
}
10361037

1037-
fn should_encode_variances(def_kind: DefKind) -> bool {
1038+
fn should_encode_variances<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, def_kind: DefKind) -> bool {
10381039
match def_kind {
10391040
DefKind::Struct
10401041
| DefKind::Union
@@ -1053,7 +1054,6 @@ fn should_encode_variances(def_kind: DefKind) -> bool {
10531054
| DefKind::Static(..)
10541055
| DefKind::Const
10551056
| DefKind::ForeignMod
1056-
| DefKind::TyAlias
10571057
| DefKind::Impl { .. }
10581058
| DefKind::Trait
10591059
| DefKind::TraitAlias
@@ -1067,6 +1067,10 @@ fn should_encode_variances(def_kind: DefKind) -> bool {
10671067
| DefKind::Closure
10681068
| DefKind::Generator
10691069
| DefKind::ExternCrate => false,
1070+
DefKind::TyAlias => {
1071+
tcx.features().lazy_type_alias
1072+
|| tcx.type_of(def_id).instantiate_identity().has_opaque_types()
1073+
}
10701074
}
10711075
}
10721076

@@ -1349,7 +1353,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
13491353
self.encode_default_body_stability(def_id);
13501354
self.encode_deprecation(def_id);
13511355
}
1352-
if should_encode_variances(def_kind) {
1356+
if should_encode_variances(tcx, def_id, def_kind) {
13531357
let v = self.tcx.variances_of(def_id);
13541358
record_array!(self.tables.variances_of[def_id] <- v);
13551359
}

‎compiler/rustc_middle/src/hir/place.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ pub enum ProjectionKind {
3636

3737
/// A subslice covering a range of values like `B[x..y]`.
3838
Subslice,
39+
40+
/// A conversion from an opaque type to its hidden type so we can
41+
/// do further projections on it.
42+
OpaqueCast,
3943
}
4044

4145
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]

‎compiler/rustc_middle/src/query/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -749,7 +749,7 @@ rustc_queries! {
749749
separate_provide_extern
750750
}
751751

752-
/// Gets a map with the variance of every item; use `item_variance` instead.
752+
/// Gets a map with the variance of every item; use `variances_of` instead.
753753
query crate_variances(_: ()) -> &'tcx ty::CrateVariancesMap<'tcx> {
754754
arena_cache
755755
desc { "computing the variances for items in this crate" }

‎compiler/rustc_middle/src/traits/solve.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ impl<'tcx> std::ops::Deref for ExternalConstraints<'tcx> {
147147
}
148148

149149
/// Additional constraints returned on success.
150-
#[derive(Debug, PartialEq, Eq, Clone, Hash, HashStable, Default)]
150+
#[derive(Debug, PartialEq, Eq, Clone, Hash, HashStable, Default, TypeVisitable, TypeFoldable)]
151151
pub struct ExternalConstraintsData<'tcx> {
152152
// FIXME: implement this.
153153
pub region_constraints: QueryRegionConstraints<'tcx>,

‎compiler/rustc_middle/src/ty/closure.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,8 @@ impl<'tcx> CapturedPlace<'tcx> {
174174
// Ignore derefs for now, as they are likely caused by
175175
// autoderefs that don't appear in the original code.
176176
HirProjectionKind::Deref => {}
177+
// Just change the type to the hidden type, so we can actually project.
178+
HirProjectionKind::OpaqueCast => {}
177179
proj => bug!("Unexpected projection {:?} in captured place", proj),
178180
}
179181
ty = proj.ty;

‎compiler/rustc_middle/src/ty/visit.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -88,14 +88,10 @@ pub trait TypeVisitableExt<'tcx>: TypeVisitable<TyCtxt<'tcx>> {
8888
self.has_type_flags(TypeFlags::HAS_INFER)
8989
}
9090
fn has_placeholders(&self) -> bool {
91-
self.has_type_flags(
92-
TypeFlags::HAS_RE_PLACEHOLDER
93-
| TypeFlags::HAS_TY_PLACEHOLDER
94-
| TypeFlags::HAS_CT_PLACEHOLDER,
95-
)
91+
self.has_type_flags(TypeFlags::HAS_PLACEHOLDER)
9692
}
9793
fn has_non_region_placeholders(&self) -> bool {
98-
self.has_type_flags(TypeFlags::HAS_TY_PLACEHOLDER | TypeFlags::HAS_CT_PLACEHOLDER)
94+
self.has_type_flags(TypeFlags::HAS_PLACEHOLDER - TypeFlags::HAS_RE_PLACEHOLDER)
9995
}
10096
fn has_param(&self) -> bool {
10197
self.has_type_flags(TypeFlags::HAS_PARAM)

‎compiler/rustc_mir_build/src/build/expr/as_place.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,9 @@ fn strip_prefix<'a, 'tcx>(
236236
}
237237
assert_matches!(iter.next(), Some(ProjectionElem::Field(..)));
238238
}
239+
HirProjectionKind::OpaqueCast => {
240+
assert_matches!(iter.next(), Some(ProjectionElem::OpaqueCast(..)));
241+
}
239242
HirProjectionKind::Index | HirProjectionKind::Subslice => {
240243
bug!("unexpected projection kind: {:?}", projection);
241244
}

‎compiler/rustc_mir_build/src/thir/cx/expr.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1072,6 +1072,9 @@ impl<'tcx> Cx<'tcx> {
10721072
variant_index,
10731073
name: field,
10741074
},
1075+
HirProjectionKind::OpaqueCast => {
1076+
ExprKind::Use { source: self.thir.exprs.push(captured_place_expr) }
1077+
}
10751078
HirProjectionKind::Index | HirProjectionKind::Subslice => {
10761079
// We don't capture these projections, so we can ignore them here
10771080
continue;

‎compiler/rustc_trait_selection/src/solve/canonicalize.rs

Lines changed: 35 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -207,23 +207,18 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> {
207207
t
208208
}
209209

210-
fn fold_region(&mut self, mut r: ty::Region<'tcx>) -> ty::Region<'tcx> {
211-
match self.canonicalize_mode {
212-
CanonicalizeMode::Input => {
213-
// Don't resolve infer vars in input, since it affects
214-
// caching and may cause trait selection bugs which rely
215-
// on regions to be equal.
216-
}
217-
CanonicalizeMode::Response { .. } => {
218-
if let ty::ReVar(vid) = *r {
219-
r = self
220-
.infcx
221-
.inner
222-
.borrow_mut()
223-
.unwrap_region_constraints()
224-
.opportunistic_resolve_var(self.infcx.tcx, vid);
225-
}
226-
}
210+
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
211+
if let ty::ReVar(vid) = *r {
212+
let resolved_region = self
213+
.infcx
214+
.inner
215+
.borrow_mut()
216+
.unwrap_region_constraints()
217+
.opportunistic_resolve_var(self.infcx.tcx, vid);
218+
assert_eq!(
219+
r, resolved_region,
220+
"region var should have been resolved, {r} -> {resolved_region}"
221+
);
227222
}
228223

229224
let kind = match *r {
@@ -278,38 +273,22 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> {
278273
ty::Region::new_late_bound(self.interner(), self.binder_index, br)
279274
}
280275

281-
fn fold_ty(&mut self, mut t: Ty<'tcx>) -> Ty<'tcx> {
276+
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
282277
let kind = match *t.kind() {
283-
ty::Infer(ty::TyVar(mut vid)) => {
284-
// We need to canonicalize the *root* of our ty var.
285-
// This is so that our canonical response correctly reflects
286-
// any equated inference vars correctly!
287-
let root_vid = self.infcx.root_var(vid);
288-
if root_vid != vid {
289-
t = Ty::new_var(self.infcx.tcx, root_vid);
290-
vid = root_vid;
291-
}
292-
293-
match self.infcx.probe_ty_var(vid) {
294-
Ok(t) => return self.fold_ty(t),
295-
Err(ui) => CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)),
296-
}
278+
ty::Infer(ty::TyVar(vid)) => {
279+
assert_eq!(self.infcx.root_var(vid), vid, "ty vid should have been resolved");
280+
let Err(ui) = self.infcx.probe_ty_var(vid) else {
281+
bug!("ty var should have been resolved: {t}");
282+
};
283+
CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui))
297284
}
298285
ty::Infer(ty::IntVar(vid)) => {
299-
let nt = self.infcx.opportunistic_resolve_int_var(vid);
300-
if nt != t {
301-
return self.fold_ty(nt);
302-
} else {
303-
CanonicalVarKind::Ty(CanonicalTyVarKind::Int)
304-
}
286+
assert_eq!(self.infcx.opportunistic_resolve_int_var(vid), t);
287+
CanonicalVarKind::Ty(CanonicalTyVarKind::Int)
305288
}
306289
ty::Infer(ty::FloatVar(vid)) => {
307-
let nt = self.infcx.opportunistic_resolve_float_var(vid);
308-
if nt != t {
309-
return self.fold_ty(nt);
310-
} else {
311-
CanonicalVarKind::Ty(CanonicalTyVarKind::Float)
312-
}
290+
assert_eq!(self.infcx.opportunistic_resolve_float_var(vid), t);
291+
CanonicalVarKind::Ty(CanonicalTyVarKind::Float)
313292
}
314293
ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
315294
bug!("fresh var during canonicalization: {t:?}")
@@ -372,22 +351,19 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> {
372351
Ty::new_bound(self.infcx.tcx, self.binder_index, bt)
373352
}
374353

375-
fn fold_const(&mut self, mut c: ty::Const<'tcx>) -> ty::Const<'tcx> {
354+
fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> {
376355
let kind = match c.kind() {
377-
ty::ConstKind::Infer(ty::InferConst::Var(mut vid)) => {
378-
// We need to canonicalize the *root* of our const var.
379-
// This is so that our canonical response correctly reflects
380-
// any equated inference vars correctly!
381-
let root_vid = self.infcx.root_const_var(vid);
382-
if root_vid != vid {
383-
c = ty::Const::new_var(self.infcx.tcx, root_vid, c.ty());
384-
vid = root_vid;
385-
}
386-
387-
match self.infcx.probe_const_var(vid) {
388-
Ok(c) => return self.fold_const(c),
389-
Err(universe) => CanonicalVarKind::Const(universe, c.ty()),
390-
}
356+
ty::ConstKind::Infer(ty::InferConst::Var(vid)) => {
357+
assert_eq!(
358+
self.infcx.root_const_var(vid),
359+
vid,
360+
"const var should have been resolved"
361+
);
362+
let Err(ui) = self.infcx.probe_const_var(vid) else {
363+
bug!("const var should have been resolved");
364+
};
365+
// FIXME: we should fold this ty eventually
366+
CanonicalVarKind::Const(ui, c.ty())
391367
}
392368
ty::ConstKind::Infer(ty::InferConst::Fresh(_)) => {
393369
bug!("fresh var during canonicalization: {c:?}")

‎compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs

Lines changed: 109 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,15 @@ use rustc_index::IndexVec;
1616
use rustc_infer::infer::canonical::query_response::make_query_region_constraints;
1717
use rustc_infer::infer::canonical::CanonicalVarValues;
1818
use rustc_infer::infer::canonical::{CanonicalExt, QueryRegionConstraints};
19+
use rustc_infer::infer::InferCtxt;
1920
use rustc_middle::traits::query::NoSolution;
2021
use rustc_middle::traits::solve::{
21-
ExternalConstraints, ExternalConstraintsData, MaybeCause, PredefinedOpaquesData, QueryInput,
22+
ExternalConstraintsData, MaybeCause, PredefinedOpaquesData, QueryInput,
23+
};
24+
use rustc_middle::ty::{
25+
self, BoundVar, GenericArgKind, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
26+
TypeVisitableExt,
2227
};
23-
use rustc_middle::ty::{self, BoundVar, GenericArgKind, Ty, TyCtxt, TypeFoldable};
2428
use rustc_span::DUMMY_SP;
2529
use std::iter;
2630
use std::ops::Deref;
@@ -32,6 +36,10 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
3236
&self,
3337
goal: Goal<'tcx, T>,
3438
) -> (Vec<ty::GenericArg<'tcx>>, CanonicalInput<'tcx, T>) {
39+
let opaque_types = self.infcx.clone_opaque_types_for_query_response();
40+
let (goal, opaque_types) =
41+
(goal, opaque_types).fold_with(&mut EagerResolver { infcx: self.infcx });
42+
3543
let mut orig_values = Default::default();
3644
let canonical_goal = Canonicalizer::canonicalize(
3745
self.infcx,
@@ -40,11 +48,9 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
4048
QueryInput {
4149
goal,
4250
anchor: self.infcx.defining_use_anchor,
43-
predefined_opaques_in_body: self.tcx().mk_predefined_opaques_in_body(
44-
PredefinedOpaquesData {
45-
opaque_types: self.infcx.clone_opaque_types_for_query_response(),
46-
},
47-
),
51+
predefined_opaques_in_body: self
52+
.tcx()
53+
.mk_predefined_opaques_in_body(PredefinedOpaquesData { opaque_types }),
4854
},
4955
);
5056
(orig_values, canonical_goal)
@@ -70,34 +76,43 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
7076
);
7177

7278
let certainty = certainty.unify_with(goals_certainty);
79+
if let Certainty::OVERFLOW = certainty {
80+
// If we have overflow, it's probable that we're substituting a type
81+
// into itself infinitely and any partial substitutions in the query
82+
// response are probably not useful anyways, so just return an empty
83+
// query response.
84+
//
85+
// This may prevent us from potentially useful inference, e.g.
86+
// 2 candidates, one ambiguous and one overflow, which both
87+
// have the same inference constraints.
88+
//
89+
// Changing this to retain some constraints in the future
90+
// won't be a breaking change, so this is good enough for now.
91+
return Ok(self.make_ambiguous_response_no_constraints(MaybeCause::Overflow));
92+
}
7393

74-
let response = match certainty {
75-
Certainty::Yes | Certainty::Maybe(MaybeCause::Ambiguity) => {
76-
let external_constraints = self.compute_external_query_constraints()?;
77-
Response { var_values: self.var_values, external_constraints, certainty }
78-
}
79-
Certainty::Maybe(MaybeCause::Overflow) => {
80-
// If we have overflow, it's probable that we're substituting a type
81-
// into itself infinitely and any partial substitutions in the query
82-
// response are probably not useful anyways, so just return an empty
83-
// query response.
84-
//
85-
// This may prevent us from potentially useful inference, e.g.
86-
// 2 candidates, one ambiguous and one overflow, which both
87-
// have the same inference constraints.
88-
//
89-
// Changing this to retain some constraints in the future
90-
// won't be a breaking change, so this is good enough for now.
91-
return Ok(self.make_ambiguous_response_no_constraints(MaybeCause::Overflow));
92-
}
93-
};
94+
let var_values = self.var_values;
95+
let external_constraints = self.compute_external_query_constraints()?;
96+
97+
let (var_values, mut external_constraints) =
98+
(var_values, external_constraints).fold_with(&mut EagerResolver { infcx: self.infcx });
99+
// Remove any trivial region constraints once we've resolved regions
100+
external_constraints
101+
.region_constraints
102+
.outlives
103+
.retain(|(outlives, _)| outlives.0.as_region().map_or(true, |re| re != outlives.1));
94104

95105
let canonical = Canonicalizer::canonicalize(
96106
self.infcx,
97107
CanonicalizeMode::Response { max_input_universe: self.max_input_universe },
98108
&mut Default::default(),
99-
response,
109+
Response {
110+
var_values,
111+
certainty,
112+
external_constraints: self.tcx().mk_external_constraints(external_constraints),
113+
},
100114
);
115+
101116
Ok(canonical)
102117
}
103118

@@ -143,7 +158,9 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
143158
/// further constrained by inference, that will be passed back in the var
144159
/// values.
145160
#[instrument(level = "debug", skip(self), ret)]
146-
fn compute_external_query_constraints(&self) -> Result<ExternalConstraints<'tcx>, NoSolution> {
161+
fn compute_external_query_constraints(
162+
&self,
163+
) -> Result<ExternalConstraintsData<'tcx>, NoSolution> {
147164
// We only check for leaks from universes which were entered inside
148165
// of the query.
149166
self.infcx.leak_check(self.max_input_universe, None).map_err(|e| {
@@ -173,9 +190,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
173190
self.predefined_opaques_in_body.opaque_types.iter().all(|(pa, _)| pa != a)
174191
});
175192

176-
Ok(self
177-
.tcx()
178-
.mk_external_constraints(ExternalConstraintsData { region_constraints, opaque_types }))
193+
Ok(ExternalConstraintsData { region_constraints, opaque_types })
179194
}
180195

181196
/// After calling a canonical query, we apply the constraints returned
@@ -333,3 +348,65 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
333348
Ok(())
334349
}
335350
}
351+
352+
/// Resolves ty, region, and const vars to their inferred values or their root vars.
353+
struct EagerResolver<'a, 'tcx> {
354+
infcx: &'a InferCtxt<'tcx>,
355+
}
356+
357+
impl<'tcx> TypeFolder<TyCtxt<'tcx>> for EagerResolver<'_, 'tcx> {
358+
fn interner(&self) -> TyCtxt<'tcx> {
359+
self.infcx.tcx
360+
}
361+
362+
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
363+
match *t.kind() {
364+
ty::Infer(ty::TyVar(vid)) => match self.infcx.probe_ty_var(vid) {
365+
Ok(t) => t.fold_with(self),
366+
Err(_) => Ty::new_var(self.infcx.tcx, self.infcx.root_var(vid)),
367+
},
368+
ty::Infer(ty::IntVar(vid)) => self.infcx.opportunistic_resolve_int_var(vid),
369+
ty::Infer(ty::FloatVar(vid)) => self.infcx.opportunistic_resolve_float_var(vid),
370+
_ => {
371+
if t.has_infer() {
372+
t.super_fold_with(self)
373+
} else {
374+
t
375+
}
376+
}
377+
}
378+
}
379+
380+
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
381+
match *r {
382+
ty::ReVar(vid) => self
383+
.infcx
384+
.inner
385+
.borrow_mut()
386+
.unwrap_region_constraints()
387+
.opportunistic_resolve_var(self.infcx.tcx, vid),
388+
_ => r,
389+
}
390+
}
391+
392+
fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> {
393+
match c.kind() {
394+
ty::ConstKind::Infer(ty::InferConst::Var(vid)) => {
395+
// FIXME: we need to fold the ty too, I think.
396+
match self.infcx.probe_const_var(vid) {
397+
Ok(c) => c.fold_with(self),
398+
Err(_) => {
399+
ty::Const::new_var(self.infcx.tcx, self.infcx.root_const_var(vid), c.ty())
400+
}
401+
}
402+
}
403+
_ => {
404+
if c.has_infer() {
405+
c.super_fold_with(self)
406+
} else {
407+
c
408+
}
409+
}
410+
}
411+
}
412+
}

‎compiler/rustc_type_ir/src/lib.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,11 @@ bitflags! {
216216
/// Does this have `ConstKind::Placeholder`?
217217
const HAS_CT_PLACEHOLDER = 1 << 8;
218218

219+
/// Does this have placeholders?
220+
const HAS_PLACEHOLDER = TypeFlags::HAS_TY_PLACEHOLDER.bits
221+
| TypeFlags::HAS_RE_PLACEHOLDER.bits
222+
| TypeFlags::HAS_CT_PLACEHOLDER.bits;
223+
219224
/// `true` if there are "names" of regions and so forth
220225
/// that are local to a particular fn/inferctxt
221226
const HAS_FREE_LOCAL_REGIONS = 1 << 9;

‎src/bootstrap/config.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2004,7 +2004,8 @@ impl Config {
20042004
.unwrap();
20052005
if !(source_version == rustc_version
20062006
|| (source_version.major == rustc_version.major
2007-
&& source_version.minor == rustc_version.minor + 1))
2007+
&& (source_version.minor == rustc_version.minor
2008+
|| source_version.minor == rustc_version.minor + 1)))
20082009
{
20092010
let prev_version = format!("{}.{}.x", source_version.major, source_version.minor - 1);
20102011
eprintln!(

‎src/tools/clippy/clippy_utils/src/sugg.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1011,6 +1011,8 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
10111011
},
10121012
// note: unable to trigger `Subslice` kind in tests
10131013
ProjectionKind::Subslice => (),
1014+
// Doesn't have surface syntax. Only occurs in patterns.
1015+
ProjectionKind::OpaqueCast => (),
10141016
ProjectionKind::Deref => {
10151017
// Explicit derefs are typically handled later on, but
10161018
// some items do not need explicit deref, such as array accesses,

‎tests/rustdoc-json/type/inherent_associated_type_bound.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,15 @@
55
// @set Carrier = '$.index[*][?(@.name=="Carrier")].id'
66
pub struct Carrier<'a>(&'a ());
77

8-
// @is '$.index[*][?(@.name=="User")].inner.typedef.type.function_pointer.generic_params[*].name' \""'b"\"
9-
// @is '$.index[*][?(@.name=="User")].inner.typedef.type.function_pointer.decl.inputs[0][1].qualified_path.self_type.resolved_path.id' $Carrier
10-
// @is '$.index[*][?(@.name=="User")].inner.typedef.type.function_pointer.decl.inputs[0][1].qualified_path.self_type.resolved_path.args.angle_bracketed.args[0].lifetime' \""'b"\"
11-
// @is '$.index[*][?(@.name=="User")].inner.typedef.type.function_pointer.decl.inputs[0][1].qualified_path.name' '"Focus"'
12-
// @is '$.index[*][?(@.name=="User")].inner.typedef.type.function_pointer.decl.inputs[0][1].qualified_path.trait' null
13-
// @is '$.index[*][?(@.name=="User")].inner.typedef.type.function_pointer.decl.inputs[0][1].qualified_path.args.angle_bracketed.args[0].type.primitive' '"i32"'
14-
15-
pub type User = for<'b> fn(Carrier<'b>::Focus<i32>);
8+
// @count "$.index[*][?(@.name=='user')].inner.function.decl.inputs[*]" 1
9+
// @is "$.index[*][?(@.name=='user')].inner.function.decl.inputs[0][0]" '"_"'
10+
// @is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.generic_params[*].name' \""'b"\"
11+
// @is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.decl.inputs[0][1].qualified_path.self_type.resolved_path.id' $Carrier
12+
// @is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.decl.inputs[0][1].qualified_path.self_type.resolved_path.args.angle_bracketed.args[0].lifetime' \""'b"\"
13+
// @is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.decl.inputs[0][1].qualified_path.name' '"Focus"'
14+
// @is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.decl.inputs[0][1].qualified_path.trait' null
15+
// @is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.decl.inputs[0][1].qualified_path.args.angle_bracketed.args[0].type.primitive' '"i32"'
16+
pub fn user(_: for<'b> fn(Carrier<'b>::Focus<i32>)) {}
1617

1718
impl<'a> Carrier<'a> {
1819
pub type Focus<T> = &'a mut T;

‎tests/rustdoc-json/type/inherent_associated_type_projections.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@
55
// @set Parametrized = '$.index[*][?(@.name=="Parametrized")].id'
66
pub struct Parametrized<T>(T);
77

8-
// @is '$.index[*][?(@.name=="Test")].inner.typedef.type.qualified_path.self_type.resolved_path.id' $Parametrized
9-
// @is '$.index[*][?(@.name=="Test")].inner.typedef.type.qualified_path.self_type.resolved_path.args.angle_bracketed.args[0].type.primitive' \"i32\"
10-
// @is '$.index[*][?(@.name=="Test")].inner.typedef.type.qualified_path.name' '"Proj"'
11-
// @is '$.index[*][?(@.name=="Test")].inner.typedef.type.qualified_path.trait' null
12-
pub type Test = Parametrized<i32>::Proj;
8+
// @count "$.index[*][?(@.name=='test')].inner.function.decl.inputs[*]" 1
9+
// @is "$.index[*][?(@.name=='test')].inner.function.decl.inputs[0][0]" '"_"'
10+
// @is '$.index[*][?(@.name=="test")].inner.function.decl.inputs[0][1].qualified_path.self_type.resolved_path.id' $Parametrized
11+
// @is '$.index[*][?(@.name=="test")].inner.function.decl.inputs[0][1].qualified_path.self_type.resolved_path.args.angle_bracketed.args[0].type.primitive' \"i32\"
12+
// @is '$.index[*][?(@.name=="test")].inner.function.decl.inputs[0][1].qualified_path.name' '"Proj"'
13+
// @is '$.index[*][?(@.name=="test")].inner.function.decl.inputs[0][1].qualified_path.trait' null
14+
pub fn test(_: Parametrized<i32>::Proj) {}
1315

1416
/// param_bool
1517
impl Parametrized<bool> {

‎tests/rustdoc/inherent-projections.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ impl Owner {
1313
}
1414

1515
// Make sure we handle bound vars correctly.
16-
// @has 'inherent_projections/type.User.html' '//pre[@class="rust item-decl"]' "for<'a> fn(_: Carrier<'a>::Focus)"
17-
pub type User = for<'a> fn(Carrier<'a>::Focus);
16+
// @has 'inherent_projections/fn.user.html' '//pre[@class="rust item-decl"]' "user(_: for<'a> fn(_: Carrier<'a>::Focus))"
17+
pub fn user(_: for<'a> fn(Carrier<'a>::Focus)) {}
1818

1919
pub struct Carrier<'a>(&'a ());
2020

@@ -27,11 +27,11 @@ impl<'a> Carrier<'a> {
2727
// FIXME(inherent_associated_types): Below we link to `Proj` but we should link to `Proj-1`.
2828
// The current test checks for the buggy behavior for demonstration purposes.
2929

30-
// @has 'inherent_projections/type.Test.html'
31-
// @has - '//pre[@class="rust item-decl"]' "Parametrized<i32>"
30+
// @has 'inherent_projections/fn.test.html'
31+
// @has - '//pre[@class="rust item-decl"]' "test(_: Parametrized<i32>::Proj)"
3232
// @has - '//pre[@class="rust item-decl"]//a[@class="associatedtype"]/@href' 'struct.Parametrized.html#associatedtype.Proj'
3333
// @!has - '//pre[@class="rust item-decl"]//a[@class="associatedtype"]/@href' 'struct.Parametrized.html#associatedtype.Proj-1'
34-
pub type Test = Parametrized<i32>::Proj;
34+
pub fn test(_: Parametrized<i32>::Proj) {}
3535

3636
pub struct Parametrized<T>(T);
3737

‎tests/ui/associated-inherent-types/issue-111879-0.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,8 @@
55

66
pub struct Carrier<'a>(&'a ());
77

8-
pub type User = for<'b> fn(Carrier<'b>::Focus<i32>);
9-
108
impl<'a> Carrier<'a> {
11-
pub type Focus<T> = &'a mut User; //~ ERROR overflow evaluating associated type
9+
pub type Focus<T> = &'a mut for<'b> fn(Carrier<'b>::Focus<i32>); //~ ERROR overflow evaluating associated type
1210
}
1311

1412
fn main() {}
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error: overflow evaluating associated type `Carrier<'b>::Focus<i32>`
2-
--> $DIR/issue-111879-0.rs:11:25
2+
--> $DIR/issue-111879-0.rs:9:25
33
|
4-
LL | pub type Focus<T> = &'a mut User;
5-
| ^^^^^^^^^^^^
4+
LL | pub type Focus<T> = &'a mut for<'b> fn(Carrier<'b>::Focus<i32>);
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66

77
error: aborting due to previous error
88

‎tests/ui/associated-inherent-types/late-bound-regions.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33

44
// Test if we correctly normalize `S<'a>::P` with respect to late-bound regions.
55

6-
type Function = for<'a> fn(&'a i32) -> S<'a>::P;
7-
86
struct S<'a>(&'a ());
97

108
trait Inter {
@@ -16,7 +14,7 @@ impl<'a> S<'a> {
1614
}
1715

1816
fn ret_ref_local<'e>() -> &'e i32 {
19-
let f: Function = |x| x;
17+
let f: for<'a> fn(&'a i32) -> S<'a>::P = |x| x;
2018

2119
let local = 0;
2220
f(&local) //~ ERROR cannot return value referencing local variable `local`

‎tests/ui/associated-inherent-types/late-bound-regions.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0515]: cannot return value referencing local variable `local`
2-
--> $DIR/late-bound-regions.rs:22:5
2+
--> $DIR/late-bound-regions.rs:20:5
33
|
44
LL | f(&local)
55
| ^^------^

‎tests/ui/associated-inherent-types/not-found-self-type-differs.alias.stderr

Lines changed: 0 additions & 16 deletions
This file was deleted.

‎tests/ui/associated-inherent-types/not-found-self-type-differs.local.stderr

Lines changed: 0 additions & 16 deletions
This file was deleted.
Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
// revisions: local alias
2-
31
#![feature(inherent_associated_types)]
42
#![allow(incomplete_features)]
53

@@ -13,10 +11,7 @@ impl<T> Family<Result<T, ()>> {
1311
type Proj = Self;
1412
}
1513

16-
#[cfg(alias)]
17-
type Alias = Family<Option<()>>::Proj; //[alias]~ ERROR associated type `Proj` not found for `Family<Option<()>>`
18-
1914
fn main() {
20-
#[cfg(local)]
21-
let _: Family<std::path::PathBuf>::Proj = (); //[local]~ ERROR associated type `Proj` not found for `Family<PathBuf>`
15+
let _: Family<Option<()>>::Proj; //~ ERROR associated type `Proj` not found for `Family<Option<()>>`
16+
let _: Family<std::path::PathBuf>::Proj = (); //~ ERROR associated type `Proj` not found for `Family<PathBuf>`
2217
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
error[E0220]: associated type `Proj` not found for `Family<Option<()>>` in the current scope
2+
--> $DIR/not-found-self-type-differs.rs:15:32
3+
|
4+
LL | struct Family<T>(T);
5+
| ---------------- associated item `Proj` not found for this struct
6+
...
7+
LL | let _: Family<Option<()>>::Proj;
8+
| ^^^^ associated item not found in `Family<Option<()>>`
9+
|
10+
= note: the associated type was found for
11+
- `Family<()>`
12+
- `Family<Result<T, ()>>`
13+
14+
error[E0220]: associated type `Proj` not found for `Family<PathBuf>` in the current scope
15+
--> $DIR/not-found-self-type-differs.rs:16:40
16+
|
17+
LL | struct Family<T>(T);
18+
| ---------------- associated item `Proj` not found for this struct
19+
...
20+
LL | let _: Family<std::path::PathBuf>::Proj = ();
21+
| ^^^^ associated item not found in `Family<PathBuf>`
22+
|
23+
= note: the associated type was found for
24+
- `Family<()>`
25+
- `Family<Result<T, ()>>`
26+
27+
error: aborting due to 2 previous errors
28+
29+
For more information about this error, try `rustc --explain E0220`.

‎tests/ui/associated-inherent-types/substitute-params-bad.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ impl<T, S> Subj<(T, S)> {
1717
}
1818

1919
fn main() {
20-
type A = S<()>::P;
20+
let _: S<()>::P;
2121

2222
let _: Subj<(i32, i32)>::Un = 0i32; //~ ERROR mismatched types
2323
}

‎tests/ui/associated-inherent-types/substitute-params.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@ impl<T> S<(T,)> {
1515

1616
fn main() {
1717
// Regression test for issue #104240.
18-
type A = S<()>::P;
19-
let _: A = ();
18+
let _: S<()>::P = ();
2019

2120
// Regression test for issue #107468.
2221
let _: S<(i32,)>::Un = 0i32;

‎tests/ui/associated-inherent-types/type-alias-bounds-are-enforced.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
// check-pass
1+
// FIXME(inherent_associated_types): This should be `check-pass`
2+
// known-bug: #108491
23
// compile-flags: --crate-type=lib
34

45
#![feature(inherent_associated_types)]
@@ -17,7 +18,6 @@
1718

1819
pub type Alias<T: Bound> = (Source<T>::Assoc,);
1920

20-
2121
pub struct Source<T>(T);
2222
pub trait Bound {}
2323

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
error[E0391]: cycle detected when expanding type alias `Alias`
2+
--> $DIR/type-alias-bounds-are-enforced.rs:19:1
3+
|
4+
LL | pub type Alias<T: Bound> = (Source<T>::Assoc,);
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
note: ...which requires computing the variances of `Source`...
8+
--> $DIR/type-alias-bounds-are-enforced.rs:21:1
9+
|
10+
LL | pub struct Source<T>(T);
11+
| ^^^^^^^^^^^^^^^^^^^^
12+
= note: ...which requires computing the variances for items in this crate...
13+
= note: ...which again requires expanding type alias `Alias`, completing the cycle
14+
note: cycle used when collecting item types in top-level module
15+
--> $DIR/type-alias-bounds-are-enforced.rs:5:1
16+
|
17+
LL | / #![feature(inherent_associated_types)]
18+
LL | | #![allow(incomplete_features)]
19+
LL | |
20+
LL | | // Bounds on the self type play a major role in the resolution of inherent associated types (*).
21+
... |
22+
LL | | pub type Assoc = ();
23+
LL | | }
24+
| |_^
25+
= 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
26+
27+
error[E0391]: cycle detected when expanding type alias `Alias`
28+
--> $DIR/type-alias-bounds-are-enforced.rs:19:1
29+
|
30+
LL | pub type Alias<T: Bound> = (Source<T>::Assoc,);
31+
| ^^^^^^^^^^^^^^^^^^^^^^^^
32+
|
33+
note: ...which requires computing the variances of `Source`...
34+
--> $DIR/type-alias-bounds-are-enforced.rs:21:1
35+
|
36+
LL | pub struct Source<T>(T);
37+
| ^^^^^^^^^^^^^^^^^^^^
38+
= note: ...which requires computing the variances for items in this crate...
39+
= note: ...which again requires expanding type alias `Alias`, completing the cycle
40+
note: cycle used when collecting item types in top-level module
41+
--> $DIR/type-alias-bounds-are-enforced.rs:5:1
42+
|
43+
LL | / #![feature(inherent_associated_types)]
44+
LL | | #![allow(incomplete_features)]
45+
LL | |
46+
LL | | // Bounds on the self type play a major role in the resolution of inherent associated types (*).
47+
... |
48+
LL | | pub type Assoc = ();
49+
LL | | }
50+
| |_^
51+
= 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
52+
53+
error: aborting due to 2 previous errors
54+
55+
For more information about this error, try `rustc --explain E0391`.

‎tests/ui/lazy-type-alias/variance.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// This is a regression test for issue #114221.
2+
// Check that we compute variances for lazy type aliases.
3+
4+
// check-pass
5+
6+
#![feature(lazy_type_alias)]
7+
#![allow(incomplete_features)]
8+
9+
// [+] `A` is covariant over `'a`.
10+
struct A<'a>(Co<'a>);
11+
12+
// [+] `Co` is covariant over `'a`.
13+
type Co<'a> = &'a ();
14+
15+
fn co<'a>(x: A<'static>) {
16+
let _: A<'a> = x;
17+
}
18+
19+
// [-] `B` is contravariant over `'a`.
20+
struct B<'a>(Contra<'a>);
21+
22+
// [-] `Contra` is contravariant over `'a`.
23+
type Contra<'a> = fn(&'a ());
24+
25+
fn contra<'a>(x: B<'a>) {
26+
let _: B<'static> = x;
27+
}
28+
29+
struct C<T, U>(CoContra<T, U>);
30+
31+
// [+, -] `CoContra` is covariant over `T` and contravariant over `U`.
32+
type CoContra<T, U> = Option<(T, fn(U))>;
33+
34+
fn co_contra<'a>(x: C<&'static (), &'a ()>) -> C<&'a (), &'static ()> {
35+
x
36+
}
37+
38+
fn main() {}

‎tests/ui/type-alias-impl-trait/issue-96572-unconstrained.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#![feature(type_alias_impl_trait)]
22
// check-pass
3+
// revisions: default edition2021
4+
//[edition2021] compile-flags: --edition 2021
35

46
fn main() {
57
type T = impl Copy;

0 commit comments

Comments
 (0)
Please sign in to comment.