about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthew Jasper <mjjasper1@gmail.com>2020-05-10 11:25:23 +0100
committerMatthew Jasper <mjjasper1@gmail.com>2020-06-11 16:24:01 +0100
commitb87e8eae29014ed3f07cc6c736100021facd8d48 (patch)
tree10bb17cfbacb5f41d0ece8c4946d5b03cf4dbcc3
parent50c0192c64241d723066add22c53d472e2b9cba9 (diff)
downloadrust-b87e8eae29014ed3f07cc6c736100021facd8d48.tar.gz
rust-b87e8eae29014ed3f07cc6c736100021facd8d48.zip
Check associated opaque types in check_opaque_types
-rw-r--r--src/librustc_mir/borrow_check/type_check/free_region_relations.rs8
-rw-r--r--src/librustc_typeck/check/wfcheck.rs23
-rw-r--r--src/test/ui/type-alias-impl-trait/impl-with-unconstrained-param.rs18
-rw-r--r--src/test/ui/type-alias-impl-trait/impl-with-unconstrained-param.stderr15
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-60564.rs7
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-60564.stderr14
6 files changed, 58 insertions, 27 deletions
diff --git a/src/librustc_mir/borrow_check/type_check/free_region_relations.rs b/src/librustc_mir/borrow_check/type_check/free_region_relations.rs
index f97dff14645..5707127340d 100644
--- a/src/librustc_mir/borrow_check/type_check/free_region_relations.rs
+++ b/src/librustc_mir/borrow_check/type_check/free_region_relations.rs
@@ -259,7 +259,13 @@ impl UniversalRegionRelationsBuilder<'cx, 'tcx> {
                     .param_env
                     .and(type_op::normalize::Normalize::new(ty))
                     .fully_perform(self.infcx)
-                    .unwrap_or_else(|_| bug!("failed to normalize {:?}", ty));
+                    .unwrap_or_else(|_| {
+                        self.infcx
+                            .tcx
+                            .sess
+                            .delay_span_bug(DUMMY_SP, &format!("failed to normalize {:?}", ty));
+                        (self.infcx.tcx.types.err, None)
+                    });
                 let constraints2 = self.add_implied_bounds(ty);
                 normalized_inputs_and_output.push(ty);
                 constraints1.into_iter().chain(constraints2)
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index 7d9bf975c69..8a83952c4fc 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -806,7 +806,11 @@ fn check_where_clauses<'tcx, 'fcx>(
 
     let mut predicates = predicates.instantiate_identity(fcx.tcx);
 
-    if let Some((return_ty, span)) = return_ty {
+    if let Some((mut return_ty, span)) = return_ty {
+        if return_ty.has_infer_types_or_consts() {
+            fcx.select_obligations_where_possible(false, |_| {});
+            return_ty = fcx.resolve_vars_if_possible(&return_ty);
+        }
         let opaque_types = check_opaque_types(tcx, fcx, def_id.expect_local(), span, return_ty);
         for _ in 0..opaque_types.len() {
             predicates.spans.push(span);
@@ -893,10 +897,16 @@ fn check_opaque_types<'fcx, 'tcx>(
                 trace!("check_opaque_types: opaque_ty, {:?}, {:?}", def_id, substs);
                 let generics = tcx.generics_of(def_id);
                 // Only check named `impl Trait` types defined in this crate.
-                // FIXME(eddyb) is  `generics.parent.is_none()` correct? It seems
-                // potentially risky wrt associated types in `impl`s.
-                if generics.parent.is_none() && def_id.is_local() {
+                if !def_id.is_local() {
+                    return ty;
+                }
                     let opaque_hir_id = tcx.hir().as_local_hir_id(def_id.expect_local());
+                if let hir::ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn: Some(_), .. }) =
+                    tcx.hir().expect_item(opaque_hir_id).kind
+                {
+                    // Don't check return position impl trait.
+                    return ty;
+                }
                     if may_define_opaque_type(tcx, fn_def_id, opaque_hir_id) {
                         trace!("check_opaque_types: may define, generics={:#?}", generics);
                         let mut seen_params: FxHashMap<_, Vec<_>> = FxHashMap::default();
@@ -924,9 +934,7 @@ fn check_opaque_types<'fcx, 'tcx>(
                                     true
                                 }
 
-                                GenericArgKind::Const(ct) => {
-                                    matches!(ct.val, ty::ConstKind::Param(_))
-                                }
+                            GenericArgKind::Const(ct) => matches!(ct.val, ty::ConstKind::Param(_)),
                             };
 
                             if arg_is_param {
@@ -988,7 +996,6 @@ fn check_opaque_types<'fcx, 'tcx>(
                             substituted_predicates.push(substituted_pred);
                         }
                     }
-                } // if is_named_opaque_type
             } // if let Opaque
             ty
         },
diff --git a/src/test/ui/type-alias-impl-trait/impl-with-unconstrained-param.rs b/src/test/ui/type-alias-impl-trait/impl-with-unconstrained-param.rs
new file mode 100644
index 00000000000..bc6543a9229
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/impl-with-unconstrained-param.rs
@@ -0,0 +1,18 @@
+// Ensure that we don't ICE if associated type impl trait is used in an impl
+// with an unconstrained type parameter.
+
+#![feature(type_alias_impl_trait)]
+
+trait X {
+    type I;
+    fn f() -> Self::I;
+}
+
+impl<T> X for () {
+    type I = impl Sized;
+    //~^ ERROR could not find defining uses
+    fn f() -> Self::I {}
+    //~^ ERROR type annotations needed
+}
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/impl-with-unconstrained-param.stderr b/src/test/ui/type-alias-impl-trait/impl-with-unconstrained-param.stderr
new file mode 100644
index 00000000000..e8b677113db
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/impl-with-unconstrained-param.stderr
@@ -0,0 +1,15 @@
+error[E0282]: type annotations needed
+  --> $DIR/impl-with-unconstrained-param.rs:14:23
+   |
+LL |     fn f() -> Self::I {}
+   |                       ^^ cannot infer type for type parameter `T`
+
+error: could not find defining uses
+  --> $DIR/impl-with-unconstrained-param.rs:12:14
+   |
+LL |     type I = impl Sized;
+   |              ^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/type-alias-impl-trait/issue-60564.rs b/src/test/ui/type-alias-impl-trait/issue-60564.rs
index 4eb7f7836d8..78def0d1136 100644
--- a/src/test/ui/type-alias-impl-trait/issue-60564.rs
+++ b/src/test/ui/type-alias-impl-trait/issue-60564.rs
@@ -17,11 +17,8 @@ where
 {
     type BitsIter = IterBitsIter<T, E, u8>;
     fn iter_bits(self, n: u8) -> Self::BitsIter {
-    //~^ ERROR non-defining opaque type use in defining scope
-    //~| ERROR non-defining opaque type use in defining scope
-        (0u8..n)
-            .rev()
-            .map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap())
+        //~^ ERROR non-defining opaque type use in defining scope
+        (0u8..n).rev().map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap())
     }
 }
 
