From 5d07a6ceb4d54ad05d701fa8344468d9a8d707a5 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 16 Nov 2021 13:46:03 +0000 Subject: [PATCH 1/2] Actually instantiate the opaque type when checking bounds Before this change, `instantiate_opaque_types` was a no-op --- compiler/rustc_typeck/src/check/check.rs | 16 ++++++------ .../issue-57611-trait-alias.nll.stderr | 26 ++++++++++++++++++- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index fd7b3a55dfb97..619d5073c6904 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -626,6 +626,7 @@ pub(super) fn check_opaque_for_cycles<'tcx>( /// /// Without this check the above code is incorrectly accepted: we would ICE if /// some tried, for example, to clone an `Option>`. +#[instrument(skip(tcx))] fn check_opaque_meets_bounds<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, @@ -643,7 +644,7 @@ fn check_opaque_meets_bounds<'tcx>( let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); let param_env = tcx.param_env(def_id); - tcx.infer_ctxt().enter(move |infcx| { + tcx.infer_ctxt().with_opaque_type_inference(def_id).enter(move |infcx| { let inh = Inherited::new(infcx, def_id); let infcx = &inh.infcx; let opaque_ty = tcx.mk_opaque(def_id.to_def_id(), substs); @@ -656,16 +657,15 @@ fn check_opaque_meets_bounds<'tcx>( let opaque_type_map = infcx.inner.borrow().opaque_types.clone(); for (OpaqueTypeKey { def_id, substs }, opaque_defn) in opaque_type_map { - match infcx - .at(&misc_cause, param_env) - .eq(opaque_defn.concrete_ty, tcx.type_of(def_id).subst(tcx, substs)) - { + let hidden_type = tcx.type_of(def_id).subst(tcx, substs); + trace!(?hidden_type); + match infcx.at(&misc_cause, param_env).eq(opaque_defn.concrete_ty, hidden_type) { Ok(infer_ok) => inh.register_infer_ok_obligations(infer_ok), Err(ty_err) => tcx.sess.delay_span_bug( - opaque_defn.definition_span, + span, &format!( - "could not unify `{}` with revealed type:\n{}", - opaque_defn.concrete_ty, ty_err, + "could not check bounds on revealed type `{}`:\n{}", + hidden_type, ty_err, ), ), } diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr index 8c9cb742fac91..a4ccae4eb7ed9 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr @@ -10,5 +10,29 @@ error: higher-ranked subtype error LL | |x| x | ^^^^^ -error: aborting due to 2 previous errors +error[E0308]: mismatched types + --> $DIR/issue-57611-trait-alias.rs:17:16 + | +LL | type Bar = impl Baz; + | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected type `for<'r> Fn<(&'r X,)>` + found type `Fn<(&'static X,)>` +note: this closure does not fulfill the lifetime requirements + --> $DIR/issue-57611-trait-alias.rs:21:9 + | +LL | |x| x + | ^^^^^ + +error: implementation of `FnOnce` is not general enough + --> $DIR/issue-57611-trait-alias.rs:17:16 + | +LL | type Bar = impl Baz; + | ^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough + | + = note: closure with signature `fn(&'static X) -> &'static X` must implement `FnOnce<(&'0 X,)>`, for any lifetime `'0`... + = note: ...but it actually implements `FnOnce<(&'static X,)>` + +error: aborting due to 4 previous errors +For more information about this error, try `rustc --explain E0308`. From 15f7e818ec83cd8b6a726e625b24e1507d8687ee Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 1 Dec 2021 16:34:40 +0000 Subject: [PATCH 2/2] Check all opaque types, even return position impl trait. While not necessary right now, this is the safe choice and will be necessary for lazy TAIT. --- compiler/rustc_typeck/src/check/check.rs | 32 +++++++++++++----------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 619d5073c6904..3ac2dfd866957 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -626,7 +626,7 @@ pub(super) fn check_opaque_for_cycles<'tcx>( /// /// Without this check the above code is incorrectly accepted: we would ICE if /// some tried, for example, to clone an `Option>`. -#[instrument(skip(tcx))] +#[instrument(level = "debug", skip(tcx))] fn check_opaque_meets_bounds<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, @@ -634,17 +634,14 @@ fn check_opaque_meets_bounds<'tcx>( span: Span, origin: &hir::OpaqueTyOrigin, ) { - match origin { - // Checked when type checking the function containing them. - hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => return, - // Can have different predicates to their defining use - hir::OpaqueTyOrigin::TyAlias => {} - } - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - let param_env = tcx.param_env(def_id); + let defining_use_anchor = match *origin { + hir::OpaqueTyOrigin::FnReturn(did) | hir::OpaqueTyOrigin::AsyncFn(did) => did, + hir::OpaqueTyOrigin::TyAlias => def_id, + }; + let param_env = tcx.param_env(defining_use_anchor); - tcx.infer_ctxt().with_opaque_type_inference(def_id).enter(move |infcx| { + tcx.infer_ctxt().with_opaque_type_inference(defining_use_anchor).enter(move |infcx| { let inh = Inherited::new(infcx, def_id); let infcx = &inh.infcx; let opaque_ty = tcx.mk_opaque(def_id.to_def_id(), substs); @@ -678,10 +675,17 @@ fn check_opaque_meets_bounds<'tcx>( infcx.report_fulfillment_errors(&errors, None, false); } - // Finally, resolve all regions. This catches wily misuses of - // lifetime parameters. - let fcx = FnCtxt::new(&inh, param_env, hir_id); - fcx.regionck_item(hir_id, span, FxHashSet::default()); + match origin { + // Checked when type checking the function containing them. + hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => return, + // Can have different predicates to their defining use + hir::OpaqueTyOrigin::TyAlias => { + // Finally, resolve all regions. This catches wily misuses of + // lifetime parameters. + let fcx = FnCtxt::new(&inh, param_env, hir_id); + fcx.regionck_item(hir_id, span, FxHashSet::default()); + } + } }); }