Skip to content
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

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

Closed
Closed
Show file tree
Hide file tree
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
Expand Up @@ -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.
Expand Down Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
4 changes: 2 additions & 2 deletions src/test/compile-fail/ufcs-partially-resolved.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand All @@ -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`
}