Skip to content

Allow default type to be projected in the fully monomorphic case #42411

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 4 additions & 25 deletions src/librustc/traits/project.rs
Original file line number Diff line number Diff line change
@@ -38,28 +38,9 @@ use util::common::FN_OUTPUT_NAME;
/// more or less conservative.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Reveal {
/// At type-checking time, we refuse to project any associated
/// type that is marked `default`. Non-`default` ("final") types
/// are always projected. This is necessary in general for
/// soundness of specialization. However, we *could* allow
/// projections in fully-monomorphic cases. We choose not to,
/// because we prefer for `default type` to force the type
/// definition to be treated abstractly by any consumers of the
/// impl. Concretely, that means that the following example will
/// fail to compile:
///
/// ```
/// trait Assoc {
/// type Output;
/// }
///
/// impl<T> Assoc for T {
/// default type Output = bool;
/// }
///
/// fn main() {
/// let <() as Assoc>::Output = true;
/// }
/// At type-checking time, we avoid projecting the concrete type of
/// `impl Trait`. We do allow other monomorphic projections, such as
/// `default type` in the fully monomorphic case.
UserFacing,

/// At trans time, all monomorphic projections will succeed.
@@ -949,15 +930,13 @@ fn assemble_candidates_from_impls<'cx, 'gcx, 'tcx>(
// get a result which isn't correct for all monomorphizations.
let new_candidate = if !is_default {
Some(ProjectionTyCandidate::Select)
} else if obligation.param_env.reveal == Reveal::All {
} else {
assert!(!poly_trait_ref.needs_infer());
if !poly_trait_ref.needs_subst() {
Some(ProjectionTyCandidate::Select)
} else {
None
}
} else {
None
};

candidate_set.vec.extend(new_candidate);
Original file line number Diff line number Diff line change
@@ -32,10 +32,10 @@ fn generic<T>() -> <T as Foo>::Assoc {
}

fn monomorphic() -> () {
// Even though we know that `()` is not specialized in a
// downstream crate, typeck refuses to project here.
// Since we know that `()` is not specialized in a
// downstream crate, typeck allows projection here.

generic::<()>() //~ ERROR mismatched types
generic::<()>()
}

fn main() {
Original file line number Diff line number Diff line change
@@ -32,10 +32,10 @@ fn generic<T>() -> <T as Foo>::Assoc {
}

fn monomorphic() -> () {
// Even though we know that `()` is not specialized in a
// downstream crate, typeck refuses to project here.
// Since we know that `()` is not specialized in a
// downstream crate, typeck allows projection here.

generic::<()>() //~ ERROR mismatched types
generic::<()>()
}

fn main() {
4 changes: 2 additions & 2 deletions src/test/compile-fail/ufcs-partially-resolved.rs
Original file line number Diff line number Diff line change
@@ -45,7 +45,7 @@ fn main() {
<u8 as A>::N::NN; //~ ERROR cannot find associated type `N` in `A`
let _: <u8 as Tr>::Y::NN; //~ ERROR ambiguous associated type
let _: <u8 as E>::Y::NN; //~ ERROR expected associated type, found variant `E::Y`
<u8 as Tr>::Y::NN; //~ ERROR no associated item named `NN` found for type `<u8 as Tr>::Y`
<u8 as Tr>::Y::NN; //~ ERROR no associated item named `NN` found for type `u16`
<u8 as E>::Y::NN; //~ ERROR expected associated type, found variant `E::Y`

let _: <u8 as Tr::N>::NN; //~ ERROR cannot find associated type `NN` in `Tr::N`
@@ -62,5 +62,5 @@ fn main() {
let _: <u8 as Dr>::Z; //~ ERROR expected associated type, found method `Dr::Z`
<u8 as Dr>::X; //~ ERROR expected method or associated constant, found associated type `Dr::X`
let _: <u8 as Dr>::Z::N; //~ ERROR expected associated type, found method `Dr::Z`
<u8 as Dr>::X::N; //~ ERROR no associated item named `N` found for type `<u8 as Dr>::X`
<u8 as Dr>::X::N; //~ ERROR no associated item named `N` found for type `u16`
}