Enforce well formedness for type alias impl trait's hidden type
This commit is contained in:
parent
e50ff9b452
commit
eca0ead17d
6 changed files with 111 additions and 2 deletions
|
@ -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, MultiSpan, 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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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() {
|
||||
}
|
|
@ -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`.
|
|
@ -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);
|
||||
}
|
|
@ -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`.
|
Loading…
Add table
Add a link
Reference in a new issue