Auto merge of #121394 - oli-obk:define_opaque_types, r=compiler-errors

some smaller DefiningOpaqueTypes::No -> Yes switches

r? `@compiler-errors`

These are some easy cases, so let's get them out of the way first.
I added tests exercising the specialization code paths that I believe weren't tested so far.

follow-up to https://github.com/rust-lang/rust/pull/117348
This commit is contained in:
bors 2024-04-04 17:42:07 +00:00
commit a4b11c8e60
31 changed files with 522 additions and 49 deletions

View file

@ -918,7 +918,8 @@ pub(super) fn enforce_context_effects(
let param = callee_args.const_at(host_effect_index);
let cause = self.misc(span);
match self.at(&cause, self.param_env).eq(infer::DefineOpaqueTypes::No, effect, param) {
// We know the type of `effect` to be `bool`, there will be no opaque type inference.
match self.at(&cause, self.param_env).eq(infer::DefineOpaqueTypes::Yes, effect, param) {
Ok(infer::InferOk { obligations, value: () }) => {
self.register_predicates(obligations);
}

View file

@ -400,7 +400,7 @@ fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
// what our ideal rcvr ty would look like.
let _ = self
.at(&ObligationCause::dummy(), self.param_env)
.eq(DefineOpaqueTypes::No, method.sig.inputs()[idx + 1], arg_ty)
.eq(DefineOpaqueTypes::Yes, method.sig.inputs()[idx + 1], arg_ty)
.ok()?;
self.select_obligations_where_possible(|errs| {
// Yeet the errors, we're already reporting errors.
@ -479,7 +479,7 @@ fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
.and_then(|method| {
let _ = self
.at(&ObligationCause::dummy(), self.param_env)
.eq(DefineOpaqueTypes::No, ideal_rcvr_ty, expected_ty)
.eq(DefineOpaqueTypes::Yes, ideal_rcvr_ty, expected_ty)
.ok()?;
Some(method)
});

View file

@ -44,10 +44,7 @@
use rustc_infer::traits::query::NoSolution;
use rustc_infer::traits::ObligationCause;
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase};
use rustc_middle::ty::error::{
ExpectedFound,
TypeError::{FieldMisMatch, Sorts},
};
use rustc_middle::ty::error::{ExpectedFound, TypeError::Sorts};
use rustc_middle::ty::GenericArgsRef;
use rustc_middle::ty::{self, AdtKind, Ty, TypeVisitableExt};
use rustc_session::errors::ExprParenthesesNeeded;
@ -1811,7 +1808,10 @@ fn check_expr_struct_fields(
let target_ty = self.field_ty(base_expr.span, f, args);
let cause = self.misc(base_expr.span);
match self.at(&cause, self.param_env).sup(
DefineOpaqueTypes::No,
// We're already using inference variables for any params, and don't allow converting
// between different structs, so there is no way this ever actually defines an opaque type.
// Thus choosing `Yes` is fine.
DefineOpaqueTypes::Yes,
target_ty,
fru_ty,
) {
@ -1819,16 +1819,12 @@ fn check_expr_struct_fields(
self.register_predicates(obligations)
}
Err(_) => {
// This should never happen, since we're just subtyping the
// remaining_fields, but it's fine to emit this, I guess.
self.err_ctxt()
.report_mismatched_types(
&cause,
target_ty,
fru_ty,
FieldMisMatch(variant.name, ident.name),
)
.emit();
span_bug!(
cause.span(),
"subtyping remaining fields of type changing FRU failed: {target_ty} != {fru_ty}: {}::{}",
variant.name,
ident.name,
);
}
}
}

View file

@ -687,7 +687,7 @@ fn has_error_or_infer<'tcx>(tys: impl IntoIterator<Item = Ty<'tcx>>) -> bool {
// Using probe here, since we don't want this subtyping to affect inference.
let subtyping_error = self.probe(|_| {
self.at(&self.misc(arg_span), self.param_env)
.sup(DefineOpaqueTypes::No, formal_input_ty, coerced_ty)
.sup(DefineOpaqueTypes::Yes, formal_input_ty, coerced_ty)
.err()
});

View file

@ -843,7 +843,9 @@ pub fn can_sub<T>(&self, param_env: ty::ParamEnv<'tcx>, expected: T, actual: T)
{
let origin = &ObligationCause::dummy();
self.probe(|_| {
self.at(origin, param_env).sub(DefineOpaqueTypes::No, expected, actual).is_ok()
// We're only answering whether there could be a subtyping relation, and with
// opaque types, "there could be one", via registering a hidden type.
self.at(origin, param_env).sub(DefineOpaqueTypes::Yes, expected, actual).is_ok()
})
}
@ -852,7 +854,9 @@ pub fn can_eq<T>(&self, param_env: ty::ParamEnv<'tcx>, a: T, b: T) -> bool
T: at::ToTrace<'tcx>,
{
let origin = &ObligationCause::dummy();
self.probe(|_| self.at(origin, param_env).eq(DefineOpaqueTypes::No, a, b).is_ok())
// We're only answering whether the types could be the same, and with
// opaque types, "they can be the same", via registering a hidden type.
self.probe(|_| self.at(origin, param_env).eq(DefineOpaqueTypes::Yes, a, b).is_ok())
}
#[instrument(skip(self), level = "debug")]

View file

@ -720,7 +720,8 @@ pub(super) fn eq<T: ToTrace<'tcx>>(
) -> Result<(), NoSolution> {
self.infcx
.at(&ObligationCause::dummy(), param_env)
.eq(DefineOpaqueTypes::No, lhs, rhs)
// New solver ignores DefineOpaqueTypes, so choose Yes for consistency
.eq(DefineOpaqueTypes::Yes, lhs, rhs)
.map(|InferOk { value: (), obligations }| {
self.add_goals(GoalSource::Misc, obligations.into_iter().map(|o| o.into()));
})
@ -759,7 +760,8 @@ pub(super) fn sub<T: ToTrace<'tcx>>(
) -> Result<(), NoSolution> {
self.infcx
.at(&ObligationCause::dummy(), param_env)
.sub(DefineOpaqueTypes::No, sub, sup)
// New solver ignores DefineOpaqueTypes, so choose Yes for consistency
.sub(DefineOpaqueTypes::Yes, sub, sup)
.map(|InferOk { value: (), obligations }| {
self.add_goals(GoalSource::Misc, obligations.into_iter().map(|o| o.into()));
})
@ -779,7 +781,8 @@ pub(super) fn relate<T: ToTrace<'tcx>>(
) -> Result<(), NoSolution> {
self.infcx
.at(&ObligationCause::dummy(), param_env)
.relate(DefineOpaqueTypes::No, lhs, variance, rhs)
// New solver ignores DefineOpaqueTypes, so choose Yes for consistency
.relate(DefineOpaqueTypes::Yes, lhs, variance, rhs)
.map(|InferOk { value: (), obligations }| {
self.add_goals(GoalSource::Misc, obligations.into_iter().map(|o| o.into()));
})
@ -803,7 +806,8 @@ pub(super) fn eq_and_get_goals<T: ToTrace<'tcx>>(
) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, NoSolution> {
self.infcx
.at(&ObligationCause::dummy(), param_env)
.eq(DefineOpaqueTypes::No, lhs, rhs)
// New solver ignores DefineOpaqueTypes, so choose Yes for consistency
.eq(DefineOpaqueTypes::Yes, lhs, rhs)
.map(|InferOk { value: (), obligations }| {
obligations.into_iter().map(|o| o.into()).collect()
})

View file

@ -182,7 +182,8 @@ fn rematch_impl<'tcx>(
let mut nested = infcx
.at(&ObligationCause::dummy(), goal.param_env)
.eq(DefineOpaqueTypes::No, goal.predicate.trait_ref, impl_trait_ref)
// New solver ignores DefineOpaqueTypes, so choose Yes for consistency
.eq(DefineOpaqueTypes::Yes, goal.predicate.trait_ref, impl_trait_ref)
.map_err(|_| SelectionError::Unimplemented)?
.into_obligations();
@ -257,7 +258,8 @@ fn rematch_unsize<'tcx>(
nested.extend(
infcx
.at(&ObligationCause::dummy(), goal.param_env)
.eq(DefineOpaqueTypes::No, a_elem_ty, b_elem_ty)
// New solver ignores DefineOpaqueTypes, so choose Yes for consistency
.eq(DefineOpaqueTypes::Yes, a_elem_ty, b_elem_ty)
.expect("expected rematch to succeed")
.into_obligations(),
);
@ -300,7 +302,8 @@ fn rematch_unsize<'tcx>(
nested.extend(
infcx
.at(&ObligationCause::dummy(), goal.param_env)
.eq(DefineOpaqueTypes::No, unsized_a_ty, b_ty)
// New solver ignores DefineOpaqueTypes, so choose Yes for consistency
.eq(DefineOpaqueTypes::Yes, unsized_a_ty, b_ty)
.expect("expected rematch to succeed")
.into_obligations(),
);
@ -329,7 +332,8 @@ fn rematch_unsize<'tcx>(
nested.extend(
infcx
.at(&ObligationCause::dummy(), goal.param_env)
.eq(DefineOpaqueTypes::No, unsized_a_ty, b_ty)
// New solver ignores DefineOpaqueTypes, so choose Yes for consistency
.eq(DefineOpaqueTypes::Yes, unsized_a_ty, b_ty)
.expect("expected rematch to succeed")
.into_obligations(),
);

View file

@ -477,7 +477,8 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) {
if ty.is_ty_var() {
let Ok(InferOk { value: (), obligations }) =
self.infcx.at(&ObligationCause::dummy(), ty::ParamEnv::empty()).eq(
DefineOpaqueTypes::No,
// Comparing against a type variable never registers hidden types anyway
DefineOpaqueTypes::Yes,
ty,
Ty::new_placeholder(
self.infcx.tcx,
@ -504,7 +505,9 @@ fn visit_const(&mut self, ct: ty::Const<'tcx>) {
if ct.is_ct_infer() {
let Ok(InferOk { value: (), obligations }) =
self.infcx.at(&ObligationCause::dummy(), ty::ParamEnv::empty()).eq(
DefineOpaqueTypes::No,
// The types of the constants are the same, so there is no hidden type
// registration happening anyway.
DefineOpaqueTypes::Yes,
ct,
ty::Const::new_placeholder(
self.infcx.tcx,
@ -532,7 +535,8 @@ fn visit_region(&mut self, r: ty::Region<'tcx>) {
if r.is_var() {
let Ok(InferOk { value: (), obligations }) =
self.infcx.at(&ObligationCause::dummy(), ty::ParamEnv::empty()).eq(
DefineOpaqueTypes::No,
// Lifetimes don't contain opaque types (or any types for that matter).
DefineOpaqueTypes::Yes,
r,
ty::Region::new_placeholder(
self.infcx.tcx,

View file

@ -3842,7 +3842,9 @@ fn note_function_argument_obligation<G: EmissionGuarantee>(
self.probe(|_| {
match self
.at(&ObligationCause::misc(expr.span, body_id), param_env)
.eq(DefineOpaqueTypes::No, expected, actual)
// Doesn't actually matter if we define opaque types here, this is just used for
// diagnostics, and the result is never kept around.
.eq(DefineOpaqueTypes::Yes, expected, actual)
{
Ok(_) => (), // We ignore nested obligations here for now.
Err(err) => type_diffs.push(err),

View file

@ -429,7 +429,8 @@ fn process_obligation(
// as the cause of an overflow.
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
match self.selcx.infcx.at(&obligation.cause, obligation.param_env).eq(
DefineOpaqueTypes::No,
// Only really excercised by generic_const_exprs
DefineOpaqueTypes::Yes,
ct.ty(),
ty,
) {
@ -571,7 +572,9 @@ fn process_obligation(
if let Ok(new_obligations) = infcx
.at(&obligation.cause, obligation.param_env)
.trace(c1, c2)
.eq(DefineOpaqueTypes::No, a.args, b.args)
// Can define opaque types as this is only reachable with
// `generic_const_exprs`
.eq(DefineOpaqueTypes::Yes, a.args, b.args)
{
return ProcessResult::Changed(mk_pending(
new_obligations.into_obligations(),
@ -582,7 +585,9 @@ fn process_obligation(
(_, _) => {
if let Ok(new_obligations) = infcx
.at(&obligation.cause, obligation.param_env)
.eq(DefineOpaqueTypes::No, c1, c2)
// Can define opaque types as this is only reachable with
// `generic_const_exprs`
.eq(DefineOpaqueTypes::Yes, c1, c2)
{
return ProcessResult::Changed(mk_pending(
new_obligations.into_obligations(),
@ -623,7 +628,9 @@ fn process_obligation(
match (evaluate(c1), evaluate(c2)) {
(Ok(c1), Ok(c2)) => {
match self.selcx.infcx.at(&obligation.cause, obligation.param_env).eq(
DefineOpaqueTypes::No,
// Can define opaque types as this is only reachable with
// `generic_const_exprs`
DefineOpaqueTypes::Yes,
c1,
c2,
) {

View file

@ -906,7 +906,9 @@ fn evaluate_predicate_recursively<'o>(
.infcx
.at(&obligation.cause, obligation.param_env)
.trace(c1, c2)
.eq(DefineOpaqueTypes::No, a.args, b.args)
// Can define opaque types as this is only reachable with
// `generic_const_exprs`
.eq(DefineOpaqueTypes::Yes, a.args, b.args)
{
return self.evaluate_predicates_recursively(
previous_stack,
@ -919,7 +921,9 @@ fn evaluate_predicate_recursively<'o>(
if let Ok(InferOk { obligations, value: () }) = self
.infcx
.at(&obligation.cause, obligation.param_env)
.eq(DefineOpaqueTypes::No, c1, c2)
// Can define opaque types as this is only reachable with
// `generic_const_exprs`
.eq(DefineOpaqueTypes::Yes, c1, c2)
{
return self.evaluate_predicates_recursively(
previous_stack,
@ -949,7 +953,9 @@ fn evaluate_predicate_recursively<'o>(
match (evaluate(c1), evaluate(c2)) {
(Ok(c1), Ok(c2)) => {
match self.infcx.at(&obligation.cause, obligation.param_env).eq(
DefineOpaqueTypes::No,
// Can define opaque types as this is only reachable with
// `generic_const_exprs`
DefineOpaqueTypes::Yes,
c1,
c2,
) {
@ -982,7 +988,8 @@ fn evaluate_predicate_recursively<'o>(
ty::PredicateKind::Ambiguous => Ok(EvaluatedToAmbig),
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
match self.infcx.at(&obligation.cause, obligation.param_env).eq(
DefineOpaqueTypes::No,
// Only really excercised by generic_const_exprs
DefineOpaqueTypes::Yes,
ct.ty(),
ty,
) {

View file

@ -247,7 +247,12 @@ fn fulfill_implication<'tcx>(
// do the impls unify? If not, no specialization.
let Ok(InferOk { obligations: more_obligations, .. }) = infcx
.at(&ObligationCause::dummy(), param_env)
.eq(DefineOpaqueTypes::No, source_trait, target_trait)
// Ok to use `Yes`, as all the generic params are already replaced by inference variables,
// which will match the opaque type no matter if it is defining or not.
// Any concrete type that would match the opaque would already be handled by coherence rules,
// and thus either be ok to match here and already have errored, or it won't match, in which
// case there is no issue anyway.
.eq(DefineOpaqueTypes::Yes, source_trait, target_trait)
else {
debug!("fulfill_implication: {:?} does not unify with {:?}", source_trait, target_trait);
return Err(());

View file

@ -47,7 +47,7 @@ pub(crate) fn get_blanket_impls(&mut self, item_def_id: DefId) -> Vec<Item> {
// Require the type the impl is implemented on to match
// our type, and ignore the impl if there was a mismatch.
let Ok(eq_result) = infcx.at(&traits::ObligationCause::dummy(), param_env).eq(
DefineOpaqueTypes::No,
DefineOpaqueTypes::Yes,
impl_trait_ref.self_ty(),
impl_ty,
) else {

View file

@ -0,0 +1,18 @@
#![feature(generic_const_exprs, type_alias_impl_trait)]
#![allow(incomplete_features)]
type Foo = impl Sized;
fn with_bound<const N: usize>() -> Foo
where
[u8; (N / 2) as usize]: Sized,
{
let _: [u8; (N / 2) as Foo] = [0; (N / 2) as usize];
//~^ ERROR mismatched types
//~| ERROR non-primitive cast: `usize` as `Foo`
todo!()
}
fn main() {
with_bound::<4>();
}

View file

@ -0,0 +1,22 @@
error[E0308]: mismatched types
--> $DIR/opaque_type.rs:10:17
|
LL | type Foo = impl Sized;
| ---------- the found opaque type
...
LL | let _: [u8; (N / 2) as Foo] = [0; (N / 2) as usize];
| ^^^^^^^^^^^^^^ expected `usize`, found opaque type
|
= note: expected type `usize`
found opaque type `Foo`
error[E0605]: non-primitive cast: `usize` as `Foo`
--> $DIR/opaque_type.rs:10:17
|
LL | let _: [u8; (N / 2) as Foo] = [0; (N / 2) as usize];
| ^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0308, E0605.
For more information about an error, try `rustc --explain E0308`.

View file

@ -0,0 +1,13 @@
#![feature(type_alias_impl_trait)]
type Foo = impl Sized;
//~^ ERROR: cycle
//~| ERROR: cycle
fn foo<const C: Foo>() {}
//~^ ERROR: `Foo` is forbidden as the type of a const generic parameter
fn main() {
foo::<42>();
//~^ ERROR: mismatched types
}

View file

@ -0,0 +1,125 @@
error[E0308]: mismatched types
--> $DIR/opaque_types.rs:11:11
|
LL | type Foo = impl Sized;
| ---------- the expected opaque type
...
LL | foo::<42>();
| ^^ expected opaque type, found integer
|
= note: expected opaque type `Foo`
found type `{integer}`
error[E0391]: cycle detected when computing type of `Foo::{opaque#0}`
--> $DIR/opaque_types.rs:3:12
|
LL | type Foo = impl Sized;
| ^^^^^^^^^^
|
note: ...which requires computing type of opaque `Foo::{opaque#0}`...
--> $DIR/opaque_types.rs:3:12
|
LL | type Foo = impl Sized;
| ^^^^^^^^^^
note: ...which requires type-checking `main`...
--> $DIR/opaque_types.rs:10:1
|
LL | fn main() {
| ^^^^^^^^^
note: ...which requires evaluating type-level constant...
--> $DIR/opaque_types.rs:11:11
|
LL | foo::<42>();
| ^^
note: ...which requires const-evaluating + checking `main::{constant#0}`...
--> $DIR/opaque_types.rs:11:11
|
LL | foo::<42>();
| ^^
note: ...which requires caching mir of `main::{constant#0}` for CTFE...
--> $DIR/opaque_types.rs:11:11
|
LL | foo::<42>();
| ^^
note: ...which requires elaborating drops for `main::{constant#0}`...
--> $DIR/opaque_types.rs:11:11
|
LL | foo::<42>();
| ^^
= note: ...which requires normalizing `Foo`...
= note: ...which again requires computing type of `Foo::{opaque#0}`, completing the cycle
note: cycle used when checking that `Foo::{opaque#0}` is well-formed
--> $DIR/opaque_types.rs:3:12
|
LL | type Foo = impl Sized;
| ^^^^^^^^^^
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
error: `Foo` is forbidden as the type of a const generic parameter
--> $DIR/opaque_types.rs:7:17
|
LL | fn foo<const C: Foo>() {}
| ^^^
|
= note: the only supported types are integers, `bool` and `char`
error[E0391]: cycle detected when computing type of opaque `Foo::{opaque#0}`
--> $DIR/opaque_types.rs:3:12
|
LL | type Foo = impl Sized;
| ^^^^^^^^^^
|
note: ...which requires type-checking `main`...
--> $DIR/opaque_types.rs:10:1
|
LL | fn main() {
| ^^^^^^^^^
note: ...which requires evaluating type-level constant...
--> $DIR/opaque_types.rs:11:11
|
LL | foo::<42>();
| ^^
note: ...which requires const-evaluating + checking `main::{constant#0}`...
--> $DIR/opaque_types.rs:11:11
|
LL | foo::<42>();
| ^^
note: ...which requires caching mir of `main::{constant#0}` for CTFE...
--> $DIR/opaque_types.rs:11:11
|
LL | foo::<42>();
| ^^
note: ...which requires elaborating drops for `main::{constant#0}`...
--> $DIR/opaque_types.rs:11:11
|
LL | foo::<42>();
| ^^
note: ...which requires borrow-checking `main::{constant#0}`...
--> $DIR/opaque_types.rs:11:11
|
LL | foo::<42>();
| ^^
note: ...which requires promoting constants in MIR for `main::{constant#0}`...
--> $DIR/opaque_types.rs:11:11
|
LL | foo::<42>();
| ^^
note: ...which requires const checking `main::{constant#0}`...
--> $DIR/opaque_types.rs:11:11
|
LL | foo::<42>();
| ^^
= note: ...which requires computing whether `Foo` is freeze...
= note: ...which requires evaluating trait selection obligation `Foo: core::marker::Freeze`...
= note: ...which again requires computing type of opaque `Foo::{opaque#0}`, completing the cycle
note: cycle used when computing type of `Foo::{opaque#0}`
--> $DIR/opaque_types.rs:3:12
|
LL | type Foo = impl Sized;
| ^^^^^^^^^^
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
error: aborting due to 4 previous errors
Some errors have detailed explanations: E0308, E0391.
For more information about an error, try `rustc --explain E0308`.

View file

@ -0,0 +1,17 @@
#![feature(type_alias_impl_trait)]
type Foo = impl Sized;
fn foo<const C: u32>() {}
const C: Foo = 42;
fn bar()
where
Foo:,
{
foo::<C>();
//~^ ERROR: mismatched types
}
fn main() {}

View file

@ -0,0 +1,15 @@
error[E0308]: mismatched types
--> $DIR/opaque_types2.rs:13:11
|
LL | type Foo = impl Sized;
| ---------- the found opaque type
...
LL | foo::<C>();
| ^ expected `u32`, found opaque type
|
= note: expected type `u32`
found opaque type `Foo`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0308`.

View file

@ -5,7 +5,7 @@ fn fine(x: impl Into<u32>) -> impl Into<u32> { x }
fn bad_in_ret_position(x: impl Into<u32>) -> impl Into<impl Debug> { x }
//~^ ERROR nested `impl Trait` is not allowed
//~| ERROR the trait bound `impl Debug: From<impl Into<u32>>` is not satisfied
//~| ERROR the trait bound `impl Into<u32>: Into<impl Debug>` is not satisfied
fn bad_in_fn_syntax(x: fn() -> impl Into<impl Debug>) {}
//~^ ERROR nested `impl Trait` is not allowed
@ -18,7 +18,7 @@ fn bad_in_arg_position(_: impl Into<impl Debug>) { }
impl X {
fn bad(x: impl Into<u32>) -> impl Into<impl Debug> { x }
//~^ ERROR nested `impl Trait` is not allowed
//~| ERROR the trait bound `impl Debug: From<impl Into<u32>>` is not satisfied
//~| ERROR the trait bound `impl Into<u32>: Into<impl Debug>` is not satisfied
}
fn allowed_in_assoc_type() -> impl Iterator<Item=impl Fn()> {

View file

@ -42,20 +42,20 @@ LL | fn bad_in_fn_syntax(x: fn() -> impl Into<impl Debug>) {}
|
= note: `impl Trait` is only allowed in arguments and return types of functions and methods
error[E0277]: the trait bound `impl Debug: From<impl Into<u32>>` is not satisfied
error[E0277]: the trait bound `impl Into<u32>: Into<impl Debug>` is not satisfied
--> $DIR/nested_impl_trait.rs:6:46
|
LL | fn bad_in_ret_position(x: impl Into<u32>) -> impl Into<impl Debug> { x }
| ^^^^^^^^^^^^^^^^^^^^^ the trait `From<impl Into<u32>>` is not implemented for `impl Debug`, which is required by `impl Into<u32>: Into<impl Debug>`
| ^^^^^^^^^^^^^^^^^^^^^ the trait `From<impl Into<u32>>` is not implemented for `impl Into<u32>`, which is required by `impl Into<u32>: Into<impl Debug>`
|
= help: the trait `Into<U>` is implemented for `T`
= note: required for `impl Into<u32>` to implement `Into<impl Debug>`
error[E0277]: the trait bound `impl Debug: From<impl Into<u32>>` is not satisfied
error[E0277]: the trait bound `impl Into<u32>: Into<impl Debug>` is not satisfied
--> $DIR/nested_impl_trait.rs:19:34
|
LL | fn bad(x: impl Into<u32>) -> impl Into<impl Debug> { x }
| ^^^^^^^^^^^^^^^^^^^^^ the trait `From<impl Into<u32>>` is not implemented for `impl Debug`, which is required by `impl Into<u32>: Into<impl Debug>`
| ^^^^^^^^^^^^^^^^^^^^^ the trait `From<impl Into<u32>>` is not implemented for `impl Into<u32>`, which is required by `impl Into<u32>: Into<impl Debug>`
|
= help: the trait `Into<U>` is implemented for `T`
= note: required for `impl Into<u32>` to implement `Into<impl Debug>`

View file

@ -0,0 +1,30 @@
#![feature(type_alias_impl_trait)]
struct Foo<T>(T);
impl Foo<u32> {
fn method() {}
fn method2(self) {}
}
type Bar = impl Sized;
fn bar() -> Bar {
42_u32
}
impl Foo<Bar> {
fn foo() -> Bar {
Self::method();
//~^ ERROR: no function or associated item named `method` found for struct `Foo<Bar>`
Foo::<Bar>::method();
//~^ ERROR: no function or associated item named `method` found for struct `Foo<Bar>`
let x = Foo(bar());
Foo::method2(x);
let x = Self(bar());
Self::method2(x);
//~^ ERROR: no function or associated item named `method2` found for struct `Foo<Bar>`
todo!()
}
}
fn main() {}

View file

@ -0,0 +1,36 @@
error[E0599]: no function or associated item named `method` found for struct `Foo<Bar>` in the current scope
--> $DIR/opaque_param_in_ufc.rs:17:15
|
LL | struct Foo<T>(T);
| ------------- function or associated item `method` not found for this struct
...
LL | Self::method();
| ^^^^^^ function or associated item not found in `Foo<Bar>`
|
= note: the function or associated item was found for
- `Foo<u32>`
error[E0599]: no function or associated item named `method` found for struct `Foo<Bar>` in the current scope
--> $DIR/opaque_param_in_ufc.rs:19:21
|
LL | struct Foo<T>(T);
| ------------- function or associated item `method` not found for this struct
...
LL | Foo::<Bar>::method();
| ^^^^^^ function or associated item not found in `Foo<Bar>`
|
= note: the function or associated item was found for
- `Foo<u32>`
error[E0599]: no function or associated item named `method2` found for struct `Foo<Bar>` in the current scope
--> $DIR/opaque_param_in_ufc.rs:24:15
|
LL | struct Foo<T>(T);
| ------------- function or associated item `method2` not found for this struct
...
LL | Self::method2(x);
| ^^^^^^^ function or associated item not found in `Foo<Bar>`
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0599`.

View file

@ -0,0 +1,12 @@
#![feature(type_alias_impl_trait)]
struct Foo;
type Bar = impl Sized;
//~^ ERROR unconstrained opaque type
impl Foo {
fn foo(self: Bar) {}
//~^ ERROR: invalid `self` parameter type: Bar
}
fn main() {}

View file

@ -0,0 +1,20 @@
error: unconstrained opaque type
--> $DIR/arbitrary-self-opaque.rs:4:12
|
LL | type Bar = impl Sized;
| ^^^^^^^^^^
|
= note: `Bar` must be used in combination with a concrete type within the same module
error[E0307]: invalid `self` parameter type: Bar
--> $DIR/arbitrary-self-opaque.rs:8:18
|
LL | fn foo(self: Bar) {}
| ^^^
|
= note: type of `self` must be `Self` or a type that dereferences to it
= help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0307`.

View file

@ -0,0 +1,31 @@
// Test that specializing on opaque types is allowed
//@ check-pass
#![feature(min_specialization, type_alias_impl_trait)]
trait SpecTrait<U> {
fn f();
}
impl<U> SpecTrait<U> for () {
default fn f() {}
}
type Opaque = impl Tuple;
trait Tuple {}
impl Tuple for () {}
impl SpecTrait<Opaque> for () {
fn f() {}
}
impl SpecTrait<u32> for () {
fn f() {}
}
fn foo() -> Opaque {}
fn main() {}

View file

@ -0,0 +1,28 @@
// Test that specializing on opaque types is allowed
#![feature(min_specialization, type_alias_impl_trait)]
trait SpecTrait<U, V> {
fn f();
}
impl<U> SpecTrait<U, ()> for () {
default fn f() {}
}
type Opaque = impl Tuple;
trait Tuple {}
impl Tuple for () {}
// FIXME: this passes if we use `<(), ()>` here instead of `<(), Opaque>`,
// even though there can't be more overlap from the opaque version
impl SpecTrait<(), Opaque> for () {
//~^ ERROR: conflicting implementations
fn f() {}
}
fn foo() -> Opaque {}
fn main() {}

View file

@ -0,0 +1,12 @@
error[E0119]: conflicting implementations of trait `SpecTrait<(), ()>` for type `()`
--> $DIR/impl-on-opaque2.rs:21:1
|
LL | impl<U> SpecTrait<U, ()> for () {
| ------------------------------- first implementation here
...
LL | impl SpecTrait<(), Opaque> for () {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0119`.

View file

@ -0,0 +1,17 @@
error[E0308]: mismatched types
--> $DIR/illegal-upcast-from-impl-opaque.rs:26:5
|
LL | type Foo = impl Sized;
| ---------- the found opaque type
LL |
LL | fn illegal(x: &dyn Sub<Assoc = Foo>) -> &dyn Super<Assoc = i32> {
| ----------------------- expected `&dyn Super<Assoc = i32>` because of return type
LL | x
| ^ expected trait `Super`, found trait `Sub`
|
= note: expected reference `&dyn Super<Assoc = i32>`
found reference `&dyn Sub<Assoc = Foo>`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0308`.

View file

@ -0,0 +1,14 @@
error: internal compiler error: error performing operation: query type op
--> $DIR/illegal-upcast-from-impl-opaque.rs:25:1
|
LL | fn illegal(x: &dyn Sub<Assoc = Foo>) -> &dyn Super<Assoc = i32> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note:
--> $DIR/illegal-upcast-from-impl-opaque.rs:25:1
|
LL | fn illegal(x: &dyn Sub<Assoc = Foo>) -> &dyn Super<Assoc = i32> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
query stack during panic:
end of query stack

View file

@ -0,0 +1,29 @@
//@ revisions: current next
//@[next] compile-flags: -Znext-solver
//@[next] failure-status: 101
//@[next] known-bug: unknown
//@[next] normalize-stderr-test "note: .*\n\n" -> ""
//@[next] normalize-stderr-test "thread 'rustc' panicked.*\n.*\n" -> ""
//@[next] normalize-stderr-test "(error: internal compiler error: [^:]+):\d+:\d+: " -> "$1:LL:CC: "
//@[next] normalize-stderr-test "delayed at .*" -> ""
//@[next] rustc-env:RUST_BACKTRACE=0
#![feature(trait_upcasting, type_alias_impl_trait)]
trait Super {
type Assoc;
}
trait Sub: Super {}
impl<T: ?Sized> Super for T {
type Assoc = i32;
}
type Foo = impl Sized;
fn illegal(x: &dyn Sub<Assoc = Foo>) -> &dyn Super<Assoc = i32> {
x //[current]~ mismatched types
}
fn main() {}