about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs207
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs13
-rw-r--r--tests/ui/associated-inherent-types/assoc-inherent-late-bound.rs14
-rw-r--r--tests/ui/associated-inherent-types/issue-111404-1.rs1
-rw-r--r--tests/ui/associated-inherent-types/issue-111404-1.stderr10
5 files changed, 128 insertions, 117 deletions
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 94b182e09f6..b9a4806e6c2 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -26,12 +26,13 @@ use rustc_hir::def::{CtorOf, DefKind, Namespace, Res};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::{walk_generics, Visitor as _};
 use rustc_hir::{GenericArg, GenericArgs, OpaqueTyOrigin};
-use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt};
+use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
 use rustc_infer::traits::ObligationCause;
 use rustc_middle::middle::stability::AllowUnstable;
 use rustc_middle::ty::GenericParamDefKind;
 use rustc_middle::ty::{
-    self, Const, GenericArgKind, GenericArgsRef, IsSuggestable, Ty, TyCtxt, TypeVisitableExt,
+    self, Const, GenericArgKind, GenericArgsRef, IsSuggestable, ParamEnv, Ty, TyCtxt,
+    TypeVisitableExt,
 };
 use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS;
 use rustc_span::edit_distance::find_best_match_for_name;
@@ -39,8 +40,7 @@ use rustc_span::symbol::{kw, Ident, Symbol};
 use rustc_span::{sym, BytePos, Span, DUMMY_SP};
 use rustc_target::spec::abi;
 use rustc_trait_selection::traits::wf::object_region_bounds;
-use rustc_trait_selection::traits::{self, NormalizeExt, ObligationCtxt};
-use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
+use rustc_trait_selection::traits::{self, ObligationCtxt};
 
 use std::fmt::Display;
 use std::slice;
@@ -1606,133 +1606,110 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         // FIXME(inherent_associated_types): Acquiring the ParamEnv this early leads to cycle errors
         // when inside of an ADT (#108491) or where clause.
         let param_env = tcx.param_env(block.owner);
-        let cause = ObligationCause::misc(span, block.owner.def_id);
 
-        let mut fulfillment_errors = Vec::new();
-        let mut applicable_candidates: Vec<_> = infcx.probe(|_| {
-            // Regions are not considered during selection.
-            let self_ty = self_ty
-                .fold_with(&mut BoundVarEraser { tcx, universe: infcx.create_next_universe() });
-
-            struct BoundVarEraser<'tcx> {
-                tcx: TyCtxt<'tcx>,
-                universe: ty::UniverseIndex,
-            }
-
-            // FIXME(non_lifetime_binders): Don't assign the same universe to each placeholder.
-            impl<'tcx> TypeFolder<TyCtxt<'tcx>> for BoundVarEraser<'tcx> {
-                fn interner(&self) -> TyCtxt<'tcx> {
-                    self.tcx
-                }
+        let mut universes = if self_ty.has_escaping_bound_vars() {
+            vec![None; self_ty.outer_exclusive_binder().as_usize()]
+        } else {
+            vec![]
+        };
 
-                fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
-                    // FIXME(@lcnr): This is broken, erasing bound regions
-                    // impacts selection as it results in different types.
-                    if r.is_bound() { self.tcx.lifetimes.re_erased } else { r }
-                }
+        let (impl_, (assoc_item, def_scope)) =
+            crate::traits::project::with_replaced_escaping_bound_vars(
+                infcx,
+                &mut universes,
+                self_ty,
+                |self_ty| {
+                    self.select_inherent_assoc_type_candidates(
+                        infcx, name, span, self_ty, param_env, candidates,
+                    )
+                },
+            )?;
+
+        self.check_assoc_ty(assoc_item, name, def_scope, block, span);
+
+        // FIXME(fmease): Currently creating throwaway `parent_args` to please
+        // `create_args_for_associated_item`. Modify the latter instead (or sth. similar) to
+        // not require the parent args logic.
+        let parent_args = ty::GenericArgs::identity_for_item(tcx, impl_);
+        let args = self.create_args_for_associated_item(span, assoc_item, segment, parent_args);
+        let args = tcx.mk_args_from_iter(
+            std::iter::once(ty::GenericArg::from(self_ty))
+                .chain(args.into_iter().skip(parent_args.len())),
+        );
 
-                fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-                    match *ty.kind() {
-                        ty::Bound(_, bv) => Ty::new_placeholder(
-                            self.tcx,
-                            ty::PlaceholderType { universe: self.universe, bound: bv },
-                        ),
-                        _ => ty.super_fold_with(self),
-                    }
-                }
+        let ty = Ty::new_alias(tcx, ty::Inherent, ty::AliasTy::new(tcx, assoc_item, args));
 
