handle specialization in the new trait solver
uwu :3
This commit is contained in:
parent
8f43b85954
commit
009db53e49
20 changed files with 290 additions and 51 deletions
|
|
@ -590,6 +590,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
|||
self.defaultness(def_id).has_value()
|
||||
}
|
||||
|
||||
fn impl_specializes(self, impl_def_id: Self::DefId, victim_def_id: Self::DefId) -> bool {
|
||||
self.specializes((impl_def_id, victim_def_id))
|
||||
}
|
||||
|
||||
fn impl_is_default(self, impl_def_id: DefId) -> bool {
|
||||
self.defaultness(impl_def_id).is_default()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ use rustc_type_ir::{
|
|||
};
|
||||
use tracing::{debug, instrument};
|
||||
|
||||
use super::has_only_region_constraints;
|
||||
use super::trait_goals::TraitGoalProvenVia;
|
||||
use crate::delegate::SolverDelegate;
|
||||
use crate::solve::inspect::ProbeKind;
|
||||
|
|
@ -771,6 +772,69 @@ where
|
|||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) enum AllowInferenceConstraints {
|
||||
Yes,
|
||||
No,
|
||||
}
|
||||
|
||||
impl<D, I> EvalCtxt<'_, D>
|
||||
where
|
||||
D: SolverDelegate<Interner = I>,
|
||||
I: Interner,
|
||||
{
|
||||
/// Check whether we can ignore impl candidates due to specialization.
|
||||
///
|
||||
/// This is only necessary for `feature(specialization)` and seems quite ugly.
|
||||
pub(super) fn filter_specialized_impls(
|
||||
&mut self,
|
||||
allow_inference_constraints: AllowInferenceConstraints,
|
||||
candidates: &mut Vec<Candidate<I>>,
|
||||
) {
|
||||
match self.typing_mode() {
|
||||
TypingMode::Coherence => return,
|
||||
TypingMode::Analysis { .. }
|
||||
| TypingMode::Borrowck { .. }
|
||||
| TypingMode::PostBorrowckAnalysis { .. }
|
||||
| TypingMode::PostAnalysis => {}
|
||||
}
|
||||
|
||||
let mut i = 0;
|
||||
'outer: while i < candidates.len() {
|
||||
let CandidateSource::Impl(victim_def_id) = candidates[i].source else {
|
||||
i += 1;
|
||||
continue;
|
||||
};
|
||||
|
||||
for (j, c) in candidates.iter().enumerate() {
|
||||
if i == j {
|
||||
continue;
|
||||
}
|
||||
|
||||
let CandidateSource::Impl(other_def_id) = c.source else {
|
||||
continue;
|
||||
};
|
||||
|
||||
// See if we can toss out `victim` based on specialization.
|
||||
//
|
||||
// While this requires us to know *for sure* that the `lhs` impl applies
|
||||
// we still use modulo regions here. This is fine as specialization currently
|
||||
// assumes that specializing impls have to be always applicable, meaning that
|
||||
// the only allowed region constraints may be constraints also present on the default impl.
|
||||
if matches!(allow_inference_constraints, AllowInferenceConstraints::Yes)
|
||||
|| has_only_region_constraints(c.result)
|
||||
{
|
||||
if self.cx().impl_specializes(other_def_id, victim_def_id) {
|
||||
candidates.remove(i);
|
||||
continue 'outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/// Assemble and merge candidates for goals which are related to an underlying trait
|
||||
/// goal. Right now, this is normalizes-to and host effect goals.
|
||||
|
|
@ -857,7 +921,7 @@ where
|
|||
}
|
||||
}
|
||||
TraitGoalProvenVia::Misc => {
|
||||
let candidates =
|
||||
let mut candidates =
|
||||
self.assemble_and_evaluate_candidates(goal, AssembleCandidatesFrom::All);
|
||||
|
||||
// Prefer "orphaned" param-env normalization predicates, which are used
|
||||
|
|
@ -871,6 +935,13 @@ where
|
|||
return Ok(response);
|
||||
}
|
||||
|
||||
// We drop specialized impls to allow normalization via a final impl here. In case
|
||||
// the specializing impl has different inference constraints from the specialized
|
||||
// impl, proving the trait goal is already ambiguous, so we never get here. This
|
||||
// means we can just ignore inference constraints and don't have to special-case
|
||||
// constraining the normalized-to `term`.
|
||||
self.filter_specialized_impls(AllowInferenceConstraints::Yes, &mut candidates);
|
||||
|
||||
let responses: Vec<_> = candidates.iter().map(|c| c.result).collect();
|
||||
if let Some(response) = self.try_merge_responses(&responses) {
|
||||
Ok(response)
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ use rustc_type_ir::{
|
|||
};
|
||||
use tracing::{instrument, trace};
|
||||
|
||||
use super::has_only_region_constraints;
|
||||
use crate::coherence;
|
||||
use crate::delegate::SolverDelegate;
|
||||
use crate::solve::inspect::{self, ProofTreeBuilder};
|
||||
|
|
@ -476,13 +477,8 @@ where
|
|||
Ok(response) => response,
|
||||
};
|
||||
|
||||
let has_changed = if !response.value.var_values.is_identity_modulo_regions()
|
||||
|| !response.value.external_constraints.opaque_types.is_empty()
|
||||
{
|
||||
HasChanged::Yes
|
||||
} else {
|
||||
HasChanged::No
|
||||
};
|
||||
let has_changed =
|
||||
if !has_only_region_constraints(response) { HasChanged::Yes } else { HasChanged::No };
|
||||
|
||||
let (normalization_nested_goals, certainty) =
|
||||
self.instantiate_and_apply_query_response(goal.param_env, orig_values, response);
|
||||
|
|
|
|||
|
|
@ -70,6 +70,17 @@ fn has_no_inference_or_external_constraints<I: Interner>(
|
|||
&& normalization_nested_goals.is_empty()
|
||||
}
|
||||
|
||||
fn has_only_region_constraints<I: Interner>(response: ty::Canonical<I, Response<I>>) -> bool {
|
||||
let ExternalConstraintsData {
|
||||
region_constraints: _,
|
||||
ref opaque_types,
|
||||
ref normalization_nested_goals,
|
||||
} = *response.value.external_constraints;
|
||||
response.value.var_values.is_identity_modulo_regions()
|
||||
&& opaque_types.is_empty()
|
||||
&& normalization_nested_goals.is_empty()
|
||||
}
|
||||
|
||||
impl<'a, D, I> EvalCtxt<'a, D>
|
||||
where
|
||||
D: SolverDelegate<Interner = I>,
|
||||
|
|
|
|||
|
|
@ -213,9 +213,6 @@ where
|
|||
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||
};
|
||||
|
||||
// In case the associated item is hidden due to specialization, we have to
|
||||
// return ambiguity this would otherwise be incomplete, resulting in
|
||||
// unsoundness during coherence (#105782).
|
||||
let target_item_def_id = match ecx.fetch_eligible_assoc_item(
|
||||
goal_trait_ref,
|
||||
goal.predicate.def_id(),
|
||||
|
|
@ -223,8 +220,28 @@ where
|
|||
) {
|
||||
Ok(Some(target_item_def_id)) => target_item_def_id,
|
||||
Ok(None) => {
|
||||
return ecx
|
||||
.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS);
|
||||
match ecx.typing_mode() {
|
||||
// In case the associated item is hidden due to specialization, we have to
|
||||
// return ambiguity this would otherwise be incomplete, resulting in
|
||||
// unsoundness during coherence (#105782).
|
||||
ty::TypingMode::Coherence => {
|
||||
return ecx.evaluate_added_goals_and_make_canonical_response(
|
||||
Certainty::AMBIGUOUS,
|
||||
);
|
||||
}
|
||||
// Outside of coherence, we treat the associated item as rigid instead.
|
||||
ty::TypingMode::Analysis { .. }
|
||||
| ty::TypingMode::Borrowck { .. }
|
||||
| ty::TypingMode::PostBorrowckAnalysis { .. }
|
||||
| ty::TypingMode::PostAnalysis => {
|
||||
ecx.structurally_instantiate_normalizes_to_term(
|
||||
goal,
|
||||
goal.predicate.alias,
|
||||
);
|
||||
return ecx
|
||||
.evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
|
||||
}
|
||||
};
|
||||
}
|
||||
Err(guar) => return error_response(ecx, guar),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ use tracing::{instrument, trace};
|
|||
|
||||
use crate::delegate::SolverDelegate;
|
||||
use crate::solve::assembly::structural_traits::{self, AsyncCallableRelevantTypes};
|
||||
use crate::solve::assembly::{self, AssembleCandidatesFrom, Candidate};
|
||||
use crate::solve::assembly::{self, AllowInferenceConstraints, AssembleCandidatesFrom, Candidate};
|
||||
use crate::solve::inspect::ProbeKind;
|
||||
use crate::solve::{
|
||||
BuiltinImplSource, CandidateSource, Certainty, EvalCtxt, Goal, GoalSource, MaybeCause,
|
||||
|
|
@ -1338,6 +1338,8 @@ where
|
|||
};
|
||||
}
|
||||
|
||||
self.filter_specialized_impls(AllowInferenceConstraints::No, &mut candidates);
|
||||
|
||||
// If there are *only* global where bounds, then make sure to return that this
|
||||
// is still reported as being proven-via the param-env so that rigid projections
|
||||
// operate correctly. Otherwise, drop all global where-bounds before merging the
|
||||
|
|
|
|||
|
|
@ -286,6 +286,8 @@ pub trait Interner:
|
|||
|
||||
fn has_item_definition(self, def_id: Self::DefId) -> bool;
|
||||
|
||||
fn impl_specializes(self, impl_def_id: Self::DefId, victim_def_id: Self::DefId) -> bool;
|
||||
|
||||
fn impl_is_default(self, impl_def_id: Self::DefId) -> bool;
|
||||
|
||||
fn impl_trait_ref(self, impl_def_id: Self::DefId) -> ty::EarlyBinder<Self, ty::TraitRef<Self>>;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/prefer-specializing-impl-over-default.rs:5:12
|
||||
|
|
||||
LL | #![feature(specialization)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
|
||||
= help: consider using `min_specialization` instead, which is more stable and complete
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/prefer-specializing-impl-over-default.rs:5:12
|
||||
|
|
||||
LL | #![feature(specialization)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
|
||||
= help: consider using `min_specialization` instead, which is more stable and complete
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
//@ revisions: current next
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
//@ check-pass
|
||||
#![feature(specialization)]
|
||||
//~^ WARN the feature `specialization` is incomplete
|
||||
|
||||
trait WithAssoc: 'static {
|
||||
type Assoc;
|
||||
}
|
||||
impl<T: 'static> WithAssoc for (T,) {
|
||||
type Assoc = ();
|
||||
}
|
||||
|
||||
struct GenericArray<U: WithAssoc>(U::Assoc);
|
||||
|
||||
trait AbiExample {
|
||||
fn example();
|
||||
}
|
||||
impl<U: WithAssoc> AbiExample for GenericArray<U> {
|
||||
fn example() {}
|
||||
}
|
||||
impl<T> AbiExample for T {
|
||||
default fn example() {}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _ = GenericArray::<((),)>::example();
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/specialization-default-projection.rs:1:12
|
||||
--> $DIR/specialization-default-projection.rs:5:12
|
||||
|
|
||||
LL | #![feature(specialization)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
@ -9,7 +9,7 @@ LL | #![feature(specialization)]
|
|||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/specialization-default-projection.rs:21:5
|
||||
--> $DIR/specialization-default-projection.rs:25:5
|
||||
|
|
||||
LL | fn generic<T>() -> <T as Foo>::Assoc {
|
||||
| ----------------- expected `<T as Foo>::Assoc` because of return type
|
||||
|
|
@ -23,7 +23,7 @@ LL | ()
|
|||
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/specialization-default-projection.rs:28:5
|
||||
--> $DIR/specialization-default-projection.rs:32:5
|
||||
|
|
||||
LL | fn monomorphic() -> () {
|
||||
| -- expected `()` because of return type
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/specialization-default-projection.rs:5:12
|
||||
|
|
||||
LL | #![feature(specialization)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
|
||||
= help: consider using `min_specialization` instead, which is more stable and complete
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/specialization-default-projection.rs:25:5
|
||||
|
|
||||
LL | fn generic<T>() -> <T as Foo>::Assoc {
|
||||
| ----------------- expected `<T as Foo>::Assoc` because of return type
|
||||
...
|
||||
LL | ()
|
||||
| ^^ types differ
|
||||
|
|
||||
= note: expected associated type `<T as Foo>::Assoc`
|
||||
found unit type `()`
|
||||
= help: consider constraining the associated type `<T as Foo>::Assoc` to `()` or calling a method that returns `<T as Foo>::Assoc`
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/specialization-default-projection.rs:32:5
|
||||
|
|
||||
LL | fn monomorphic() -> () {
|
||||
| -- expected `()` because of return type
|
||||
...
|
||||
LL | generic::<()>()
|
||||
| ^^^^^^^^^^^^^^^- help: consider using a semicolon here: `;`
|
||||
| |
|
||||
| types differ
|
||||
|
|
||||
= note: expected unit type `()`
|
||||
found associated type `<() as Foo>::Assoc`
|
||||
= help: consider constraining the associated type `<() as Foo>::Assoc` to `()`
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
|
||||
|
||||
error: aborting due to 2 previous errors; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
|
@ -1,3 +1,7 @@
|
|||
//@ revisions: current next
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
|
||||
#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
|
||||
|
||||
// Make sure we can't project defaulted associated types
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/specialization-default-types.rs:5:12
|
||||
--> $DIR/specialization-default-types.rs:9:12
|
||||
|
|
||||
LL | #![feature(specialization)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
@ -9,7 +9,7 @@ LL | #![feature(specialization)]
|
|||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/specialization-default-types.rs:15:9
|
||||
--> $DIR/specialization-default-types.rs:19:9
|
||||
|
|
||||
LL | default type Output = Box<T>;
|
||||
| ----------------------------- associated type is `default` and may be overridden
|
||||
|
|
@ -22,7 +22,7 @@ LL | Box::new(self)
|
|||
found struct `Box<T>`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/specialization-default-types.rs:25:5
|
||||
--> $DIR/specialization-default-types.rs:29:5
|
||||
|
|
||||
LL | fn trouble<T>(t: T) -> Box<T> {
|
||||
| ------ expected `Box<T>` because of return type
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/specialization-default-types.rs:9:12
|
||||
|
|
||||
LL | #![feature(specialization)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
|
||||
= help: consider using `min_specialization` instead, which is more stable and complete
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/specialization-default-types.rs:19:9
|
||||
|
|
||||
LL | default type Output = Box<T>;
|
||||
| ----------------------------- associated type is `default` and may be overridden
|
||||
LL | default fn generate(self) -> Self::Output {
|
||||
| ------------ expected `<T as Example>::Output` because of return type
|
||||
LL | Box::new(self)
|
||||
| ^^^^^^^^^^^^^^ types differ
|
||||
|
|
||||
= note: expected associated type `<T as Example>::Output`
|
||||
found struct `Box<T>`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/specialization-default-types.rs:29:5
|
||||
|
|
||||
LL | fn trouble<T>(t: T) -> Box<T> {
|
||||
| ------ expected `Box<T>` because of return type
|
||||
LL | Example::generate(t)
|
||||
| ^^^^^^^^^^^^^^^^^^^^ types differ
|
||||
|
|
||||
= note: expected struct `Box<T>`
|
||||
found associated type `<T as Example>::Output`
|
||||
= help: consider constraining the associated type `<T as Example>::Output` to `Box<T>`
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
|
||||
|
||||
error: aborting due to 2 previous errors; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
|
@ -1,3 +1,7 @@
|
|||
//@ revisions: current next
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
|
||||
// It should not be possible to use the concrete value of a defaulted
|
||||
// associated type in the impl defining it -- otherwise, what happens
|
||||
// if it's overridden?
|
||||
|
|
|
|||
|
|
@ -10,11 +10,8 @@ trait Default {
|
|||
|
||||
impl<T> Default for T {
|
||||
default type Id = T;
|
||||
// This will be fixed by #111994
|
||||
fn intu(&self) -> &Self::Id {
|
||||
//~^ ERROR type annotations needed
|
||||
//~| ERROR cannot normalize `<T as Default>::Id: '_`
|
||||
self //~ ERROR cannot satisfy
|
||||
self //~ ERROR mismatched types
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -25,6 +22,7 @@ fn transmute<T: Default<Id = U>, U: Copy>(t: T) -> U {
|
|||
use std::num::NonZero;
|
||||
|
||||
fn main() {
|
||||
let s = transmute::<u8, Option<NonZero<u8>>>(0); //~ ERROR cannot satisfy
|
||||
let s = transmute::<u8, Option<NonZero<u8>>>(0);
|
||||
//~^ ERROR type mismatch resolving `<u8 as Default>::Id == Option<NonZero<u8>>`
|
||||
assert_eq!(s, None);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,37 +8,32 @@ LL | #![feature(specialization)]
|
|||
= help: consider using `min_specialization` instead, which is more stable and complete
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
error: cannot normalize `<T as Default>::Id: '_`
|
||||
--> $DIR/specialization-transmute.rs:14:5
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/specialization-transmute.rs:14:9
|
||||
|
|
||||
LL | fn intu(&self) -> &Self::Id {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/specialization-transmute.rs:14:23
|
||||
|
|
||||
LL | fn intu(&self) -> &Self::Id {
|
||||
| ^^^^^^^^^ cannot infer type for reference `&<T as Default>::Id`
|
||||
|
||||
error[E0284]: type annotations needed: cannot satisfy `<T as Default>::Id normalizes-to T`
|
||||
--> $DIR/specialization-transmute.rs:17:9
|
||||
|
|
||||
| --------- expected `&<T as Default>::Id` because of return type
|
||||
LL | self
|
||||
| ^^^^ cannot satisfy `<T as Default>::Id normalizes-to T`
|
||||
| ^^^^ types differ
|
||||
|
|
||||
= note: expected reference `&<T as Default>::Id`
|
||||
found reference `&T`
|
||||
|
||||
error[E0284]: type annotations needed: cannot satisfy `<u8 as Default>::Id normalizes-to Option<NonZero<u8>>`
|
||||
--> $DIR/specialization-transmute.rs:28:13
|
||||
error[E0271]: type mismatch resolving `<u8 as Default>::Id == Option<NonZero<u8>>`
|
||||
--> $DIR/specialization-transmute.rs:25:50
|
||||
|
|
||||
LL | let s = transmute::<u8, Option<NonZero<u8>>>(0);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `<u8 as Default>::Id normalizes-to Option<NonZero<u8>>`
|
||||
| ------------------------------------ ^ types differ
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required by a bound in `transmute`
|
||||
--> $DIR/specialization-transmute.rs:21:25
|
||||
--> $DIR/specialization-transmute.rs:18:25
|
||||
|
|
||||
LL | fn transmute<T: Default<Id = U>, U: Copy>(t: T) -> U {
|
||||
| ^^^^^^ required by this bound in `transmute`
|
||||
|
||||
error: aborting due to 4 previous errors; 1 warning emitted
|
||||
error: aborting due to 2 previous errors; 1 warning emitted
|
||||
|
||||
Some errors have detailed explanations: E0282, E0284.
|
||||
For more information about an error, try `rustc --explain E0282`.
|
||||
Some errors have detailed explanations: E0271, E0308.
|
||||
For more information about an error, try `rustc --explain E0271`.
|
||||
|
|
|
|||
|
|
@ -18,5 +18,5 @@ fn test<T: Default<Id = U>, U>() {}
|
|||
|
||||
fn main() {
|
||||
test::<u32, ()>();
|
||||
//~^ ERROR cannot satisfy `<u32 as Default>::Id normalizes-to ()`
|
||||
//~^ ERROR type mismatch resolving `<u32 as Default>::Id == ()`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@ LL | #![feature(specialization)]
|
|||
= help: consider using `min_specialization` instead, which is more stable and complete
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
error[E0284]: type annotations needed: cannot satisfy `<u32 as Default>::Id normalizes-to ()`
|
||||
--> $DIR/specialization-unconstrained.rs:20:5
|
||||
error[E0271]: type mismatch resolving `<u32 as Default>::Id == ()`
|
||||
--> $DIR/specialization-unconstrained.rs:20:12
|
||||
|
|
||||
LL | test::<u32, ()>();
|
||||
| ^^^^^^^^^^^^^^^^^ cannot satisfy `<u32 as Default>::Id normalizes-to ()`
|
||||
| ^^^ types differ
|
||||
|
|
||||
note: required by a bound in `test`
|
||||
--> $DIR/specialization-unconstrained.rs:17:20
|
||||
|
|
@ -22,4 +22,4 @@ LL | fn test<T: Default<Id = U>, U>() {}
|
|||
|
||||
error: aborting due to 1 previous error; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0284`.
|
||||
For more information about this error, try `rustc --explain E0271`.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue