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:
commit
a4b11c8e60
31 changed files with 522 additions and 49 deletions
|
@ -918,7 +918,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -400,7 +400,7 @@ impl<'a, 'tcx> FnCtxt<'a, '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 @@ impl<'a, 'tcx> FnCtxt<'a, '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)
|
||||
});
|
||||
|
|
|
@ -44,10 +44,7 @@ use rustc_infer::infer::InferOk;
|
|||
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 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
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 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
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,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -687,7 +687,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// 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()
|
||||
});
|
||||
|
||||
|
|
|
@ -843,7 +843,9 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
{
|
||||
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 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
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")]
|
||||
|
|
|
@ -720,7 +720,8 @@ impl<'tcx> EvalCtxt<'_, '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 @@ impl<'tcx> EvalCtxt<'_, '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 @@ impl<'tcx> EvalCtxt<'_, '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 @@ impl<'tcx> EvalCtxt<'_, '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()
|
||||
})
|
||||
|
|
|
@ -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(),
|
||||
);
|
||||
|
|
|
@ -477,7 +477,8 @@ fn plug_infer_with_placeholders<'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 plug_infer_with_placeholders<'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 plug_infer_with_placeholders<'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,
|
||||
|
|
|
@ -3842,7 +3842,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
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),
|
||||
|
|
|
@ -429,7 +429,8 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
|
|||
// 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 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
|
|||
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 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
|
|||
(_, _) => {
|
||||
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 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
|
|||
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,
|
||||
) {
|
||||
|
|
|
@ -906,7 +906,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
.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 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
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 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
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 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
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,
|
||||
) {
|
||||
|
|
|
@ -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(());
|
||||
|
|
|
@ -47,7 +47,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
|
|||
// 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 {
|
||||
|
|
18
tests/ui/const-generics/generic_const_exprs/opaque_type.rs
Normal file
18
tests/ui/const-generics/generic_const_exprs/opaque_type.rs
Normal 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>();
|
||||
}
|
|
@ -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`.
|
13
tests/ui/const-generics/opaque_types.rs
Normal file
13
tests/ui/const-generics/opaque_types.rs
Normal 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
|
||||
}
|
125
tests/ui/const-generics/opaque_types.stderr
Normal file
125
tests/ui/const-generics/opaque_types.stderr
Normal 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`.
|
17
tests/ui/const-generics/opaque_types2.rs
Normal file
17
tests/ui/const-generics/opaque_types2.rs
Normal 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() {}
|
15
tests/ui/const-generics/opaque_types2.stderr
Normal file
15
tests/ui/const-generics/opaque_types2.stderr
Normal 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`.
|
|
@ -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 @@ struct X;
|
|||
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()> {
|
||||
|
|
|
@ -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>`
|
||||
|
|
30
tests/ui/methods/opaque_param_in_ufc.rs
Normal file
30
tests/ui/methods/opaque_param_in_ufc.rs
Normal 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() {}
|
36
tests/ui/methods/opaque_param_in_ufc.stderr
Normal file
36
tests/ui/methods/opaque_param_in_ufc.stderr
Normal 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`.
|
12
tests/ui/self/arbitrary-self-opaque.rs
Normal file
12
tests/ui/self/arbitrary-self-opaque.rs
Normal 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() {}
|
20
tests/ui/self/arbitrary-self-opaque.stderr
Normal file
20
tests/ui/self/arbitrary-self-opaque.stderr
Normal 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`.
|
31
tests/ui/specialization/min_specialization/impl-on-opaque.rs
Normal file
31
tests/ui/specialization/min_specialization/impl-on-opaque.rs
Normal 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() {}
|
|
@ -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() {}
|
|
@ -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`.
|
|
@ -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`.
|
|
@ -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
|
|
@ -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() {}
|
Loading…
Add table
Reference in a new issue