-                fn fold_const(
-                    &mut self,
-                    ct: ty::Const<'tcx>,
-                ) -> <TyCtxt<'tcx> as rustc_type_ir::Interner>::Const {
-                    assert!(!ct.ty().has_escaping_bound_vars());
-
-                    match ct.kind() {
-                        ty::ConstKind::Bound(_, bv) => ty::Const::new_placeholder(
-                            self.tcx,
-                            ty::PlaceholderConst { universe: self.universe, bound: bv },
-                            ct.ty(),
-                        ),
-                        _ => ct.super_fold_with(self),
-                    }
-                }
-            }
+        Ok(Some((ty, assoc_item)))
+    }
 
-            let InferOk { value: self_ty, obligations } =
-                infcx.at(&cause, param_env).normalize(self_ty);
+    fn select_inherent_assoc_type_candidates(
+        &self,
+        infcx: &InferCtxt<'tcx>,
+        name: Ident,
+        span: Span,
+        self_ty: Ty<'tcx>,
+        param_env: ParamEnv<'tcx>,
+        candidates: Vec<(DefId, (DefId, DefId))>,
+    ) -> Result<(DefId, (DefId, DefId)), ErrorGuaranteed> {
+        let tcx = self.tcx();
+        let mut fulfillment_errors = Vec::new();
 
-            candidates
-                .iter()
-                .copied()
-                .filter(|&(impl_, _)| {
-                    infcx.probe(|_| {
-                        let ocx = ObligationCtxt::new(infcx);
-                        ocx.register_obligations(obligations.clone());
-
-                        let impl_args = infcx.fresh_args_for_item(span, impl_);
-                        let impl_ty = tcx.type_of(impl_).instantiate(tcx, impl_args);
-                        let impl_ty = ocx.normalize(&cause, param_env, impl_ty);
-
-                        // Check that the self types can be related.
-                        if ocx.eq(&ObligationCause::dummy(), param_env, impl_ty, self_ty).is_err() {
-                            return false;
-                        }
+        let applicable_candidates: Vec<_> = candidates
+            .iter()
+            .copied()
+            .filter(|&(impl_, _)| {
+                infcx.probe(|_| {
+                    let ocx = ObligationCtxt::new(infcx);
+                    let self_ty = ocx.normalize(&ObligationCause::dummy(), param_env, self_ty);
+
+                    let impl_args = infcx.fresh_args_for_item(span, impl_);
+                    let impl_ty = tcx.type_of(impl_).instantiate(tcx, impl_args);
+                    let impl_ty = ocx.normalize(&ObligationCause::dummy(), param_env, impl_ty);
+
+                    // Check that the self types can be related.
+                    if ocx.eq(&ObligationCause::dummy(), param_env, impl_ty, self_ty).is_err() {
+                        return false;
+                    }
 
-                        // Check whether the impl imposes obligations we have to worry about.
-                        let impl_bounds = tcx.predicates_of(impl_).instantiate(tcx, impl_args);
-                        let impl_bounds = ocx.normalize(&cause, param_env, impl_bounds);
-                        let impl_obligations = traits::predicates_for_generics(
-                            |_, _| cause.clone(),
-                            param_env,
-                            impl_bounds,
-                        );
-                        ocx.register_obligations(impl_obligations);
+                    // Check whether the impl imposes obligations we have to worry about.
+                    let impl_bounds = tcx.predicates_of(impl_).instantiate(tcx, impl_args);
+                    let impl_bounds =
+                        ocx.normalize(&ObligationCause::dummy(), param_env, impl_bounds);
+                    let impl_obligations = traits::predicates_for_generics(
+                        |_, _| ObligationCause::dummy(),
+                        param_env,
+                        impl_bounds,
+                    );
+                    ocx.register_obligations(impl_obligations);
 
-                        let mut errors = ocx.select_where_possible();
-                        if !errors.is_empty() {
-                            fulfillment_errors.append(&mut errors);
-                            return false;
-                        }
+                    let mut errors = ocx.select_where_possible();
+                    if !errors.is_empty() {
+                        fulfillment_errors.append(&mut errors);
+                        return false;
+                    }
 
-                        true
-                    })
+                    true
                 })
-                .collect()
-        });
+            })
+            .collect();
 
-        if applicable_candidates.len() > 1 {
-            return Err(self.complain_about_ambiguous_inherent_assoc_type(
+        match &applicable_candidates[..] {
+            &[] => Err(self.complain_about_inherent_assoc_type_not_found(
                 name,
-                applicable_candidates.into_iter().map(|(_, (candidate, _))| candidate).collect(),
+                self_ty,
+                candidates,
+                fulfillment_errors,
                 span,
-            ));
-        }
+            )),
 
-        if let Some((impl_, (assoc_item, def_scope))) = applicable_candidates.pop() {
-            self.check_assoc_ty(assoc_item, name, def_scope, block, span);
-
-            // FIXME(fmease): Currently creating throwaway `parent_args` to please
-            // `create_args_for_associated_item`. Modify the latter instead (or sth. similar) to
-            // not require the parent args logic.
-            let parent_args = ty::GenericArgs::identity_for_item(tcx, impl_);
-            let args = self.create_args_for_associated_item(span, assoc_item, segment, parent_args);
-            let args = tcx.mk_args_from_iter(
-                std::iter::once(ty::GenericArg::from(self_ty))
-                    .chain(args.into_iter().skip(parent_args.len())),
-            );
-
-            let ty = Ty::new_alias(tcx, ty::Inherent, ty::AliasTy::new(tcx, assoc_item, args));
+            &[applicable_candidate] => Ok(applicable_candidate),
 
-            return Ok(Some((ty, assoc_item)));
+            &[_, ..] => Err(self.complain_about_ambiguous_inherent_assoc_type(
+                name,
+                applicable_candidates.into_iter().map(|(_, (candidate, _))| candidate).collect(),
+                span,
+            )),
         }
-
-        Err(self.complain_about_inherent_assoc_type_not_found(
-            name,
-            self_ty,
-            candidates,
-            fulfillment_errors,
-            span,
-        ))
     }
 
     fn lookup_assoc_ty(
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 8f5afdf0a1f..3be14951703 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -1454,7 +1454,18 @@ pub fn compute_inherent_assoc_ty_args<'a, 'b, 'tcx>(
 
     // Infer the generic parameters of the impl by unifying the
     // impl type with the self type of the projection.
-    let self_ty = alias_ty.self_ty();
+    let mut self_ty = alias_ty.self_ty();
+    if !selcx.infcx.next_trait_solver() {
+        self_ty = normalize_with_depth_to(
+            selcx,
+            param_env,
+            cause.clone(),
+            depth + 1,
+            self_ty,
+            obligations,
+        );
+    }
+
     match selcx.infcx.at(&cause, param_env).eq(DefineOpaqueTypes::No, impl_ty, self_ty) {
         Ok(mut ok) => obligations.append(&mut ok.obligations),
         Err(_) => {
diff --git a/tests/ui/associated-inherent-types/assoc-inherent-late-bound.rs b/tests/ui/associated-inherent-types/assoc-inherent-late-bound.rs
new file mode 100644
index 00000000000..b6993f66fe7
--- /dev/null
+++ b/tests/ui/associated-inherent-types/assoc-inherent-late-bound.rs
@@ -0,0 +1,14 @@
+// check-pass
+
+#![feature(inherent_associated_types)]
+#![allow(incomplete_features)]
+
+struct Foo<T>(T);
+
+impl<'a> Foo<fn(&'a ())> {
+    type Assoc = &'a ();
+}
+
+fn bar(_: for<'a> fn(Foo<fn(Foo<fn(&'static ())>::Assoc)>::Assoc)) {}
+
+fn main() {}
diff --git a/tests/ui/associated-inherent-types/issue-111404-1.rs b/tests/ui/associated-inherent-types/issue-111404-1.rs
index f4ad5d7ff6c..dd62e59f07d 100644
--- a/tests/ui/associated-inherent-types/issue-111404-1.rs
+++ b/tests/ui/associated-inherent-types/issue-111404-1.rs
@@ -9,5 +9,6 @@ impl<'a> Foo<fn(&'a ())> {
 
 fn bar(_: fn(Foo<for<'b> fn(Foo<fn(&'b ())>::Assoc)>::Assoc)) {}
 //~^ ERROR higher-ranked subtype error
+//~| ERROR higher-ranked subtype error
 
 fn main() {}
diff --git a/tests/ui/associated-inherent-types/issue-111404-1.stderr b/tests/ui/associated-inherent-types/issue-111404-1.stderr
index 2c78e3a1fb7..cf4d4a5f19b 100644
--- a/tests/ui/associated-inherent-types/issue-111404-1.stderr
+++ b/tests/ui/associated-inherent-types/issue-111404-1.stderr
@@ -4,5 +4,13 @@ error: higher-ranked subtype error
 LL | fn bar(_: fn(Foo<for<'b> fn(Foo<fn(&'b ())>::Assoc)>::Assoc)) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 1 previous error
+error: higher-ranked subtype error
+  --> $DIR/issue-111404-1.rs:10:1
+   |
+LL | fn bar(_: fn(Foo<for<'b> fn(Foo<fn(&'b ())>::Assoc)>::Assoc)) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: aborting due to 2 previous errors