diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs index 312bd38178f..6efc1e7302c 100644 --- a/compiler/rustc_trait_selection/src/infer.rs +++ b/compiler/rustc_trait_selection/src/infer.rs @@ -1,5 +1,5 @@ use crate::traits::query::evaluate_obligation::InferCtxtExt as _; -use crate::traits::{self, ObligationCtxt}; +use crate::traits::{self, DefiningAnchor, ObligationCtxt}; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; @@ -80,7 +80,7 @@ fn type_implements_trait( pub trait InferCtxtBuilderExt<'tcx> { fn enter_canonical_trait_query( - &mut self, + self, canonical_key: &Canonical<'tcx, K>, operation: impl FnOnce(&ObligationCtxt<'_, 'tcx>, K) -> Result, ) -> Result, NoSolution> @@ -108,7 +108,7 @@ impl<'tcx> InferCtxtBuilderExt<'tcx> for InferCtxtBuilder<'tcx> { /// have `'tcx` be free on this function so that we can talk about /// `K: TypeFoldable>`.) fn enter_canonical_trait_query( - &mut self, + self, canonical_key: &Canonical<'tcx, K>, operation: impl FnOnce(&ObligationCtxt<'_, 'tcx>, K) -> Result, ) -> Result, NoSolution> @@ -117,8 +117,9 @@ fn enter_canonical_trait_query( R: Debug + TypeFoldable>, Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable<'tcx>, { - let (infcx, key, canonical_inference_vars) = - self.build_with_canonical(DUMMY_SP, canonical_key); + let (infcx, key, canonical_inference_vars) = self + .with_opaque_type_inference(DefiningAnchor::Bubble) + .build_with_canonical(DUMMY_SP, canonical_key); let ocx = ObligationCtxt::new(&infcx); let value = operation(&ocx, key)?; ocx.make_canonicalized_query_response(canonical_inference_vars, value) diff --git a/tests/ui/impl-trait/defined-by-trait-resolution.rs b/tests/ui/impl-trait/defined-by-trait-resolution.rs new file mode 100644 index 00000000000..1744046ddbb --- /dev/null +++ b/tests/ui/impl-trait/defined-by-trait-resolution.rs @@ -0,0 +1,12 @@ +//! The trait query `foo: Fn() -> u8` is a valid defining use of RPIT. + +// build-pass + +fn returns_u8(_: impl Fn() -> u8) {} + +pub fn foo() -> impl Sized { + returns_u8(foo); + 0u8 +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/defined-by-user-annotation.rs b/tests/ui/type-alias-impl-trait/defined-by-user-annotation.rs new file mode 100644 index 00000000000..5a421ea1dc0 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/defined-by-user-annotation.rs @@ -0,0 +1,19 @@ +// User type annotation in fn bodies is a a valid defining site for opaque types. +// check-pass +#![feature(type_alias_impl_trait)] + +trait Equate { type Proj; } +impl Equate for T { type Proj = T; } + +trait Indirect { type Ty; } +impl> Indirect for (A, B) { type Ty = (); } + +type Opq = impl Sized; +fn define_1(_: Opq) { + let _ = None::<<(Opq, u8) as Indirect>::Ty>; +} +fn define_2() -> Opq { + 0u8 +} + +fn main() {}