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

The never type can be named despite its feature gate #58733

Open
SimonSapin opened this issue Feb 25, 2019 · 8 comments
Open

The never type can be named despite its feature gate #58733

SimonSapin opened this issue Feb 25, 2019 · 8 comments
Labels
A-stability Area: issues related to #[stable] and #[unstable] attributes themselves. C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@SimonSapin
Copy link
Contributor

Reported by @xfix in #33417 (comment).

trait MyTrait {
    type Output;
}

impl<T> MyTrait for fn() -> T {
    type Output = T;
}

type Void = <fn() -> ! as MyTrait>::Output;

fn main() {
    let _a: Void;
}

The never type is unstable (#35121) but the code above (which doesn’t use any feature gate) compiles in Rust 1.12.0 (which I think is the first with #35162), 1.32.0, and 1.34.0-nightly (aadbc45 2019-02-23). In 1.11.0, it errors with:

error: the trait bound `fn() -> !: MyTrait` is not satisfied [--explain E0277]
  --> a.rs:12:13
   |>
12 |>     let _a: Void;
   |>             ^^^^
help: the following implementations were found:
help:   <fn() -> T as MyTrait>

error: aborting due to previous error
@SimonSapin SimonSapin added A-stability Area: issues related to #[stable] and #[unstable] attributes themselves. C-bug Category: This is a bug. labels Feb 25, 2019
@SimonSapin SimonSapin changed the title It is possible to indirectly name the never type despite its feature gate The never type can be named despite its feature gate Feb 25, 2019
@varkor
Copy link
Member

varkor commented Feb 25, 2019

This case can be reduced to the following:

fn foo() -> ! {
    unimplemented!()
}

which is as a result of this // Do nothing special-case in the feature gate code:

fn visit_fn_ret_ty(&mut self, ret_ty: &'a ast::FunctionRetTy) {
if let ast::FunctionRetTy::Ty(ref output_ty) = *ret_ty {
if let ast::TyKind::Never = output_ty.node {
// Do nothing
} else {
self.visit_ty(output_ty)
}
}
}

This was intentionally added in 4d1a30c.

@Nemo157
Copy link
Member

Nemo157 commented Feb 25, 2019

@varkor that on its own is just a diverging function, which has been supported since Rust 1.0.0 (and probably long before).

@varkor
Copy link
Member

varkor commented Feb 25, 2019

@Nemo157: ah, I see. Originally, diverging functions were separate from the never type, but since they became unified, there's nothing to distinguish a diverging function from a function returning never. It seems unavoidable to have ! in potentially any position if we have it in some, because of tricks like this.

@Centril
Copy link
Contributor

Centril commented Feb 26, 2019

Idea: Could we emit a warning when encounter constructs such as the one in the issue description?

@pnkfelix
Copy link
Member

I'm curious what we can/should consider the bug here to be.

Specifically, in the absence of #![feature(never_type)], should we consider fn() -> ! to not be covered by the blanket impl impl<T> MyTrait for fn() -> T ?

(And maybe this question is going to be made irrelevant so soon that it need not be answered...)

@pnkfelix
Copy link
Member

Ah yes I think my previous question is made obsolete by PR #65355

@Centril Centril closed this as completed Nov 22, 2019
@Mathspy
Copy link

Mathspy commented Dec 12, 2019

Is this issue relevant again because of #67224?

@estebank estebank reopened this Dec 13, 2019
@danielhenrymantilla
Copy link
Contributor

should we consider fn() -> ! to not be covered by the blanket impl impl<T> MyTrait for fn() -> T ?

@pnkfelix that doesn't look like it would be that much better, because then people could also write impl MyTrait for fn() -> ! {}, so we'd have to ban diverging function pointer types from ever being named within trait impls at all (or at least among the impl inputs).


Given the current situation with ! having almost been stabilized but for the fallback-inference-regressions regarding Infallible-becoming-!, I think that having the Never alias, alone (not involving Infallible), seems to be fine? Provided, of course, that no people try to rely on Never and Infallible being distinct, which is a caveat already covered in https://doc.rust-lang.org/1.58.0/core/convert/enum.Infallible.html#future-compatibility.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-stability Area: issues related to #[stable] and #[unstable] attributes themselves. C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

8 participants