diff --git a/src/test/ui/type-alias-impl-trait/issue-60564.stderr b/src/test/ui/type-alias-impl-trait/issue-60564.stderr
index 55984609437..66fa862ef9d 100644
--- a/src/test/ui/type-alias-impl-trait/issue-60564.stderr
+++ b/src/test/ui/type-alias-impl-trait/issue-60564.stderr
@@ -4,23 +4,11 @@ error: non-defining opaque type use in defining scope
 LL |     fn iter_bits(self, n: u8) -> Self::BitsIter {
    |                                  ^^^^^^^^^^^^^^
    |
-note: used non-generic type `_` for generic parameter
-  --> $DIR/issue-60564.rs:8:22
-   |
-LL | type IterBitsIter<T, E, I> = impl std::iter::Iterator<Item = I>;
-   |                      ^
-
-error: non-defining opaque type use in defining scope
-  --> $DIR/issue-60564.rs:19:34
-   |
-LL |     fn iter_bits(self, n: u8) -> Self::BitsIter {
-   |                                  ^^^^^^^^^^^^^^
-   |
 note: used non-generic type `u8` for generic parameter
   --> $DIR/issue-60564.rs:8:25
    |
 LL | type IterBitsIter<T, E, I> = impl std::iter::Iterator<Item = I>;
    |                         ^
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error