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

Delay ambiguity span bug in normalize query iff not rustdoc #103368

Merged
merged 2 commits into from
Oct 23, 2022
Merged
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
21 changes: 19 additions & 2 deletions compiler/rustc_trait_selection/src/traits/query/normalize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use rustc_infer::traits::Normalized;
use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable};
use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable};
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitor};
use rustc_span::DUMMY_SP;

use std::ops::ControlFlow;

Expand Down Expand Up @@ -253,7 +254,15 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
let result = tcx.normalize_projection_ty(c_data)?;
// We don't expect ambiguity.
if result.is_ambiguous() {
bug!("unexpected ambiguity: {:?} {:?}", c_data, result);
// Rustdoc normalizes possibly not well-formed types, so only
// treat this as a bug if we're not in rustdoc.
if !tcx.sess.opts.actually_rustdoc {
tcx.sess.delay_span_bug(
DUMMY_SP,
format!("unexpected ambiguity: {:?} {:?}", c_data, result),
);
}
return Err(NoSolution);
}
let InferOk { value: result, obligations } =
self.infcx.instantiate_query_response_and_region_obligations(
Expand Down Expand Up @@ -296,7 +305,15 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
let result = tcx.normalize_projection_ty(c_data)?;
// We don't expect ambiguity.
if result.is_ambiguous() {
bug!("unexpected ambiguity: {:?} {:?}", c_data, result);
// Rustdoc normalizes possibly not well-formed types, so only
// treat this as a bug if we're not in rustdoc.
if !tcx.sess.opts.actually_rustdoc {
tcx.sess.delay_span_bug(
DUMMY_SP,
format!("unexpected ambiguity: {:?} {:?}", c_data, result),
);
}
return Err(NoSolution);
}
let InferOk { value: result, obligations } =
self.infcx.instantiate_query_response_and_region_obligations(
Expand Down
24 changes: 24 additions & 0 deletions src/test/rustdoc/not-wf-ambiguous-normalization.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// compile-flags: -Znormalize-docs

#![feature(type_alias_impl_trait)]

trait Allocator {
type Buffer;
}

struct DefaultAllocator;

// This unconstrained impl parameter causes the normalization of
// `<DefaultAllocator as Allocator>::Buffer` to be ambiguous,
// which caused an ICE with `-Znormalize-docs`.
impl<T> Allocator for DefaultAllocator {
type Buffer = ();
}

type A = impl Fn(<DefaultAllocator as Allocator>::Buffer);

fn foo() -> A {
|_| ()
}

fn main() {}
85 changes: 85 additions & 0 deletions src/test/ui/impl-trait/issue-103181-1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// edition:2021

mod hyper {
use std::{fmt::Debug, future::Future, marker::PhantomData, pin::Pin, task::Poll};

pub trait HttpBody {
type Error;
}
impl HttpBody for () {
//~^ ERROR not all trait items implemented, missing: `Error`
// don't implement `Error` here for the ICE
}

pub struct Server<I, S>(I, S);

pub fn serve<I, S>(_: S) -> Server<I, S> {
todo!()
}

impl<S, B> Future for Server<(), S>
where
S: MakeServiceRef<(), (), ResBody = B>,
B: HttpBody,
B::Error: Debug,
{
type Output = ();

fn poll(self: Pin<&mut Self>, _: &mut std::task::Context<'_>) -> Poll<Self::Output> {
todo!()
}
}

pub trait MakeServiceRef<Target, ReqBody> {
type ResBody;
}

impl<T, S> MakeServiceRef<(), ()> for T
where
T: for<'a> Service<&'a (), Response = S>,
S: Service<()>,
{
type ResBody = ();
}

pub struct MakeServiceFn<F>(pub F);
pub struct ServiceFn<F, R>(pub PhantomData<(F, R)>);

pub trait Service<Request> {
type Response;
}

impl<'t, F, Ret, Target, Svc> Service<&'t Target> for MakeServiceFn<F>
where
F: Fn() -> Ret,
Ret: Future<Output = Result<Svc, ()>>,
{
type Response = Svc;
}

impl<F, ReqBody, Ret, ResBody, E> Service<ReqBody> for ServiceFn<F, ReqBody>
where
F: Fn() -> Ret,
Ret: Future<Output = Result<ResBody, E>>,
{
type Response = ResBody;
}
}

async fn smarvice() -> Result<(), ()> {
Ok(())
}

fn service_fn<F, R, S>(f: F) -> hyper::ServiceFn<F, R>
where
F: Fn() -> S,
{
hyper::ServiceFn(std::marker::PhantomData)
}

async fn iceice() {
let service = hyper::MakeServiceFn(|| async { Ok::<_, ()>(service_fn(|| smarvice())) });
hyper::serve::<(), _>(service).await;
}

fn main() {}
12 changes: 12 additions & 0 deletions src/test/ui/impl-trait/issue-103181-1.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
error[E0046]: not all trait items implemented, missing: `Error`
--> $DIR/issue-103181-1.rs:9:5
|
LL | type Error;
| ---------- `Error` from trait
LL | }
LL | impl HttpBody for () {
| ^^^^^^^^^^^^^^^^^^^^ missing `Error` in implementation

error: aborting due to previous error

For more information about this error, try `rustc --explain E0046`.
29 changes: 29 additions & 0 deletions src/test/ui/impl-trait/issue-103181-2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// edition:2021

trait SendFuture: Send {
type Output;
}

impl<Fut: Send> SendFuture for Fut {
type Output = ();
}

async fn broken_fut() {
ident_error;
//~^ ERROR cannot find value `ident_error` in this scope
}

// triggers normalization of `<Fut as SendFuture>::Output`,
// which requires `Fut: Send`.
fn normalize<Fut: SendFuture>(_: Fut, _: Fut::Output) {}

async fn iceice<A, B>()
// <- async fn is necessary
where
A: Send,
B: Send, // <- a second bound
{
normalize(broken_fut(), ());
}

fn main() {}
9 changes: 9 additions & 0 deletions src/test/ui/impl-trait/issue-103181-2.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
error[E0425]: cannot find value `ident_error` in this scope
--> $DIR/issue-103181-2.rs:12:5
|
LL | ident_error;
| ^^^^^^^^^^^ not found in this scope

error: aborting due to previous error

For more information about this error, try `rustc --explain E0425`.