about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_data_structures/src/vec_map.rs2
-rw-r--r--compiler/rustc_typeck/src/check/check.rs10
-rw-r--r--compiler/rustc_typeck/src/check/regionck.rs2
-rw-r--r--src/test/ui/type-alias-impl-trait/underconstrained_generic.rs28
-rw-r--r--src/test/ui/type-alias-impl-trait/underconstrained_generic.stderr19
-rw-r--r--src/test/ui/type-alias-impl-trait/underconstrained_lifetime.rs34
-rw-r--r--src/test/ui/type-alias-impl-trait/underconstrained_lifetime.stderr20
7 files changed, 112 insertions, 3 deletions
diff --git a/compiler/rustc_data_structures/src/vec_map.rs b/compiler/rustc_data_structures/src/vec_map.rs
index 2f4b3844430..86be0bd8775 100644
--- a/compiler/rustc_data_structures/src/vec_map.rs
+++ b/compiler/rustc_data_structures/src/vec_map.rs
@@ -144,7 +144,7 @@ impl<'a, K, V> IntoIterator for &'a VecMap<K, V> {
     }
 }
 
-impl<'a, K, V> IntoIterator for &'a mut VecMap<K, V> {
+impl<'a, K: 'a, V: 'a> IntoIterator for &'a mut VecMap<K, V> {
     type Item = (&'a K, &'a mut V);
     type IntoIter = impl Iterator<Item = Self::Item>;
 
diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs
index 9ebafc26f61..1841451580f 100644
--- a/compiler/rustc_typeck/src/check/check.rs
+++ b/compiler/rustc_typeck/src/check/check.rs
@@ -12,12 +12,13 @@ use rustc_hir::lang_items::LangItem;
 use rustc_hir::{def::Res, ItemKind, Node, PathSegment};
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt};
+use rustc_infer::traits::Obligation;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
 use rustc_middle::ty::subst::GenericArgKind;
 use rustc_middle::ty::util::{Discr, IntTypeExt};
-use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt};
+use rustc_middle::ty::{self, ParamEnv, ToPredicate, Ty, TyCtxt};
 use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVENTIONS};
 use rustc_span::symbol::sym;
 use rustc_span::{self, Span};
@@ -674,6 +675,13 @@ fn check_opaque_meets_bounds<'tcx>(
             }
         }
 
+        // Additionally require the hidden type to be well-formed with only the generics of the opaque type.
+        // Defining use functions may have more bounds than the opaque type, which is ok, as long as the
+        // hidden type is well formed even without those bounds.
+        let predicate =
+            ty::Binder::dummy(ty::PredicateKind::WellFormed(hidden_type.into())).to_predicate(tcx);
+        inh.register_predicate(Obligation::new(misc_cause, param_env, predicate));
+
         // Check that all obligations are satisfied by the implementation's
         // version.
         let errors = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx);
diff --git a/compiler/rustc_typeck/src/check/regionck.rs b/compiler/rustc_typeck/src/check/regionck.rs
index 513e8576f2d..e18cb31acbd 100644
--- a/compiler/rustc_typeck/src/check/regionck.rs
+++ b/compiler/rustc_typeck/src/check/regionck.rs
@@ -171,8 +171,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
     /// Region checking during the WF phase for items. `wf_tys` are the
     /// types from which we should derive implied bounds, if any.
