Rollup merge of #103368 - compiler-errors:normalization-ambiguity-bug, r=oli-obk
Delay ambiguity span bug in normalize query iff not rustdoc Oli and I decided that the compiler debt of adding another usage of `tcx.sess.opts.actually_rustdoc` is fine, because we don't really want to add more complexity to the normalize query, and moving rustdoc to use fulfill normalization (`fully_normalize`, i.e. not use the normalize query) is unnecessary overhead given that it's skipping binders and stuff. r? oli-obk Fixes #102827 Fixes #103181
This commit is contained in:
commit
72f75d18b1
@ -14,6 +14,7 @@
|
||||
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;
|
||||
|
||||
@ -253,7 +254,15 @@ fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
|
||||
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(
|
||||
@ -296,7 +305,15 @@ fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
|
||||
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(
|
||||
|
24
src/test/rustdoc/not-wf-ambiguous-normalization.rs
Normal file
24
src/test/rustdoc/not-wf-ambiguous-normalization.rs
Normal file
@ -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
src/test/ui/impl-trait/issue-103181-1.rs
Normal file
85
src/test/ui/impl-trait/issue-103181-1.rs
Normal file
@ -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
src/test/ui/impl-trait/issue-103181-1.stderr
Normal file
12
src/test/ui/impl-trait/issue-103181-1.stderr
Normal file
@ -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
src/test/ui/impl-trait/issue-103181-2.rs
Normal file
29
src/test/ui/impl-trait/issue-103181-2.rs
Normal file
@ -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
src/test/ui/impl-trait/issue-103181-2.stderr
Normal file
9
src/test/ui/impl-trait/issue-103181-2.stderr
Normal file
@ -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`.
|
Loading…
Reference in New Issue
Block a user