+    #[instrument(level = "debug", skip(self))]
     pub fn regionck_item(&self, item_id: hir::HirId, span: Span, wf_tys: FxHashSet<Ty<'tcx>>) {
-        debug!("regionck_item(item.id={:?}, wf_tys={:?})", item_id, wf_tys);
         let subject = self.tcx.hir().local_def_id(item_id);
         let mut rcx = RegionCtxt::new(self, item_id, Subject(subject), self.param_env);
         rcx.outlives_environment.add_implied_bounds(self, wf_tys, item_id, span);
diff --git a/src/test/ui/type-alias-impl-trait/underconstrained_generic.rs b/src/test/ui/type-alias-impl-trait/underconstrained_generic.rs
new file mode 100644
index 00000000000..22264670f37
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/underconstrained_generic.rs
@@ -0,0 +1,28 @@
+#![feature(type_alias_impl_trait)]
+
+use std::marker::PhantomData;
+
+trait Trait {
+    fn foo<T, U>(t: T) -> U;
+}
+
+trait ProofForConversion<X> {
+    fn convert<T, U>(_: PhantomData<Self>, r: T) -> U;
+}
+
+impl<X: Trait> ProofForConversion<X> for () {
+    fn convert<T, U>(_: PhantomData<Self>, r: T) -> U {
+        X::foo(r)
+    }
+}
+
+type Converter<T> = impl ProofForConversion<T>;
+//~^ ERROR the trait bound `T: Trait` is not satisfied
+
+fn _defining_use<T: Trait>() -> Converter<T> {
+    ()
+}
+
+
+fn main() {
+}
diff --git a/src/test/ui/type-alias-impl-trait/underconstrained_generic.stderr b/src/test/ui/type-alias-impl-trait/underconstrained_generic.stderr
new file mode 100644
index 00000000000..1c305abcfeb
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/underconstrained_generic.stderr
@@ -0,0 +1,19 @@
+error[E0277]: the trait bound `T: Trait` is not satisfied
+  --> $DIR/underconstrained_generic.rs:19:21
+   |
+LL | type Converter<T> = impl ProofForConversion<T>;
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `T`
+   |
+note: required because of the requirements on the impl of `ProofForConversion<T>` for `()`
+  --> $DIR/underconstrained_generic.rs:13:16
+   |
+LL | impl<X: Trait> ProofForConversion<X> for () {
+   |                ^^^^^^^^^^^^^^^^^^^^^     ^^
+help: consider restricting type parameter `T`
+   |
+LL | type Converter<T: Trait> = impl ProofForConversion<T>;
+   |                 +++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/type-alias-impl-trait/underconstrained_lifetime.rs b/src/test/ui/type-alias-impl-trait/underconstrained_lifetime.rs
new file mode 100644
index 00000000000..c5b2e8a1c5e
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/underconstrained_lifetime.rs
@@ -0,0 +1,34 @@
+#![feature(type_alias_impl_trait)]
+
+use std::marker::PhantomData;
+
+trait ProofForConversion<'a, 'b> {
+    fn convert<T: ?Sized>(_: PhantomData<Self>, r: &'a T) -> &'b T;
+}
+
+impl<'a, 'b> ProofForConversion<'a, 'b> for &'b &'a () {
+    fn convert<T: ?Sized>(_: PhantomData<Self>, r: &'a T) -> &'b T {
+        r
+    }
+}
+
+type Converter<'a, 'b> = impl ProofForConversion<'a, 'b>;
+//~^ ERROR reference has a longer lifetime than the data it references
+
+// Even _defining_use with an explicit `'a: 'b` compiles fine, too.
+fn _defining_use<'a, 'b>(x: &'b &'a ()) -> Converter<'a, 'b> {
+    x
+}
+
+fn extend_lifetime<'a, 'b, T: ?Sized>(x: &'a T) -> &'b T {
+    Converter::<'a, 'b>::convert(PhantomData, x)
+}
+
+fn main() {
+    let d;
+    {
+        let x = "Hello World".to_string();
+        d = extend_lifetime(&x);
+    }
+    println!("{}", d);
+}
diff --git a/src/test/ui/type-alias-impl-trait/underconstrained_lifetime.stderr b/src/test/ui/type-alias-impl-trait/underconstrained_lifetime.stderr
new file mode 100644
index 00000000000..12d85a49d01
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/underconstrained_lifetime.stderr
@@ -0,0 +1,20 @@
+error[E0491]: in type `&'b &'a ()`, reference has a longer lifetime than the data it references
+  --> $DIR/underconstrained_lifetime.rs:15:26
+   |
+LL | type Converter<'a, 'b> = impl ProofForConversion<'a, 'b>;
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the pointer is valid for the lifetime `'b` as defined here
+  --> $DIR/underconstrained_lifetime.rs:15:20
+   |
+LL | type Converter<'a, 'b> = impl ProofForConversion<'a, 'b>;
+   |                    ^^
+note: but the referenced data is only valid for the lifetime `'a` as defined here
+  --> $DIR/underconstrained_lifetime.rs:15:16
+   |
+LL | type Converter<'a, 'b> = impl ProofForConversion<'a, 'b>;
+   |                ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0491`.